Graph Swiss API returns errors in a single, predictable JSON envelope. The HTTP status code tells you the broad category; the code field tells you the exact reason.Error envelope#
{
"success": false,
"error": "Human-readable message",
"code": "MACHINE_READABLE_CODE"
}
Some errors carry extra context fields. The most common shapes:Validation errors#
A failed input validation returns HTTP 400 with an issues array. Each issue points to the offending field path and a message.{
"success": false,
"error": "Validation failed",
"code": "VALIDATION_ERROR",
"issues": [
{ "path": "body.email", "message": "Invalid email" },
{ "path": "query.limit", "message": "Expected number, received string" }
]
}
Unhandled internal errors#
If the API hits an unexpected failure, you'll get HTTP 500 and the response includes the request ID so you can quote it in a support ticket.{
"success": false,
"error": "Internal server error",
"code": "INTERNAL_ERROR",
"request_id": "0f4b2e2e-9c2a-4d2c-8b91-3a86d5f6f1c7"
}
Code reference#
Authentication and credits#
| Code | HTTP | When it fires |
|---|
MISSING_API_KEY | 401 | The X-API-Key header was not sent. |
INVALID_KEY | 401 | The key is malformed or unknown. |
KEY_REVOKED | 401 | The key was valid but has been revoked. |
KEY_EXPIRED | 401 | The key has expired. |
SUBSCRIPTION_REQUIRED | 402 | Your plan does not cover this endpoint. |
FEATURE_UNAVAILABLE | 402 | This feature is not enabled on your plan. |
INSUFFICIENT_CREDITS | 402 | Your wallet balance cannot cover this call. |
SCOPE_MISMATCH | 403 | The key is valid but lacks scope for this endpoint. |
RATE_LIMIT_EXCEEDED | 429 | Too many requests in the current window. Back off. |
AUTHORIZATION_FAILED | varies | Generic fallback when the upstream auth check rejected the request without a recognized code. |
Request and resource#
| Code | HTTP | When it fires |
|---|
VALIDATION_ERROR | 400 | Request failed schema validation. The issues array tells you which fields. |
BAD_REQUEST | 400 | Request was syntactically valid but semantically wrong. |
NOT_FOUND | 404 | The requested resource does not exist. |
Upstream and gateway#
| Code | HTTP | When it fires |
|---|
UPSTREAM_4XX | 502 | A backing service rejected our request with a 4xx. Usually a misconfiguration on our side — retry won't help. |
UPSTREAM_5XX | 502 | A backing service returned 5xx. We've already retried internally; if you still see this, the service is broken. |
UPSTREAM_TIMEOUT | 504 | A backing service did not respond in time. Safe to retry with backoff. |
UPSTREAM_UNAVAILABLE | 503 | A backing service is unreachable. Try again shortly. |
INTERNAL_ERROR | 500 | Unhandled internal error. Capture the request_id and report it. |
How to react#
| Class | Recommended action |
|---|
MISSING_API_KEY, INVALID_KEY, KEY_REVOKED, KEY_EXPIRED | Fix the key. Don't retry. |
INSUFFICIENT_CREDITS, SUBSCRIPTION_REQUIRED | Top up credits or upgrade plan, then retry. |
RATE_LIMIT_EXCEEDED | Wait until the X-RateLimit-Reset window, then retry. |
4xx (other) | Fix the request. Don't retry until you do. |
UPSTREAM_TIMEOUT, UPSTREAM_UNAVAILABLE | Retry with exponential backoff (e.g. 200 ms, 400 ms, 800 ms). Cap at 3–5 attempts. |
UPSTREAM_5XX | One retry is reasonable; we've already retried internally. |
UPSTREAM_4XX | Don't retry — this signals an issue on our side. Report the request_id. |
INTERNAL_ERROR | Capture request_id and contact support. |
Refunds on failed requests#
When the gateway returns 5xx, the credits charged for that request are automatically refunded to your wallet. You only pay for requests that successfully reach the upstream service.Always log the request ID#
Every error response carries an X-Request-Id header. Log it on your side. It's the single piece of information that lets us trace the failure end-to-end. See Request ID. Modified at 2026-05-01 06:35:44