Errors
Every error response follows the same envelope:
{
"error": "human-readable message",
"code": "machine_readable_code",
"request_id": "req_a1b2c3"
}error is intended for log lines and humans; code is what your client
should branch on. request_id is the same value returned in the
X-Request-ID response header — quote it when filing a support ticket.
Status codes
| Status | Class | Retry? |
|---|---|---|
400 Bad Request | Validation / malformed JSON | No — fix the request |
401 Unauthorized | Missing/invalid credentials | No — re-auth |
403 Forbidden | Authenticated but not allowed | No |
404 Not Found | Resource doesn’t exist or you can’t see it | No |
409 Conflict | Slug taken, idempotency-key mismatch, state collision | No (fix), or yes (refresh state then retry) |
422 Unprocessable Entity | Schema-valid but semantically wrong | No |
429 Too Many Requests | Rate limited — see Retry-After header | Yes after backoff |
500 Internal Server Error | Server bug — quote request_id | Yes with backoff |
502 / 503 / 504 | Transient infrastructure | Yes with exponential backoff |
Common error codes
| Code | Meaning |
|---|---|
validation_failed | One or more fields fail schema validation |
slug_taken | The requested vanity slug is already in use |
link_destination_unsafe | Destination URL flagged by url-scanner |
quota_exceeded | Workspace hit a soft/hard limit on links or clicks |
domain_not_verified | Custom domain DNS hasn’t propagated |
idempotency_key_mismatch | Same key, different payload — change one |
audit_immutable | Tried to mutate an already-counter-signed BAA |
Idempotency
Mutating endpoints accept an Idempotency-Key header. Same key + same
body within 24h returns the original response (replayed from cache).
Same key + different body returns 409 idempotency_key_mismatch.
curl -X POST https://api.elido.app/v1/links \
-H "Authorization: Bearer $ELIDO_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ "destination_url": "https://example.com" }'Retries
Retry only 429, 5xx, and network errors. Use exponential backoff
with jitter (e.g. min(60s, 2^attempt + random(0, 1000ms))). For
429, prefer the Retry-After value when present.
The first-party SDKs implement this automatically.