Skip to navigation

Error Handling

Understanding ETERA API error responses

Error Response Format

All ETERA APIs return errors in a consistent JSON format:

{
"error": {
"code": "VALIDATION_ERROR",
"message": "The 'checkIn' field is required",
"status": 400,
"details": []
}
}

HTTP Status Codes

4xx Client Errors
CodeMeaning
400Bad Request — Invalid parameters or malformed request body
401Unauthorized — Missing or invalid API key
403Forbidden — Insufficient permissions for this resource
404Not Found — Resource does not exist
409Conflict — Resource state conflict (e.g., double booking)
422Unprocessable Entity — Validation failure on request body
429Too Many Requests — Rate limit exceeded
CodeMeaning
500Internal Server Error — Something went wrong on our end
502Bad Gateway — Upstream service unavailable
503Service Unavailable — Service temporarily down
504Gateway Timeout — Upstream service took too long

For 5xx errors, always implement retry logic with exponential backoff. These are typically transient issues.


Error Codes

Common error codes returned in the error.code field:

CodeDescription
VALIDATION_ERRORRequest body failed validation
AUTHENTICATION_ERRORInvalid or expired credentials
AUTHORIZATION_ERRORInsufficient permissions
NOT_FOUNDRequested resource not found
RATE_LIMIT_EXCEEDEDToo many requests
BOOKING_CONFLICTConflicting reservation
PAYMENT_FAILEDPayment processing error
SERVICE_UNAVAILABLEUpstream service is down

Retry Strategy

For 429 and 5xx errors, implement exponential backoff:

1

First retry

Wait 1 second, then retry the request

2

Second retry

Wait 2 seconds, then retry

3

Third retry

Wait 4 seconds, then retry

4

Give up

After 3 retries, log the error and notify the user

Implementation

async function fetchWithRetry(
url: string,
options: RequestInit,
retries = 3
) {
for (let attempt = 0; attempt < retries; attempt++) {
const response = await fetch(url, options);
if (response.ok) return response;
if (response.status === 429 || response.status >= 500) {
const delay = Math.pow(2, attempt) * 1000;
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
throw new Error(`Request failed: ${response.status}`);
}
throw new Error("Max retries exceeded");
}

For 429 responses, check the Retry-After header if present — it indicates exactly how long to wait before retrying.


Common Scenarios

Your token has expired or is invalid. Re-authenticate using your preferred method:

if (response.status === 401) {
const newToken = await refreshAuth();
// Retry with new token
}

See Authentication for details on token refresh.

Check the error.details array for field-level validation messages:

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"status": 422,
"details": [
{ "field": "checkIn", "message": "Must be a future date" },
{ "field": "partySize", "message": "Must be between 1 and 20" }
]
}
}

You’ve exceeded the rate limit. Check these headers:

HeaderDescription
X-RateLimit-LimitMaximum requests per window
X-RateLimit-RemainingRemaining requests in current window
X-RateLimit-ResetUnix timestamp when the window resets
Retry-AfterSeconds to wait before retrying

The requested time slot or resource is no longer available. Fetch updated availability and let the user choose an alternative.


Next Steps