Error Handling
Error handling patterns — retry decisions, immutability, CANCEL and recreate, deduplication, and rate limits.
This guide covers operational recovery patterns for integrating with the Carrot API.
For endpoint error codes and payload format, see API Errors.
Classify failures first
4xx: request/data/integration issues. Fix payload or flow.5xx: transient platform or upstream issues. Retry with backoff.
Retry decision table
| Status Code | Error | Action |
|---|---|---|
400 | Validation error | Abort — fix the payload and resubmit |
401 / 403 | Authentication/authorization | Abort — check credentials or permissions |
404 | Resource not found | Abort — verify IDs in the request path |
409 | PENDING_PROCESS_CONFLICT_ERROR | Retry after 2-5 seconds — a background process is in progress |
409 | Other conflict errors | Abort — fix data conflict (e.g. duplicate), do not retry as-is |
422 | Unprocessable entity | Abort — fix the payload structure |
429 | Rate limit exceeded | Retry with exponential backoff |
500 | Internal server error | Retry with exponential backoff + deduplicationId |
502 / 503 / 504 | Gateway/service unavailable | Retry with exponential backoff + deduplicationId |
Retry strategy
- Use bounded exponential backoff for transient failures (start at 1s, max 30s, max 5 retries).
- Reuse
deduplicationIdon retryable create/event calls — see below. - Stop retrying on deterministic validation failures (
4xxother than409 PENDING_PROCESS_CONFLICT_ERRORand429).
deduplicationId mechanics
The deduplicationId is your idempotency key for write operations:
- Generate a unique ID before the first attempt
- Store it alongside the operation in your system
- Reuse the same ID on every retry of that operation
The ID is scoped per Network Integrator. If the server already processed your request, the retry returns the original response instead of creating a duplicate. This is critical for POST /documents and POST /documents/{id}/events.
Immutability recovery pattern
Because documents follow an immutable event-sourced model (see Core Concepts), a wrong timeline step cannot be corrected in place.
CANCEL and recreate
When a document has incorrect data (e.g. wrong participant), cancel it and create a corrected replacement:
1. POST /v1/documents/{wrongDocumentId}/events
{ "name": "CANCEL", ... }
2. POST /v1/documents
{ ...corrected document data... }
3. POST /v1/documents/{newDocumentId}/events
{
"name": "RELATED",
"relatedDocument": {
"documentId": "{wrongDocumentId}",
"bidirectional": true
},
...
}The RELATED event creates a traceability link between the cancelled document and its replacement, maintaining an auditable history.
Rate limiting
The Carrot API enforces per-integrator rate limits (see Rate Limits for the full reference):
| Environment | Limit |
|---|---|
| Test / Sandbox | 5 requests per second |
| Production | 10 requests per second |
Implement a client-side token bucket or leaky bucket to stay within limits. When you receive a 429, apply exponential backoff before retrying.
Observability
Log these fields from every API response for debugging and support:
- Request ID — returned in response headers
- Your
externalId— your internal correlation ID - Error envelope fields —
errors[].code,errors[].id,errors[].timestamp - Retry count — how many attempts were made
- Terminal failure reason — why retries stopped