RouteMateRouteMate
Developer Guide

API-documentatie

Alles wat je nodig hebt om je bezorgplatform met RouteMate te integreren.

Overzicht

Aan de slag

Met de RouteMate Integration API kun je leveringsjobs programmatisch importeren, routes automatisch optimaliseren en jobstatus opvragen vanuit je bestaande systemen.

Basis-URL

https://api.routemate.app/v1

Hoe het werkt

  1. Maak een integratie aan — Ga in de RouteMate-webapp naar Integraties en klik op Integratie aanmaken. Je ontvangt een client_id en client_secret.
  2. Haal een toegangstoken op — Wissel je gegevens in voor een tijdelijk bearer token dat 1 uur geldig is.
  3. Importeer een job — Verstuur je bezorgstops via POST. RouteMate geocodeert de adressen, optimaliseert de routevolgorde en wijst de job toe aan een chauffeur.
  4. Controleer de status — Bekijk op elk moment de voortgang van je job om te zien welke stops zijn voltooid.

Vereisten

  • Een RouteMate-account op het Team- of Enterprise-plan
  • Een organisatie die is aangemaakt in de RouteMate-webapp
  • Een actieve integratie met client credentials
Authenticatie

Client credentials flow

De API gebruikt OAuth2 client credentials. Je secret wordt nooit opgeslagen; alleen een SHA-256-hash wordt op onze servers bewaard.

Beveiligingsmodel

  • Client secrets worden met SHA-256 gehasht en nooit in platte tekst opgeslagen
  • Access tokens zijn opaque (geen JWT's) en 1 uur geldig
  • Tokens zijn eenmalig bruikbaar en beperkt tot je integratie
  • Alle requests moeten via HTTPS worden gedaan
  • Stuur het token met elke request mee: Authorization: Bearer <token>

Belangrijk: Je client_secret wordt maar één keer getoond wanneer je de integratie aanmaakt. Bewaar het veilig, bijvoorbeeld in omgevingsvariabelen of een secrets manager. Als je het verliest, moet je het opnieuw genereren vanuit het RouteMate-dashboard.

Endpoint

Toegangstoken ophalen

POST/v1/integration-token
Credentials uitwisselen voor een bearer token
Roep dit endpoint aan om een tijdelijk toegangstoken te ontvangen. Voeg het toe aan de Authorization-header van volgende requests.

Request body

FieldTypeRequiredDescription
client_idstringYesDe client-ID van je integratie (begint met rm_ci_)
client_secretstringYesHet client secret van je integratie (begint met rm_cs_)

Voorbeeldverzoek

curl -X POST https://api.routemate.app/v1/integration-token \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "rm_ci_abc123...",
    "client_secret": "rm_cs_xyz789..."
  }'

Succesrespons 200

{
  "access_token": "rm_at_e5988dd1b91a4ff3827c5d2ed416ccbe37ae227a",
  "token_type": "Bearer",
  "expires_in": 3600
}

Foutresponsen

400client_id of client_secret ontbreekt

401Ongeldige credentials (verkeerd secret of onbekende client_id)

403De integratie is uitgeschakeld

Endpoint

Job en stops importeren

POST/v1/integration-import
Een leveringsjob met stops aanmaken
Importeer een leveringsjob met een of meer stops. RouteMate geocodeert adressen zonder coördinaten, optimaliseert de aflevervolgorde en wijst de route toe aan een chauffeur.

Request headers

FieldTypeRequiredDescription
AuthorizationstringYesBearer <access_token>
Content-TypestringYesapplication/json
Idempotency-KeystringNoUnieke sleutel om dubbele imports te voorkomen (24 uur geldig)

Request body — Jobvelden

FieldTypeRequiredDescription
external_job_idstringYesJe unieke identifier voor deze job (moet uniek zijn per integratie)
titlestringYesTitel van de job (bijvoorbeeld Morning Deliveries - Zone A)
driver_emailstringYesE-mailadres van de chauffeur die je wilt toewijzen. Als de chauffeur een RouteMate-account heeft, ziet die de route in de app. Anders wordt er een uitnodiging aangemaakt.
scheduled_datestringNoGeplande datum in ISO-formaat (YYYY-MM-DD)
timezonestringNoIANA-tijdzone (bijvoorbeeld Australia/Brisbane of America/New_York)
metadataobjectNoAangepaste sleutel-waardedata gekoppeld aan de job
stopsarrayYesArray met stopobjecten (zie Stopvelden hieronder)

Voorbeeldverzoek

curl -X POST https://api.routemate.app/v1/integration-import \
  -H "Authorization: Bearer rm_at_your_token_here" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-batch-2026-03-09-001" \
  -d '{
    "external_job_id": "BATCH-2026-03-09-A",
    "title": "Morning Deliveries - Zone A",
    "driver_email": "driver@example.com",
    "scheduled_date": "2026-03-09",
    "timezone": "Australia/Brisbane",
    "stops": [
      {
        "external_stop_id": "ORD-1001",
        "address": "1 George St, Brisbane QLD 4000, Australia",
        "label": "John Smith",
        "notes": "Leave at front door",
        "priority": 1,
        "parcel_count": 2
      },
      {
        "external_stop_id": "ORD-1002",
        "address": "100 Queen St, Brisbane QLD 4000, Australia",
        "label": "Jane Doe",
        "notes": "Ring doorbell",
        "priority": 2
      },
      {
        "external_stop_id": "ORD-1003",
        "address": "South Bank Parklands, Brisbane QLD 4101, Australia",
        "label": "Bob Wilson",
        "priority": 3,
        "parcel_count": 1
      }
    ]
  }'

Succesrespons 200

{
  "job_id": "e7ad097b-bc51-4d01-9b04-0e372d80613a",
  "external_job_id": "BATCH-2026-03-09-A",
  "route_id": "1c2a8c0b-1b69-4a04-85b1-608b2ebe3878",
  "driver_email": "driver@example.com",
  "driver_resolved": true,
  "driver_user_id": "573b6bee-aa3d-4cb0-af87-620bba0db049",
  "stops_imported": 3,
  "stops_geocoded": 3,
  "stops_geocode_failed": 0,
  "optimization": {
    "total_distance_km": 12.4,
    "total_duration_minutes": 25,
    "encoded_polyline": "fvmfDqmfe\\bPtA..."
  },
  "stops": [
    {
      "external_stop_id": "ORD-1001",
      "address": "1 George St, Brisbane QLD 4000, Australia",
      "latitude": -27.4710,
      "longitude": 153.0234,
      "label": "John Smith",
      "notes": "Leave at front door",
      "sort_order": 0,
      "priority": 1,
      "parcel_count": 2,
      "status": "pending"
    },
    {
      "external_stop_id": "ORD-1003",
      "address": "South Bank Parklands, Brisbane QLD 4101, Australia",
      "latitude": -27.4753,
      "longitude": 153.0208,
      "label": "Bob Wilson",
      "notes": null,
      "sort_order": 1,
      "priority": 3,
      "parcel_count": 1,
      "status": "pending"
    },
    {
      "external_stop_id": "ORD-1002",
      "address": "100 Queen St, Brisbane QLD 4000, Australia",
      "latitude": -27.4688,
      "longitude": 153.0281,
      "label": "Jane Doe",
      "notes": "Ring doorbell",
      "sort_order": 2,
      "priority": 2,
      "parcel_count": 1,
      "status": "pending"
    }
  ],
  "deep_link": "https://app.routemate.app/app/jobs/e7ad097b-...",
  "warnings": [
    { "code": "ADDRESS_GEOCODED", "message": "3 stop(s) were geocoded from address text" },
    { "code": "ROUTE_OPTIMIZED", "message": "Route optimized: 12.4 km, 25 min" }
  ]
}

Opmerking: Opmerking: de stops-array wordt teruggegeven in geoptimaliseerde aflevervolgorde volgens sort_order, niet in de volgorde waarin je deze hebt ingestuurd.

Waarschuwingscodes

FieldTypeRequiredDescription
ROUTE_OPTIMIZEDinfoNoRoute is succesvol geoptimaliseerd met afstand en duur
ADDRESS_GEOCODEDinfoNoEen of meer stops zijn gegeocodeerd op basis van adrestekst
DRIVER_AUTO_ADDEDinfoNoDe chauffeur had al een RouteMate-account en is automatisch aan je organisatie toegevoegd
DRIVER_NOT_FOUNDwarningNoGeen RouteMate-account gevonden voor dit e-mailadres. Er is een uitnodiging aangemaakt.
GEOCODE_FAILEDwarningNoEen stopadres kon niet worden gegeocodeerd. Geef in plaats daarvan latitude/longitude op.
Endpoint

Jobstatus opvragen

GET/v1/integration-jobs
Jobdetails en stopstatussen ophalen
Vraag de huidige status van een job op, inclusief alle stops en hun afleverstatus. Resultaten zijn beperkt tot je integratie.

Queryparameters

FieldTypeRequiredDescription
external_job_idstringNoJe externe job-ID (de waarde die je bij import hebt meegestuurd)
job_idstringNoDe interne RouteMate job-UUID

Ten minste een van external_job_id of job_id moet worden opgegeven.

Voorbeeldverzoek

curl "https://api.routemate.app/v1/integration-jobs?external_job_id=BATCH-2026-03-09-A" \
  -H "Authorization: Bearer rm_at_your_token_here"

Succesrespons 200

{
  "job_id": "e7ad097b-bc51-4d01-9b04-0e372d80613a",
  "external_job_id": "BATCH-2026-03-09-A",
  "title": "Morning Deliveries - Zone A",
  "status": "assigned",
  "driver_email": "driver@example.com",
  "driver_resolved": true,
  "driver_user_id": "573b6bee-...",
  "route_id": "1c2a8c0b-...",
  "scheduled_date": "2026-03-09",
  "timezone": "Australia/Brisbane",
  "metadata": {},
  "stop_count": 3,
  "status_counts": {
    "pending": 2,
    "completed": 1
  },
  "deep_link": "https://app.routemate.app/app/jobs/e7ad097b-...",
  "stops": [
    {
      "external_stop_id": "ORD-1001",
      "address": "1 George St, Brisbane QLD 4000",
      "latitude": -27.4710,
      "longitude": 153.0234,
      "label": "John Smith",
      "notes": "Leave at front door",
      "status": "completed",
      "priority": 1,
      "parcel_count": 2
    },
    ...
  ],
  "created_at": "2026-03-09T08:30:00.000Z",
  "updated_at": "2026-03-09T10:15:00.000Z"
}

Jobstatussen

FieldTypeRequiredDescription
pendingstatusNoJob is aangemaakt, maar de chauffeur is nog niet toegewezen of opgelost
assignedstatusNoDe chauffeur is toegewezen en kan de route in de app zien
in_progressstatusNoDe chauffeur is met de route gestart
completedstatusNoAlle stops zijn afgeleverd
Referentie

Stopvelden

Volledige lijst met beschikbare velden voor elke stop in het importverzoek.

FieldTypeRequiredDescription
external_stop_idstringYesJe unieke identifier voor deze stop (moet uniek zijn binnen de job)
addressstringYesVolledig straatadres. Wordt gegeocodeerd als latitude/longitude niet zijn meegegeven.
latitudenumberNoBreedtegraad in decimale graden. Slaat geocodering over als ook longitude is opgegeven.
longitudenumberNoLengtegraad in decimale graden. Slaat geocodering over als ook latitude is opgegeven.
labelstringNoZichtbaar label (bijvoorbeeld klantnaam of bestelnummer)
notesstringNoBezorginstructies voor de chauffeur
service_typestringNoType service (bijvoorbeeld delivery, pickup of service_call)
duration_minutesnumberNoVerwachte servicetijd op deze stop in minuten
time_window_startstringNoVroegste bezorgtijd (ISO 8601 datetime)
time_window_endstringNoLaatste bezorgtijd (ISO 8601 datetime)
prioritynumberNoPrioriteitsniveau (lager getal = hogere prioriteit). Standaard: 0
parcel_countnumberNoAantal pakketten voor deze stop. Standaard: 1
metadataobjectNoAangepaste sleutel-waardedata gekoppeld aan deze stop

Tip: Tip: latitude en longitude direct meesturen is sneller en betrouwbaarder dan geocodering.

Functie

Routeoptimalisatie

Elke import optimaliseert automatisch de bezorgvolgorde voor minimale rijtijd en afstand.

Hoe optimalisatie werkt

  1. Alle stops zonder coördinaten worden gegeocodeerd op basis van hun adrestekst
  2. De eerste stop wordt behandeld als vertrekpunt en de laatste als bestemming
  3. Alle tussenliggende stops worden geoptimaliseerd voor de kortste rijroute met de Google Routes API
  4. Het veld sort_order van elke stop wordt bijgewerkt om de geoptimaliseerde volgorde weer te geven
  5. De routepolyline, totale afstand en geschatte duur worden berekend

Responsvelden

FieldTypeRequiredDescription
optimization.total_distance_kmnumberNoTotale routeafstand in kilometers
optimization.total_duration_minutesnumberNoGeschatte totale rijtijd in minuten
optimization.encoded_polylinestringNoGoogle Encoded Polyline om de route op een kaart te tonen

Opmerking: Opmerking: optimalisatie vereist minstens 2 stops met geldige coördinaten. Als geocodering voor sommige stops mislukt, wordt de route alleen geoptimaliseerd met de stops die wel succesvol zijn gegeocodeerd.

Betrouwbaarheid

Idempotentie

Herhaal mislukte requests veilig zonder dubbele jobs aan te maken.

