Rola & zakres
Firma e-commerce z własnym ERP (NetSuite) wysyłała przez narzędzie SaaS, z wiążącymi się z tym kosztami i ograniczoną kontrolą nad umowami z przewoźnikami. CarrierAPI to self-hostowany zamiennik: jedno API, które tworzy etykiety, porównuje stawki, śledzi przesyłki i przetwarza wsady u wielu przewoźników, z tymi samymi punktami styku co poprzednie narzędzie, dzięki czemu przejście z NetSuite mogło być podmianą drop-in zamiast przebudowy.
- Architektura adapterów per przewoźnik (PostNL, DHL Express i UPS jako zestaw podstawowy; DHL Parcel, FedEx, GLS i sam SendCloud jako adaptery dodatkowe), więc dodanie nowego przewoźnika nie wymaga zmian w reszcie systemu.
- Podmiana drop-in poprzedniego narzędzia SaaS wewnątrz NetSuite: te same nazwy pól niestandardowych, minimalne zmiany w istniejącej integracji SuiteScript.
- Bezpośrednie wpięcie w rekordy Item Fulfillment w NetSuite, plus synchronizacja z Shopify i integracja z Amazonem obok przewoźników.
- Dwa sposoby zarządzania danymi dostępowymi przewoźników: przez interfejs (zapis w bazie, wariant preferowany) albo przez zmienne środowiskowe (ścieżka legacy dla istniejących wdrożeń).
Efekty
- Koszty wysyłki i umowy z przewoźnikami z powrotem we własnych rękach, zamiast zależności od stawek i warunków pośredniej warstwy SaaS.
- Naprawiono rozpoznawanie adresów dla klasy adresów wcześniej błędnie parsowanych (wyciąganie numeru domu brało przez pomyłkę ostatnią liczbę zamiast pierwszej po nazwie ulicy — błędnie np. przy adresach ośrodków wypoczynkowych z numerem domu i numerem domku).
- Uzgadnianie faktur z UPS działało dalej po tym, jak UPS dwukrotnie zmienił format eksportu swoich faktur, bo wykrywanie kolumn oparto na treści zamiast na stałych pozycjach, z kontrolą względem sumy, którą podaje sama faktura.
- Załatano wyciek sesji, przez który usunięci użytkownicy zachowywali dostęp nawet przez 24 godziny, bo sprawdzano tylko podpis i termin ważności tokenu — a nie to, czy konto wciąż istnieje.
Architektura
Każdy przewoźnik to adapter za wspólnym interfejsem (tworzenie i anulowanie przesyłek, pobieranie stawek, śledzenie, dostępne usługi) — podpięcie nowego przewoźnika nie rusza reszty systemu. Backend to FastAPI (Python, async) z PostgreSQL jako główną bazą i workerem tła opartym na Redis (arq) do wsadowego przetwarzania etykiet, żeby tworzenie setek etykiet naraz nie blokowało API. Same etykiety trafiają do MinIO (zgodne z S3), więc magazyn plików nie jest przywiązany do jednego dostawcy chmury. Frontend to dashboard Next.js/React do zarządzania przesyłkami, ustawieniami przewoźników i danymi dostępowymi. Całość działa self-hosted przez Docker Compose za Traefikiem, wdrażana z Coolify.
Wybór modelu
Żadnego AI/LLM — to celowo system deterministyczny: etykiety, stawki i śledzenie muszą być przewidywalne i możliwe do skontrolowania, a nie generowane. Kluczowym wyborem było tu self-hosted kontra SaaS: narzędzie SaaS uruchamia się szybciej, ale platforma self-hostowana daje kontrolę nad umowami z przewoźnikami, brak opłaty za etykietę czy przesyłkę na rzecz warstwy pośredniej i możliwość zbudowania funkcji (jak bezpośrednia integracja z NetSuite) dokładnie na miarę, zamiast czekać na to, co dostawca SaaS obsłuży albo nie.
Koszty & opóźnienia
- Infrastruktura self-hostowana (Docker Compose, PostgreSQL, Redis, MinIO) zamiast stałej opłaty SaaS od przesyłki.
- Wsadowe generowanie etykiet działa asynchronicznie przez kolejkę Redis (arq), więc tworzenie setek etykiet naraz utrzymuje API responsywne zamiast kazać czekać zlecającemu.
- Uzgadnianie faktur sprawdzone na prawdziwych fakturach UPS: m.in. faktura na 1275 pozycji o wartości 4855,72 € i eksport na 2275 pozycji, oba przetworzone poprawnie po poprawce w wykrywaniu kolumn.
Wnioski
Parsowanie adresów holenderskich wykładało się na konkretnej klasie adresów (ośrodki wypoczynkowe z numerem domu i osobnym numerem domku, np. „Hessenweg 83 41”), bo parser brał ostatnią liczbę w linii ulicy za numer domu zamiast pierwszej po nazwie ulicy. Rozwiązane wspólnym parserem, zweryfikowanym na realnym przypadku. Import faktur UPS psuł się dwa razy, bo UPS zmieniał format eksportu faktur (przesuwała się liczba i kolejność kolumn); podejście ze stałymi pozycjami kolumn zastąpiono wykrywaniem opartym na treści, którego wynik krzyżuje się z sumą podaną przez samą fakturę. Ostrzeżenia walidacji adresu początkowo całkowicie blokowały utworzenie przesyłki; wycofano to do blokowania jedynie automatycznego zakupu etykiety, żeby oznaczona przesyłka pozostawała widoczna i możliwa do ponowienia zamiast się zacinać. I podatność sesji: usunięci użytkownicy zachowywali dostęp nawet przez 24 godziny, bo tokeny sprawdzano tylko pod kątem podpisu i wygaśnięcia, a nie istnienia konta — naprawione przez weryfikację przy każdym żądaniu, że konto wciąż istnieje.