{"components":{"schemas":{"BuildingsAccess":{"description":"Access descriptor for the 3D-buildings tilesets (OGC 3D Tiles, real roof shapes): a CDN base URL plus a signed query string that validates for every tileset artifact beneath it. The `@rijwind/sdk` `Map` consumes this automatically when 3D buildings are shown.","properties":{"baseUrl":{"description":"Buildings CDN origin to prepend to tileset paths.","example":"https://cdn.rijwind.com/buildings","type":"string"},"countries":{"description":"Countries with 3D-building coverage (ISO 3166-1 alpha-2). The\ntileset for a country lives at `{baseUrl}/{CC}/tileset.json`.","example":["NL"],"items":{"type":"string"},"type":"array"},"coverage":{"additionalProperties":{"items":{"format":"double","type":"number"},"type":"array"},"description":"Bounding box `[west, south, east, north]` (WGS84) per covered country —\nuse it to load a country's tileset only when the viewport reaches it.","example":{"NL":[3.2,50.7,7.3,53.6]},"propertyNames":{"type":"string"},"type":"object"},"expiresAt":{"description":"Unix timestamp (seconds) when the signature expires.","example":1715680000,"format":"int64","type":"integer"},"query":{"description":"Signed query string — append after `?` on any tileset artifact URL.","example":"token=9bQ1…&expires=1715680000&token_path=%2Fbuildings%2F","type":"string"}},"required":["baseUrl","query","expiresAt","countries","coverage"],"type":"object"},"Costing":{"description":"Routing profile. `auto` (car), `bicycle`, or `pedestrian` (foot).","enum":["auto","bicycle","pedestrian"],"type":"string"},"CostingOptions":{"description":"Profile-specific options, keyed by the profile they apply to. Only the entry matching `costing` is used.","properties":{"auto":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ProfileOptions"}]},"bicycle":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ProfileOptions"}]},"pedestrian":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ProfileOptions"}]}},"type":"object"},"DirectionsOptions":{"properties":{"language":{"description":"Language for narrative directions.","example":"en-US","type":["string","null"]}},"type":"object"},"ElevationPoint":{"properties":{"elevation":{"description":"Elevation in metres above sea level, or `null` where there is no\ncoverage (e.g. open ocean).","example":322.4,"format":"double","type":["number","null"]},"lat":{"example":50.7536,"format":"double","type":"number"},"lon":{"example":6.0208,"format":"double","type":"number"}},"required":["lat","lon"],"type":"object"},"ElevationRequest":{"description":"Elevation lookup. Provide either `points` (discrete coordinates) or `encodedPolyline` (a route, resampled server-side) — exactly one is required.","properties":{"encodedPolyline":{"description":"A route as a single encoded polyline (precision 6). The server samples\nit at `samples` evenly-spaced points — send a whole GPS track this way\nrather than thousands of individual points.","example":"_p~iF~ps|U_ulLnnqC","type":["string","null"]},"points":{"description":"Up to 512 discrete `(lat, lon)` points to look up. Omit when using\n`encodedPolyline`.","items":{"$ref":"#/components/schemas/LngLat"},"maxItems":512,"type":["array","null"]},"samples":{"description":"Number of evenly-spaced samples for `encodedPolyline` mode. Default\n256, capped at 1000.","example":256,"format":"int32","minimum":0,"type":["integer","null"]}},"type":"object"},"ElevationResponse":{"description":"Elevations in the same order as the request — one per input point, or one per sample along the polyline.","properties":{"elevations":{"items":{"$ref":"#/components/schemas/ElevationPoint"},"type":"array"}},"required":["elevations"],"type":"object"},"ErrorResponse":{"description":"Standard error envelope. The `error` field is a stable, machine-readable code; the `message` field is for humans and may be rewritten for clarity between releases.","properties":{"error":{"description":"Machine-readable error code, e.g. `quota_exhausted`.","example":"quota_exhausted","type":"string"},"message":{"description":"Human-readable explanation.","example":"Monthly request quota exceeded for this key.","type":"string"}},"required":["error","message"],"type":"object"},"ImageryLayer":{"description":"One satellite or aerial imagery archive (raster PMTiles) in the session. Feed `url` to a MapLibre `raster` source through the `pmtiles://` protocol.","properties":{"attribution":{"description":"Required credit as an HTML snippet — put it in the source's\n`attribution` so it shows in the map's attribution control. `null`\nwhen the source needs none.","example":"Luchtfoto: <a href=\"https://www.beeldmateriaal.nl\" target=\"_blank\" rel=\"noreferrer\">Beeldmateriaal.nl</a> CC BY 4.0","type":["string","null"]},"bounds":{"description":"`[west, south, east, north]` (WGS84); `null` = global.","example":[3.2,50.7,7.3,53.6],"items":{"format":"double","type":"number"},"type":["array","null"]},"country":{"description":"Country the archive covers (ISO 3166-1 alpha-2); `null` = global.","example":"NL","type":["string","null"]},"id":{"description":"Stable identifier of the archive (also a good MapLibre source id).","example":"satellite-nl","type":"string"},"maxzoom":{"description":"Deepest zoom with tiles; beyond it the layer is overzoomed.","example":18,"format":"int32","minimum":0,"type":["integer","null"]},"minzoom":{"description":"Lowest zoom with tiles (cross-fade an `aerial` layer in over the\nhalf zoom level above it).","example":13,"format":"int32","minimum":0,"type":["integer","null"]},"region":{"description":"Optional part of the country, e.g. `Caribisch Nederland`.","example":null,"type":["string","null"]},"role":{"description":"Where it sits in the stack: `base` (fills open ocean and the poles),\n`mosaic` (global satellite), `ocean` (water overlay — fade it out\npast ~z9), `aerial` (high-resolution country imagery).","example":"aerial","type":["string","null"]},"url":{"description":"Signed archive URL; refresh together with the tile URLs.","example":"https://cdn.rijwind.com/tiles/satellite-nl.pmtiles?token=4Xp8…&expires=1715680000","type":"string"}},"required":["id","url"],"type":"object"},"IsochroneContour":{"description":"One contour for an isochrone request — either `time` (minutes) or `distance` (in the request's `units`). `color` is a hex color without the leading hash, used for the rendered polygon's stroke and fill.","properties":{"color":{"description":"Hex color without leading hash.","example":"ff0000","type":["string","null"]},"distance":{"format":"double","type":["number","null"]},"time":{"example":15.0,"format":"double","type":["number","null"]}},"type":"object"},"IsochroneFeature":{"properties":{"geometry":{"description":"GeoJSON geometry — Polygon or LineString depending on the `polygons` flag."},"properties":{"$ref":"#/components/schemas/IsochroneFeatureProperties"},"type":{"type":"string"}},"required":["type","properties","geometry"],"type":"object"},"IsochroneFeatureProperties":{"properties":{"color":{"type":["string","null"]},"contour":{"format":"double","type":["number","null"]},"metric":{"type":["string","null"]}},"type":"object"},"IsochroneRequest":{"properties":{"contours":{"description":"One contour per reachable-area band. The product\n`len(locations) × len(contours)` must not exceed 4.","items":{"$ref":"#/components/schemas/IsochroneContour"},"maxItems":4,"minItems":1,"type":"array"},"costing":{"$ref":"#/components/schemas/Costing"},"locations":{"items":{"$ref":"#/components/schemas/LngLat"},"maxItems":4,"minItems":1,"type":"array"},"polygons":{"description":"Return polygons instead of GeoJSON LineStrings.","type":["boolean","null"]}},"required":["locations","costing","contours"],"type":"object"},"IsochroneResponse":{"description":"GeoJSON FeatureCollection with one feature per contour.","properties":{"features":{"items":{"$ref":"#/components/schemas/IsochroneFeature"},"type":"array"},"type":{"type":"string"}},"required":["type","features"],"type":"object"},"LngLat":{"description":"A `(lat, lon)` pair. Latitude is in [-90, 90], longitude in [-180, 180].","properties":{"lat":{"example":52.3676,"format":"double","type":"number"},"lon":{"example":4.9041,"format":"double","type":"number"}},"required":["lat","lon"],"type":"object"},"LocationType":{"description":"`break` (default): a stop that ends one leg and starts the next. The incoming and outgoing legs each snap to the waypoint on their own, so where several roads lie equally close (a dual carriageway, a bridge with a cycle track) they can end and start a few meters apart, and the route may turn around at the stop.\n\n`break_through`: also a stop with separate legs, but the outgoing leg continues from exactly where the incoming leg arrived, so the legs always connect. Turning around at the stop is not allowed; if continuing is impossible (a dead end), the request fails with no route found. Use it on stops the route passes through, and keep `break` where turning around is expected.","enum":["break","break_through"],"type":"string"},"MapMatchingRequest":{"description":"Snap a noisy GPS trace to the road network. Provide the trace either as a `shape` array of `(lat, lon)` points or as an `encodedPolyline` string — exactly one is required.","properties":{"costing":{"$ref":"#/components/schemas/Costing"},"encodedPolyline":{"description":"The GPS trace as a single encoded polyline (precision 6). An\nalternative to `shape` for compact transport of long traces.","example":"_p~iF~ps|U_ulLnnqC","type":["string","null"]},"shape":{"description":"The GPS trace as ordered `(lat, lon)` points. Capped at 100 points;\nuse `encodedPolyline` for longer traces. Omit when using\n`encodedPolyline`.","items":{"$ref":"#/components/schemas/LngLat"},"maxItems":100,"type":["array","null"]},"shapeMatch":{"description":"How aggressively to snap to roads. `map_snap` (default) matches to\nthe road network; `walk_or_snap` and `edge_walk` trade accuracy for\nspeed on dense traces.","example":"map_snap","type":["string","null"]},"units":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Units"}]}},"required":["costing"],"type":"object"},"MatrixCell":{"properties":{"distance":{"description":"Distance in the requested units. `null` if the pair is unreachable.","example":60.4,"format":"double","type":["number","null"]},"fromIndex":{"format":"int32","minimum":0,"type":"integer"},"time":{"description":"Travel time in seconds. `null` if the pair is unreachable.","example":4810.0,"format":"double","type":["number","null"]},"toIndex":{"format":"int32","minimum":0,"type":"integer"}},"required":["fromIndex","toIndex"],"type":"object"},"MatrixRequest":{"properties":{"costing":{"$ref":"#/components/schemas/Costing"},"sources":{"items":{"$ref":"#/components/schemas/LngLat"},"minItems":1,"type":"array"},"targets":{"items":{"$ref":"#/components/schemas/LngLat"},"minItems":1,"type":"array"},"units":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Units"}]}},"required":["sources","targets","costing"],"type":"object"},"MatrixResponse":{"description":"Matrix response. Outer array indexes sources, inner array indexes targets — `M × N` cells in row-major order.","properties":{"sourcesToTargets":{"items":{"items":{"$ref":"#/components/schemas/MatrixCell"},"type":"array"},"type":"array"},"units":{"type":"string"}},"required":["sourcesToTargets","units"],"type":"object"},"OptimizedRouteRequest":{"description":"Find the optimal visiting order over a set of waypoints and return a route that visits them in that order. The first and last locations stay fixed; the stops in between are reordered.","properties":{"costing":{"$ref":"#/components/schemas/Costing"},"locations":{"description":"Two or more waypoints. The first is the start and the last is the\nend; the intermediate stops are reordered for the shortest total\ntrip. Capped at 20 locations.","items":{"$ref":"#/components/schemas/LngLat"},"maxItems":20,"minItems":2,"type":"array"},"units":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Units"}]}},"required":["locations","costing"],"type":"object"},"PlaceFeature":{"properties":{"geometry":{"$ref":"#/components/schemas/PointGeometry"},"properties":{"$ref":"#/components/schemas/PlaceProperties"},"type":{"description":"Fixed string `\"Feature\"`.","type":"string"}},"required":["type","geometry","properties"],"type":"object"},"PlaceFeatureCollection":{"description":"Standard GeoJSON FeatureCollection, ranked by relevance.","properties":{"features":{"items":{"$ref":"#/components/schemas/PlaceFeature"},"type":"array"},"type":{"type":"string"}},"required":["type","features"],"type":"object"},"PlaceProperties":{"description":"Geographic metadata for a place. Optional fields are omitted when the underlying record doesn't carry them — e.g. a country-level result has no `street`.","properties":{"city":{"example":"Amsterdam","type":["string","null"]},"country":{"example":"Netherlands","type":["string","null"]},"countrycode":{"description":"ISO 3166-1 alpha-2 country code.","example":"NL","type":["string","null"]},"name":{"description":"Display name of the place.","example":"Damrak","type":["string","null"]},"postcode":{"example":"1012","type":["string","null"]},"state":{"example":"North Holland","type":["string","null"]},"street":{"example":"Damrak","type":["string","null"]},"type":{"description":"What kind of place this is — `street`, `house`, `locality`, `city`,\n`district`, `region`, `country`, etc.","example":"street","type":["string","null"]}},"type":"object"},"PointGeometry":{"properties":{"coordinates":{"description":"`[lon, lat]`.","example":[4.9041,52.3676],"items":{"format":"double","type":"number"},"type":"array"},"type":{"description":"Fixed string `\"Point\"`.","example":"Point","type":"string"}},"required":["type","coordinates"],"type":"object"},"ProfileOptions":{"properties":{"excludeFerries":{"description":"Exclude ferries entirely. The route then never uses a ferry, and\nwaypoints never snap onto one; if no route exists without a ferry,\nthe request fails.","example":true,"type":["boolean","null"]},"useFerry":{"description":"Preference for ferries, from `0` (avoid when possible) to `1`\n(prefer). A preference only: a ferry is still used when there is no\nreasonable alternative. Defaults to `0.5`.","example":0,"format":"double","type":["number","null"]}},"type":"object"},"RouteLeg":{"properties":{"maneuvers":{"items":{"$ref":"#/components/schemas/RouteManeuver"},"type":"array"},"shape":{"description":"Encoded polyline at 1e-6 precision (the standard Google polyline\nalgorithm with 6 decimals instead of 5). Decoders are available for\nevery major language — in JavaScript, `@mapbox/polyline` with the\nprecision set to 6 returns `[lat, lon]` pairs.","type":"string"},"summary":{"$ref":"#/components/schemas/RouteSummary"}},"required":["shape","summary","maneuvers"],"type":"object"},"RouteLocation":{"description":"A waypoint. Each waypoint is snapped to the nearest road or path that the chosen profile may use.","properties":{"lat":{"example":52.3676,"format":"double","type":"number"},"lon":{"example":4.9041,"format":"double","type":"number"},"radius":{"description":"Meters around the waypoint in which every road or path is considered\nas a snapping candidate, not only the closest. This is not a limit —\nuse `searchCutoff` for that. Defaults to 0.","example":0,"format":"double","type":["number","null"]},"searchCutoff":{"description":"Maximum snapping distance in meters. If no usable road or path lies\nwithin this distance, the request fails with `400` (error code 171)\ninstead of snapping further away. Use it to enforce a strict snapping\nlimit. Defaults to 35,000.","example":50,"format":"double","type":["number","null"]},"type":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/LocationType","description":"How the route treats an intermediate waypoint. Ignored on the first\nand last waypoint."}]}},"required":["lat","lon"],"type":"object"},"RouteManeuver":{"properties":{"beginShapeIndex":{"format":"int32","minimum":0,"type":"integer"},"endShapeIndex":{"format":"int32","minimum":0,"type":"integer"},"instruction":{"example":"Head north on Damrak.","type":"string"},"length":{"format":"double","type":"number"},"time":{"format":"double","type":"number"}},"required":["instruction","length","time","beginShapeIndex","endShapeIndex"],"type":"object"},"RouteRequest":{"properties":{"costing":{"$ref":"#/components/schemas/Costing"},"costingOptions":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CostingOptions"}]},"directionsOptions":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DirectionsOptions"}]},"locations":{"description":"Two or more ordered waypoints. The first is the origin, the last is the destination.","items":{"$ref":"#/components/schemas/RouteLocation"},"minItems":2,"type":"array"},"units":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Units"}]}},"required":["locations","costing"],"type":"object"},"RouteResponse":{"description":"Route response. The interesting fields are `trip.summary` (totals) and `trip.legs[i].shape` (an encoded polyline ready to render).","properties":{"trip":{"$ref":"#/components/schemas/Trip"}},"required":["trip"],"type":"object"},"RouteSummary":{"properties":{"length":{"description":"Total length in the requested units.","example":60.4,"format":"double","type":"number"},"maxLat":{"format":"double","type":["number","null"]},"maxLon":{"format":"double","type":["number","null"]},"minLat":{"format":"double","type":["number","null"]},"minLon":{"format":"double","type":["number","null"]},"time":{"description":"Total travel time in seconds.","example":4810.0,"format":"double","type":"number"}},"required":["length","time"],"type":"object"},"SignedTileUrl":{"description":"Short-lived signed URL pointing at the basemap on `cdn.rijwind.com`. The signature is bound to the requester's IP and expires after a short TTL — refresh it within a tile session rather than re-signing on a fixed schedule (the `@rijwind/sdk` tile-session helper does this for you).","properties":{"buildings":{"$ref":"#/components/schemas/BuildingsAccess","description":"Access descriptor for the 3D-buildings tilesets. Always included —\nrendering 3D buildings is part of the same tile session, so it adds\nno quota cost. Compose the per-country tileset URL as\n`{baseUrl}/{CC}/tileset.json?{query}` and append the same query to\nevery tile it references. Refresh together with the tile URLs."},"expiresAt":{"description":"Unix timestamp (seconds) when the signature expires.","example":1715680000,"format":"int64","type":"integer"},"imagery":{"description":"Every satellite / aerial imagery archive available to this session,\nbottom → top: draw them in this order (later entries above earlier\nones — country aerials, highest resolution last). The named\n`satellite…Url` fields above point at the same archives and stay for\nexisting integrations; new countries only appear here. Empty when no\nimagery is available. Same session, no extra quota cost.","items":{"$ref":"#/components/schemas/ImageryLayer"},"type":"array"},"satelliteBaseUrl":{"description":"Signed URL for the global base imagery archive (raster, z0–7) — ocean\nbathymetry and polar ice. Layer it BELOW the satellite source: the\nsatellite mosaic covers land only, so this is what fills open water\nand the poles. Same session, no extra quota cost.","example":"https://cdn.rijwind.com/tiles/satellite-base.pmtiles?token=2Nc5…&expires=1715680000","type":["string","null"]},"satelliteBesUrl":{"description":"Signed URL for the Caribbean Netherlands aerial archive (raster,\nz13–21). A separate source from the mainland one — it reaches a deeper\nzoom — layered the same way. Same session, no extra quota cost.","example":"https://cdn.rijwind.com/tiles/satellite-nl-bes.pmtiles?token=5Rt9…&expires=1715680000","type":["string","null"]},"satelliteNlUrl":{"description":"Signed URL for the high-resolution Netherlands aerial archive\n(raster, z13–18) — layer it above the global satellite source.\nSame session, no extra quota cost. Kept for existing integrations;\n`imagery` lists this archive and every other covered country.","example":"https://cdn.rijwind.com/tiles/satellite-nl.pmtiles?token=4Xp8…&expires=1715680000","type":["string","null"]},"satelliteOceanUrl":{"description":"Signed URL for the water-only overlay (raster, z0–7). Draw it ABOVE the\nsatellite source and fade it out past ~z9: the satellite mosaic covers\nwater poorly, so this renders the sea instead. Same session, no extra\nquota cost.","example":"https://cdn.rijwind.com/tiles/satellite-ocean.pmtiles?token=8Yh3…&expires=1715680000","type":["string","null"]},"satelliteUrl":{"description":"Signed URL for the global satellite imagery archive (raster, z0–13).\nFeed it to a MapLibre `raster` source for the Satellite / Hybrid\nstyles. Present once satellite imagery is available on the account's\nregion; rendering it is part of the same tile session, so it adds no\nquota cost. Refresh together with the tile URLs.","example":"https://cdn.rijwind.com/tiles/satellite.pmtiles?token=7Kd2…&expires=1715680000","type":["string","null"]},"terrainUrl":{"description":"Signed URL for the optional terrain (elevation) archive — feed it to a\nMapLibre `raster-dem` source with `encoding: \"terrarium\"` for hillshade\nor 3D terrain. Shares this session's expiry; refresh both together.\nRendering terrain is part of the same tile session, so it adds no quota\ncost.","example":"https://cdn.rijwind.com/tiles/terrain.pmtiles?token=9bQ1…&expires=1715680000","type":"string"},"traffic":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/TrafficAccess","description":"Present when the request opted into the live traffic layer via\n`?traffic=`. Compose artifact URLs as `{baseUrl}/{path}?{query}` —\nthe signed query validates for every traffic artifact, so the\nrotating live-state filenames need no re-signing. Refresh together\nwith the tile URLs."}]},"url":{"description":"Signed URL ready to feed to MapLibre's `pmtiles://` protocol handler.","example":"https://cdn.rijwind.com/tiles/planet.pmtiles?token=2Tw9…&expires=1715680000","type":"string"}},"required":["url","expiresAt","terrainUrl","imagery","buildings"],"type":"object"},"TrafficAccess":{"description":"Access descriptor for the live traffic layer: a CDN base URL plus a signed query string that validates for every traffic artifact (geometry tiles, live state, incidents) beneath it.","properties":{"baseUrl":{"description":"Traffic CDN origin to prepend to artifact paths.","example":"https://cdn.rijwind.com/traffic","type":"string"},"countries":{"description":"Countries included in this grant (ISO 3166-1 alpha-2).","example":["NL"],"items":{"type":"string"},"type":"array"},"expiresAt":{"description":"Unix timestamp (seconds) when the signature expires.","example":1715680000,"format":"int64","type":"integer"},"query":{"description":"Signed query string — append after `?` on any artifact URL.","example":"token=9bQ1…&expires=1715680000&token_path=%2F","type":"string"}},"required":["baseUrl","query","expiresAt","countries"],"type":"object"},"Trip":{"properties":{"language":{"example":"en-US","type":"string"},"legs":{"items":{"$ref":"#/components/schemas/RouteLeg"},"type":"array"},"status":{"example":0,"format":"int32","type":"integer"},"statusMessage":{"example":"Found route between points","type":"string"},"summary":{"$ref":"#/components/schemas/RouteSummary"},"units":{"example":"kilometers","type":"string"}},"required":["summary","legs","status","statusMessage","units","language"],"type":"object"},"Units":{"enum":["kilometers","miles"],"type":"string"}},"securitySchemes":{"ApiKey":{"bearerFormat":"rw_live_…","description":"Pass your API key as a Bearer token in the `Authorization` header. Keys are scoped to a project; their plain text is shown once at creation in the dashboard. Keys starting with `rw_test_` use the same routes but are intended for staging/CI.","scheme":"bearer","type":"http"}}},"info":{"contact":{"email":"info@rijwind.com","name":"Rijwind support","url":"https://rijwind.com"},"description":"A cloud-native, European, privacy-friendly maps API.\n\nOne key, three surfaces: a vector basemap delivered from a global CDN, forward and reverse geocoding over a worldwide place index, and routing — turn-by-turn directions, travel-time matrices, and reachable-area isochrones — for car, bike, and pedestrian profiles.\n\nEvery endpoint shares the same authentication model (a single Bearer key) and the same per-user monthly quota. Manage keys and quota in the dashboard at https://rijwind.com/dashboard.\n\n**Status:** v1 is live. Versioning is in the URL path, so when v2 lands v1 keeps working until announced end-of-life.","license":{"name":"Terms of service","url":"https://rijwind.com/terms"},"title":"Rijwind API","version":"1.0.0"},"openapi":"3.1.0","paths":{"/directions-matrix/v1":{"post":{"description":"Calculate the travel time and distance between every source and every target — the cost grows with `M × N`, the number of pairs.\n\n**Quota cost:** `M × N` units per call (`M = sources`, `N = targets`). Capped at `M × N ≤ 2500`; requests beyond that return 400 without charging quota.","operationId":"matrix","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatrixRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatrixResponse"}}},"description":"Matrix response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Body malformed, costing unsupported, or `M × N > 2500`."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing, malformed, or revoked API key."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Monthly quota exhausted."}},"security":[{"ApiKey":[]}],"summary":"Travel-time matrix.","tags":["Routing"]}},"/directions/v1":{"post":{"description":"Calculate a route between two or more waypoints.\n\n**Quota cost:** 1 unit per call.","operationId":"route","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}},"description":"Route response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Malformed body or unsupported costing profile."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing, malformed, or revoked API key."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Monthly quota exhausted."}},"security":[{"ApiKey":[]}],"summary":"Turn-by-turn directions.","tags":["Routing"]}},"/elevation/v1":{"post":{"description":"Look up ground elevation for discrete points or along a route. For a route, send the geometry as an `encodedPolyline` and the server resamples it to `samples` evenly-spaced points — ideal for building an elevation profile from a GPS track without sending every point.\n\n**Quota cost:** 1 unit per call. The `points` array is capped at 512; for a longer track use `encodedPolyline` (resampled to at most 1000 points).","operationId":"elevation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ElevationRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ElevationResponse"}}},"description":"Elevations in request order."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Body malformed, neither input provided, or more than 512 points."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing, malformed, or revoked API key."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Monthly quota exhausted."}},"security":[{"ApiKey":[]}],"summary":"Elevation along points or a route.","tags":["Routing"]}},"/isochrone/v1":{"post":{"description":"Compute reachable-area polygons (isochrones) from one or more origins. Each contour is a time or distance band, returned as a GeoJSON Feature.\n\n**Quota cost:** `5 × L × C` units per call (`L = locations`, `C = contours`). Capped at `L × C ≤ 4`; requests beyond that return 400.","operationId":"isochrone","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IsochroneRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IsochroneResponse"}}},"description":"Isochrone response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Body malformed, costing unsupported, or `L × C > 4`."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing, malformed, or revoked API key."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Monthly quota exhausted."}},"security":[{"ApiKey":[]}],"summary":"Reachable-area polygons.","tags":["Routing"]}},"/map-matching/v1":{"post":{"description":"Snap a noisy GPS trace to the road network and return a clean, route-shaped result — the same response envelope as `/directions/v1`. Provide the trace as a `shape` array or an `encodedPolyline`.\n\n**Quota cost:** 1 unit per call. The `shape` array is capped at 100 points; requests beyond that return 400 without charging quota.","operationId":"map_matching","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MapMatchingRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}},"description":"Matched route."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Body malformed, costing unsupported, or trace exceeds 100 points."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing, malformed, or revoked API key."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Monthly quota exhausted."}},"security":[{"ApiKey":[]}],"summary":"Snap a GPS trace to roads.","tags":["Routing"]}},"/optimized-route/v1":{"post":{"description":"Find the optimal visiting order over a set of waypoints (a travelling-salesman solve) and return a route that visits them in that order. The first and last locations stay fixed.\n\n**Quota cost:** `N` units per call, where `N` is the number of locations. Capped at 20 locations; requests beyond that return 400 without charging quota.","operationId":"optimized_route","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OptimizedRouteRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}},"description":"Optimized route."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Body malformed, costing unsupported, fewer than 2 locations, or more than 20."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing, malformed, or revoked API key."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Monthly quota exhausted."}},"security":[{"ApiKey":[]}],"summary":"Optimal waypoint ordering.","tags":["Routing"]}},"/search/geocode/v1/autocomplete":{"get":{"description":"Type-ahead variant of `/search/geocode/v1/forward`, billed at a tenth of the cost — fire it on every keystroke from a search bar.\n\n**Quota cost:** 0.1 unit per call.","operationId":"geocode_autocomplete","parameters":[{"description":"Free-text query, typically a partial input.","example":"amst","in":"query","name":"q","required":true,"schema":{"type":"string"}},{"description":"Result language: `en`, `de`, `fr`, or `default` for local names (also the fallback when a result has no name in the requested language). Omit for local names; any other value is rejected with `400 bad_request`.","example":"en","in":"query","name":"lang","required":false,"schema":{"type":"string"}},{"description":"Maximum number of suggestions.","example":5,"in":"query","name":"limit","required":false,"schema":{"format":"int32","minimum":0,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaceFeatureCollection"}}},"description":"Autocomplete suggestions."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Query parameters failed validation."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing, malformed, or revoked API key."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Monthly quota exhausted."}},"security":[{"ApiKey":[]}],"summary":"Geocode autocomplete (type-ahead).","tags":["Geocoding"]}},"/search/geocode/v1/forward":{"get":{"description":"Turn a place name or address into coordinates. Returns a GeoJSON FeatureCollection ranked by relevance.\n\n**Quota cost:** 1 unit per call.","operationId":"geocode_search","parameters":[{"description":"Free-text query.","example":"Damrak 1, Amsterdam","in":"query","name":"q","required":true,"schema":{"type":"string"}},{"description":"Result language: `en`, `de`, `fr`, or `default` for local names (also the fallback when a result has no name in the requested language). Omit for local names; any other value is rejected with `400 bad_request`.","example":"en","in":"query","name":"lang","required":false,"schema":{"type":"string"}},{"description":"Maximum number of results.","example":5,"in":"query","name":"limit","required":false,"schema":{"format":"int32","minimum":0,"type":"integer"}},{"description":"Bias results toward this latitude.","in":"query","name":"lat","required":false,"schema":{"format":"double","type":"number"}},{"description":"Bias results toward this longitude.","in":"query","name":"lon","required":false,"schema":{"format":"double","type":"number"}},{"description":"Restrict results to a bounding box: `minLon,minLat,maxLon,maxLat`.","in":"query","name":"bbox","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaceFeatureCollection"}}},"description":"Forward-geocode results."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Query parameters failed validation."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing, malformed, or revoked API key."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Monthly quota exhausted (hard-cap plans only)."}},"security":[{"ApiKey":[]}],"summary":"Forward geocode.","tags":["Geocoding"]}},"/search/geocode/v1/reverse":{"get":{"description":"Turn coordinates into the nearest named place.\n\n**Quota cost:** 1 unit per call.","operationId":"geocode_reverse","parameters":[{"description":"Latitude.","example":52.3676,"in":"query","name":"lat","required":true,"schema":{"format":"double","type":"number"}},{"description":"Longitude.","example":4.9041,"in":"query","name":"lon","required":true,"schema":{"format":"double","type":"number"}},{"description":"Result language: `en`, `de`, `fr`, or `default` for local names (also the fallback when a result has no name in the requested language). Omit for local names; any other value is rejected with `400 bad_request`.","example":"en","in":"query","name":"lang","required":false,"schema":{"type":"string"}},{"description":"Search radius in kilometers.","example":1.0,"in":"query","name":"radius","required":false,"schema":{"format":"double","type":"number"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaceFeatureCollection"}}},"description":"Reverse-geocode result."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Query parameters failed validation."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing, malformed, or revoked API key."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Monthly quota exhausted."}},"security":[{"ApiKey":[]}],"summary":"Reverse geocode.","tags":["Geocoding"]}},"/styles/v1/{style}/static/{position}/{size}":{"get":{"description":"Render a static map image — a map drawn server-side and returned as a PNG, WebP, or JPEG you can drop straight into an `<img>` tag. Pass your API key as `?key=…`.\n\nThe viewport is `{lon},{lat},{zoom}` (optionally `,{bearing},{pitch}`), a bounding box `[{minLon},{minLat},{maxLon},{maxLat}]`, or the literal `auto` to frame the overlays. Add markers, paths, and a circle via the query string.\n\n**Quota cost:** 1 unit per image; 2 units for `@2x` (High-DPI).","operationId":"static_map","parameters":[{"description":"Basemap style: `light`, `dark`, `grayscale`, `white`, or `black`.","example":"light","in":"path","name":"style","required":true,"schema":{"type":"string"}},{"description":"`{lon},{lat},{zoom}` (optionally `,{bearing},{pitch}`), a bounding box `[{minLon},{minLat},{maxLon},{maxLat}]`, or `auto`.","example":"4.9041,52.3676,12","in":"path","name":"position","required":true,"schema":{"type":"string"}},{"description":"`{w}x{h}`, optional `@2x` for High-DPI, optional `.png`/`.webp`/`.jpg`. Max 1280 per side.","example":"800x500@2x.png","in":"path","name":"size","required":true,"schema":{"type":"string"}},{"description":"Marker `lon,lat|color|size|label` (color hex no `#`; size `s|m|l`). Repeatable.","in":"query","name":"marker","required":false,"schema":{"type":"string"}},{"description":"Path `stroke:color|width:n|opacity:n|fill:color|fillOpacity:n|<geometry>` (named fields, any order; geometry `enc:<polyline>` or `lon,lat;lon,lat;…`). Repeatable.","in":"query","name":"path","required":false,"schema":{"type":"string"}},{"description":"Circle around the center: `radius:meters|stroke:color|strokeWidth:n|fill:color|fillOpacity:n`.","in":"query","name":"circle","required":false,"schema":{"type":"string"}},{"description":"Inner padding (px) when fitting a bbox or `auto` — 1–4 CSS-order values, e.g. `40` or `40,20,40,20`.","in":"query","name":"padding","required":false,"schema":{"type":"string"}},{"description":"Attribution corner `bottomright|bottomleft|topleft|topright`, or `false` to omit it (you must then credit OpenStreetMap elsewhere).","in":"query","name":"attribution","required":false,"schema":{"type":"string"}},{"description":"Label language. `local` (default) shows native names; otherwise a language code such as `en`, `de`, `fr`, `nl`, `es`. Names without that language fall back to local.","example":"en","in":"query","name":"lang","required":false,"schema":{"type":"string"}},{"description":"Set `false` to hide all basemap labels — place names, road labels, road shields, and POI icons — for a clean, label-free map. Default `true`. Markers you add keep their own labels.","in":"query","name":"labels","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"content":{"image/png":{}},"description":"Rendered map image."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Invalid style, size, or viewport."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing, malformed, or revoked API key."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Monthly quota exhausted."}},"security":[{"ApiKey":[]}],"summary":"Render a static map image.","tags":["Static Maps"]}},"/tiles/v1/terrain/{z}/{x}/{y}":{"get":{"description":"Raw elevation tiles that power the **Outdoor** style's contour lines. The `@rijwind/sdk` `Map` wires these up automatically when you use `MapStyle.OUTDOOR`. Integrating without the SDK? Point a contour generator such as [maplibre-contour](https://github.com/onthegomap/maplibre-contour) at this URL (Terrarium encoding, max zoom 12) and pass your key as `?key=` — contour generators run in a web worker and can't send an `Authorization` header, so the key rides the query string (use an origin-restricted key). Tiles are Terrarium-encoded WebP.\n\n**Quota cost:** free — terrain tiles are part of the map session, billed once when the session opens (see `/tiles/v1/token`).","operationId":"get_terrain_tile","parameters":[{"description":"Zoom level (0–12).","example":12,"in":"path","name":"z","required":true,"schema":{"format":"int32","minimum":0,"type":"integer"}},{"description":"Tile column.","example":2116,"in":"path","name":"x","required":true,"schema":{"format":"int32","minimum":0,"type":"integer"}},{"description":"Tile row (an optional `.webp`/`.png` suffix is accepted).","example":1375,"in":"path","name":"y","required":true,"schema":{"format":"int32","minimum":0,"type":"integer"}}],"responses":{"200":{"content":{"image/webp":{}},"description":"Terrarium-encoded WebP terrain tile."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Zoom out of range or malformed tile coordinate."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing, malformed, or revoked API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Origin not in the project's allow-list."},"404":{"description":"No terrain tile at this coordinate (e.g. open ocean)."}},"security":[{"ApiKey":[]}],"summary":"Terrain DEM tile (for Outdoor-style contour lines).","tags":["Tiles"]}},"/tiles/v1/token":{"get":{"description":"Returns a short-lived, IP-bound signed URL for the vector basemap. Feed it to MapLibre's `pmtiles://` protocol handler. Pass a stable `session` id (one per map instance) so background URL refreshes within the session are billed once — the `@rijwind/sdk` tile-session helper manages this for you.\n\n**Quota cost:** 1 unit per tile session; refreshes within the same session are free. Omit `session` to be billed per request instead. Adding the live traffic layer (`?traffic=`) costs 1 extra unit per session. The response also always carries a `buildings` block — access to the 3D buildings tilesets with each covered country's bounding box — and an `imagery` list of every satellite / aerial archive in the session, both free within the session (the SDK consumes them for 3D buildings and the Satellite / Hybrid styles).","operationId":"sign_tile_url","parameters":[{"description":"Stable, client-minted identifier for the map instance (e.g. a UUID, `[A-Za-z0-9_-]`, ≤128 chars). The first token for a session is billed 1 unit; subsequent tokens for the same session within the session window are free. Omit to be billed per request.","example":"8f14e45f-ceea-467a-9e0b-1c2d3e4f5a6b","in":"query","name":"session","required":false,"schema":{"type":"string"}},{"description":"Opt this session into the live traffic layer: `1`/`true` for every available country, or a comma-separated ISO country list (e.g. `NL`). Adds a `traffic` block to the response and 1 unit to the session; refreshes stay free.","example":"NL","in":"query","name":"traffic","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignedTileUrl"}}},"description":"Signed URL."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Missing, malformed, or revoked API key."},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Origin not in the project's allow-list."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Monthly quota exhausted (hard-cap plans only)."}},"security":[{"ApiKey":[]}],"summary":"Sign a tile-server URL.","tags":["Tiles"]}}},"servers":[{"description":"Production","url":"https://api.rijwind.com"}],"tags":[{"description":"Short-lived signed URLs for the vector basemap, plus terrain tiles for Outdoor-style contour lines.","name":"Tiles"},{"description":"Forward + reverse geocoding over a worldwide place index.","name":"Geocoding"},{"description":"Turn-by-turn directions, travel-time matrices, reachable-area isochrones, GPS map matching, and optimized waypoint ordering.","name":"Routing"},{"description":"Server-rendered map images for `<img>` tags, with markers, paths, and circles.","name":"Static Maps"}]}