Skip to content

Error Handling

ICDC surfaces vendor errors and platform controls via standard HTTP responses.

  • 400 Bad Request — invalid parameters
  • 401 Unauthorized — missing/invalid X-Api-Key
  • 403 Forbidden — token lacks scope or access not approved
  • 404 Not Found — path invalid or resource missing
  • 409 Conflict — request conflicts with current state
  • 429 Too Many Requests — rate limit exceeded
  • 5xx Server Error — transient platform/vendor errors
{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Try again later.",
"requestId": "abcd-1234"
}
}

Shape may vary by data source. Always parse defensively.

  • Use exponential backoff with jitter for 429/5xx.
  • Respect Retry-After if provided.
  • Avoid retrying non‑idempotent requests unless vendor docs allow.
async function fetchWithBackoff(url, opts = {}, maxRetries = 5) {
let delayMs = 500;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const res = await fetch(url, opts);
if (res.status !== 429 && res.status < 500) return res;
const retryAfter = res.headers.get('retry-after');
const base = retryAfter ? Number(retryAfter) * 1000 : delayMs;
const jitter = Math.floor(Math.random() * 250);
await new Promise(r => setTimeout(r, base + jitter));
delayMs = Math.min(delayMs * 2, 8000);
}
throw new Error('Max retries exceeded');
}
import time, random, requests
def get_with_backoff(url, params=None, headers=None, max_retries=5):
delay = 0.5
for attempt in range(max_retries + 1):
resp = requests.get(url, params=params, headers=headers, timeout=30)
if resp.status_code != 429 and resp.status_code < 500:
return resp
retry_after = resp.headers.get('retry-after')
base = float(retry_after) if retry_after else delay
time.sleep(base + random.random() * 0.25)
delay = min(delay * 2, 8.0)
raise RuntimeError('Max retries exceeded')

See also Rate Limits & Metering.

  • Log requestId values to correlate with ICDC support.
  • Monitor 4xx vs 5xx rates to detect auth vs availability issues.