Authentication
Most API requests need an API key. These don’t: POST /v1/diagrams/validate, POST /v1/diagrams/preview, GET /v1/public/diagrams/{id}, POST /v1/public/diagrams/{id}/report, and the signed image links that GET /v1/diagrams/{id}/render returns. The Diagrams API page lists every endpoint.
The MCP server at https://api.zindex.ai/mcp also signs people in with their Zindex account (OAuth 2.1), for clients such as claude.ai and ChatGPT that can’t send a key; Connect over HTTPS explains it. Those sign-in tokens work only on /mcp. Every REST endpoint takes an API key.
API key format
Keys are prefixed for identification: dsp_sk_<64-random-hex-chars>
The server stores only the SHA-256 hash of the key. The plaintext key is shown once on creation and cannot be retrieved again.
Sending your key
Include the key in the Authorization header:
Authorization: Bearer dsp_sk_abc123...
Diagram ownership
A diagram belongs to the user account that saved it. Any of that account’s API keys can read and edit the diagram, and so can the account’s signed-in dashboard session. You can rotate or add keys without losing access. Requesting a diagram owned by another account returns 404 NOT_FOUND, the same as a diagram that doesn’t exist.
Email verification
Until the account has verified its email, saving, editing, deleting, restoring, sharing and reporting a diagram return 403 Forbidden:
{ "error": "Verify this account's email address before saving diagrams: https://zindex.ai/verify-email", "code": "EMAIL_NOT_VERIFIED" }
Send the user to https://zindex.ai/verify-email to clear it. Reads, renders and the endpoints that need no key are never gated.
Creating API keys
Use the key management endpoint to create additional keys:
curl -s https://api.zindex.ai/v1/auth/keys \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Production Key" }'
The response includes the new key - store it securely, as it cannot be retrieved again.
Plan limits
Each workspace is on a plan (free, builder, growth, enterprise) that caps four resources: diagrams, monthly diagram updates, monthly renders, and API keys. The full numbers are on the pricing page. When the account reaches its cap on diagrams, updates or renders, the call that would go over it returns 403 Forbidden:
{
"error": "This account's plan allows 50 diagrams; it has 50.",
"code": "LIMIT_REACHED",
"limit": "scenes",
"maximum": 50,
"current": 50
}
limit names the cap that was hit, and maximum and current give the numbers. Creating an API key past the apiKeys cap returns code: "PLAN_LIMIT_EXCEEDED" instead, with limit, current, maximumAllowed, plan and upgradeUrl, and an error that names the plan and the upgrade link.
Which endpoints enforce which cap:
| Cap | Endpoint | Resets |
|---|---|---|
scenes | POST /v1/diagrams and diagram_create | When you delete a diagram |
updatesPerMonth | POST /v1/diagrams/{id}/revisions and diagram_edit | Start of the next calendar month |
rendersPerMonth | GET /v1/diagrams/{id}/render and diagram_render | Start of the next calendar month |
apiKeys | POST /v1/auth/keys | When you revoke an existing key |
Every saved revision counts toward updatesPerMonth, however it was made. Each call to GET /v1/diagrams/{id}/render counts toward rendersPerMonth; diagram_render is refused once that cap is reached but doesn’t add to the count, and opening an image link never counts. Retrying a create with the same key returns the existing diagram and isn’t counted again. Read endpoints, the endpoints that need no key, and enterprise-plan workspaces are never gated. Don’t retry a LIMIT_REACHED or PLAN_LIMIT_EXCEEDED response. The cap holds until capacity is freed, the month rolls over or the workspace upgrades. The dashboard shows current usage against each cap, so users can see where they stand before they reach one.
Rate limiting
Every endpoint except GET /health is rate-limited over a sliding one-minute window.
| Caller | Requests per minute | Counted per |
|---|---|---|
| Signed in: an API key, MCP sign-in or the dashboard | 60 on the free plan, 120 on Builder, 600 on Growth and 6,000 on Enterprise, plus a burst of 10 | Account. All of its keys and sign-ins share one limit |
| No key | 30, plus a burst of 10 | IP address |
POST /v1/diagrams/validate and POST /v1/diagrams/preview always count per IP address, at the no-key limit, even when a key is sent.
Over the limit, the API answers 429 Too Many Requests with { "error": "Rate limit exceeded", "retryAfter": 12 } and a Retry-After header, both in seconds. Wait that long, then try again.
Responses carry X-RateLimit-Remaining, the requests left in the current window. A 429 also carries X-RateLimit-Reset, the Unix time in seconds when the oldest request in the window drops out of it.