# Request body

The JSON body of `POST /v1/map`. Every field of the map spec, as a tree: `routes[]` means "each element of `routes`". Fields without a default are optional unless a description says otherwise.

| Path | Type / values | Default | Description |
|---|---|---|---|
| `area.query` | string | — | Name or id, as in the string form. |
| `area.level` | integer, 1–11 | — | Only match areas at this OSM admin level (2 = country; regions and municipalities vary by country). |
| `area.country` | string | — | Only match areas inside this ISO 3166-1 alpha-2 country. |
| `area.geojson.type` | `Polygon` \| `MultiPolygon` \| `Feature` | — | GeoJSON type. |
| `area.geojson` | object | — | A GeoJSON Polygon, MultiPolygon, or Feature with one of those geometries. |
| `area` | string \| object | — | The area to frame and highlight. Ambiguous names return 409 with candidates. |
| `bounds` | array | — | Explicit frame `[west, south, east, north]`; overrides automatic framing. Cannot be combined with `center`/`zoom`. |
| `center.lat` | number, -85.06–85.06 | — | Latitude (WGS84). |
| `center.lon` | number, -180–180 | — | Longitude (WGS84). |
| `center` | object | — | Center of the map. With `zoom`, this is an exact camera (as in other static map APIs) and nothing else affects the frame. Without `zoom`, the zoom is chosen so the area, routes, shapes and points fit around this center. |
| `zoom` | number, 0–22 | — | Zoom level, 0 (whole world) to 22, in the usual web-map zoom units (512 px tiles, as MapLibre and Mapbox GL: at zoom z the world is 512·2^z CSS px wide). With `center`, an exact camera; without `center`, the map is centered on the content at this zoom. Not available with the globe projection. |
| `routes[].geometry.type` | `LineString` \| `MultiLineString` \| `Feature` | — | GeoJSON type. |
| `routes[].geometry` | object | — | A line you already have (e.g. from your own routing provider). |
| `routes[].polyline` | string | — | The line as an encoded polyline (Google algorithm). |
| `routes[].polylinePrecision` | `5` \| `6` | `5` | Polyline precision: 5 (Google) or 6 (Valhalla/OSRM). |
| `routes[].from.lat` | number, -90–90 | — | Latitude (WGS84). |
| `routes[].from.lon` | number, -180–180 | — | Longitude (WGS84). |
| `routes[].from.place` | string | — | Place name to look up (imported OSM places first, then the server's geocoder if configured); its name becomes the default label. |
| `routes[].from` | object | — | Start point when the server should compute the line. |
| `routes[].to.lat` | number, -90–90 | — | Latitude (WGS84). |
| `routes[].to.lon` | number, -180–180 | — | Longitude (WGS84). |
| `routes[].to.place` | string | — | Place name to look up (imported OSM places first, then the server's geocoder if configured); its name becomes the default label. |
| `routes[].to` | object | — | Finish point when the server should compute the line. |
| `routes[].via[].lat` | number, -90–90 | — | Latitude (WGS84). |
| `routes[].via[].lon` | number, -180–180 | — | Longitude (WGS84). |
| `routes[].via[].place` | string | — | Place name to look up (imported OSM places first, then the server's geocoder if configured); its name becomes the default label. |
| `routes[].via[]` | object | — | A route end or via point: `{lat, lon}` or `{place}`. |
| `routes[].via` | array | `[]` | Points the route must pass through, in order. |
| `routes[].profile` | `car` \| `bike` \| `foot` \| `straight` \| `geodesic` | `geodesic` | How endpoints are connected: routed by `car`/`bike`/`foot` (needs a routing engine on the server or your `X-Routing-Key`), or locally as `straight` segments or `geodesic` great-circle arcs. The default `geodesic` always works (no routing engine, key or plan feature needed) and is the true shortest path, so it suits flights and locator maps; ask for `car`/`bike`/`foot` explicitly for roads. |
| `routes[].provider` | `valhalla` \| `openrouteservice` \| `graphhopper` | — | Routing provider (default: the server's). openrouteservice and GraphHopper need a key (server-side or `X-Routing-Key`). |
| `routes[].color` | string | `#d01c1c` | Color of the route line. |
| `routes[].width` | number, 0.5–20 | `3` | Line width in px. |
| `routes[].casingColor` | string | `#ffffff` | Outline drawn under the line so it reads on busy basemaps. |
| `routes[].casingWidth` | number, 0–10 | `1.5` | Outline width on each side in px; 0 = none. |
| `routes[].dash` | array | — | Dash pattern in line widths, e.g. `[2, 1.5]`. |
| `routes[].opacity` | number, 0–1 | `1` | Line opacity. |
| `routes[].start.label` | string | — | Label at this end (default: the place name, if the end was given as a place). |
| `routes[].start.labelPosition` | `auto` \| `right` \| `left` \| `top` \| `bottom` \| `top-right` \| `top-left` \| `bottom-right` \| `bottom-left` | `auto` | Where the label goes relative to the marker. `auto` picks the first free spot and falls back to a leader line. |
| `routes[].start.labelSize` | number, 6–48 | `16` | Label text size in CSS px. |
| `routes[].start.labelWeight` | integer, 100–900 | — | Font weight for this label (overrides `font.weight`). |
| `routes[].start.labelColor` | string | — | Label color (default: the basemap theme's label color). |
| `routes[].start.marker.shape` | `pin` \| `dot` \| `ring` \| `flag` \| `triangle` \| `circle` \| `square` \| `star` \| `diamond` | — | Marker preset. Defaults depend on the role: plain point → `pin`, route start → `ring`, route finish → `flag`. |
| `routes[].start.marker.color` | string | — | Marker fill color. |
| `routes[].start.marker.size` | number, 4–64 | — | Marker height in CSS pixels (multiplied by `scale`). Default depends on the shape. |
| `routes[].start.marker.strokeColor` | string | — | Outline color (default white where the shape has an outline). |
| `routes[].start.marker.strokeWidth` | number, 0–8 | — | Outline width in px; 0 = none. `dot` and `pin` have a thin default outline. |
| `routes[].start.marker.icon` | string | — | Custom icon instead of the shape: an SVG/PNG `data:` URI, or an https URL on a host the server allows (`WHEREBOX_ICON_HOSTS`). SVGs with external references or scripts are rejected. |
| `routes[].start.marker.anchor` | `center` \| `bottom` | — | Which point of a custom icon sits on the location: its center, or its bottom edge (pin-shaped icons). |
| `routes[].start.marker` | object | — | Marker style; every field is optional and falls back to the role default. |
| `routes[].start.show` | boolean | `true` | `false` hides the marker and label for this end. |
| `routes[].start` | object | `{}` | Marker and label for one end of the route. |
| `routes[].finish.label` | string | — | Label at this end (default: the place name, if the end was given as a place). |
| `routes[].finish.labelPosition` | `auto` \| `right` \| `left` \| `top` \| `bottom` \| `top-right` \| `top-left` \| `bottom-right` \| `bottom-left` | `auto` | Where the label goes relative to the marker. `auto` picks the first free spot and falls back to a leader line. |
| `routes[].finish.labelSize` | number, 6–48 | `16` | Label text size in CSS px. |
| `routes[].finish.labelWeight` | integer, 100–900 | — | Font weight for this label (overrides `font.weight`). |
| `routes[].finish.labelColor` | string | — | Label color (default: the basemap theme's label color). |
| `routes[].finish.marker.shape` | `pin` \| `dot` \| `ring` \| `flag` \| `triangle` \| `circle` \| `square` \| `star` \| `diamond` | — | Marker preset. Defaults depend on the role: plain point → `pin`, route start → `ring`, route finish → `flag`. |
| `routes[].finish.marker.color` | string | — | Marker fill color. |
| `routes[].finish.marker.size` | number, 4–64 | — | Marker height in CSS pixels (multiplied by `scale`). Default depends on the shape. |
| `routes[].finish.marker.strokeColor` | string | — | Outline color (default white where the shape has an outline). |
| `routes[].finish.marker.strokeWidth` | number, 0–8 | — | Outline width in px; 0 = none. `dot` and `pin` have a thin default outline. |
| `routes[].finish.marker.icon` | string | — | Custom icon instead of the shape: an SVG/PNG `data:` URI, or an https URL on a host the server allows (`WHEREBOX_ICON_HOSTS`). SVGs with external references or scripts are rejected. |
| `routes[].finish.marker.anchor` | `center` \| `bottom` | — | Which point of a custom icon sits on the location: its center, or its bottom edge (pin-shaped icons). |
| `routes[].finish.marker` | object | — | Marker style; every field is optional and falls back to the role default. |
| `routes[].finish.show` | boolean | `true` | `false` hides the marker and label for this end. |
| `routes[].finish` | object | `{}` | Marker and label for one end of the route. |
| `routes[]` | object | — | A line between points: given as geometry/polyline, routed between `from` and `to`, or straight/geodesic. |
| `routes` | array | `[]` | Routes to draw (GET supports one; POST up to 10). |
| `shapes[].geojson.type` | string | — | GeoJSON type (LineString, Polygon, Feature, FeatureCollection, …). |
| `shapes[].geojson` | object | — | Any GeoJSON geometry, Feature or FeatureCollection. |
| `shapes[].color` | string | `#555555` | Line color of the shape. |
| `shapes[].width` | number, 0–20 | `2` | Line width in px; 0 = no line. |
| `shapes[].dash` | array | — | Dash pattern in line widths. |
| `shapes[].opacity` | number, 0–1 | `1` | Line opacity. |
| `shapes[].fill` | string | — | Fill color for polygons (no fill if unset). |
| `shapes[].fillOpacity` | number, 0–1 | `0.25` | Fill opacity for polygons. |
| `shapes[]` | object | — | An extra line or polygon drawn on the map (e.g. a boundary arc or a buffer zone). |
| `shapes` | array | `[]` | Extra lines and polygons, drawn in order (later ones on top). Up to 50; in GET, repeat `shape`. |
| `font.family` | `noto-sans` \| `noto-serif` \| `noto-sans-mono` | `noto-sans` | A bundled family, or your own TTF/OTF/WOFF as a `data:` URI or an https URL on an allowed host (`WHEREBOX_FONT_HOSTS`). Missing glyphs fall back to Noto Sans, then Noto Sans Mono. |
| `font.weight` | integer, 100–900 | `400` | Weight for all labels (100–900; the nearest bundled weight is used). |
| `font` | object | `{}` | Font for everything we draw (labels, title); the basemap keeps its own fonts. |
| `title.text` | string | — | Title text (one line; long titles shrink, then get an ellipsis). |
| `title.position` | `top` \| `bottom` | `top` | Band above or below the map. |
| `title.align` | `left` \| `center` \| `right` | `left` | Text alignment in the band. |
| `title.size` | number, 8–64 | `18` | Text size in CSS px. |
| `title.weight` | integer, 100–900 | `600` | Font weight. |
| `title.color` | string | — | Text color (default: the theme label color). |
| `title.background` | string | — | Band background (default: white, or near-black on the dark preset). |
| `title.dividerColor` | string | — | Line between the band and the map. |
| `title.dividerWidth` | number, 0–6 | `1` | Divider width in px; 0 = none. |
| `title.padding` | number, 0–40 | `10` | Space around the text in px. |
| `title` | object | — | A title band, drawn inside the requested width×height (the map gets the rest). |
| `pois[].lat` | number, -90–90 | — | Latitude (WGS84). Any coordinate works; no lookup is done. |
| `pois[].lon` | number, -180–180 | — | Longitude (WGS84). |
| `pois[].place` | string | — | A place name to look up instead of coordinates (cities, peaks, mountain ranges…). Looked up in the imported OSM places first, then in the server's geocoder if one is configured. The label defaults to the place name. |
| `pois[].label` | string | — | Label text. A newline (`\n` in GET) starts a new line. |
| `pois[].labelPosition` | `auto` \| `right` \| `left` \| `top` \| `bottom` \| `top-right` \| `top-left` \| `bottom-right` \| `bottom-left` | `auto` | Where the label goes relative to the marker. `auto` picks the first free spot and falls back to a leader line. |
| `pois[].labelSize` | number, 6–48 | `16` | Label text size in CSS px. |
| `pois[].labelWeight` | integer, 100–900 | — | Font weight for this label (overrides `font.weight`). |
| `pois[].labelColor` | string | — | Label color (default: the basemap theme's label color). |
| `pois[].marker.shape` | `pin` \| `dot` \| `ring` \| `flag` \| `triangle` \| `circle` \| `square` \| `star` \| `diamond` | — | Marker preset. Defaults depend on the role: plain point → `pin`, route start → `ring`, route finish → `flag`. |
| `pois[].marker.color` | string | — | Marker fill color. |
| `pois[].marker.size` | number, 4–64 | — | Marker height in CSS pixels (multiplied by `scale`). Default depends on the shape. |
| `pois[].marker.strokeColor` | string | — | Outline color (default white where the shape has an outline). |
| `pois[].marker.strokeWidth` | number, 0–8 | — | Outline width in px; 0 = none. `dot` and `pin` have a thin default outline. |
| `pois[].marker.icon` | string | — | Custom icon instead of the shape: an SVG/PNG `data:` URI, or an https URL on a host the server allows (`WHEREBOX_ICON_HOSTS`). SVGs with external references or scripts are rejected. |
| `pois[].marker.anchor` | `center` \| `bottom` | — | Which point of a custom icon sits on the location: its center, or its bottom edge (pin-shaped icons). |
| `pois[].marker` | object | — | Marker style; every field is optional and falls back to the role default. |
| `pois[].leader` | boolean | `true` | When no free spot is next to the marker, place the label further out with a thin leader line. |
| `pois[]` | object | — | A point on the map: coordinates or a place name, with an optional label and marker. |
| `pois` | array | `[]` | Points with markers and labels (up to 50). |
| `width` | integer, 64–2048 | `600` | Image width in CSS px (the output is width × `scale` pixels). |
| `height` | integer, 64–2048 | `400` | Image height in CSS px, including the title band if any. |
| `scale` | integer, 1–3 | `1` | Pixel ratio for high-DPI output (2 = retina). |
| `format` | `png` \| `jpeg` \| `webp` | `png` | Image format (GET can also use the path extension: /v1/map.png, .jpg, .webp). |
| `quality` | integer, 1–100 | `90` | JPEG/WebP quality. |
| `padding` | number, 0–0.45 | `0.04` | Space around the framed content as a fraction of the image size. |
| `projection` | `mercator` \| `globe` \| `auto` | `mercator` | Map projection. `mercator` is the usual flat web map. `globe` draws an orthographic globe, which keeps continent-spanning routes and high latitudes true to shape; the content must fit on one hemisphere (within 85° of the view center), and neighbor labels are not available. `auto` picks the globe when the content spans more than 50° or Mercator would stretch it more than 2.5× between its lowest and highest latitude, else Mercator. |
| `globe.view` | `full` \| `fit` | `full` | How much of the globe to show. `full` (default): the whole globe, centered on your content, with space around it; recognizable at a glance as a globe. `fit`: zoomed in until the content fills the image; a larger scale with more detail along the route, but only part of the globe is visible. |
| `globe` | object | `{}` | Globe options (with `projection` `globe`, or `auto` when it picks the globe). |
| `basemap.preset` | `locator-relief` \| `light` \| `dark` \| `none` | `locator-relief` | Built-in basemap: shaded relief (Wikipedia locator style), light, dark, or `none`: no map at all, only a plain `background` color with your area outline, shapes, routes and points on it (the "outline of Texas with a star" look). No key needed. |
| `basemap.styleUrl` | string | — | Any MapLibre style.json URL; overrides `preset`. `{key}` in the URL is replaced with `providerKey`. |
| `basemap.providerKey` | string | — | Key for a commercial style (prefer the `X-Provider-Key` header so it stays out of URLs). |
| `basemap.background` | `transparent` | — | Background color for preset `none` (default white): any hex color, or `transparent` for a PNG/WebP with a transparent background that sits on any page. Labels, outline and attribution switch to light colors on a dark background. Only valid with preset `none`; `transparent` does not work with JPEG. |
| `basemap` | object | `{}` | The map underneath: a built-in preset or your own style. |
| `highlight.fade` | number, 0–1 | `0.45` (varies by preset) | How much the surroundings are washed out: 0 = not at all, 1 = fully covered. |
| `highlight.fadeColor` | string | `#ffffff` (varies by preset) | Color the surroundings fade towards. |
| `highlight.outlineColor` | string | `#555555` (varies by preset) | Area outline color. |
| `highlight.outlineWidth` | number, 0–10 | `1.1` (varies by preset) | Area outline width in px; 0 = none. |
| `highlight.tint` | string | — | Optional color tint drawn over the area. |
| `highlight.tintOpacity` | number, 0–1 | `0.15` (varies by preset) | Opacity of `tint`. |
| `highlight.subdivisions` | boolean \| string \| integer, `auto`, 3–11 | `auto` (varies by preset) | Inner admin borders: `auto` draws the next level that splits the area, a number forces that admin level, `false` hides them. |
| `highlight.subdivisionColor` | string | `#8a8a8a` (varies by preset) | Color of the inner admin borders. |
| `highlight.subdivisionWidth` | number, 0–6 | `0.6` (varies by preset) | Width of the inner admin borders in px. |
| `highlight.desaturate` | number, 0–1 | `0` (varies by preset) | Outside the area: 0 = full color, 1 = grayscale (applied on top of `fade`). |
| `highlight.blur` | number, 0–20 | `0` (varies by preset) | Outside the area: blur radius in CSS px; 0 = sharp. |
| `highlight.subArea.query` | string | — | Name or id, as in the string form. |
| `highlight.subArea.level` | integer, 1–11 | — | Only match areas at this OSM admin level (2 = country; regions and municipalities vary by country). |
| `highlight.subArea.country` | string | — | Only match areas inside this ISO 3166-1 alpha-2 country. |
| `highlight.subArea.geojson.type` | `Polygon` \| `MultiPolygon` \| `Feature` | — | GeoJSON type. |
| `highlight.subArea.geojson` | object | — | A GeoJSON Polygon, MultiPolygon, or Feature with one of those geometries. |
| `highlight.subArea` | string \| object | — | A second, smaller area highlighted inside the framed one (e.g. a region within its country). |
| `highlight.subAreaColor` | string | `#d03030` (varies by preset) | Fill and outline color of `subArea`. |
| `highlight.subAreaOpacity` | number, 0–1 | `0.35` (varies by preset) | Fill opacity of `subArea`. |
| `highlight.subAreaOutlineWidth` | number, 0–10 | `1.2` (varies by preset) | Outline width of `subArea` in px; 0 = none. |
| `highlight` | object | `{}` | How the area stands out. Unset fields use the basemap preset's defaults (see the presets reference). |
| `attribution` | `bottom-right` \| `bottom-left` \| `top-right` \| `top-left` \| `none` | `bottom-right` | Corner for the data attribution, or `none` to leave it off the image. The data licenses (OpenStreetMap ODbL, and Natural Earth/terrain credits where used) still require it: with `none` you must show the attribution next to the image yourself. The text to show is returned in the `X-Attribution` response header. |
| `logo` | `bottom-right` \| `bottom-left` \| `top-right` \| `top-left` \| `none` | `bottom-left` | Corner for the small `wherebox.dev` mark (9.5 px text), or `none` to hide it. Hiding the logo requires a logo-removal license (see the Fair use guide); it is not enforced technically. |
| `legend.position` | `right` \| `left` \| `top` \| `bottom` | `right` | Side of the map the legend panel goes on. |
| `legend.title` | string | — | Heading above the legend entries. |
| `legend.size` | number, 8–32 | `13` | Legend text size in CSS px; the numbered circles scale with it. |
| `legend.color` | string | — | Legend text color (default: the theme label color). |
| `legend.background` | string | — | Legend panel background (default: white, near-black on the dark preset, or the `background` of preset `none`). |
| `legend.badgeColor` | string | — | Fill of the numbered circles (default: each point's marker color; route ends use the route color). |
| `legend.badgeTextColor` | string | `#ffffff` | Number color inside the circles. |
| `legend` | object | — | A classic map legend. With it, every labeled point (and labeled route end) is drawn as a numbered circle instead of its label, and the panel lists "number – label" pairs on the chosen side. The panel is inside the requested width×height; the map gets the rest. |
| `neighbors.show` | `name` \| `code` \| `flag` \| `flag+code` \| `flag+name` | `name` | What to show for each neighboring country: its name, its international vehicle registration code (D, A, SK…), its flag, or a flag with code/name. |
| `neighbors.which` | `touching` \| `visible` | `touching` | `touching` = countries bordering the area; `visible` = every other country in the frame. |
| `neighbors.fit` | `extend` \| `shrink` \| `drop` | `extend` | When a label does not fit in the visible part of its country: `extend` grows the image on that side (the output becomes larger than width×height; see `X-Image-Width`), `shrink` reduces the label to 70 %, `drop` omits it. |
| `neighbors.size` | number, 6–32 | `12` | Text size in CSS px; flags are sized to match. |
| `neighbors.color` | string | — | Text color (default: the theme's muted label color). |
| `neighbors.uppercase` | boolean | `false` | Uppercase country names. |
| `neighbors.max` | integer, 1–30 | `12` | At most this many countries are labeled (largest visible first). |
| `neighbors` | object | — | Label the countries around the area (needs an `area`). |
| `worldview` | `ar` \| `bd` \| `br` \| `cn` \| `de` \| `eg` \| `es` \| `fr` \| `gb` \| `gr` \| `id` \| `il` \| `in` \| `it` \| `jp` \| `kr` \| `ma` \| `nl` \| `np` \| `pk` \| `pl` \| `ps` \| `pt` \| `ru` \| `sa` \| `se` \| `tr` \| `tw` \| `ua` \| `us` \| `vn` | — | Draw country borders as this country sees them (ISO 3166-1 alpha-2, e.g. `in`, `cn`, `us`, `ma`). Replaces the basemap's country and disputed borders with Natural Earth's borders for that worldview, and uses its country shapes for a highlighted country and for neighbor labels. Regions, cities and everything below country level stay OpenStreetMap. Default: the basemap's borders (OpenStreetMap, on-the-ground control). |
| `lang` | string | — | Label language (ISO 639-1). Default: local names (Deutschland, Polska), as on Wikipedia locator maps. |

The same schema is part of [openapi.json](/docs/openapi.json) (`components.schemas.MapSpec`).

<details>
<summary>Full JSON Schema</summary>

```json
{
  "type": "object",
  "properties": {
    "area": {
      "anyOf": [
        {
          "type": "string",
          "minLength": 1,
          "maxLength": 200,
          "description": "A name (\"Czechia\", \"Zlínský kraj\"), or an id: `iso:CZ`, `iso:CZ-72`, `osm:r51684`, `wikidata:Q213`.",
          "examples": [
            "Czechia"
          ]
        },
        {
          "type": "object",
          "properties": {
            "query": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "description": "Name or id, as in the string form.",
              "examples": [
                "Nová Ves"
              ]
            },
            "level": {
              "description": "Only match areas at this OSM admin level (2 = country; regions and municipalities vary by country).",
              "examples": [
                8
              ],
              "type": "integer",
              "minimum": 1,
              "maximum": 11
            },
            "country": {
              "description": "Only match areas inside this ISO 3166-1 alpha-2 country.",
              "examples": [
                "CZ"
              ],
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            }
          },
          "required": [
            "query"
          ],
          "description": "A name lookup narrowed by admin level and/or country, for ambiguous names."
        },
        {
          "type": "object",
          "properties": {
            "geojson": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "enum": [
                    "Polygon",
                    "MultiPolygon",
                    "Feature"
                  ],
                  "description": "GeoJSON type.",
                  "examples": [
                    "Polygon"
                  ]
                }
              },
              "required": [
                "type"
              ],
              "additionalProperties": {},
              "description": "A GeoJSON Polygon, MultiPolygon, or Feature with one of those geometries."
            }
          },
          "required": [
            "geojson"
          ],
          "description": "Your own area geometry instead of a lookup."
        }
      ],
      "description": "The area to frame and highlight. Ambiguous names return 409 with candidates.",
      "examples": [
        "Czechia"
      ]
    },
    "bounds": {
      "description": "Explicit frame `[west, south, east, north]`; overrides automatic framing. Cannot be combined with `center`/`zoom`.",
      "examples": [
        [
          12.09,
          48.55,
          18.86,
          51.06
        ]
      ],
      "type": "array",
      "prefixItems": [
        {
          "type": "number",
          "minimum": -180,
          "maximum": 180
        },
        {
          "type": "number",
          "minimum": -85.06,
          "maximum": 85.06
        },
        {
          "type": "number",
          "minimum": -180,
          "maximum": 180
        },
        {
          "type": "number",
          "minimum": -85.06,
          "maximum": 85.06
        }
      ],
      "items": false,
      "minItems": 4,
      "maxItems": 4
    },
    "center": {
      "description": "Center of the map. With `zoom`, this is an exact camera (as in other static map APIs) and nothing else affects the frame. Without `zoom`, the zoom is chosen so the area, routes, shapes and points fit around this center.",
      "examples": [
        {
          "lat": 50.08,
          "lon": 14.42
        }
      ],
      "type": "object",
      "properties": {
        "lat": {
          "type": "number",
          "minimum": -85.06,
          "maximum": 85.06,
          "description": "Latitude (WGS84).",
          "examples": [
            50.08
          ]
        },
        "lon": {
          "type": "number",
          "minimum": -180,
          "maximum": 180,
          "description": "Longitude (WGS84).",
          "examples": [
            14.42
          ]
        }
      },
      "required": [
        "lat",
        "lon"
      ]
    },
    "zoom": {
      "description": "Zoom level, 0 (whole world) to 22, in the usual web-map zoom units (512 px tiles, as MapLibre and Mapbox GL: at zoom z the world is 512·2^z CSS px wide). With `center`, an exact camera; without `center`, the map is centered on the content at this zoom. Not available with the globe projection.",
      "examples": [
        12
      ],
      "type": "number",
      "minimum": 0,
      "maximum": 22
    },
    "routes": {
      "default": [],
      "description": "Routes to draw (GET supports one; POST up to 10).",
      "maxItems": 10,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "geometry": {
            "description": "A line you already have (e.g. from your own routing provider).",
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "LineString",
                  "MultiLineString",
                  "Feature"
                ],
                "description": "GeoJSON type.",
                "examples": [
                  "LineString"
                ]
              }
            },
            "required": [
              "type"
            ],
            "additionalProperties": {}
          },
          "polyline": {
            "description": "The line as an encoded polyline (Google algorithm).",
            "examples": [
              "_p~iF~ps|U_ulLnnqC_mqNvxq`@"
            ],
            "type": "string",
            "maxLength": 200000
          },
          "polylinePrecision": {
            "default": 5,
            "description": "Polyline precision: 5 (Google) or 6 (Valhalla/OSRM).",
            "examples": [
              5
            ],
            "anyOf": [
              {
                "type": "number",
                "const": 5
              },
              {
                "type": "number",
                "const": 6
              }
            ]
          },
          "from": {
            "description": "Start point when the server should compute the line.",
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "lat": {
                    "type": "number",
                    "minimum": -90,
                    "maximum": 90,
                    "description": "Latitude (WGS84).",
                    "examples": [
                      40.4168
                    ]
                  },
                  "lon": {
                    "type": "number",
                    "minimum": -180,
                    "maximum": 180,
                    "description": "Longitude (WGS84).",
                    "examples": [
                      -3.7038
                    ]
                  }
                },
                "required": [
                  "lat",
                  "lon"
                ],
                "description": "Coordinates."
              },
              {
                "type": "object",
                "properties": {
                  "place": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "Place name to look up (imported OSM places first, then the server's geocoder if configured); its name becomes the default label.",
                    "examples": [
                      "Sevilla"
                    ]
                  }
                },
                "required": [
                  "place"
                ],
                "description": "A place name to look up."
              }
            ],
            "examples": [
              {
                "lat": 40.4168,
                "lon": -3.7038
              }
            ]
          },
          "to": {
            "description": "Finish point when the server should compute the line.",
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "lat": {
                    "type": "number",
                    "minimum": -90,
                    "maximum": 90,
                    "description": "Latitude (WGS84).",
                    "examples": [
                      40.4168
                    ]
                  },
                  "lon": {
                    "type": "number",
                    "minimum": -180,
                    "maximum": 180,
                    "description": "Longitude (WGS84).",
                    "examples": [
                      -3.7038
                    ]
                  }
                },
                "required": [
                  "lat",
                  "lon"
                ],
                "description": "Coordinates."
              },
              {
                "type": "object",
                "properties": {
                  "place": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "Place name to look up (imported OSM places first, then the server's geocoder if configured); its name becomes the default label.",
                    "examples": [
                      "Sevilla"
                    ]
                  }
                },
                "required": [
                  "place"
                ],
                "description": "A place name to look up."
              }
            ],
            "examples": [
              {
                "lat": 40.4168,
                "lon": -3.7038
              }
            ]
          },
          "via": {
            "default": [],
            "description": "Points the route must pass through, in order.",
            "maxItems": 20,
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "object",
                  "properties": {
                    "lat": {
                      "type": "number",
                      "minimum": -90,
                      "maximum": 90,
                      "description": "Latitude (WGS84).",
                      "examples": [
                        40.4168
                      ]
                    },
                    "lon": {
                      "type": "number",
                      "minimum": -180,
                      "maximum": 180,
                      "description": "Longitude (WGS84).",
                      "examples": [
                        -3.7038
                      ]
                    }
                  },
                  "required": [
                    "lat",
                    "lon"
                  ],
                  "description": "Coordinates."
                },
                {
                  "type": "object",
                  "properties": {
                    "place": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "description": "Place name to look up (imported OSM places first, then the server's geocoder if configured); its name becomes the default label.",
                      "examples": [
                        "Sevilla"
                      ]
                    }
                  },
                  "required": [
                    "place"
                  ],
                  "description": "A place name to look up."
                }
              ],
              "description": "A route end or via point: `{lat, lon}` or `{place}`.",
              "examples": [
                {
                  "lat": 40.4168,
                  "lon": -3.7038
                }
              ]
            }
          },
          "profile": {
            "default": "geodesic",
            "type": "string",
            "enum": [
              "car",
              "bike",
              "foot",
              "straight",
              "geodesic"
            ],
            "description": "How endpoints are connected: routed by `car`/`bike`/`foot` (needs a routing engine on the server or your `X-Routing-Key`), or locally as `straight` segments or `geodesic` great-circle arcs. The default `geodesic` always works (no routing engine, key or plan feature needed) and is the true shortest path, so it suits flights and locator maps; ask for `car`/`bike`/`foot` explicitly for roads.",
            "examples": [
              "geodesic"
            ]
          },
          "provider": {
            "description": "Routing provider (default: the server's). openrouteservice and GraphHopper need a key (server-side or `X-Routing-Key`).",
            "examples": [
              "valhalla"
            ],
            "type": "string",
            "enum": [
              "valhalla",
              "openrouteservice",
              "graphhopper"
            ]
          },
          "color": {
            "default": "#d01c1c",
            "type": "string",
            "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
            "description": "Color of the route line.",
            "examples": [
              "#d01c1c"
            ]
          },
          "width": {
            "default": 3,
            "description": "Line width in px.",
            "examples": [
              3
            ],
            "type": "number",
            "minimum": 0.5,
            "maximum": 20
          },
          "casingColor": {
            "default": "#ffffff",
            "type": "string",
            "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
            "description": "Outline drawn under the line so it reads on busy basemaps.",
            "examples": [
              "#ffffff"
            ]
          },
          "casingWidth": {
            "default": 1.5,
            "description": "Outline width on each side in px; 0 = none.",
            "examples": [
              1.5
            ],
            "type": "number",
            "minimum": 0,
            "maximum": 10
          },
          "dash": {
            "description": "Dash pattern in line widths, e.g. `[2, 1.5]`.",
            "examples": [
              [
                2,
                1.5
              ]
            ],
            "maxItems": 8,
            "type": "array",
            "items": {
              "type": "number",
              "minimum": 0,
              "maximum": 50
            }
          },
          "opacity": {
            "default": 1,
            "description": "Line opacity.",
            "examples": [
              1
            ],
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "start": {
            "default": {},
            "type": "object",
            "properties": {
              "label": {
                "description": "Label at this end (default: the place name, if the end was given as a place).",
                "examples": [
                  "Madrid"
                ],
                "type": "string",
                "maxLength": 160
              },
              "labelPosition": {
                "default": "auto",
                "type": "string",
                "enum": [
                  "auto",
                  "right",
                  "left",
                  "top",
                  "bottom",
                  "top-right",
                  "top-left",
                  "bottom-right",
                  "bottom-left"
                ],
                "description": "Where the label goes relative to the marker. `auto` picks the first free spot and falls back to a leader line.",
                "examples": [
                  "auto"
                ]
              },
              "labelSize": {
                "default": 16,
                "description": "Label text size in CSS px.",
                "examples": [
                  16
                ],
                "type": "number",
                "minimum": 6,
                "maximum": 48
              },
              "labelWeight": {
                "description": "Font weight for this label (overrides `font.weight`).",
                "examples": [
                  700
                ],
                "type": "integer",
                "minimum": 100,
                "maximum": 900
              },
              "labelColor": {
                "type": "string",
                "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
                "description": "Label color (default: the basemap theme's label color).",
                "examples": [
                  "#1a1a1a"
                ]
              },
              "marker": {
                "type": "object",
                "properties": {
                  "shape": {
                    "type": "string",
                    "enum": [
                      "pin",
                      "dot",
                      "ring",
                      "flag",
                      "triangle",
                      "circle",
                      "square",
                      "star",
                      "diamond"
                    ],
                    "description": "Marker preset. Defaults depend on the role: plain point → `pin`, route start → `ring`, route finish → `flag`.",
                    "examples": [
                      "pin"
                    ]
                  },
                  "color": {
                    "type": "string",
                    "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
                    "description": "Marker fill color.",
                    "examples": [
                      "#e02020"
                    ]
                  },
                  "size": {
                    "type": "number",
                    "minimum": 4,
                    "maximum": 64,
                    "description": "Marker height in CSS pixels (multiplied by `scale`). Default depends on the shape.",
                    "examples": [
                      20
                    ]
                  },
                  "strokeColor": {
                    "type": "string",
                    "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
                    "description": "Outline color (default white where the shape has an outline).",
                    "examples": [
                      "#ffffff"
                    ]
                  },
                  "strokeWidth": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 8,
                    "description": "Outline width in px; 0 = none. `dot` and `pin` have a thin default outline.",
                    "examples": [
                      1.5
                    ]
                  },
                  "icon": {
                    "type": "string",
                    "maxLength": 200000,
                    "description": "Custom icon instead of the shape: an SVG/PNG `data:` URI, or an https URL on a host the server allows (`WHEREBOX_ICON_HOSTS`). SVGs with external references or scripts are rejected.",
                    "examples": [
                      "data:image/svg+xml;base64,PHN2Zy8+"
                    ]
                  },
                  "anchor": {
                    "type": "string",
                    "enum": [
                      "center",
                      "bottom"
                    ],
                    "description": "Which point of a custom icon sits on the location: its center, or its bottom edge (pin-shaped icons).",
                    "examples": [
                      "bottom"
                    ]
                  }
                },
                "description": "Marker style; every field is optional and falls back to the role default."
              },
              "show": {
                "default": true,
                "description": "`false` hides the marker and label for this end.",
                "examples": [
                  true
                ],
                "type": "boolean"
              }
            },
            "description": "Marker and label for one end of the route."
          },
          "finish": {
            "default": {},
            "type": "object",
            "properties": {
              "label": {
                "description": "Label at this end (default: the place name, if the end was given as a place).",
                "examples": [
                  "Madrid"
                ],
                "type": "string",
                "maxLength": 160
              },
              "labelPosition": {
                "default": "auto",
                "type": "string",
                "enum": [
                  "auto",
                  "right",
                  "left",
                  "top",
                  "bottom",
                  "top-right",
                  "top-left",
                  "bottom-right",
                  "bottom-left"
                ],
                "description": "Where the label goes relative to the marker. `auto` picks the first free spot and falls back to a leader line.",
                "examples": [
                  "auto"
                ]
              },
              "labelSize": {
                "default": 16,
                "description": "Label text size in CSS px.",
                "examples": [
                  16
                ],
                "type": "number",
                "minimum": 6,
                "maximum": 48
              },
              "labelWeight": {
                "description": "Font weight for this label (overrides `font.weight`).",
                "examples": [
                  700
                ],
                "type": "integer",
                "minimum": 100,
                "maximum": 900
              },
              "labelColor": {
                "type": "string",
                "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
                "description": "Label color (default: the basemap theme's label color).",
                "examples": [
                  "#1a1a1a"
                ]
              },
              "marker": {
                "type": "object",
                "properties": {
                  "shape": {
                    "type": "string",
                    "enum": [
                      "pin",
                      "dot",
                      "ring",
                      "flag",
                      "triangle",
                      "circle",
                      "square",
                      "star",
                      "diamond"
                    ],
                    "description": "Marker preset. Defaults depend on the role: plain point → `pin`, route start → `ring`, route finish → `flag`.",
                    "examples": [
                      "pin"
                    ]
                  },
                  "color": {
                    "type": "string",
                    "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
                    "description": "Marker fill color.",
                    "examples": [
                      "#e02020"
                    ]
                  },
                  "size": {
                    "type": "number",
                    "minimum": 4,
                    "maximum": 64,
                    "description": "Marker height in CSS pixels (multiplied by `scale`). Default depends on the shape.",
                    "examples": [
                      20
                    ]
                  },
                  "strokeColor": {
                    "type": "string",
                    "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
                    "description": "Outline color (default white where the shape has an outline).",
                    "examples": [
                      "#ffffff"
                    ]
                  },
                  "strokeWidth": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 8,
                    "description": "Outline width in px; 0 = none. `dot` and `pin` have a thin default outline.",
                    "examples": [
                      1.5
                    ]
                  },
                  "icon": {
                    "type": "string",
                    "maxLength": 200000,
                    "description": "Custom icon instead of the shape: an SVG/PNG `data:` URI, or an https URL on a host the server allows (`WHEREBOX_ICON_HOSTS`). SVGs with external references or scripts are rejected.",
                    "examples": [
                      "data:image/svg+xml;base64,PHN2Zy8+"
                    ]
                  },
                  "anchor": {
                    "type": "string",
                    "enum": [
                      "center",
                      "bottom"
                    ],
                    "description": "Which point of a custom icon sits on the location: its center, or its bottom edge (pin-shaped icons).",
                    "examples": [
                      "bottom"
                    ]
                  }
                },
                "description": "Marker style; every field is optional and falls back to the role default."
              },
              "show": {
                "default": true,
                "description": "`false` hides the marker and label for this end.",
                "examples": [
                  true
                ],
                "type": "boolean"
              }
            },
            "description": "Marker and label for one end of the route."
          }
        },
        "description": "A line between points: given as geometry/polyline, routed between `from` and `to`, or straight/geodesic."
      }
    },
    "shapes": {
      "default": [],
      "description": "Extra lines and polygons, drawn in order (later ones on top). Up to 50; in GET, repeat `shape`.",
      "maxItems": 50,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "geojson": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "description": "GeoJSON type (LineString, Polygon, Feature, FeatureCollection, …).",
                "examples": [
                  "LineString"
                ]
              }
            },
            "required": [
              "type"
            ],
            "additionalProperties": {},
            "description": "Any GeoJSON geometry, Feature or FeatureCollection."
          },
          "color": {
            "default": "#555555",
            "type": "string",
            "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
            "description": "Line color of the shape.",
            "examples": [
              "#555555"
            ]
          },
          "width": {
            "default": 2,
            "description": "Line width in px; 0 = no line.",
            "examples": [
              2
            ],
            "type": "number",
            "minimum": 0,
            "maximum": 20
          },
          "dash": {
            "description": "Dash pattern in line widths.",
            "examples": [
              [
                3,
                2
              ]
            ],
            "maxItems": 8,
            "type": "array",
            "items": {
              "type": "number",
              "minimum": 0,
              "maximum": 50
            }
          },
          "opacity": {
            "default": 1,
            "description": "Line opacity.",
            "examples": [
              1
            ],
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "fill": {
            "type": "string",
            "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
            "description": "Fill color for polygons (no fill if unset).",
            "examples": [
              "#ffcc00"
            ]
          },
          "fillOpacity": {
            "default": 0.25,
            "description": "Fill opacity for polygons.",
            "examples": [
              0.25
            ],
            "type": "number",
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [
          "geojson"
        ],
        "description": "An extra line or polygon drawn on the map (e.g. a boundary arc or a buffer zone)."
      }
    },
    "font": {
      "default": {},
      "type": "object",
      "properties": {
        "family": {
          "default": "noto-sans",
          "description": "A bundled family, or your own TTF/OTF/WOFF as a `data:` URI or an https URL on an allowed host (`WHEREBOX_FONT_HOSTS`). Missing glyphs fall back to Noto Sans, then Noto Sans Mono.",
          "examples": [
            "noto-serif"
          ],
          "anyOf": [
            {
              "type": "string",
              "enum": [
                "noto-sans",
                "noto-serif",
                "noto-sans-mono"
              ],
              "description": "Bundled font family.",
              "examples": [
                "noto-sans"
              ]
            },
            {
              "type": "string",
              "maxLength": 2000000
            }
          ]
        },
        "weight": {
          "default": 400,
          "description": "Weight for all labels (100–900; the nearest bundled weight is used).",
          "examples": [
            600
          ],
          "type": "integer",
          "minimum": 100,
          "maximum": 900
        }
      },
      "description": "Font for everything we draw (labels, title); the basemap keeps its own fonts."
    },
    "title": {
      "type": "object",
      "properties": {
        "text": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200,
          "description": "Title text (one line; long titles shrink, then get an ellipsis).",
          "examples": [
            "Madrid – Seville"
          ]
        },
        "position": {
          "default": "top",
          "description": "Band above or below the map.",
          "examples": [
            "top"
          ],
          "type": "string",
          "enum": [
            "top",
            "bottom"
          ]
        },
        "align": {
          "default": "left",
          "description": "Text alignment in the band.",
          "examples": [
            "left"
          ],
          "type": "string",
          "enum": [
            "left",
            "center",
            "right"
          ]
        },
        "size": {
          "default": 18,
          "description": "Text size in CSS px.",
          "examples": [
            18
          ],
          "type": "number",
          "minimum": 8,
          "maximum": 64
        },
        "weight": {
          "default": 600,
          "description": "Font weight.",
          "examples": [
            600
          ],
          "type": "integer",
          "minimum": 100,
          "maximum": 900
        },
        "color": {
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Text color (default: the theme label color).",
          "examples": [
            "#1a1a1a"
          ]
        },
        "background": {
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Band background (default: white, or near-black on the dark preset).",
          "examples": [
            "#ffffff"
          ]
        },
        "dividerColor": {
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Line between the band and the map.",
          "examples": [
            "#cfcfcf"
          ]
        },
        "dividerWidth": {
          "default": 1,
          "description": "Divider width in px; 0 = none.",
          "examples": [
            1
          ],
          "type": "number",
          "minimum": 0,
          "maximum": 6
        },
        "padding": {
          "default": 10,
          "description": "Space around the text in px.",
          "examples": [
            10
          ],
          "type": "number",
          "minimum": 0,
          "maximum": 40
        }
      },
      "required": [
        "text"
      ],
      "description": "A title band, drawn inside the requested width×height (the map gets the rest)."
    },
    "pois": {
      "default": [],
      "description": "Points with markers and labels (up to 50).",
      "maxItems": 50,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "lat": {
            "description": "Latitude (WGS84). Any coordinate works; no lookup is done.",
            "examples": [
              49.13
            ],
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "lon": {
            "description": "Longitude (WGS84).",
            "examples": [
              17.33
            ],
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          "place": {
            "description": "A place name to look up instead of coordinates (cities, peaks, mountain ranges…). Looked up in the imported OSM places first, then in the server's geocoder if one is configured. The label defaults to the place name.",
            "examples": [
              "Chřiby"
            ],
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "label": {
            "description": "Label text. A newline (`\\n` in GET) starts a new line.",
            "examples": [
              "Crash Site\n(near Urda)"
            ],
            "type": "string",
            "maxLength": 160
          },
          "labelPosition": {
            "default": "auto",
            "type": "string",
            "enum": [
              "auto",
              "right",
              "left",
              "top",
              "bottom",
              "top-right",
              "top-left",
              "bottom-right",
              "bottom-left"
            ],
            "description": "Where the label goes relative to the marker. `auto` picks the first free spot and falls back to a leader line.",
            "examples": [
              "auto"
            ]
          },
          "labelSize": {
            "default": 16,
            "description": "Label text size in CSS px.",
            "examples": [
              16
            ],
            "type": "number",
            "minimum": 6,
            "maximum": 48
          },
          "labelWeight": {
            "description": "Font weight for this label (overrides `font.weight`).",
            "examples": [
              700
            ],
            "type": "integer",
            "minimum": 100,
            "maximum": 900
          },
          "labelColor": {
            "type": "string",
            "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
            "description": "Label color (default: the basemap theme's label color).",
            "examples": [
              "#1a1a1a"
            ]
          },
          "marker": {
            "type": "object",
            "properties": {
              "shape": {
                "type": "string",
                "enum": [
                  "pin",
                  "dot",
                  "ring",
                  "flag",
                  "triangle",
                  "circle",
                  "square",
                  "star",
                  "diamond"
                ],
                "description": "Marker preset. Defaults depend on the role: plain point → `pin`, route start → `ring`, route finish → `flag`.",
                "examples": [
                  "pin"
                ]
              },
              "color": {
                "type": "string",
                "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
                "description": "Marker fill color.",
                "examples": [
                  "#e02020"
                ]
              },
              "size": {
                "type": "number",
                "minimum": 4,
                "maximum": 64,
                "description": "Marker height in CSS pixels (multiplied by `scale`). Default depends on the shape.",
                "examples": [
                  20
                ]
              },
              "strokeColor": {
                "type": "string",
                "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
                "description": "Outline color (default white where the shape has an outline).",
                "examples": [
                  "#ffffff"
                ]
              },
              "strokeWidth": {
                "type": "number",
                "minimum": 0,
                "maximum": 8,
                "description": "Outline width in px; 0 = none. `dot` and `pin` have a thin default outline.",
                "examples": [
                  1.5
                ]
              },
              "icon": {
                "type": "string",
                "maxLength": 200000,
                "description": "Custom icon instead of the shape: an SVG/PNG `data:` URI, or an https URL on a host the server allows (`WHEREBOX_ICON_HOSTS`). SVGs with external references or scripts are rejected.",
                "examples": [
                  "data:image/svg+xml;base64,PHN2Zy8+"
                ]
              },
              "anchor": {
                "type": "string",
                "enum": [
                  "center",
                  "bottom"
                ],
                "description": "Which point of a custom icon sits on the location: its center, or its bottom edge (pin-shaped icons).",
                "examples": [
                  "bottom"
                ]
              }
            },
            "description": "Marker style; every field is optional and falls back to the role default."
          },
          "leader": {
            "default": true,
            "description": "When no free spot is next to the marker, place the label further out with a thin leader line.",
            "examples": [
              true
            ],
            "type": "boolean"
          }
        },
        "description": "A point on the map: coordinates or a place name, with an optional label and marker."
      }
    },
    "width": {
      "default": 600,
      "description": "Image width in CSS px (the output is width × `scale` pixels).",
      "examples": [
        468
      ],
      "type": "integer",
      "minimum": 64,
      "maximum": 2048
    },
    "height": {
      "default": 400,
      "description": "Image height in CSS px, including the title band if any.",
      "examples": [
        280
      ],
      "type": "integer",
      "minimum": 64,
      "maximum": 2048
    },
    "scale": {
      "default": 1,
      "description": "Pixel ratio for high-DPI output (2 = retina).",
      "examples": [
        2
      ],
      "type": "integer",
      "minimum": 1,
      "maximum": 3
    },
    "format": {
      "default": "png",
      "type": "string",
      "enum": [
        "png",
        "jpeg",
        "webp"
      ],
      "description": "Image format (GET can also use the path extension: /v1/map.png, .jpg, .webp).",
      "examples": [
        "png"
      ]
    },
    "quality": {
      "default": 90,
      "description": "JPEG/WebP quality.",
      "examples": [
        90
      ],
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "padding": {
      "default": 0.04,
      "description": "Space around the framed content as a fraction of the image size.",
      "examples": [
        0.04
      ],
      "type": "number",
      "minimum": 0,
      "maximum": 0.45
    },
    "projection": {
      "default": "mercator",
      "type": "string",
      "enum": [
        "mercator",
        "globe",
        "auto"
      ],
      "description": "Map projection. `mercator` is the usual flat web map. `globe` draws an orthographic globe, which keeps continent-spanning routes and high latitudes true to shape; the content must fit on one hemisphere (within 85° of the view center), and neighbor labels are not available. `auto` picks the globe when the content spans more than 50° or Mercator would stretch it more than 2.5× between its lowest and highest latitude, else Mercator.",
      "examples": [
        "globe"
      ]
    },
    "globe": {
      "default": {},
      "type": "object",
      "properties": {
        "view": {
          "default": "full",
          "description": "How much of the globe to show. `full` (default): the whole globe, centered on your content, with space around it; recognizable at a glance as a globe. `fit`: zoomed in until the content fills the image; a larger scale with more detail along the route, but only part of the globe is visible.",
          "examples": [
            "full"
          ],
          "type": "string",
          "enum": [
            "full",
            "fit"
          ]
        }
      },
      "description": "Globe options (with `projection` `globe`, or `auto` when it picks the globe)."
    },
    "basemap": {
      "default": {},
      "type": "object",
      "properties": {
        "preset": {
          "default": "locator-relief",
          "type": "string",
          "enum": [
            "locator-relief",
            "light",
            "dark",
            "none"
          ],
          "description": "Built-in basemap: shaded relief (Wikipedia locator style), light, dark, or `none`: no map at all, only a plain `background` color with your area outline, shapes, routes and points on it (the \"outline of Texas with a star\" look). No key needed.",
          "examples": [
            "locator-relief"
          ]
        },
        "styleUrl": {
          "description": "Any MapLibre style.json URL; overrides `preset`. `{key}` in the URL is replaced with `providerKey`.",
          "examples": [
            "https://api.maptiler.com/maps/streets-v2/style.json?key={key}"
          ],
          "type": "string",
          "format": "uri"
        },
        "providerKey": {
          "description": "Key for a commercial style (prefer the `X-Provider-Key` header so it stays out of URLs).",
          "examples": [
            "your-provider-key"
          ],
          "type": "string",
          "maxLength": 200
        },
        "background": {
          "description": "Background color for preset `none` (default white): any hex color, or `transparent` for a PNG/WebP with a transparent background that sits on any page. Labels, outline and attribution switch to light colors on a dark background. Only valid with preset `none`; `transparent` does not work with JPEG.",
          "examples": [
            "#000000"
          ],
          "anyOf": [
            {
              "type": "string",
              "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
            },
            {
              "type": "string",
              "const": "transparent"
            }
          ]
        }
      },
      "description": "The map underneath: a built-in preset or your own style."
    },
    "highlight": {
      "default": {},
      "type": "object",
      "properties": {
        "fade": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "How much the surroundings are washed out: 0 = not at all, 1 = fully covered.",
          "examples": [
            0.45
          ]
        },
        "fadeColor": {
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Color the surroundings fade towards.",
          "examples": [
            "#ffffff"
          ]
        },
        "outlineColor": {
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Area outline color.",
          "examples": [
            "#555555"
          ]
        },
        "outlineWidth": {
          "type": "number",
          "minimum": 0,
          "maximum": 10,
          "description": "Area outline width in px; 0 = none.",
          "examples": [
            1.1
          ]
        },
        "tint": {
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Optional color tint drawn over the area.",
          "examples": [
            "#d03030"
          ]
        },
        "tintOpacity": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "Opacity of `tint`.",
          "examples": [
            0.15
          ]
        },
        "subdivisions": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "string",
              "const": "auto"
            },
            {
              "type": "integer",
              "minimum": 3,
              "maximum": 11
            }
          ],
          "description": "Inner admin borders: `auto` draws the next level that splits the area, a number forces that admin level, `false` hides them.",
          "examples": [
            "auto"
          ]
        },
        "subdivisionColor": {
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Color of the inner admin borders.",
          "examples": [
            "#8a8a8a"
          ]
        },
        "subdivisionWidth": {
          "type": "number",
          "minimum": 0,
          "maximum": 6,
          "description": "Width of the inner admin borders in px.",
          "examples": [
            0.6
          ]
        },
        "desaturate": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "Outside the area: 0 = full color, 1 = grayscale (applied on top of `fade`).",
          "examples": [
            0.8
          ]
        },
        "blur": {
          "type": "number",
          "minimum": 0,
          "maximum": 20,
          "description": "Outside the area: blur radius in CSS px; 0 = sharp.",
          "examples": [
            1.5
          ]
        },
        "subArea": {
          "anyOf": [
            {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "description": "A name (\"Czechia\", \"Zlínský kraj\"), or an id: `iso:CZ`, `iso:CZ-72`, `osm:r51684`, `wikidata:Q213`.",
              "examples": [
                "Czechia"
              ]
            },
            {
              "type": "object",
              "properties": {
                "query": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "description": "Name or id, as in the string form.",
                  "examples": [
                    "Nová Ves"
                  ]
                },
                "level": {
                  "description": "Only match areas at this OSM admin level (2 = country; regions and municipalities vary by country).",
                  "examples": [
                    8
                  ],
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 11
                },
                "country": {
                  "description": "Only match areas inside this ISO 3166-1 alpha-2 country.",
                  "examples": [
                    "CZ"
                  ],
                  "type": "string",
                  "minLength": 2,
                  "maxLength": 2
                }
              },
              "required": [
                "query"
              ],
              "description": "A name lookup narrowed by admin level and/or country, for ambiguous names."
            },
            {
              "type": "object",
              "properties": {
                "geojson": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "enum": [
                        "Polygon",
                        "MultiPolygon",
                        "Feature"
                      ],
                      "description": "GeoJSON type.",
                      "examples": [
                        "Polygon"
                      ]
                    }
                  },
                  "required": [
                    "type"
                  ],
                  "additionalProperties": {},
                  "description": "A GeoJSON Polygon, MultiPolygon, or Feature with one of those geometries."
                }
              },
              "required": [
                "geojson"
              ],
              "description": "Your own area geometry instead of a lookup."
            }
          ],
          "description": "A second, smaller area highlighted inside the framed one (e.g. a region within its country).",
          "examples": [
            "Zlínský kraj"
          ]
        },
        "subAreaColor": {
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Fill and outline color of `subArea`.",
          "examples": [
            "#d03030"
          ]
        },
        "subAreaOpacity": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "Fill opacity of `subArea`.",
          "examples": [
            0.35
          ]
        },
        "subAreaOutlineWidth": {
          "type": "number",
          "minimum": 0,
          "maximum": 10,
          "description": "Outline width of `subArea` in px; 0 = none.",
          "examples": [
            1.2
          ]
        }
      },
      "description": "How the area stands out. Unset fields use the basemap preset's defaults (see the presets reference)."
    },
    "attribution": {
      "default": "bottom-right",
      "description": "Corner for the data attribution, or `none` to leave it off the image. The data licenses (OpenStreetMap ODbL, and Natural Earth/terrain credits where used) still require it: with `none` you must show the attribution next to the image yourself. The text to show is returned in the `X-Attribution` response header.",
      "examples": [
        "bottom-right"
      ],
      "type": "string",
      "enum": [
        "bottom-right",
        "bottom-left",
        "top-right",
        "top-left",
        "none"
      ]
    },
    "logo": {
      "default": "bottom-left",
      "description": "Corner for the small `wherebox.dev` mark (9.5 px text), or `none` to hide it. Hiding the logo requires a logo-removal license (see the Fair use guide); it is not enforced technically.",
      "examples": [
        "bottom-left"
      ],
      "type": "string",
      "enum": [
        "bottom-right",
        "bottom-left",
        "top-right",
        "top-left",
        "none"
      ]
    },
    "legend": {
      "type": "object",
      "properties": {
        "position": {
          "default": "right",
          "type": "string",
          "enum": [
            "right",
            "left",
            "top",
            "bottom"
          ],
          "description": "Side of the map the legend panel goes on.",
          "examples": [
            "right"
          ]
        },
        "title": {
          "description": "Heading above the legend entries.",
          "examples": [
            "Stops"
          ],
          "type": "string",
          "minLength": 1,
          "maxLength": 80
        },
        "size": {
          "default": 13,
          "description": "Legend text size in CSS px; the numbered circles scale with it.",
          "examples": [
            13
          ],
          "type": "number",
          "minimum": 8,
          "maximum": 32
        },
        "color": {
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Legend text color (default: the theme label color).",
          "examples": [
            "#1a1a1a"
          ]
        },
        "background": {
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Legend panel background (default: white, near-black on the dark preset, or the `background` of preset `none`).",
          "examples": [
            "#ffffff"
          ]
        },
        "badgeColor": {
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Fill of the numbered circles (default: each point's marker color; route ends use the route color).",
          "examples": [
            "#e02020"
          ]
        },
        "badgeTextColor": {
          "default": "#ffffff",
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Number color inside the circles.",
          "examples": [
            "#ffffff"
          ]
        }
      },
      "description": "A classic map legend. With it, every labeled point (and labeled route end) is drawn as a numbered circle instead of its label, and the panel lists \"number – label\" pairs on the chosen side. The panel is inside the requested width×height; the map gets the rest."
    },
    "neighbors": {
      "type": "object",
      "properties": {
        "show": {
          "default": "name",
          "type": "string",
          "enum": [
            "name",
            "code",
            "flag",
            "flag+code",
            "flag+name"
          ],
          "description": "What to show for each neighboring country: its name, its international vehicle registration code (D, A, SK…), its flag, or a flag with code/name.",
          "examples": [
            "flag+code"
          ]
        },
        "which": {
          "default": "touching",
          "description": "`touching` = countries bordering the area; `visible` = every other country in the frame.",
          "examples": [
            "touching"
          ],
          "type": "string",
          "enum": [
            "touching",
            "visible"
          ]
        },
        "fit": {
          "default": "extend",
          "description": "When a label does not fit in the visible part of its country: `extend` grows the image on that side (the output becomes larger than width×height; see `X-Image-Width`), `shrink` reduces the label to 70 %, `drop` omits it.",
          "examples": [
            "extend"
          ],
          "type": "string",
          "enum": [
            "extend",
            "shrink",
            "drop"
          ]
        },
        "size": {
          "default": 12,
          "description": "Text size in CSS px; flags are sized to match.",
          "examples": [
            12
          ],
          "type": "number",
          "minimum": 6,
          "maximum": 32
        },
        "color": {
          "type": "string",
          "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$",
          "description": "Text color (default: the theme's muted label color).",
          "examples": [
            "#666666"
          ]
        },
        "uppercase": {
          "default": false,
          "description": "Uppercase country names.",
          "examples": [
            true
          ],
          "type": "boolean"
        },
        "max": {
          "default": 12,
          "description": "At most this many countries are labeled (largest visible first).",
          "examples": [
            12
          ],
          "type": "integer",
          "minimum": 1,
          "maximum": 30
        }
      },
      "description": "Label the countries around the area (needs an `area`)."
    },
    "worldview": {
      "description": "Draw country borders as this country sees them (ISO 3166-1 alpha-2, e.g. `in`, `cn`, `us`, `ma`). Replaces the basemap's country and disputed borders with Natural Earth's borders for that worldview, and uses its country shapes for a highlighted country and for neighbor labels. Regions, cities and everything below country level stay OpenStreetMap. Default: the basemap's borders (OpenStreetMap, on-the-ground control).",
      "examples": [
        "in"
      ],
      "type": "string",
      "enum": [
        "ar",
        "bd",
        "br",
        "cn",
        "de",
        "eg",
        "es",
        "fr",
        "gb",
        "gr",
        "id",
        "il",
        "in",
        "it",
        "jp",
        "kr",
        "ma",
        "nl",
        "np",
        "pk",
        "pl",
        "ps",
        "pt",
        "ru",
        "sa",
        "se",
        "tr",
        "tw",
        "ua",
        "us",
        "vn"
      ]
    },
    "lang": {
      "description": "Label language (ISO 639-1). Default: local names (Deutschland, Polska), as on Wikipedia locator maps.",
      "examples": [
        "en"
      ],
      "type": "string",
      "pattern": "^[a-z]{2,3}$"
    }
  },
  "description": "Everything about one map image. Without an `area`, the map is framed on routes, shapes and points (or `bounds`)."
}
```

</details>
