Error Handling
All error responses follow a consistent JSON format with success: false and an error message.
Error Response Format
{
"success": false,
"error": "Description of what went wrong"
}
HTTP Status Codes
| Code | Meaning | When It Happens |
|---|---|---|
400 | Bad Request | Missing or invalid parameters in your request body or query string |
401 | Unauthorized | Missing, invalid, expired, or revoked API key |
403 | Forbidden | Key is valid but lacks the required scope for this endpoint |
404 | Not Found | Resource doesnβt exist or doesnβt belong to your tenant |
429 | Too Many Requests | Rate limit exceeded β wait and retry |
500 | Internal Server Error | Something went wrong on our end β contact support |
Handling Errors
const res = await fetch("https://api.scootsign.com/api/v1/jds/nonexistent", {
headers: { "X-API-Key": process.env.ARAM_API_KEY },
});
if (!res.ok) {
const { error } = await res.json();
switch (res.status) {
case 401: console.error("Auth failed:", error); break;
case 403: console.error("Insufficient scope:", error); break;
case 404: console.error("Not found:", error); break;
case 429:
const retryAfter = res.headers.get("X-RateLimit-Reset");
console.error("Rate limited, retry after:", retryAfter);
break;
default: console.error("API error:", res.status, error);
}
}
Retry Strategy
For 429 and 5xx errors, use exponential backoff:
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const res = await fetch(url, options);
if (res.ok) return res.json();
if (res.status === 429 || res.status >= 500) {
const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
await new Promise(r => setTimeout(r, delay));
continue;
}
throw new Error(`API error ${res.status}: ${(await res.json()).error}`);
}
throw new Error("Max retries exceeded");
}