Wherebox
On this page

Points and labels

A point is a location with a marker and an optional label. Up to 50 per map. In GET, repeat poi= once per point; in POST, use the pois array.

Coordinates or place names#

Give lat,lon when you know where it is, or place:Name to look it up.

GET/v1/map.png
GET /v1/map.png?area=Zlínský+kraj&poi=49.13,17.33|label:Chřiby&w=400&h=300
A point from coordinates
GET/v1/map.png
GET /v1/map.png?area=Zlínský+kraj&poi=place:Zlín&poi=place:Kroměříž&poi=place:Uherské+Hradiště&w=400&h=300
Three points looked up by name

Place lookups cover cities, peaks, mountain ranges and similar names, and prefer a match inside the framed area. The label defaults to the place name; set label: to override it. Coordinates are used exactly as given, with no lookup. Find place names with GET /v1/places/search?q=….

Names are looked up in the server's imported OpenStreetMap places first. A server can also configure a geocoder (Nominatim or Photon) for names its data does not have, such as places outside the imported region. When the server has none, an unknown name returns 404 not-found with close matches in suggestions. If the geocoder itself fails, the response is 502 upstream-failed or 504 upstream-timeout, so retry those rather than treating them as "no such place". Self-hosters: see Geocoder fallback.

After the location, a point takes |key:value options. All of them are in the poi reference. In JSON the same options are fields of each pois entry:

POST/v1/map
{
  "area": "Zlínský kraj",
  "pois": [
    { "lat": 49.13, "lon": 17.33, "label": "Chřiby", "marker": { "shape": "triangle", "color": "#e02020" } },
    { "place": "Zlín", "marker": { "shape": "circle", "color": "#222222", "size": 9 } }
  ],
  "width": 400,
  "height": 300
}
Map rendered by the poi-post example

Markers#

A plain point is a pin. Pick another preset with marker:, and tune color:, size: and stroke:/strokewidth:.

GET/v1/map.png
GET /v1/map.png?area=Zlínský+kraj&w=480&h=320&poi=49.40,17.60|marker:star|color:%23e0a000|label:star&poi=49.40,17.95|marker:diamond|color:%231565c0|label:diamond&poi=49.20,17.45|marker:square|color:%232e7d32|label:square&poi=49.20,17.80|marker:circle|color:%23222222|label:circle&poi=49.05,17.30|marker:triangle|label:triangle&poi=49.05,17.70|marker:dot|label:dot
Several marker presets

Which presets exist, their default sizes and which one a point, a route start or a route finish gets by default is in the markers reference. The role matters: a plain point is a pin, a route start a ring, a route finish a flag (see Routes). Setting marker: replaces the role default.

Custom icons#

Use icon instead of a preset marker for logos or your own pins. It takes an SVG or PNG as a data: URI, or an https URL on a host the server operator allows. anchor:bottom puts the bottom edge of the icon on the location, which is what pin-shaped icons need; the default is the center.

POST/v1/map
{
  "area": "Zlínský kraj",
  "pois": [
    {
      "lat": 49.2266,
      "lon": 17.6667,
      "label": "Zlín",
      "marker": {
        "icon": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSI0MCIgdmlld0JveD0iMCAwIDMyIDQwIj48cGF0aCBkPSJNMTYgMEM3IDAgMCA3IDAgMTZjMCAxMiAxNiAyNCAxNiAyNHMxNi0xMiAxNi0yNEMzMiA3IDI1IDAgMTYgMHoiIGZpbGw9IiMxNTY1YzAiLz48Y2lyY2xlIGN4PSIxNiIgY3k9IjE2IiByPSI2IiBmaWxsPSIjZmZmIi8+PC9zdmc+",
        "anchor": "bottom",
        "size": 30
      }
    }
  ],
  "width": 400,
  "height": 300
}
A custom SVG pin

size is the icon height in CSS pixels. In a GET URL the icon must be URL-encoded (base64 contains +, / and =), so POST is the practical way to send one.

Security notes for icons#

Fetching a user-supplied URL is how servers get attacked, so the rules are strict. They are the server's, not yours, but they decide what works:

  • Remote icons are off unless the operator lists hosts in WHEREBOX_ICON_HOSTS. Until then only data: URIs work. See the configuration reference.
  • Remote icons must be https, are never fetched through redirects, and are capped in size and time.
  • The type must really be an image (PNG signature check); SVGs containing a DOCTYPE or entities, external references, or scripts are rejected.
  • A rejected icon is an error, not a silent fallback: you get 400 bad-request (see Errors and limits).

If you embed untrusted SVG from your own users, sanitize it before it reaches the API as well; the server's checks are a safety net, not a content policy.

Labels#

Set the text with label:. A \n starts a new line. Labels avoid each other, the markers, the route lines and the image edge.

GET/v1/map.png
GET /v1/map.png?area=Moravskoslezský+kraj&w=420&h=300&poi=49.5465,18.4472|label:Lysá hora\n1323 m|weight:700|marker:triangle|color:%23202020
A two-line, bold label

In GET, | cannot appear inside a label; send a POST if you need one. In JSON write a real newline: "label": "Lysá hora\n1323 m".

Position, size, weight and color#

pos: puts the label next to the marker (right, left, top, bottom, the four corners, or auto, the default). labelsize:, weight: and labelcolor: style it. weight: overrides the map-wide fontweight for this label only; see Typography.

GET/v1/map.png
GET /v1/map.png?area=Zlínský+kraj&w=420&h=300&poi=place:Zlín|pos:bottom|labelsize:18|weight:700&poi=place:Kroměříž|pos:left|labelcolor:%231565c0
Labels placed below and to the left

Crowded points and leader lines#

With pos:auto, a label first tries the spots next to its marker. If they are all taken, the label moves further out and a thin leader line connects it back. That keeps nearby points readable without you placing anything.

GET/v1/map.png
GET /v1/map.png?bounds=17.636,49.212,17.698,49.241&w=480&h=340&poi=49.2266,17.6693|label:Náměstí+Míru&poi=49.2277,17.6685|label:Zámek&poi=49.2282,17.6667|label:Divadlo&poi=49.2277,17.6649|label:Nádraží&poi=49.2266,17.6641|label:Radnice&poi=49.2255,17.6649|label:Muzeum&poi=49.2250,17.6667|label:Park&poi=49.2255,17.6685|label:Škola
Eight close points: labels moved out with leader lines

Turn this off per point with leader:false; the label then sits at the nearest position even if it overlaps something:

GET/v1/map.png
GET /v1/map.png?bounds=17.636,49.212,17.698,49.241&w=480&h=340&poi=49.2266,17.6693|label:Náměstí+Míru|leader:false&poi=49.2277,17.6685|label:Zámek|leader:false&poi=49.2282,17.6667|label:Divadlo|leader:false&poi=49.2277,17.6649|label:Nádraží|leader:false&poi=49.2266,17.6641|label:Radnice|leader:false&poi=49.2255,17.6649|label:Muzeum|leader:false&poi=49.2250,17.6667|label:Park|leader:false&poi=49.2255,17.6685|label:Škola|leader:false
The same points without leader lines

Options: poi (pos, labelsize, weight, labelcolor, leader).