Error Handling & Retries
A robust integration is built around two assumptions: the network will fail, and the same request may execute more than once. This guide shows how to handle Cronozen errors correctly without creating duplicate decisions, double-charged payments, or broken DPU chains.Error Response Shape
Every Cronozen error follows the same shape:requestId — it lets us trace the exact request server-side when you contact support.
HTTP Status Codes
| Status | Meaning | Should Retry? |
|---|---|---|
400 | Bad request (validation, schema) | No — fix the request |
401 | Missing or invalid API key | No — refresh credentials |
403 | Authenticated but unauthorized | No — check scope/role |
404 | Resource not found | No |
409 | Conflict (duplicate, version mismatch) | Sometimes — see below |
422 | Policy violation, semantic error | No — domain decision |
429 | Rate limited | Yes, with backoff (Retry-After header) |
500 | Server error | Yes, with backoff |
502/503/504 | Gateway/availability | Yes, with backoff |
429 and 5xx are safe to retry. Retrying 4xx errors will just produce the same error.
Idempotency Keys
For any state-changing call (creating decisions, payments, attendance), pass anIdempotency-Key header. If the same key arrives twice, Cronozen returns the original response without re-executing:
- Stable — derived from your domain (e.g.,
order-{orderId}-decision-{attempt}) - Unique per logical action — not random per HTTP request
- Long enough to avoid collisions (UUIDs work, short slugs don’t)
Recommended Retry Logic
Exponential backoff with jitter:Handling 409 Conflict
409 indicates the request collided with existing state. Common cases:
- Duplicate idempotency key with different body — fix your key derivation
- Optimistic version mismatch — refresh the resource and retry with new version
- Workflow state conflict — the workflow has moved past the step you’re trying to act on
409 errors include enough detail to decide. They are not safe to retry blindly.
DPU Sealing Failures
If a decision call succeeds but DPU sealing fails (rare — usually a transient storage error), the response includesdpu.status: "pending" instead of "sealed". Two options:
- Wait and check — poll
GET /api/v1/dpu/{id}until status issealed. - Retry the decide call with the same idempotency key — Cronozen will return the existing decision and attempt to re-seal the DPU.
Network Timeouts
Set client timeouts above Cronozen’s expected response time:| Endpoint | Typical | Timeout to set |
|---|---|---|
| Most CRUD | < 500 ms | 5 s |
POST /agents/decide (with model call) | 1–5 s | 30 s |
POST /agents/decide (with human approval) | wait-on-approval | Use webhooks |
| Long-running workflows | > 30 s | Use workflow API + polling/webhook |
What Cronozen Does on Your Behalf
- Internal services automatically retry transient downstream failures.
- DPU chain integrity is preserved even across server restarts.
- Webhook delivery is retried for 7 attempts before being marked failed (see Webhook Integration).
Debugging Checklist
When something goes wrong:- Log the full error response, including
requestId - Check whether the status is 4xx (your side) or 5xx (our side)
- For 4xx: read
error.codeanderror.message— these are designed to tell you what to fix - For 5xx: retry with backoff; if persistent, contact support with
requestId - For ambiguous (timeout, network reset): retry with the same
Idempotency-Key