Documentation

Errors

Errors are structured: { "success": false, "error": { "code": "ERR_…", "message": "…" } }. Branch on error.code, never on the human message — codes are stable, strings are not.

stable codes retry-safe

The full table

HTTPCodeMeaning and fix
401ERR_UNAUTHORIZEDMissing, invalid or revoked token. Revoked keys fail with exactly this — mint a new key.
403ERR_FORBIDDENPermission denied: a read-only key sent a write, or a key was used outside its database.
403ERR_QUOTA_EXCEEDEDPlan limit reached (databases, keys or bytes). Clean up or expect the admin to raise the ceiling.
404ERR_NOT_FOUNDUnknown or expired key / unknown database. Treat as a miss — same semantics as Redis nil.
409ERR_CONFLICTRule collision — typically minting a second key for a database that already has one active.
413ERR_PAYLOAD_TOO_LARGEValue above the value-size quota.
422ERR_VALIDATIONStrict body validation: wrong field, wrong type, unknown extra field. Fix the payload shape.
429ERR_RATE_LIMITEDToo many requests. Read Retry-After, back off, retry with jitter.
503ERR_SERVICE_UNAVAILABLEBacking store unreachable. Retry with exponential backoff.

Retrying without making it worse

  • 429 / 503 are the retryable classes: honor Retry-After, add jitter, cap retries. Everything else means "fix the request", not "send it again".
  • 404 is a miss, not an error to escalate: a key that hit its TTL answers 404 by design (see TTL policy).
  • Writes are atomic over pipelines — a rejected batch leaves no partial state, so re-sending a failed batch is always safe.
  • 429 flood guard: per-database in-flight caps reject instantly rather than queueing; keep small client connection pools instead of one giant unbounded fan-out.