All systems operational
Live FX data
Updated 2m ago
API Reference

Error Codes

All HTTP errors returned by the xchangr8 API, with causes and fixes.

HTTP Status Codes

Status Code Message Cause Fix
400 invalid_base Invalid base currency Unknown currency code in base param Use a valid 3-letter ISO code
400 invalid_symbols Invalid symbols Unknown currency code in symbols Check supported currencies
400 invalid_date Invalid date format Date not in YYYY-MM-DD Use ISO 8601 date format
400 invalid_amount Invalid amount Non-numeric or negative amount Provide a positive number
401 missing_key Missing API key No X-API-Key header or apikey param Add your API key
401 invalid_key Invalid API key Key not found or revoked Check dashboard for valid key
403 plan_limit Feature not available on your plan e.g. timeseries on Free plan Upgrade to Starter or Pro
429 rate_limited Rate limit exceeded Too many requests per minute (burst) Implement backoff, or upgrade
429 quota_exceeded Monthly quota exceeded Over monthly request limit Upgrade or wait for reset
500 server_error Internal server error Unexpected server issue Retry with exponential backoff
503 upstream_unavailable Upstream data unavailable All data sources temporarily down Retry in 30–60 seconds

Error Response Shape

All errors return a consistent JSON envelope regardless of status code.

JSON
{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded. Retry after 15 seconds.",
    "retry_after": 15
  }
}

Rate Limit Headers

Every response includes the following rate limit headers so you can monitor usage and react before hitting limits.

HTTP Headers
X-RateLimit-Limit: 333
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1749340920
Retry-After: 15
Tip: X-RateLimit-Reset is a Unix timestamp (UTC). Subtract Date.now() / 1000 from it to calculate exact seconds remaining.

Handling Errors — Code Example

The pattern below handles rate limits, respects Retry-After, and surfaces readable error messages.

JavaScript
const res = await fetch('https://api.xchangr8.com/v1/latest', {
  headers: { 'X-API-Key': 'xc8_live_YOUR_KEY' }
})

if (!res.ok) {
  const { error } = await res.json()
  if (res.status === 429) {
    // Respect Retry-After header
    const retryAfter = res.headers.get('Retry-After') || 60
    await sleep(retryAfter * 1000)
  }
  throw new Error(`xchangr8: ${error.code}${error.message}`)
}