Powrót do aktualności

Jak połączyć TSC z ERP, WMS lub portiernią przez OData i API

Pavel NOVOTNÝ
Blog
Jak połączyć TSC z ERP, WMS lub portiernią przez OData i API

Połączenie systemu rezerwacji z ERP, WMS lub aplikacją portierni nie musi zaczynać się od dużego projektu integracyjnego. W praktycznym scenariuszu przy wjeździe wystarczą cztery wywołania API: pobranie tokenu Bearer, wyszukanie rezerwacji po numerze, zapisanie przyjazdu, a później wyjazdu.

Pracownik portierni nie musi znać wewnętrznego identyfikatora rezerwacji w Time Slot Control. Korzysta z wartości, którą kierowca ma już na potwierdzeniu lub w kodzie QR: ReservationNumber. TSC zwraca przez OData właściwy rekord i jego identyfikator Id; ten sam identyfikator Id służy następnie do wykonania akcji zmieniających stan.

OData i API: dwie części jednego interfejsu

Time Slot Control łączy standard OData v4 z klasycznymi endpointami API. Podział zadań jest prosty:

  • endpoint uwierzytelniania wydaje token JWT Bearer,
  • OData umożliwia filtrowanie i pobieranie wyłącznie potrzebnych danych,
  • powiązane akcje OData wykonują konkretny krok procesu, na przykład GateArrival lub GateDeparture.

Tokenu nie pobiera się więc za pomocą „zapytania OData”. Wydaje go endpoint uwierzytelniania tego samego API TSC, a następnie token jest przesyłany w nagłówku każdego żądania OData. Przez OData systemy ERP i WMS mają też dostęp do firm, zamówień oraz pozycji zamówień; IntegrationId pozwala powiązać identyfikatory TSC z kluczami systemu źródłowego.

Pięć kroków integracji portierni z Time Slot Control: numer rezerwacji, token Bearer, zapytanie OData, przyjazd i wyjazd

Praktyczny scenariusz: portiernia rejestruje wjazd i wyjazd

Kierowca podjeżdża do portierni i podaje numer rezerwacji. Pracownik skanuje go lub wprowadza do istniejącej aplikacji. Aplikacja weryfikuje rezerwację w TSC, może porównać numer rejestracyjny, przewoźnika i planowaną godzinę, a po zezwoleniu na wjazd rejestruje obecność przewoźnika na terenie zakładu. Przy wyjeździe używa tego samego identyfikatora Id i oznacza, że przewoźnik opuścił teren.

Poniższe przykłady korzystają ze środowiska sandbox pod adresem https://api.tscsandbox.com. Zastąp symbol zastępczy {tenant} nazwą swojego środowiska. Produkcyjne API ma taką samą strukturę pod adresem https://api.timeslotcontrol.com.

Zanim zaczniesz

Utwórz w TSC dedykowane konto API. Konto wymaga roli dostępu do API oraz tylko tych uprawnień, z których integracja faktycznie korzysta—zwłaszcza odczytu rezerwacji i uruchamiania akcji przyjazdu oraz wyjazdu. Nie zapisuj hasła bezpośrednio w kodzie źródłowym; użyj menedżera sekretów albo bezpiecznej konfiguracji platformy integracyjnej.

1. Pobierz token Bearer

curl -X POST "https://api.tscsandbox.com/v1/{tenant}/Token" \
  -H "accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "Username": "api-gatehouse@example.com",
    "Password": "<secret-from-vault>"
  }'

Odpowiedź zawiera token:

{
  "token": "eyJhbGciOi..."
}

W kolejnych wywołaniach użyj tej wartości jako Authorization: Bearer <token>. Nie trzeba tworzyć osobnego tokenu dla każdego pojazdu. Integracja może bezpiecznie przechowywać go w pamięci i odnowić po wygaśnięciu albo po odpowiedzi 401 Unauthorized.

2. Pobierz rezerwację po ReservationNumber

Filtr OData wyszukuje rezerwację po numerze. Za pomocą $select aplikacja portierni pobiera tylko potrzebne pola:

