RouteMateRouteMate
Przewodnik dewelopera

Dokumentacja API

Wszystko, czego potrzebujesz, aby zintegrować swoją platformę dostaw z RouteMate.

Przegląd

Pierwsze kroki

API integracyjne RouteMate pozwala programowo importować zlecenia dostaw, automatycznie optymalizować trasy i sprawdzać status zleceń z poziomu istniejących systemów.

Bazowy URL

https://api.routemate.app/v1

Jak to działa

  1. Utwórz integrację — W aplikacji webowej RouteMate przejdź do Integracje i kliknij Utwórz integrację. Otrzymasz client_id i client_secret.
  2. Pobierz token dostępu — Wymień dane uwierzytelniające na tymczasowy bearer token ważny przez 1 godzinę.
  3. Zaimportuj zlecenie — Wyślij przystanki dostawy przez POST. RouteMate geokoduje adresy, optymalizuje kolejność trasy i przypisuje zlecenie kierowcy.
  4. Sprawdź status — W dowolnym momencie zobacz postęp zlecenia i sprawdź, które przystanki są już ukończone.

Wymagania

  • Konto RouteMate w planie Team lub Enterprise
  • Organizacja utworzona w aplikacji webowej RouteMate
  • Aktywna integracja z danymi client credentials
Uwierzytelnianie

Przepływ client credentials

API korzysta z OAuth2 client credentials. Twój secret nigdy nie jest przechowywany w postaci jawnej — na naszych serwerach zapisujemy jedynie hash SHA-256.

Model bezpieczeństwa

  • Client secrets są hashowane algorytmem SHA-256 i nigdy nie są przechowywane jawnym tekstem
  • Tokeny dostępu są niejawne (to nie JWT) i są ważne przez 1 godzinę
  • Tokeny są jednorazowe i ograniczone do Twojej integracji
  • Wszystkie żądania muszą być wykonywane przez HTTPS
  • Dołącz token do każdego żądania: Authorization: Bearer <token>

Ważne: Twój client_secret jest wyświetlany tylko raz przy tworzeniu integracji. Zapisz go bezpiecznie, na przykład w zmiennych środowiskowych lub menedżerze sekretów. Jeśli go utracisz, musisz wygenerować go ponownie w panelu RouteMate.

Endpoint

Pobierz token dostępu

POST/v1/integration-token
Wymień dane dostępu na bearer token
Wywołaj ten endpoint, aby otrzymać tymczasowy token dostępu. Dołączaj go w nagłówku Authorization do kolejnych żądań.

Treść żądania

FieldTypeRequiredDescription
client_idstringYesClient ID Twojej integracji (zaczyna się od rm_ci_)
client_secretstringYesClient secret Twojej integracji (zaczyna się od rm_cs_)

Przykładowe żądanie

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..."
  }'

Poprawna odpowiedź 200

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

Odpowiedzi błędów

400Brakuje client_id lub client_secret

401Nieprawidłowe dane uwierzytelniające (błędny secret lub nieznany client_id)

403Integracja została wyłączona

Endpoint

Importuj zlecenie i przystanki

POST/v1/integration-import
Utwórz zlecenie dostawy z przystankami
Zaimportuj zlecenie dostawy z jednym lub wieloma przystankami. RouteMate geokoduje adresy bez współrzędnych, optymalizuje kolejność dostaw i przypisuje trasę kierowcy.

Nagłówki żądania

FieldTypeRequiredDescription
AuthorizationstringYesBearer <access_token>
Content-TypestringYesapplication/json
Idempotency-KeystringNoUnikalny klucz zapobiegający duplikatom importu (ważny 24 godziny)

Treść żądania — Pola zlecenia

FieldTypeRequiredDescription
external_job_idstringYesTwój unikalny identyfikator tego zlecenia (musi być unikalny w obrębie integracji)
titlestringYesTytuł zlecenia (np. Morning Deliveries - Zone A)
driver_emailstringYesEmail kierowcy do przypisania. Jeśli ma konto RouteMate, zobaczy trasę w aplikacji. W przeciwnym razie zostanie utworzone zaproszenie.
scheduled_datestringNoZaplanowana data w formacie ISO (YYYY-MM-DD)
timezonestringNoStrefa czasowa IANA (np. Australia/Brisbane lub America/New_York)
metadataobjectNoNiestandardowe dane klucz-wartość dołączone do zlecenia
stopsarrayYesTablica obiektów przystanków (zobacz pola przystanku poniżej)

