Integracja InPost w sklepie internetowym – Paczkomaty i API ShipX
Paczkomaty to w polskim e-commerce standard, a nie wyróżnik – dla wielu klientów brak InPostu w checkoucie to powód, żeby kupić gdzie indziej. Dobra wiadomość: API ShipX jest jednym z lepiej zaprojektowanych API logistycznych na naszym rynku i integrację da się zrobić porządnie, bez wtyczek-kombajnów. Poniżej przechodzimy przez cały przepływ, którego używamy we wdrożeniach – od wyboru punktu po etykietę i statusy.
Jak to działa w całości
Zanim wejdziemy w szczegóły, pełny obraz. Integracja InPost to cztery klocki, które muszą się spiąć:
- Wybór punktu w checkoucie – klient wskazuje Paczkomat na mapie (Geowidget) albo wybiera kuriera.
- Utworzenie przesyłki – sklep wysyła do ShipX dane odbiorcy, wymiary paczki i usługę.
- Etykieta – po opłaceniu oferty ShipX zwraca PDF (albo ZPL pod drukarki termiczne), który drukuje magazyn.
- Statusy – sklep śledzi, co się dzieje z paczką, i aktualizuje zamówienie oraz maile do klienta.
Każdy z tych klocków da się spartaczyć osobno, więc przejdźmy po kolei.
Wybór Paczkomatu: Geowidget, nie własna mapa
Pierwszy odruch bywa taki, żeby pobrać listę punktów z API i wyświetlić je na własnej mapie. To ślepa uliczka – punktów jest kilkadziesiąt tysięcy, zmieniają się codziennie, a InPost i tak udostępnia gotowy, darmowy Geowidget. To web component, który osadza się jednym tagiem:
<inpost-geowidget
token="TWÓJ_TOKEN_GEOWIDGETU"
language="pl"
config="parcelCollect"
onpoint="onPointSelected"
></inpost-geowidget>
Po wybraniu punktu dostajesz zdarzenie z obiektem punktu – najważniejsze
pole to name, czyli identyfikator w stylu KRA012, który za chwilę
przekażemy do ShipX. W sklepach na Medusa.js trzymamy go w metadanych
metody dostawy koszyka, więc backend widzi wybór klienta bez żadnej
dodatkowej magii.
Dwie rzeczy, o których łatwo zapomnieć:
- Token Geowidgetu to inny token niż ShipX – generuje się go osobno w Managerze Paczek i jest jawny (działa w przeglądarce), więc nie ma co go „ukrywać”.
- Walidacja po stronie backendu – identyfikator punktu z frontendu traktujemy jak każde inne dane od użytkownika. Przed utworzeniem przesyłki sprawdzamy, że punkt istnieje i przyjmuje paczki.
Tworzenie przesyłki w ShipX
ShipX ma dwa środowiska: produkcyjne i sandbox. Zaczynamy zawsze od sandboxa – działa bez umowy z InPost i pozwala przećwiczyć wszystko, łącznie z błędami walidacji.
Przesyłkę tworzy się jednym żądaniem POST na endpoint organizacji:
POST /v1/organizations/{organization_id}/shipments
Authorization: Bearer TWÓJ_TOKEN_SHIPX
Content-Type: application/json
{
"receiver": {
"email": "klient@example.com",
"phone": "500600700"
},
"parcels": [{ "template": "small" }],
"service": "inpost_locker_standard",
"custom_attributes": {
"target_point": "KRA012"
},
"reference": "ZAM-2026-01234"
}
Kilka praktycznych uwag, które oszczędzą godzin debugowania:
- Szablony paczek (
small,medium,large) odpowiadają gabarytom A/B/C Paczkomatu. Jeśli sprzedajesz produkty o nietypowych wymiarach, podajeszdimensionsiweightjawnie – ale przy Paczkomatach i tak obowiązują limity gabarytów, więc szablon jest zwykle prostszy. referenceto Twój przyjaciel – wpisujemy tam numer zamówienia ze sklepu. Widać go potem na etykiecie i w Managerze Paczek, co ratuje życie przy reklamacjach.- Telefon odbiorcy musi być polskim numerem komórkowym – na ten numer idzie SMS z kodem odbioru. Walidujcie to w checkoucie, nie dopiero w odpowiedzi błędu z ShipX.
- Dla kuriera zamiast
target_pointpodaje się pełny adres odbiorcy, a usługę zmienia nainpost_courier_standard. Reszta przepływu jest identyczna – to duża zaleta ShipX.
Po utworzeniu przesyłka przechodzi przez cykl ofert: ShipX wycenia usługę, a sklep kupuje wybraną ofertę. Przy prostych konfiguracjach z jedną usługą da się to zautomatyzować do zera – tworzysz przesyłkę, czekasz na status z gotową ofertą i od razu ją kupujesz.
Etykieta: PDF dla biura, ZPL dla magazynu
Po opłaceniu przesyłki (status confirmed) pobiera się etykietę:
GET /v1/shipments/{shipment_id}/label?format=pdf
Format pdf wystarcza, gdy etykiety drukuje się z przeglądarki. Przy
większych wolumenach warto od razu pomyśleć o zpl – drukarki termiczne
(Zebra i klony) przyjmują go bezpośrednio, bez renderowania PDF-a, co
przy kilkuset paczkach dziennie robi realną różnicę.
We wdrożeniach B2B podpinamy pobieranie etykiety pod zmianę statusu zamówienia: magazyn oznacza zamówienie jako spakowane, system tworzy przesyłkę, kupuje ofertę, pobiera etykietę i odsyła ją do wydruku. Nikt niczego nie przeklikuje ręcznie – i o to chodzi.
Statusy: skąd sklep wie, że paczka jedzie
ShipX wystawia słownik statusów (endpoint /v1/statuses) i pozwala
śledzić przesyłkę po numerze trackingowym. W praktyce sprawdzają się dwa
podejścia:
| Podejście | Jak działa | Kiedy wybrać |
|---|---|---|
| Polling | Cykliczne odpytywanie o statusy aktywnych przesyłek | Mniejsze wolumeny, prostota |
| Webhooki | InPost wypycha zmiany statusów na Twój endpoint | Duże wolumeny, aktualizacje niemal na żywo |
Niezależnie od podejścia: mapujcie statusy InPostu na własne, prostsze statusy zamówienia. Klienta nie interesuje różnica między „przyjęta w oddziale” a „w drodze do regionu” – interesuje go „nadana”, „czeka w Paczkomacie” i „odebrana”. Mail z kodem odbioru wysyła InPost, ale dobry sklep i tak pokazuje status w koncie klienta.
Jak to wygląda w Medusa.js
W Medusa v2 logistykę spina się przez moduł fulfillmentu – provider implementuje kilka metod (utworzenie przesyłki, anulowanie, pobranie dokumentów), a resztą steruje rdzeń platformy. Szkielet wygląda tak:
class InpostFulfillmentProvider extends AbstractFulfillmentProviderService {
static identifier = "inpost";
async createFulfillment(data, items, order, fulfillment) {
const shipment = await this.shipx.createShipment({
receiver: mapReceiver(order),
parcels: mapParcels(items),
service: data.service, // locker albo courier
targetPoint: data.target_point,
reference: order.display_id,
});
return { data: { shipment_id: shipment.id } };
}
async getFulfillmentDocuments(data) {
return this.shipx.getLabel(data.shipment_id, "zpl");
}
}
To celowo szkic, nie gotowiec – sedno w tym, że integracja logistyczna
w Medusie jest modułem, nie wtyczką z marketplace’u. Macie pełną
kontrolę nad tym, kiedy przesyłka powstaje, co trafia do reference
i jak wygląda obsługa błędów. Na tej samej zasadzie zbudowaliśmy wysyłkę
w naszym pokazowym sklepie demo.koda.plus –
można tam poklikać pełny checkout z wyborem Paczkomatu.
Najczęstsze wtopy z wdrożeń
- Brak obsługi błędów walidacji – ShipX potrafi odrzucić przesyłkę (np. zły telefon). Sklep musi to pokazać obsłudze, a nie połknąć.
- Etykieta generowana przy złożeniu zamówienia – za wcześnie. Paczka może się nie spakować tego dnia, a niektóre oferty mają termin ważności. Etykieta powinna powstawać, gdy magazyn faktycznie pakuje.
- Jeden token na sandbox i produkcję – to dwa osobne środowiska z osobnymi tokenami. Trzymajcie je w zmiennych środowiskowych i nigdy w repozytorium.
- Punkt wybrany raz na zawsze – Paczkomat bywa przepełniony albo czasowo niedostępny. Warto obsłużyć redirect przesyłki i komunikat dla klienta, zamiast udawać, że problem nie istnieje.
Jeśli zamiast składać to wszystko samodzielnie wolicie mieć logistykę spiętą z resztą sklepu – od checkoutu, przez ERP, po maile – to dokładnie ten zakres robimy przy sklepach i hurtowniach na Medusa.js.