Errors
All errors are returned as application/json regardless of the requested output format.
HTTP status codes
| Status | Meaning | When it happens |
|---|---|---|
200 OK | Success | Map rendered and returned. |
304 Not Modified | Cached — no body | Sent when If-None-Match matches the current ETag. |
400 Bad Request | Validation or parser failure | A parameter value is invalid — wrong type, out of range, missing scope, or a data/markers/routes/patterns/annotations string could not be parsed. |
404 Not Found | Unknown scope | The scope value is not in the loaded topology. |
413 Content Too Large | Body too large | POST body exceeds 4 MB. |
Error shape
Every error response has this JSON structure:
{
"error": "error_code",
"message": "Human-readable description of the problem.",
"status": 400
}
error— a machine-readable code identifying the specific error.message— a human-readable explanation, often including the invalid value and what was expected.status— mirrors the HTTP status code.
Example 400 — invalid theme:
{
"error": "invalid_theme",
"message": "theme \"ocean\" not found. Available: light, light-blue, light-mono, dark, dark-blue, dark-mono",
"status": 400
}
Example 400 — missing scope:
{
"error": "missing_scope",
"message": "scope is required",
"status": 400
}
Example 404 — unknown scope:
{
"error": "invalid_scope",
"message": "Scope \"eu\" not found",
"status": 404
}
Example 400 — malformed data parameter:
{
"error": "invalid_data",
"message": "bad pair \"US-abc\" (expected id:value[:color])",
"status": 400
}
Common mistakes
Invalid scope
scope must exactly match a loaded topology ID. IDs are case-sensitive. Use the Scopes list to find the correct value.
# Wrong — lowercase
?scope=ro
# Correct
?scope=RO
Malformed data=
Each pair must be id:value or id:value:#rrggbb. The # must be URL-encoded as %23.
# Wrong — missing value
?data=US,CN,DE
# Wrong — unencoded #
?data=US:100:#ff0000
# Correct — value only
?data=US:100,CN:80,DE:60
# Correct — with per-region color override
?data=US:100:%23ff0000,CN:80,DE:60
Mixing data= and regions=
data= and regions= serve different modes. data= encodes numeric values for choropleth fills; regions= is highlight-only with no values. They are processed separately and merged, but passing both for the same region ID produces undefined colour precedence. Use one or the other per region.
Oversized POST body
The POST endpoint accepts up to 4 MB. If your payload exceeds this limit, the server returns 413. Consider:
- Reducing decimal precision in value fields.
- Omitting regions with
nullvalues if you only want to highlight a subset. - Splitting annotation strings that are close to the 200-character limit.
Too many regions
The maximum is 5000 regions per request. Requests exceeding this return:
{
"error": "too_many_regions",
"message": "region count exceeds limit (5000)",
"status": 400
}