curl --get "https://api.tscsandbox.com/odata/v1/{tenant}/Reservation" \
  -H "Authorization: Bearer ${TOKEN}" \
  --data-urlencode "\$filter=ReservationNumber eq 'R-2026-00421'" \
  --data-urlencode "\$select=Id,ReservationNumber,VehicleNumberPlate,Carrier,Start,End,RealGateVehicleArrival,RealGateVehicleDeparture" \
  --data-urlencode "\$top=2"

Typowa odpowiedź zawiera kopertę OData i tablicę value:

{
  "@odata.context": "https://api.tscsandbox.com/odata/v1/{tenant}/$metadata#Reservation(...)" ,
  "value": [
    {
      "Id": "37efcb13-f1cb-4a61-baea-adfb4337036f",
      "ReservationNumber": "R-2026-00421",
      "VehicleNumberPlate": "1AB2345",
      "Carrier": "Example Carrier",
      "Start": "2026-09-01T12:30:00Z",
      "End": "2026-09-01T13:30:00Z",
      "RealGateVehicleArrival": null,
      "RealGateVehicleDeparture": null
    }
  ]
}

W środowisku produkcyjnym kontynuuj tylko wtedy, gdy zapytanie zwróci dokładnie jeden rekord zgodny z regułami operacyjnymi. Brak wyniku wymaga ręcznej weryfikacji. Jeżeli zapytanie zwróci kilka rekordów, integracja nie może automatycznie wybierać pierwszego z nich. Użycie $top=2 pozwala wykryć taki przypadek niewielkim kosztem.

3. Oznacz przewoźnika jako obecnego na terenie zakładu

Po zweryfikowaniu rezerwacji użyj zwróconego identyfikatora Id w powiązanej akcji GateArrival:

curl -X PUT \
  "https://api.tscsandbox.com/odata/v1/{tenant}/Reservation(37efcb13-f1cb-4a61-baea-adfb4337036f)/GateArrival" \
  -H "Authorization: Bearer ${TOKEN}"

Pomyślne wywołanie zwraca 204 No Content. TSC zapisuje rzeczywisty czas przyjazdu, a zmiana jest od razu widoczna w rezerwacji. Kolejne przepływy pracy, powiadomienia i integracje mogą działać zgodnie ze standardową konfiguracją środowiska klienta.

4. Przy wyjeździe oznacz przewoźnika jako nieobecnego

Przy wyjeździe aplikacja używa tego samego identyfikatora Id. Wartość null informuje TSC, że należy użyć bieżącego czasu serwera:

curl -X PUT \
  "https://api.tscsandbox.com/odata/v1/{tenant}/Reservation(37efcb13-f1cb-4a61-baea-adfb4337036f)/GateDeparture" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{ "GateDepartureDateTime": null }'

Jeżeli urządzenie integracyjne dysponuje własnym wiarygodnym czasem zdarzenia, zamiast null może przesłać wartość UTC w formacie ISO 8601, na przykład 2026-09-01T14:32:00Z. Pomyślne wywołanie ponownie zwraca 204 No Content.

Kompletny minimalny przykład w PowerShellu

Ten sam proces można zapisać w krótkim skrypcie. Wywołania przyjazdu i wyjazdu są w praktyce uruchamiane w różnych chwilach, ale korzystają z tego samego identyfikatora rezerwacji Id:

$baseUri = 'https://api.tscsandbox.com'
$tenant = '<tenant>'
$reservationNumber = 'R-2026-00421'

$tokenResponse = Invoke-RestMethod `
  -Method Post `
  -Uri "$baseUri/v1/$tenant/Token" `
  -ContentType 'application/json' `
  -Body (@{
    Username = 'api-gatehouse@example.com'
    Password = '<secret-from-vault>'
  } | ConvertTo-Json)

$headers = @{
  Authorization = "Bearer $($tokenResponse.token)"
}

