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

CodeMeaningWhen It Happens
400Bad RequestMissing or invalid parameters in your request body or query string
401UnauthorizedMissing, invalid, expired, or revoked API key
403ForbiddenKey is valid but lacks the required scope for this endpoint
404Not FoundResource doesn’t exist or doesn’t belong to your tenant
429Too Many RequestsRate limit exceeded β€” wait and retry
500Internal Server ErrorSomething 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");
}
Aram by ScootSign docs.scootsign.com