Standard HTTP status codes with consistent JSON error objects. Detect and recover from failures programmatically.
Consistent JSON structure on every error. 4xx = client error, 5xx = server issue.
{
"error": "error_code",
"message": "Human-readable description",
"details": {},
"request_id": "req_abc123"
}Use the code (not the message) for programmatic error handling.
When the error code is validation_error, the details object contains a fields map with per-field error messages.
{
"error": "validation_error",
"message": "Validation failed",
"details": {
"fields": {
"email": "Must be a valid email address",
"password": "Must be at least 8 characters"
}
}
}Keys in the fields object match request body parameter names. Multiple fields can fail at once.
Check the HTTP status code before parsing the response body. Transient errors (429, 502, 503): retry with exponential backoff. Client errors (400-422): fix the request before retrying.
async function dyvaFetch(url, options = {}) {
const res = await fetch(url, {
...options,
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
...options.headers,
},
});
if (!res.ok) {
const error = await res.json();
switch (error.error) {
case "token_expired":
// Refresh the token and retry
await refreshToken();
return dyvaFetch(url, options);
case "rate_limit_exceeded":
// Wait and retry with backoff
const retryAfter = res.headers.get("Retry-After") || 5;
await new Promise((r) => setTimeout(r, retryAfter * 1000));
return dyvaFetch(url, options);
case "validation_error":
// Surface field-level errors to the UI
console.error("Validation errors:", error.details.fields);
throw new ValidationError(error.details.fields);
default:
throw new Error(`[${error.error}] ${error.message} (request: ${error.request_id})`);
}
}
return res.json();
}Common errors and fixes.
unauthorizedrate_limit_exceededupstream_errorplan_limitEvery API response includes an X-Request-Id header with a unique identifier. Error response bodies also include it in the request_id field.
Include the request_id when contacting support. It lets the team trace the exact request and diagnose faster.
const res = await fetch("https://api.dyva.ai/v1/dyvas", {
headers: { Authorization: `Bearer ${API_KEY}` },
});
// Always available, even on success
const requestId = res.headers.get("X-Request-Id");
console.log("Request ID:", requestId);
if (!res.ok) {
const error = await res.json();
// Also available in the error body
console.error("Error request ID:", error.request_id);
}