Errors

HTTP status codes, per-operation result statuses, and how to handle them.

HTTP status codes

A 200 response does not guarantee every resource was reserved — it means the request was processed. Check the status field on each result item.

StatusMeaningAction
200 Request processed. Check per-item status fields. Inspect each result item's status.
400 Malformed request: empty body, missing required field, or invalid value (e.g. ttlSeconds ≤ 0). Fix the request body. Error message is in the response string.
401 Missing or invalid X-Api-Key. Check the header name and key value. Retrieve a fresh key from the dashboard.
403 Unreserve: one or more requests supplied an invalid or missing release token. Body contains per-item results. Provide the correct releaseToken from the original reserve call.
404 Resource definition not found (delete endpoint). Check the resource name. Use GET /api/v1/Resource/definitions to list registered names.
429 Rate limit or tier capacity exceeded. Respect Retry-After header. Check upgradeRequired and limitType in the body.
503 Endpoint not available in the current store mode (e.g. tenant endpoints in InMemory mode). Configure a database-backed store type (Sqlite or Postgres).

Error response body

Non-200 responses carry a structured JSON body:

{
  "error":   "Daily operation limit reached (10000). Resets at midnight UTC.",
  "tier":    "Free",
  "limit":   10000,
  "retryAfter":      86394,
  "upgradeRequired": true
}

upgradeRequired: true means the limit is tier-based and can be raised by upgrading.

Reserve result statuses

StatusSuccess?Meaning
ACQUIREDResource reserved. releaseToken is set.
ALREADY_HADRequester already holds this resource. Idempotent — existing token returned.
ALREADY_HELDA different requester holds the resource. Retry later.
NOT_AVAILABLECapacity resource has no free slots.
NOT_VALIDResource is not registered (only for resources that require registration).

Unreserve result statuses

StatusSuccess?Meaning
RELINQUISHEDResource released. released lists all freed physical resources.
NOT_RESERVEDResource was already free. Safe and idempotent.
DOESNT_OWN_RESERVATIONThe requester does not hold this resource.

Rate limiting

Rate limits are enforced per {tenantId}:{tier}:{read|write}. Write operations — Reserve and Unreserve calls — each count as one op toward your tier's ops/min limit. A typical reserve-then-release cycle uses two ops.

Read operations (GET, HEAD, and POST .../check) use a separate bucket at 5× the write limit (e.g. Pro write limit = 5,000/min; read limit = 25,000/min). Read limits are an operational guard and are not part of the subscription SLA.

When a rate limit is hit, the server returns 429 with a Retry-After header giving the number of seconds to wait. For per-minute limits, this is typically a few seconds; for daily limits, it is the seconds until midnight UTC.

HTTP/1.1 429 Too Many Requests
Retry-After: 86394

{
  "error": "Daily operation limit reached (10000). Resets at midnight UTC.",
  "tier": "Free",
  "limit": 10000,
  "retryAfter": 86394,
  "upgradeRequired": true
}

Concurrent reservation limit

Each tier has a cap on the total number of simultaneously held reservations. If this limit is reached, new reserve calls return 429 with "limitType": "ConcurrentReservations". Release existing reservations or upgrade your tier to increase the limit.

TierConcurrent reservations
Free500
Starter10,000
Pro100,000
Enterprise1,000,000

Retrying safely

Reserve and unreserve are both safe to retry on network failures: