Errors
Synthient returns conventional HTTP status codes and machine-readable JSON bodies for every failure.
HTTP error shape
Most error responses follow a small, consistent JSON envelope. Validation errors use a slightly richer body so you can show field-level messages.
Generic error
{ "detail": "Invalid API Key" }
Validation error
{
"title": "Validation error",
"errors": {
"ip_address": ["must be a valid IP address"]
}
}
The HTTP Content-Type is always application/json. Empty bodies should be treated as transient infrastructure errors and retried.
Status code reference
| Status | Meaning | What to do |
|---|---|---|
| 400 Bad Request | Invalid input malformed IP, bad cursor, oversized batch. | Fix the request before retrying. The body usually identifies the offending field. |
| 401 Unauthorized | Missing or invalid x-api-key header. | Verify the key is loaded from the environment and not truncated. See Authentication. |
| 402 Payment Required | Lookup credit balance is exhausted. | Add credits, upgrade your plan, or wait for lookup_quota.resets_in to elapse. See Rate Limits. |
| 403 Forbidden | API key lacks the scope required for this endpoint. | Check granted scopes via /account/me; reach out to support to add the missing one. |
| 404 Not Found | Snapshot, domain, or other resource doesn't exist. | Don't retry the resource is genuinely missing. |
| 429 Too Many Requests | Per-key rate limit or concurrent-stream limit hit. | Back off using the Retry-After header if present; otherwise exponential backoff with jitter. See Rate Limits. |
| 500 Internal Server Error | Unexpected server error. | Retry with backoff. If the issue persists, contact support. |
| 503 Service Unavailable | Streaming or downstream backend temporarily down. | Retry with exponential backoff and jitter. |
Per-status examples
400 Bad Request
Returned when the request fails validation before any work is done. The body identifies the offending fields.
Malformed IP address
{
"title": "Validation error",
"errors": { "ip_address": ["must be a valid IP address"] }
}
Oversized batch
{
"title": "Validation error",
"errors": { "ips": ["must contain at most 1000 entries"] }
}
401 Unauthorized
The API key was missing or rejected. Check that the value is non-empty and that you're using the x-api-key header.
{ "detail": "Invalid API Key" }
402 Payment Required
You've spent your remaining lookup credits. Inspect lookup_quota.credits and lookup_quota.resets_in on /account/me to see when your balance resets.
{ "detail": "Quota exhausted" }
403 Forbidden
The key is valid but isn't scoped for the requested endpoint or feed. For example, calling /feeds/anonymizers/stream with a key that only has PROXY_FIREHOSE.
{ "detail": "Insufficient scope for this resource" }
404 Not Found
There is no parquet snapshot for the requested date, or the domain has never been observed.
{ "detail": "Snapshot not found" }
429 Too Many Requests
Returned when you exceed the per-key request rate or attempt to open more concurrent streams than your plan allows. Honour the Retry-After response header (seconds) when present.
{ "detail": "Too many concurrent streams" }
500 / 503 Server errors
A 500 indicates an unexpected fault on our side; a 503 indicates the streaming or downstream backend is briefly unavailable. Both are safe to retry use exponential backoff with jitter and cap the delay at 60 seconds.
{ "detail": "Internal Server Error" }
Recovery checklist
- Read the status code first.
4xxmeans your request needs to change;5xxmeans ours does retry safely. - Honour
Retry-Afteron429. When present, wait at least that many seconds. - Use exponential backoff with jitter. Start at 1s, double up to a 60s cap, randomize ±25% so a flock of clients don't synchronize.
- Don't retry
400,403,404. They will not become success without a code change. - Surface the
detailbody. Forward it to your logs it's the fastest way to diagnose unexpected failures.
Next steps
- Authentication fixing
401and403errors. - Rate Limits handling
402and429correctly. - Support when retries don't help.