$safeNumber = $reservationNumber.Replace("'", "''")
$filter = [Uri]::EscapeDataString("ReservationNumber eq '$safeNumber'")
$select = 'Id,ReservationNumber,VehicleNumberPlate,Carrier,RealGateVehicleArrival,RealGateVehicleDeparture'
$queryUri = "$baseUri/odata/v1/$tenant/Reservation?`$filter=$filter&`$select=$select&`$top=2"
$result = Invoke-RestMethod -Method Get -Uri $queryUri -Headers $headers
$reservations = @($result.value)

if ($reservations.Count -ne 1) {
  throw "Expected exactly one reservation, returned: $($reservations.Count)."
}

$reservationId = $reservations[0].Id

# When entry is permitted
Invoke-RestMethod `
  -Method Put `
  -Uri "$baseUri/odata/v1/$tenant/Reservation($reservationId)/GateArrival" `
  -Headers $headers

# Later, at the exit
Invoke-RestMethod `
  -Method Put `
  -Uri "$baseUri/odata/v1/$tenant/Reservation($reservationId)/GateDeparture" `
  -Headers $headers `
  -ContentType 'application/json' `
  -Body (@{ GateDepartureDateTime = $null } | ConvertTo-Json)

Przykład celowo nie zawiera prawdziwego hasła, konkretnego tenanta ani danych klienta. Aplikacja produkcyjna powinna również zapewnić bezpieczne przechowywanie sekretów, limity czasu, kontrolowane ponawianie żądań, logowanie identyfikatora korelacji oraz obsługę 401, 403, 404, 429 i innych odpowiedzi błędów.

Dlaczego ten wzorzec sprawdza się także w ERP i WMS

Portiernia jest czytelnym przykładem, ponieważ rezultat widać natychmiast. Ta sama zasada działa również wewnątrz ERP lub WMS:

  • ERP może synchronizować firmy, zamówienia i pozycje zamówień przez OData,
  • WMS może pobrać bieżącą rezerwację i przygotować rampę lub operację magazynową,
  • portiernia może rejestrować przyjazd i wyjazd bez przełączania się do innej aplikacji,
  • narzędzia BI mogą odczytywać planowane i rzeczywiste czasy, aby analizować oczekiwanie i przepustowość zakładu,
  • webhooki wychodzące mogą informować systemy podrzędne o zmianach bez regularnego odpytywania.

Integracja nie musi więc kopiować całego modelu danych. Każdy system pobiera wyłącznie informacje potrzebne w jego kroku procesu, a TSC pozostaje wiarygodnym źródłem danych o rezerwacji i jej logistycznych kamieniach milowych.

Od prototypu do bezpiecznej eksploatacji

Pierwszą wersję sprawdź w środowisku sandbox. Interaktywna dokumentacja API pod adresem api.tscsandbox.com pozwala przeglądać endpointy, podać token Bearer i od razu uzyskać przykłady wywołań. Dokładny sposób logowania opisuje dokumentacja uwierzytelniania, a możliwości filtrowania—przewodnik OData.

W środowisku produkcyjnym stosuj kilka zasad: jedno dedykowane konto dla każdej integracji, minimalne wymagane uprawnienia, hasło w bezpiecznym magazynie, ponowne użycie ważnego tokenu, wymóg dokładnie jednego wyniku oraz jednoznaczna obsługa błędów. Wywołania przyjazdu i wyjazdu projektuj tak, aby można je było bezpiecznie powtórzyć—po sukcesie integracja zapisuje identyfikator Id, a przy niepewnym wyniku najpierw ponownie pobiera aktualny stan rezerwacji.

Jeden numer rezerwacji, jeden aktualny stan w całym procesie

Największą korzyścią nie są same cztery żądania HTTP. Najważniejsze jest to, że portiernia, magazyn, dyspozytornia i ERP pracują z tą samą rezerwacją oraz tymi samymi znacznikami czasu. Znika ręczne przepisywanie danych, weryfikacja telefoniczna i opóźniona aktualizacja statusów.

Więcej możliwości znajdziesz na stronie API & Integracje Time Slot Control. Aby sprawdzić podobny scenariusz dla ERP, WMS, skanera lub portierni, zacznij od jednego konkretnego procesu w środowisku sandbox. Pierwsze działające połączenie często wymaga zaledwie kilku precyzyjnie zdefiniowanych wywołań API.