POST /render/map
The POST endpoint accepts either a JSON body (application/json) or a CSV body (text/csv) and returns an SVG or PNG map. Use POST when your data has more than ~40 regions, when you need to pass structured nested objects (markers, routes, annotations), or when you are uploading a CSV file directly from a script or pipeline.
Content types
- application/json
- text/csv
Send the full request as a JSON body. All rendering parameters and data live in the body — no query string needed.
Body schema:
{
"scope": "world",
"regions": [
{ "id": "RO", "value": 120 },
{ "id": "DE", "value": 95, "color": "#1a6bcc" },
{ "id": "FR", "value": 40, "pattern": "stripes" },
{ "id": "US", "value": 200, "annotation": "Largest economy" }
],
"theme": "dark",
"format": "png",
"width": 1200,
"height": null,
"projection": "naturalEarth1",
"colorScale": "sequential",
"classification": "quantile",
"breaks": [],
"legend": true,
"legendTitle": "GDP rank",
"legendLayout": "vertical",
"title": "World GDP",
"subtitle": "2024 estimates",
"attribution": true,
"logo": false,
"northArrow": false,
"scaleBar": false,
"graticule": false,
"labels": "ISO",
"labelMinArea": 5000,
"proportional": [
{ "id": "US", "value": 200, "color": "#ff6600" }
],
"proportionalMax": 40,
"proportionalMin": 4,
"markers": [
{
"lat": 44.43,
"lon": 26.10,
"icon": "pin",
"label": "Bucharest",
"labelPosition": "right",
"color": "#ff0000",
"size": 16,
"rotation": 0
}
],
"routes": [
{
"from": "RO",
"to": "DE",
"color": "#ffffff",
"width": 2,
"style": "dashed",
"arrow": true
}
]
}
All fields except scope are optional.
Field reference:
| Field | Type | Default | Notes |
|---|---|---|---|
scope | string | required | See Scopes. |
regions | array | — | Up to 5000 items. Each item: id (required), value (number or null), color (#rrggbb), pattern, annotation. |
theme | string | dark | dark light light-blue light-mono dark-blue dark-mono |
format | string | svg | svg or png |
width | integer | 1200 | 1–8000 pixels |
height | integer or null | null | 1–8000 pixels. null = auto (projection aspect ratio). |
projection | string | per-scope | naturalEarth1 albersUsa conicConformal mercator equalEarth |
colorScale | string | sequential | sequential diverging categorical |
classification | string | quantile | quantile jenks equal custom |
breaks | number[] | — | Custom bin edges (1–20 values). Used when classification is custom. |
legend | boolean | true | |
legendTitle | string | — | Max 64 chars |
legendLayout | string | vertical | vertical horizontal continuous |
title | string | — | Max 120 chars |
subtitle | string | — | Max 160 chars |
attribution | boolean | true | |
logo | boolean | false | |
northArrow | boolean | false | |
scaleBar | boolean | false | |
graticule | boolean | false | |
labels | "ISO" or string[] | — | "ISO" labels all polygons; array labels specific IDs. |
labelMinArea | number | — | 0–1000000 SVG units². Suppresses labels on small polygons. |
proportional | array | — | Sized circles. Each item: id, value, optional color. |
proportionalMax | number | — | Max circle radius in pixels (0–200). |
proportionalMin | number | — | Min circle radius in pixels (0–100). |
markers | array | — | Up to 1000 items. Each: lat, lon, optional icon, size, color, rotation, label, labelPosition. |
routes | array | — | Up to 500 items. Each: from, to, optional fromLatLon, toLatLon, color, width (1–20), style, arrow. |
curl example:
curl -X POST https://api.maproll.io/render/map \
-H 'Content-Type: application/json' \
-d '{
"scope": "world",
"regions": [
{"id": "RO", "value": 120},
{"id": "DE", "value": 95},
{"id": "FR", "value": 40},
{"id": "US", "value": 200}
],
"theme": "dark",
"format": "png",
"legendTitle": "GDP rank"
}' \
--output map.png
Send the region data as CSV in the body. All other rendering parameters (scope, theme, format, width, etc.) go in the query string, exactly as they would for the GET endpoint.
CSV column format:
id,value[,color]
- The header row is optional. If present, the first column must be
idand the second must be one ofvalue,val,count,n, oramount(case-insensitive). - The
colorcolumn is only parsed when the header is present and the third column is namedcolor. - Without a header, extra columns beyond the first two are ignored.
- A region row with an empty
valuecell is treated as a highlight-only entry (no choropleth fill).
Example body:
id,value,color
RO,120,#e63946
DE,95,
FR,40,
US,200,
curl example:
curl -X POST 'https://api.maproll.io/render/map?scope=world&theme=dark&format=png&legendTitle=GDP%20rank' \
-H 'Content-Type: text/csv' \
--data-binary @- \
--output map.png <<'EOF'
id,value
RO,120
DE,95
FR,40
US,200
EOF
Query parameters when using CSV:
All query parameters accepted by the GET endpoint are valid here, with the same defaults. The data= and regions= query params are not used — the CSV body replaces them. You can still pass markers=, routes=, patterns=, annotations=, and labels= as query params alongside a CSV body.
Limits
- Maximum body size: 4 MB.
- Maximum regions per request: 5000.
- Maximum markers per request: 1000.
- Maximum routes per request: 500.
Response
See Response headers & caching.
Related
GET /map.{svg,png}— URL-only,<img>-embeddable endpoint- Response headers & caching
- Errors
- Data input