Przykładowe żądanie

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
      }
    ]
  }'

Poprawna odpowiedź 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" }
  ]
}

Uwaga: Uwaga: tablica stops jest zwracana w zoptymalizowanej kolejności dostaw według sort_order, a nie w kolejności wysłania.

Kody ostrzeżeń

FieldTypeRequiredDescription
ROUTE_OPTIMIZEDinfoNoTrasa została pomyślnie zoptymalizowana wraz z dystansem i czasem
ADDRESS_GEOCODEDinfoNoJeden lub więcej przystanków zostało zgeokodowanych na podstawie adresu
DRIVER_AUTO_ADDEDinfoNoKierowca miał konto RouteMate i został automatycznie dodany do Twojej organizacji
DRIVER_NOT_FOUNDwarningNoNie znaleziono konta RouteMate dla tego adresu email. Utworzono zaproszenie.
GEOCODE_FAILEDwarningNoNie udało się zgeokodować adresu przystanku. Zamiast tego podaj latitude/longitude.
Endpoint

Sprawdź status zlecenia

GET/v1/integration-jobs
Pobierz szczegóły zlecenia i statusy przystanków
Sprawdź bieżący status zlecenia wraz ze wszystkimi przystankami i ich stanem dostawy. Wyniki są ograniczone do Twojej integracji.

Parametry zapytania

FieldTypeRequiredDescription
external_job_idstringNoTwój zewnętrzny ID zlecenia (podany podczas importu)
job_idstringNoWewnętrzny UUID zlecenia w RouteMate

Musisz podać co najmniej external_job_id lub job_id.

Przykładowe żądanie

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

Poprawna odpowiedź 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"
}

Statusy zlecenia

FieldTypeRequiredDescription
pendingstatusNoZlecenie zostało utworzone, ale kierowca nie został jeszcze przypisany lub rozpoznany
assignedstatusNoKierowca został przypisany i może zobaczyć trasę w aplikacji
in_progressstatusNoKierowca rozpoczął trasę
completedstatusNoWszystkie przystanki zostały dostarczone
Referencja

Pola przystanku

Pełna lista pól dostępnych dla każdego przystanku w żądaniu importu.

FieldTypeRequiredDescription
external_stop_idstringYesTwój unikalny identyfikator tego przystanku (musi być unikalny w obrębie zlecenia)
addressstringYesPełny adres uliczny. Zostanie zgeokodowany, jeśli latitude/longitude nie zostaną podane.
latitudenumberNoSzerokość geograficzna w stopniach dziesiętnych. Pomija geokodowanie, jeśli podano także longitude.
longitudenumberNoDługość geograficzna w stopniach dziesiętnych. Pomija geokodowanie, jeśli podano także latitude.
labelstringNoEtykieta wyświetlana użytkownikowi (np. nazwa klienta lub numer zamówienia)
notesstringNoInstrukcje dostawy dla kierowcy
service_typestringNoTyp usługi (np. delivery, pickup lub service_call)
duration_minutesnumberNoPrzewidywany czas obsługi na tym przystanku w minutach
time_window_startstringNoNajwcześniejszy czas dostawy (ISO 8601 datetime)
time_window_endstringNoNajpóźniejszy czas dostawy (ISO 8601 datetime)
prioritynumberNoPoziom priorytetu (mniejsza liczba = wyższy priorytet). Domyślnie: 0
parcel_countnumberNoLiczba paczek dla tego przystanku. Domyślnie: 1
metadataobjectNoNiestandardowe dane klucz-wartość dołączone do tego przystanku

Wskazówka: Wskazówka: bezpośrednie przekazywanie latitude i longitude jest szybsze i bardziej niezawodne niż geokodowanie.

Funkcja

Optymalizacja trasy

Każdy import automatycznie optymalizuje kolejność dostaw, aby zminimalizować dystans i czas jazdy.

