Error shape
Every error is JSON with the same shape, whatever the status code:
{
"error": {
"code": "rate_limited",
"message": "Rate limit of 60 requests/minute exceeded."
}
}
Branch on error.code, which is stable. The message is
written for a human reading a log and may be reworded.
All codes
| Status | Code | Means | Retry? |
|---|---|---|---|
| 401 | missing_key | No key was supplied. | Not until fixed |
| 401 | invalid_key | Key unknown, revoked, or not yet activated. | Not until fixed |
| 400 | missing_query | No Overpass QL found in the request. | Not until fixed |
| 400 | query_caps | [timeout:] or [maxsize:] exceeds your tier. |
Not until fixed |
| 429 | rate_limited | Too many requests per minute. | Yes, after Retry-After |
| 429 | concurrency_limit | Too many queries in flight at once. | Yes, about a second |
| 429 | quota_exceeded | Monthly request quota used up. | Next month, or upgrade |
| 503 | no_backend | No healthy, current database available. | Yes, after Retry-After |
| 504 | upstream_timeout | The query did not finish in time. | Yes, if you make it cheaper |
| 502 | upstream_error | The database failed to answer. | Yes, with backoff |
Authentication
missing_key 401
You called /api/interpreter without a key in the path, the
?key= parameter, or an Authorization header. See
passing your key.
invalid_key 401
The key was supplied but will not serve traffic. Three causes:
- Typo or truncation. Keys are copied out of email more often than they are typed. Check for a trailing space.
- Subscription ended. Cancelled subscriptions keep working to the end of the paid period and are revoked when that period expires. Payment failures go through a retry window first, so a single failed renewal does not cut you off immediately.
- Newly purchased and not yet activated. Rare, and it means we could not map your purchase to a tier automatically. It is our problem, not yours: mail hello@overspan.dev and we will fix it quickly. We deliberately never guess a tier, because guessing wrong either overcharges you in limits or hands out capacity nobody paid for.
Limits
rate_limited 429
You exceeded your requests-per-minute allowance. This is a token bucket, so short
bursts above the number are fine as long as the average holds. A
Retry-After header tells you how long until a token is available.
concurrency_limit 429
You already have your tier's maximum number of queries in flight. Unlike the rate
limit this clears as soon as one of your running queries finishes, so
Retry-After is one second. If you hit this constantly, the fix is
usually a worker pool sized to your tier rather than an upgrade.
quota_exceeded 429
You have used your monthly request allowance. It resets at the start of the next month, UTC. Rejected requests never consume quota, so a burst of 429s does not eat into your allowance.
There is no overage billing by design. If you need more before the reset, upgrade in the billing portal and the new limit applies immediately.
Query problems
missing_query 400
The request arrived with no Overpass QL. Send it as the data parameter
(GET query string or form-encoded POST body), or as the raw
request body, which is what JOSM and curl often do.
query_caps 400
Your query asked for a [timeout:] or [maxsize:] above your
tier's maximum. The message names the setting, the value you asked for, and the cap:
{
"error": {
"code": "query_caps",
"message": "[timeout:600] exceeds the indie tier maximum of 60. Lower it or upgrade your tier."
}
}
We reject rather than quietly lowering the value, because a clamped query returns different results than the one you wrote and you would have no way of knowing.
[timeout:25] and
[maxsize:256 MB]. Those are lower than the public servers' defaults, so
set both explicitly on anything heavy. Details in
differences from the public servers.
Service faults
no_backend 503
No database was both reachable and current enough to serve you. Overspan refuses to
answer from a database that has fallen behind the OSM replication feed, because
stale results that look fresh are worse than an honest error. Retry after the
interval in Retry-After; if it persists, mail us.
upstream_timeout 504
The query was accepted and started but did not finish in time. Either it is genuinely
too heavy, or the box was busy. Options, in the order worth trying: narrow the bounding
box, filter earlier in the query, split the job into chunks, raise
[timeout:] within your tier cap, or move up a tier.
upstream_error 502
The database failed to answer. This is our fault, not your query's. Retry with backoff. If it repeats, mail hello@overspan.dev with the approximate time and we will look at what happened.
Retrying well
A retry policy that treats us kindly and gets your job done:
- Honour
Retry-After. Where we send it, it is the real answer, not an estimate. - Never retry a 400 or 401 unchanged. Those need a fix, and hammering them just burns your rate limit.
- Back off exponentially on 502 and 503, with jitter, and cap the number of attempts.
- Treat 504 as a signal to shrink the query, not as a transient blip. Retrying an identical heavy query usually times out again.
- Keep concurrency at or below your tier. Sizing your worker pool to the tier removes an entire class of 429 entirely.
- Read the quota headers instead of guessing. Every response carries
X-Overspan-Quota-RemainingandX-Overspan-Quota-Reset, so a client can slow itself down before it hits the wall. Details in the quickstart.
Trying to work out whether a run went badly? The usage dashboard and the usage endpoint both break your recent requests down by outcome, so you can see which of these you actually hit and how often.
Hit something not listed here? That is a documentation bug. Mail hello@overspan.dev.