API
Errors & rate limits
The shared response envelope, the error codes every endpoint can return, and how to stay inside the limits.
The response envelope
Every response, successful or not, has a status field that tells you which shape you are holding. A success carries the credits the call cost and its payload — data is null for endpoints that only acknowledge the request:
{
"status": "success",
"cost": number, // credits deducted for this call
"data": {...} | [...] | null
}An error carries a code, and often a message explaining what went wrong:
{
"status": "error",
"error_code": string,
"message": string | string[] // when applicable
}Error codes
bad_request(400) — a field is missing or malformed.messageexplains each problem andinvalid_fieldsnames the fields that caused it.unauthorized(401) — theAuthorizationheader is missing or the key is invalid.forbidden(403) — the key is valid but not entitled to that resource.insufficient_credits(403) — your balance is too low for the call.not_found(404) — no such resource.rate_limit_exceeded(429) — too many requests.Retry-Aftersays how many seconds to wait.internal_server_error(500) — something failed on our side. Retrying after a few minutes is usually the right response.
A bad_request is worth reading in full, since it names the offending fields:
{
"status": "error",
"error_code": "bad_request",
"message": ["country_code must be one of the following values: us, de, {...}"],
"invalid_fields": ["country_code"]
}Rate limits
Limits are counted per account, so every key you hold shares one budget, and each endpoint has its own allowance:
GET /accountandGET /locations— 100 requests per minute.POST /topic-graphs— 30 requests per minute.GET /topic-graphs/:id— 200 requests per minute, sized for polling.
Staying inside them
Every response carries your current standing, so you can back off before you are refused rather than after:
X-Ratelimit-Limit— the allowance for that endpoint.X-Ratelimit-Remaining— how many requests are left in the window.X-Ratelimit-Reset— when the window resets.
If you do get a 429, wait the number of seconds in Retry-After before trying again.