Authentication

Most API requests require authentication via API key. Public endpoints (validate, render, normalize) do not require a key - see Endpoints for details.

API key format

Keys are prefixed for identification: dsp_sk_<random-32-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...

Per-user scene isolation

Each API key is associated with an ownerId. Scenes created with a key are only accessible to that key’s owner. Attempting to access another user’s scene returns 404.

Email verification

Write endpoints return 403 Forbidden with { "error": "email_not_verified", "verifyUrl": "/verify-email" } if the account has not verified its email. Send the user to https://zindex.ai/verify-email to clear it. Read endpoints and the public stateless endpoints 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: persisted scenes, monthly diagram updates, monthly renders, and API keys. The full numbers are on the pricing page. When a cap is reached the affected write endpoint returns 403 Forbidden with a structured payload:

{
  "error": "Plan limit reached on the free plan: 50 of 50 persisted scenes. Free a slot by deleting an existing scene, or upgrade your plan at https://zindex.ai/pricing.",
  "code": "PLAN_LIMIT_EXCEEDED",
  "limit": "scenes",
  "current": 50,
  "maximumAllowed": 50,
  "plan": "free",
  "upgradeUrl": "https://zindex.ai/pricing"
}

The error string is self-contained - it includes the plan slug, the count, and the upgrade URL inline so an agent or UI can display it verbatim. The structured fields (code, limit, current, maximumAllowed, plan, upgradeUrl) support programmatic branching: switch on code === "PLAN_LIMIT_EXCEEDED", read limit to know which cap was hit, render an “upgrade” CTA pointing at upgradeUrl.

Which endpoints enforce which cap:

CapEndpointResets
scenesPOST /v1/scenesWhen you delete an existing scene
updatesPerMonthPOST /v1/scenes/{id}/applyOpsStart of the next calendar month
rendersPerMonthPOST /v1/scenes/{id}/renderStart of the next calendar month
apiKeysPOST /v1/auth/keysWhen you revoke an existing key

Read endpoints, the public stateless endpoints (POST /v1/scenes/validate, /render, /normalize), and enterprise-plan workspaces are never gated. Do not retry on a PLAN_LIMIT_EXCEEDED response - the cap is sticky until capacity is freed or the workspace upgrades. The dashboard surfaces current usage against caps so users can see where they stand before hitting one.

Rate limiting

All endpoints are rate-limited to prevent abuse. Authenticated and public endpoints have separate tiers:

TierRequests/minBurstIdentifier
Authenticated6010API key
Public3010IP address

When exceeded, the API returns 429 Too Many Requests with a Retry-After header.

Response headers on every request: