Developer documentation
GrachtAlert API
A REST API for the Amsterdam canals. The public endpoints serve live water level, the full canal map (bridges, segments, closures, moorings) and the same route planner that powers grachtalert.nl. The business endpoints add congestion analytics, waterway notices and fleet data for rederijen with a business account.
Getting started
All endpoints live under a single versioned base URL:
https://api.grachtalert.nl/v1Public endpoints work without any credentials. Try the water level right from your terminal:
curl https://api.grachtalert.nl/v1/public/waterstandAuthentication
API keys, and an optional short-lived token exchange.
Authenticated endpoints expect a bearer credential in the Authorization header. Two credential types are accepted:
- API key — a long-lived key starting with
gk_live_. Created self-service from your GrachtAlert business account (see API key management). The plaintext key is shown exactly once, at creation — store it securely. - Short-lived access token — optionally exchange your API key for a JWT valid for 1 hour via
POST /auth/token, so the long-lived key itself never travels on every request.
curl https://api.grachtalert.nl/v1/vaarweg-meldingen \
-H "Authorization: Bearer gk_live_YOUR_KEY"/auth/tokenNo authExchanges a valid API key for a short-lived bearer token. The token carries the same access as the key and respects key revocation: if API access is withdrawn, outstanding tokens stop working immediately.
Body (JSON)
| Name | Type | Description |
|---|---|---|
apiKeyrequired | string | Your gk_live_… API key. |
Example request
curl -X POST https://api.grachtalert.nl/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"apiKey": "gk_live_YOUR_KEY"}'Example response
{
"data": {
"token": "eyJhbGciOiJIUzI1NiIs...",
"tokenType": "Bearer",
"expiresIn": 3600
}
}API key management
Self-service, scoped to your own account. Authenticate with an existing key, an exchanged token, or a GrachtAlert session.
/api-keysAPI key · BusinessLists your API keys: name, prefix (the first characters, to tell keys apart), creation date, last-used date and revocation date. The full key value is never returned after creation.
/api-keysAPI key · BusinessCreates a new API key. The response is the only time the plaintext key is ever shown — store it immediately.
Body (JSON)
| Name | Type | Description |
|---|---|---|
naamrequired | string | A label for the key, e.g. the integration it will be used in. |
Example response
{
"data": {
"id": "…",
"naam": "Dashboard integration",
"key_prefix": "gk_live_a1b2",
"aangemaakt_op": "2026-08-23T11:00:00Z",
"key": "gk_live_…" // shown only once
}
}/api-keys/{id}API key · BusinessRevokes a key. Revocation is immediate — requests with the key (and tokens exchanged from it) start failing with 401 right away.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | uuid | Key id, from the key list. |
Responses & errors
Authenticated endpoints wrap their payload in a { "data": … } envelope. Public endpoints return their payload directly. Errors always share one shape:
{ "error": "Human-readable message" }| Status | Meaning |
|---|---|
| 200 / 201 | Success. 201 is returned when a resource was created. |
| 400 | Invalid request — a missing or malformed parameter, or a validation error. |
| 401 | Missing, invalid or revoked credential. |
| 403 | Authenticated, but not allowed to access this resource (e.g. not your rederij or boat). |
| 404 | Resource not found. |
| 429 | Rate limit exceeded — retry later. |
| 500 / 502 | Server error, or an upstream data source (e.g. Rijkswaterstaat) failed. |
Rate limits
Requests to public endpoints are limited per endpoint, per minute — per IP for anonymous requests, per account for requests authenticated with an API key or exchanged token.
| Endpoint | Limit |
|---|---|
POST /public/calculate-route | 5 / minute |
GET /public/vaarkaart-data | 10 / minute |
All other /public/* endpoints | 10 / minute |
Exceeding a limit returns 429. Please cache /public/vaarkaart-data responses — the underlying map data changes at most a few times per day.
Public endpoints
No-auth endpoints are open to everyone. The ones marked API key · Business power the GrachtAlert site and app; programmatic access to those requires a business account's API key.
/healthNo authGateway health check. Useful as an uptime probe for your integration.
Example request
curl https://api.grachtalert.nl/v1/healthExample response
{ "data": { "status": "ok", "version": "v1" } }/public/waterstandNo authLatest measured water level of the Amsterdam canals (station Amsterdam Surinamekade), sourced live from Rijkswaterstaat. Values are in centimetres relative to NAP.
Example request
curl https://api.grachtalert.nl/v1/public/waterstandExample response
{
"waarde": -39.0,
"eenheid": "cm",
"tijdstip": "2026-08-23T09:40:00.000+01:00",
"locatieCode": "amsterdam.surinamekade",
"locatieNaam": "Amsterdam Surinamekade"
}/public/vaarkaart-dataAPI key · BusinessThe complete canal map dataset in one call: bridges (with clearance heights), canal segments, intersections, segment connections, moorings/boarding locations, active waterway notices & closures, points of interest, public toilets, authority vessel positions, themed routes and live per-segment congestion status. The response is large (several MB) — fetch it once and cache it.
Example request
curl https://api.grachtalert.nl/v1/public/vaarkaart-data \
-H "Authorization: Bearer gk_live_YOUR_KEY"Example response
{
"bruggen": [ { "id": "…", "naam": "Magere Brug", "doorvaarthoogte_cm": 240, … } ],
"segmenten": [ … ],
"kruispunten": [ … ],
"overgangen": [ … ],
"opstapplaatsen": [ … ],
"vaarwegMeldingen": [ … ],
"pois": [ … ],
"openbareToiletten": [ … ],
"autoriteitBoten": [ … ],
"segmentThemas": [ … ],
"segmentStatusLive": [ … ]
}/public/calculate-routeAPI key · BusinessPlans a route between two points on the canal network, honouring your boat's dimensions, bridge clearances, current closures and (when enabled) live congestion delays. Stops reference canal segments by segId — segment ids come from /public/vaarkaart-data. A second mode, best_order, finds the best visiting order for a set of stops instead of a fixed A→B route.
Body (JSON)
| Name | Type | Description |
|---|---|---|
mode | 'route' | 'best_order' | Defaults to 'route'. In best_order mode, van is the anchor/start, vias are the stops to order, and naar is an optional fixed final destination. |
vanrequired | stop | Start of the route: { "segId": "…" }, optionally with a point on the segment. |
naarrequired | stop | Destination. Required in 'route' mode; optional in 'best_order' mode. |
vias | stop[] | Intermediate stops, in order (route mode) or to be ordered (best_order mode). |
boatTyperequired | string | Your boat type — determines which segments are allowed. |
heeftGrootVaarbewijsrequired | boolean | Whether the skipper holds a groot vaarbewijs. |
boatHeightCmrequired | number | Boat height in cm — routes avoid bridges you cannot pass under. |
speedMultiplierrequired | number | Cruise speed as a multiplier of the segment norm (1 = normal). |
maxSnelheidKmh | number | null | Hard speed cap in km/h; omit or null for no cap. |
mooisteMinuten | number | null | Optional scenic detour budget in minutes (route mode). |
departureAt | string | null | ISO 8601 departure time; null/omitted means now (route mode). |
Example request
curl -X POST https://api.grachtalert.nl/v1/public/calculate-route \
-H "Authorization: Bearer gk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"van": { "segId": "SEGMENT_ID_A" },
"naar": { "segId": "SEGMENT_ID_B" },
"boatType": "sloep",
"heeftGrootVaarbewijs": false,
"boatHeightCm": 180,
"speedMultiplier": 1
}'/public/* routes you may encounter (route-log, melding-notificatie, abonnee-notificatie, text-to-speech, registreer-zakelijk-account, contact) exist for the GrachtAlert website and mobile app themselves and are not intended for third-party integrations.Business endpoints
Require a business account with API access, authenticated with an API key or exchanged token.
Congestion analytics (drukte)
Historical and aggregated canal traffic, derived from AIS data. Available per canal segment and city-wide. Segment ids come from /public/vaarkaart-data. Time-bucketed endpoints accept an optional date window via van / tot.
/drukte/segmenten/{segmentId}/patroonAPI key · BusinessWeekly traffic pattern for one segment: average speed and average number of active boats per weekday/time-slot, plus how many weeks of data back each value.
Path parameters
| Name | Type | Description |
|---|---|---|
segmentIdrequired | uuid | Canal segment id. |
Example request
curl https://api.grachtalert.nl/v1/drukte/segmenten/SEGMENT_ID/patroon \
-H "Authorization: Bearer gk_live_YOUR_KEY"Example response
{
"data": [
{
"weekdag": 5,
"slot": 28,
"gemiddelde_snelheid_kmh": 6.4,
"som_metingen": 412,
"aantal_weken": 8,
"gemiddeld_aantal_actieve_boten": 11.2,
"aantal_weken_actief": 8
}, …
]
}/drukte/segmenten/{segmentId}/dagAPI key · BusinessDaily number of active boats on one segment.
Path parameters
| Name | Type | Description |
|---|---|---|
segmentIdrequired | uuid | Canal segment id. |
Query parameters
| Name | Type | Description |
|---|---|---|
van | date (YYYY-MM-DD) | Start of the window (inclusive). |
tot | date (YYYY-MM-DD) | End of the window (inclusive). |
Example request
curl "https://api.grachtalert.nl/v1/drukte/segmenten/SEGMENT_ID/dag?van=2026-08-01&tot=2026-08-23" \
-H "Authorization: Bearer gk_live_YOUR_KEY"/drukte/segmenten/{segmentId}/20minAPI key · BusinessActive boats on one segment in 20-minute buckets — the finest granularity available.
Path parameters
| Name | Type | Description |
|---|---|---|
segmentIdrequired | uuid | Canal segment id. |
Query parameters
| Name | Type | Description |
|---|---|---|
van | timestamp (ISO 8601) | Start of the window (inclusive). |
tot | timestamp (ISO 8601) | End of the window (inclusive). |
/drukte/stad/patroonAPI key · BusinessCity-wide weekly traffic pattern: average number of active boats per weekday/time-slot across all canals.
/drukte/stad/dagAPI key · BusinessCity-wide daily number of active boats.
/drukte/stad/20minAPI key · BusinessCity-wide active boats in 20-minute buckets.
Query parameters
| Name | Type | Description |
|---|---|---|
van | timestamp (ISO 8601) | Start of the window (inclusive). |
tot | timestamp (ISO 8601) | End of the window (inclusive). |
/drukte/weerAPI key · BusinessDaily weather observations used in the congestion models: max temperature, precipitation, wind and weather code.
Query parameters
| Name | Type | Description |
|---|---|---|
dag | date (YYYY-MM-DD) | Return a single day (object instead of array). |
dagen | comma-separated dates | Return a specific set of days. |
Example response
{
"data": [
{ "dag": "2026-08-22", "temp_max_c": 24.1, "neerslag_mm": 0.2, "windkracht_kmh": 14, "weercode": 2 }, …
]
}/drukte/seizoensfactorAPI key · BusinessSeasonal multiplier per ISO week, used to normalise traffic expectations across the year.
Example response
{
"data": [
{ "iso_week": 34, "multiplier": 1.35, "toelichting": "Hoogseizoen" }, …
]
}Waterway notices
/vaarweg-meldingenAPI key · BusinessAll current waterway notices for the Amsterdam canals — closures, works and restrictions — synced from Rijkswaterstaat Vaarweginformatie, ordered by start date.
Example request
curl https://api.grachtalert.nl/v1/vaarweg-meldingen \
-H "Authorization: Bearer gk_live_YOUR_KEY"Fleet (your own rederij)
Business accounts are linked to one or more rederijen at registration. These endpoints are scoped to that link: you can only read and update your own rederij and its boats. Requests for anything else return 403.
/botenAPI key · BusinessLists your rederij's fleet — every boat of every company (bedrijf) linked to your rederijen, including boat dimensions, MMSI and company name.
Example request
curl https://api.grachtalert.nl/v1/boten \
-H "Authorization: Bearer gk_live_YOUR_KEY"/boten/{id}API key · BusinessUpdates one of your own boats — name, type, MMSI and dimensions.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | uuid | Boat id (must belong to your rederij). |
Body (JSON)
| Name | Type | Description |
|---|---|---|
naam | string | Boat name. |
type | string | Boat type. |
mmsi | string | null | AIS MMSI number. |
lengte_m / breedte_m / diepgang_m / hoogte_cm | number | null | Dimensions in metres (height in cm). |
/rederijen/{id}API key · BusinessYour rederij's profile, including its companies (bedrijven) and a boat count per company.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | uuid | Rederij id (must be your own). |
/rederijen/{id}API key · BusinessUpdates your rederij's name.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | uuid | Rederij id (must be your own). |
Body (JSON)
| Name | Type | Description |
|---|---|---|
naamrequired | string | New name. |
/vloot/boten/{bootId}API key · BusinessFull analytics detail for one of your boats over a date range: daily summaries, trips, stops, pier visits, coverage gaps, current position and home-location history.
Path parameters
| Name | Type | Description |
|---|---|---|
bootIdrequired | uuid | Boat id (must belong to your rederij). |
Query parameters
| Name | Type | Description |
|---|---|---|
datumVan | date (YYYY-MM-DD) | Start of the range. Defaults to today. |
datumTot | date (YYYY-MM-DD) | End of the range. Defaults to today. |
Example request
curl "https://api.grachtalert.nl/v1/vloot/boten/BOOT_ID?datumVan=2026-08-01&datumTot=2026-08-23" \
-H "Authorization: Bearer gk_live_YOUR_KEY"/vloot/boten/{bootId}/trailAPI key · BusinessRecent AIS trail and current position of one of your boats — every position with speed, heading and the speed limit of the segment at that moment, plus the average speed over the window.
Path parameters
| Name | Type | Description |
|---|---|---|
bootIdrequired | uuid | Boat id (must belong to your rederij). |
Query parameters
| Name | Type | Description |
|---|---|---|
venster | '3u' | '24u' | Window size: last 3 hours (default) or last 24 hours. |
Example response
{
"data": {
"trail": [
{ "lat": 52.3702, "lng": 4.8952, "snelheid_kmh": 5.8, "koers_graden": 214,
"ontvangen_op": "2026-08-23T10:42:11Z", "segment_limiet_kmh": 6 }, …
],
"huidige_positie": { "lat": 52.3688, "lng": 4.8931, "snelheid_kmh": 0, "ontvangen_op": "2026-08-23T11:02:41Z" },
"gemiddelde_snelheid_kmh": 5.1
}
}/vloot/boten/{bootId}/rit/{ritId}API key · BusinessMap data for a single trip: the segments sailed, the full position trail during the trip, and the departure location.
Path parameters
| Name | Type | Description |
|---|---|---|
bootIdrequired | uuid | Boat id (must belong to your rederij). |
ritIdrequired | uuid | Trip id, from the boat detail endpoint. |
/vloot/boten/{bootId}/thuislocatieAPI key · BusinessSets or clears the manual home-location override for one of your boats.
Path parameters
| Name | Type | Description |
|---|---|---|
bootIdrequired | uuid | Boat id (must belong to your rederij). |
Body (JSON)
| Name | Type | Description |
|---|---|---|
opstapplaatsIdrequired | number | null | Mooring/boarding-location id, or null to clear the override. |
Questions or missing something?
The API is under active development. If your integration needs an endpoint or field that isn't documented here, reach out via the site — we're happy to think along.