Jak działa optymalizacja

  1. Wszystkie przystanki bez współrzędnych są geokodowane na podstawie tekstu adresu
  2. Pierwszy przystanek jest traktowany jako punkt początkowy, a ostatni jako punkt docelowy
  3. Wszystkie przystanki pośrednie są optymalizowane pod kątem najkrótszej trasy przejazdu przy użyciu Google Routes API
  4. Pole sort_order dla każdego przystanku jest aktualizowane tak, aby odzwierciedlało zoptymalizowaną kolejność
  5. Obliczane są polilinia trasy, całkowity dystans i szacowany czas

Pola odpowiedzi

FieldTypeRequiredDescription
optimization.total_distance_kmnumberNoŁączny dystans trasy w kilometrach
optimization.total_duration_minutesnumberNoSzacowany łączny czas jazdy w minutach
optimization.encoded_polylinestringNoGoogle Encoded Polyline do wyświetlenia trasy na mapie

Uwaga: Uwaga: optymalizacja wymaga co najmniej 2 przystanków z prawidłowymi współrzędnymi. Jeśli geokodowanie nie powiedzie się dla części przystanków, trasa zostanie zoptymalizowana tylko z użyciem tych, które udało się zgeokodować.

Niezawodność

Idempotencja

Bezpiecznie ponawiaj nieudane żądania bez tworzenia duplikatów zleceń.

Dodaj do żądań importu nagłówek Idempotency-Key z unikalną wartością. Jeśli ten sam klucz zostanie wysłany ponownie w ciągu 24 godzin, API zwróci zapisaną odpowiedź zamiast tworzyć duplikat zlecenia.

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 '{ ... }'

Dobra praktyka: Zawsze używaj Idempotency-Key w produkcji. Użyj deterministycznego klucza, aby ponowienia sieciowe nie tworzyły duplikatów.

Referencja

Obsługa błędów

Wszystkie błędy zwracają odpowiedź JSON z polem error.

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

// lub dla błędów walidacji:
{
  "error": {
    "code": "VALIDATION_ERROR",
    "messages": [
      "external_job_id is required",
      "stops[0].address is required"
    ]
  }
}
StatusZnaczenieDziałanie
200SukcesŻądanie zostało wykonane poprawnie
400Nieprawidłowe żądanieSprawdź komunikaty o błędzie i popraw treść żądania
401Brak autoryzacjiToken jest nieważny lub wygasł. Pobierz nowy.
403ZabronioneIntegracja została wyłączona. Skontaktuj się z administratorem.
404Nie znalezionoZlecenie lub endpoint nie istnieje
405Niedozwolona metodaUżyj właściwej metody HTTP (POST lub GET)
429Za dużo żądańPoczekaj retry_after_seconds przed ponowną próbą
500Błąd serweraSpróbuj ponownie z exponential backoff. Jeśli problem się utrzymuje, skontaktuj się ze wsparciem.
Limity

Limity żądań

Limity są stosowane dla każdej integracji w ruchomym oknie 1 minuty.

PlanŻądania / minutaMaks. przystanków / import
Team60200
EnterpriseCustomCustom

Przy ograniczeniu liczby żądań API zwraca HTTP 429 z polem retry_after_seconds.

Przykłady

Pełne przykłady kodu

Gotowe do wklejenia przykłady dla popularnych języków. Wszystkie pokazują pełny przepływ: uwierzytelnienie, import i zapytanie.

#!/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 .
Wkrótce

Webhooki

Otrzymuj powiadomienia w czasie rzeczywistym, gdy dostawy zostaną zakończone.

Obsługa webhooków pojawi się wkrótce. Będzie można zarejestrować URL i otrzymywać powiadomienia POST dla zdarzeń takich jak:

  • job.completed — Wszystkie przystanki w zleceniu zostały dostarczone
  • stop.completed — Pojedynczy przystanek został ukończony (z potwierdzeniem dostawy)
  • stop.failed — Próba dostawy zakończyła się niepowodzeniem
  • driver.location — Aktualizacje GPS kierowcy w czasie rzeczywistym

Chcesz uzyskać wcześniejszy dostęp? Skontaktuj się z nami.

Gotowy do integracji?

Utwórz dane integracyjne w panelu RouteMate i zacznij importować zlecenia w kilka minut.