API keys
Create, scope, rate-limit, and rotate a business API key.
Create a key
From your VUZ dashboard: Settings → Integrations → API Keys → Generate. Or call the underlying endpoint directly (requires a logged-in dashboard session — a JWT, not an API key — since minting a key needs a stronger credential than the key itself):
POST https://api.vuz.co.il/api/v1/api-keys
Authorization: Bearer <dashboard JWT>
X-Business-Id: <your business id>
Content-Type: application/json
{
"name": "My integration",
"scopes": ["documents:write", "documents:read", "clients:write", "clients:read", "business:read", "webhooks:manage"],
"rateLimitPerMinute": 60,
"rateLimitPerHour": 5000,
"allowedIps": "52.10.20.30,203.0.113.0/24",
"expiresAt": "2027-01-01T00:00:00.000Z"
}| Field | Required | Notes |
|---|---|---|
name | ✅ | Human-readable label |
scopes | ✅ | Array of canonical scope strings — must be an exact match to what each route requires |
rateLimitPerMinute | – | Default 60 |
rateLimitPerHour | – | Default 5000 |
allowedIps | – | Comma-separated IPs/CIDR ranges. Omit for no restriction |
expiresAt | – | ISO 8601. Omit for a key that never expires |
The response returns the raw key once:
{
"id": "b6b0b8b0-...",
"rawKey": "vuz_ab12cdef3456789012345678901234567890abcdef12",
"keyPrefix": "vuz_ab12",
"scopes": ["documents:write", "documents:read", "clients:write", "clients:read", "business:read", "webhooks:manage"],
"environment": "live",
"rateLimitPerMinute": 60,
"rateLimitPerHour": 5000,
"createdAt": "2026-07-01T12:00:00.000Z"
}Only keyPrefix (the first 8 characters) is ever retrievable again — VUZ stores a SHA-256
hash, not the raw key.
The environment field and the vuz_ prefix shown above are the business API-key
format — a key's string looks the same whether it's live or sandbox. Isolation
instead comes from a completely separate sandbox database: POST /api-keys/sandbox
(Settings → Integrations → API Keys → "Sandbox key") mints a key that only ever reads/
writes sandbox data, targeting https://sandbox-api.vuz.co.il instead of
https://api.vuz.co.il. The partner/reseller API uses a different key system with a
vuz_live_* / vuz_test_* prefix that DOES encode environment in the string — see
Partner API Reference if that's you.
Use the key
Every request sends it as X-Api-Key — no Authorization header, no X-Business-Id
(the key itself is bound to exactly one business):
curl https://api.vuz.co.il/api/v1/documents \
-H "X-Api-Key: vuz_ab12cdef3456789012345678901234567890abcdef12"Rate limits
Every response carries rate-limit headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1751371260Exceeding either the per-minute or per-hour counter returns 429:
{
"error": "rate_limit_exceeded",
"message": "Rate limit exceeded: 60 requests per minute",
"retryAfter": 12
}with a Retry-After header (seconds). Back off and retry after that many seconds — do not
poll faster.
If VUZ's rate limiter's Redis backend is unreachable, requests are allowed through (fail-open) rather than blocked — a rate limiter should never become an outage.
Update, view usage, revoke
PATCH /api/v1/api-keys/{id} # change name, scopes, rate limits, IP allowlist, expiry
GET /api/v1/api-keys/{id}/usage # total requests, last 24h/30d, top IPs, top user-agents, 2xx/4xx/5xx breakdown
DELETE /api/v1/api-keys/{id} # revoke — takes effect immediatelyAll three require the dashboard JWT (not the key itself) — key management is a dashboard operation.
Audit trail
Every request authenticated with an API key writes an api_key_usage row (route, method,
status, source IP, user agent, timestamp) — visible in the usage endpoint above and in the
dashboard's API Keys screen. Use it to spot a leaked key (unfamiliar IP) or debug an
integration.

