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",
"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 → choropleth, string up to 64 chars → categorical bucket, or null for highlight-only), color (#rrggbb), pattern, annotation. Numeric and string values cannot mix in one request. |
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 or sidc (mutually exclusive), size, color, rotation, label, labelPosition. sidc is a 20- or 30-digit APP-6 / MIL-STD-2525 code — see Military symbols. |
routes | array | — | Up to 500 items. Each: from, to, optional fromLatLon, toLatLon, color, width (1–20), style, arrow, mode (great-circle | sea). |
shapes | FeatureCollection | — | Up to 500 features. User-supplied GeoJSON overlay (Point / LineString / MultiLineString / Polygon / MultiPolygon). Per-feature style via properties (fill / stroke / strokeWidth / opacity / dashArray / radius / title). See Custom shapes. |
bbox | number[] | — | [minLon, minLat, maxLon, maxLat]. Crops the projection viewport. minLon must be less than maxLon (no antimeridian span) and minLat less than maxLat. |
regionStroke | string | theme default | #rrggbb outline colour for every region. Applied to the whole regions group — per-region strokes are not supported. |
regionStrokeWidth | number | theme default | Outline width, 0–20. |
regionFill | string | — | "none" is the only accepted value. Forces every region's fill to none for an outline-only render. |
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
Categorical-by-label example: pass text labels for regions[].value and set colorScale to categorical (the GET endpoint auto-selects this; on POST it's explicit). Each distinct label gets its own color from the theme's categorical palette; the legend names the buckets.
curl -X POST https://api.maproll.io/render/map \
-H 'Content-Type: application/json' \
-d '{
"scope": "world",
"colorScale": "categorical",
"regions": [
{"id": "US", "value": "NATO"}, {"id": "GB", "value": "NATO"},
{"id": "FR", "value": "NATO"}, {"id": "DE", "value": "NATO"},
{"id": "CN", "value": "BRICS"}, {"id": "RU", "value": "BRICS"},
{"id": "IN", "value": "BRICS"}, {"id": "BR", "value": "BRICS"}
],
"theme": "dark",
"legendTitle": "Bloc"
}' \
--output map.svg
Send the region data as CSV in the body. The rendering parameters (scope, theme, format, width, etc.) go in the query string, using the same names and defaults as the GET endpoint. Only a subset of the GET parameters is read in CSV mode — see the list at the end of this tab.
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:
CSV mode reads a subset of the GET query parameters. These are honoured, with the same defaults as on GET:
scope, theme, format, width, height, projection, colorScale, legend, legendTitle, legendLayout, title, subtitle, attribution, logo, bbox, regionStroke, regionStrokeWidth, regionFill.
Everything else is ignored. data= and regions= are replaced by the CSV body. The remaining GET parameters — markers, routes, patterns, annotations, labels, labelMinArea, northArrow, scaleBar, graticule, proportional, proportionalMax, proportionalMin, classification and breaks — are still validated (an invalid value returns 400) but are not applied to the render. Use a JSON body if you need them.
Limits
- Maximum body size: 4 MB on
api.maproll.io(4,194,304 bytes). The renderer and the reverse proxy in front of the public endpoint share that ceiling; a larger body is rejected by the proxy with a413before it reaches the app. - Maximum regions per request: 5000.
- Maximum markers per request: 1000.
- Maximum routes per request: 500.
- Maximum custom shape features per request: 500.
Response
See Response headers & caching.
Related
GET /map.{svg,png}— URL-only,<img>-embeddable endpoint- Response headers & caching
- Errors
- Data input