Skip to main content

Errors, retries and idempotency

Error envelope

Assayra errors use a stable JSON shape:

{
"error": "validation_failed",
"message": "The request did not satisfy the API contract.",
"details": {
"field": "workflowId"
}
}

Never expose internal details directly to an applicant. Map known codes to your product language and retain the request correlation in protected logs.

Status codes

HTTPMeaningRecommended handling
400Invalid syntax, schema or unsupported stateCorrect the request; do not retry unchanged
401Missing or invalid credentialStop, refresh configuration and alert if unexpected
403Scope, role, entitlement or state deniedDo not retry until authorization changes
404Route/record unavailableCheck environment and tenant context
409State conflict or conflicting idempotency reuseReconcile the original result before creating a new key
429Rate limit exceededBack off with jitter and respect Retry-After when present
5xxTemporary server-side failureRetry boundedly with the same idempotency key

Idempotency keys

Authenticated mutations require Idempotency-Key in production. Use a cryptographically random value unique to the intended business operation.

Idempotency-Key: 018f65c6-7ee2-7a84-9f3c-3ee29a70dc8b

The same key and same payload return the original response. Reusing the key with a different payload is rejected. Keep the key until the network outcome is known.

const idempotencyKey = crypto.randomUUID();

await proofline.applications.create(input, { idempotencyKey });
// A network retry must reuse idempotencyKey—not generate another one.

Retry policy

Use exponential backoff with jitter, a bounded attempt count, and a final reconciliation read:

const delays = [250, 750, 2000, 5000];

for (let attempt = 0; attempt <= delays.length; attempt += 1) {
try {
return await createApplication(idempotencyKey);
} catch (error) {
if (!isRetryable(error) || attempt === delays.length) throw error;
await wait(delays[attempt] + Math.random() * 200);
}
}

Do not retry schema failures, permission failures or a 409 with a new idempotency key. That can create duplicate real-world work.