Voeg een Idempotency-Key-header met een unieke waarde toe aan importrequests. Als dezelfde sleutel binnen 24 uur opnieuw wordt verzonden, retourneert de API de gecachte response in plaats van een dubbele job te maken.

curl -X POST https://api.routemate.app/v1/integration-import \
  -H "Authorization: Bearer rm_at_your_token" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: batch-2026-03-09-zone-a" \
  -d '{ ... }'

# Safe to retry — same Idempotency-Key returns cached response
curl -X POST https://api.routemate.app/v1/integration-import \
  -H "Authorization: Bearer rm_at_your_token" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: batch-2026-03-09-zone-a" \
  -d '{ ... }'

Best practice: Gebruik altijd een Idempotency-Key in productie. Gebruik een deterministische sleutel zodat netwerkretries geen duplicaten maken.

Referentie

Foutafhandeling

Alle fouten geven een JSON-body terug met een error-veld.

{
  "error": "Rate limit exceeded",
  "retry_after_seconds": 45
}

// of voor validatiefouten:
{
  "error": {
    "code": "VALIDATION_ERROR",
    "messages": [
      "external_job_id is required",
      "stops[0].address is required"
    ]
  }
}
StatusBetekenisActie
200SuccesRequest is succesvol voltooid
400Ongeldige requestControleer de foutmeldingen en corrigeer je request body
401Niet geautoriseerdJe token is ongeldig of verlopen. Vraag een nieuwe aan.
403VerbodenJe integratie is uitgeschakeld. Neem contact op met je beheerder.
404Niet gevondenDe job of endpoint bestaat niet
405Methode niet toegestaanGebruik de juiste HTTP-methode (POST of GET)
429Te veel requestsWacht retry_after_seconds voordat je opnieuw probeert
500ServerfoutProbeer opnieuw met exponential backoff. Neem contact op met support als het probleem aanhoudt.
Limieten

Rate limits

Rate limits worden per integratie toegepast in een rollend venster van 1 minuut.

PlanRequests / minuutMax stops / import
Team60200
EnterpriseCustomCustom

Bij rate limiting retourneert de API HTTP 429 met een retry_after_seconds-veld.

Voorbeelden

Volledige codevoorbeelden

Kopieer-en-plakvoorbeelden voor veelgebruikte talen. Alle voorbeelden tonen de volledige flow: authenticeren, importeren en opvragen.

#!/bin/bash
# RouteMate API Integration Example

API_BASE="https://api.routemate.app/v1"
CLIENT_ID="rm_ci_your_client_id"
CLIENT_SECRET="rm_cs_your_client_secret"

# Step 1: Get access token
TOKEN=$(curl -s -X POST "$API_BASE/integration-token" \
  -H "Content-Type: application/json" \
  -d "{
    \"client_id\": \"$CLIENT_ID\",
    \"client_secret\": \"$CLIENT_SECRET\"
  }" | jq -r '.access_token')

echo "Access Token: $TOKEN"

# Step 2: Import a job with stops
RESULT=$(curl -s -X POST "$API_BASE/integration-import" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: my-batch-001" \
  -d '{
    "external_job_id": "BATCH-001",
    "title": "Morning Deliveries",
    "driver_email": "driver@example.com",
    "scheduled_date": "2026-03-10",
    "timezone": "Australia/Brisbane",
    "stops": [
      {
        "external_stop_id": "STOP-1",
        "address": "1 George St, Brisbane QLD 4000",
        "label": "Customer A",
        "parcel_count": 2
      },
      {
        "external_stop_id": "STOP-2",
        "address": "100 Queen St, Brisbane QLD 4000",
        "label": "Customer B",
        "notes": "Leave at reception"
      }
    ]
  }')

echo "$RESULT" | jq .

# Step 3: Query job status
JOB_ID=$(echo "$RESULT" | jq -r '.job_id')
curl -s "$API_BASE/integration-jobs?job_id=$JOB_ID" \
  -H "Authorization: Bearer $TOKEN" | jq .
Binnenkort

Webhooks

Ontvang realtime meldingen wanneer leveringen zijn voltooid.

Webhook-ondersteuning komt binnenkort. Je kunt dan een URL registreren en POST-meldingen ontvangen voor gebeurtenissen zoals:

  • job.completed — Alle stops binnen een job zijn afgeleverd
  • stop.completed — Een enkele stop is afgeleverd (inclusief bezorgbewijs)
  • stop.failed — Een bezorgpoging is mislukt
  • driver.location — Realtime GPS-updates van chauffeurs

Interesse in early access? Neem contact op.

Klaar om te integreren?

Maak je integratiegegevens aan in het RouteMate-dashboard en begin binnen enkele minuten met het importeren van jobs.