Error shape
Every error has { "error": { "message", "type", "param", "code" } }. Some add request_id, state or reason. X-Should-Retry: false marks errors a retry cannot fix.
| Status | Codes | What to do |
|---|---|---|
400 | invalid_request, invalid_routing, invalid_model_alias, unsupported_model_variant, invalid_idempotency_key | Fix the request. Not retried. |
401 | invalid_api_key | Check the key. |
402 | insufficient_credits | Add credits. Nothing was charged. |
403 | account_not_eligible | Complete the account check on your Account page. |
404 | model_not_found, no_eligible_provider, no_free_endpoints, not_found | Pick another model or loosen preferences. |
405 | method_not_allowed | Use the method in the Allow header. |
409 | idempotency_conflict, idempotency_replay_unavailable | The key was already used; see Idempotency. |
413 | request_too_large | Bodies are limited to 2 MiB. |
429 | rate_limit_exceeded, key_limit_exceeded | Wait for Retry-After, or raise the key's limit. |
499 | request_canceled | You disconnected before the answer was ready. Not charged. |
502 | upstream_verification_failed, upstream_timeout | No verified answer. Not charged; retry. |
503 | capacity_unavailable, reconciliation_required and other *_unavailable codes | Retry later. With reconciliation_required, keep the request ID: the charge is being settled. |
Response headers
| Header | Meaning |
|---|---|
X-Request-Id | The request ID. Use it for support, /v1/generation and saved answers. |
X-Zalmir-Verified: true | The answer passed the seller's signature check (X-Zalmir-Verification-Scope: response-signature). This proves who signed the bytes, not which model ran. |
X-Zalmir-Prompt-Privacy, X-Zalmir-Model-Proof | not-confidential and not-attested. |
X-Zalmir-Tool-Execution: none | Zalmir never runs tools. |
X-Zalmir-Replayed: true | A saved answer replayed for a repeated idempotent request. |
Retry-After | Seconds to wait before retrying. |
Idempotency
Send Idempotency-Key (1 to 256 printable characters, no commas) to make a retry safe. The same key with the same body never runs twice: a charged answer is replayed, otherwise you get 409 idempotency_replay_unavailable. The same key with a different body is 409 idempotency_conflict. A key cannot be combined with fallbacks across several endpoints, or with your own provider key.
curl "$BASE_URL/chat/completions" \
-H "Authorization: Bearer $API_KEY" \
-H "Idempotency-Key: order-1234" \
-H "Content-Type: application/json" \
-d '{
"model": "<model id>",
"messages": [{ "role": "user", "content": "Hello" }],
"provider": { "allow_fallbacks": false }
}'Saved answers after a disconnect
If you disconnect before the answer is ready, the request is canceled and not charged. If the answer was ready and charged, Zalmir saves the exact bytes, encrypted and readable only with your key, until you delete them or close your account. Fetch them with the original X-Request-Id:
curl "$BASE_URL/requests/00000000-0000-4000-8000-000000000000/response" \
-H "Authorization: Bearer $API_KEY"App attribution
HTTP-Referer and X-Title name your app on your Activity page. They are optional, never sent to the seller, and recorded only for charged requests.
curl "$BASE_URL/chat/completions" \
-H "Authorization: Bearer $API_KEY" \
-H "HTTP-Referer: https://myapp.example" \
-H "X-Title: My App" \
-H "Content-Type: application/json" \
-d '{
"model": "<model id>",
"messages": [{ "role": "user", "content": "Hello" }]
}'