Troubleshooting

Troubleshooting

The five issues new integrators hit most often, with the actual error payloads and the fixes that resolve them. If none of these match what you're seeing, email [email protected] with the request id from the response.

401 UNAUTHORIZED or INVALID_API_KEY

The API didn't accept the key you sent. Walk this checklist top to bottom — it accounts for ~95% of these errors:

  • Are you sending the header as x-api-key (lowercase, with hyphens)? Authorization: Bearer is not supported.
  • Is the key trimmed? Stray newlines from .env files cause silent failures — log key.length and confirm it matches the dashboard.
  • Was the key revoked? Check /dashboard/api-keys. A revoked key is permanently inactive — issue a new one.
  • Are you mixing live and test keys against the same environment? They are not interchangeable.
json
{
"error": {
"code": "UNAUTHORIZED",
"message": "Missing API key. Pass it as the x-api-key header or api_key query parameter."
}
}
json
{
"error": {
"code": "INVALID_API_KEY",
"message": "API key is not valid or has been revoked."
}
}

429 RATE_LIMIT_EXCEEDED

You've hit your plan's per-minute or per-month limit. The response always includes a Retry-After header (in seconds) — respect it instead of hammering. The standard X-RateLimit-* headers tell you exactly where you stand.

http
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1714324800
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Retry after 12 seconds."
}
}

Production-grade clients should retry with exponential backoff and a cap. The official SDKs do this automatically:

javascript
// Exponential backoff with respect for Retry-After
async function callWithRetry(url, init, attempt = 0) {
const res = await fetch(url, init)
if (res.status !== 429 || attempt >= 4) return res
const retryAfter = Number(res.headers.get("retry-after")) || 2 ** attempt
await new Promise(r => setTimeout(r, retryAfter * 1000))
return callWithRetry(url, init, attempt + 1)
}

See Rate Limits for plan-by-plan numbers.

CORS error in the browser

KhaleejiAPI is a server-to-server API. Calling it directly from a browser is intentionally blocked by CORS — and even if it weren't, doing so would expose your API key to every site visitor.

The fix is the same in every framework: put a thin proxy on your backend that attaches the key, and let the browser call your proxy.

javascript
// ❌ Don't do this in the browser — your key will leak.
fetch("https://khaleejiapi.dev/api/v1/ip/lookup?ip=8.8.8.8", {
headers: { "x-api-key": "khj_live_..." },
})
// ✅ Do this instead: call your own backend, which calls KhaleejiAPI.
fetch("/api/proxy/ip-lookup?ip=8.8.8.8")

Timeouts on AI endpoints

Standard endpoints (IP lookup, exchange rates, weather) reply in well under a second. AI-backed endpoints — translation, summarization, image processing — can take 3–8 seconds on a cold cache because they call upstream models. Default fetch timeouts of 5s will trip on those.

javascript
// Most KhaleejiAPI endpoints respond in <500ms.
// AI endpoints (translate, summarize) can take 3–8s on cold cache.
// Set a generous timeout for those.
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), 15_000)
try {
const res = await fetch(url, { signal: controller.signal, ...init })
} finally {
clearTimeout(timer)
}

If you consistently hit timeouts on cached endpoints, that's a problem on our side — file a ticket with the request id (see below).

Sporadic 5xx errors / “it worked yesterday”

Before assuming a regression, check status.khaleejiapi.dev and the upstream provider for the endpoint you called (we publish the upstream dependency for each API in its docs page).

When you contact support, include the x-request-id from the failing response. We index logs by that id and can usually pinpoint the cause within minutes.

javascript
// Every response includes an x-request-id header.
// Capture it and include it when you contact support.
const res = await fetch("https://khaleejiapi.dev/api/v1/health")
console.log("request id:", res.headers.get("x-request-id"))