Dokumentacja API i webhooków
Programuj integracje z NavyFlame: odczytuj i zapisuj zamówienia, magazyn, faktury i przesyłki przez REST API, i odbieraj podpisane webhooki o zdarzeniach w czasie zbliżonym do rzeczywistego.
Wprowadzenie
Publiczne API NavyFlame to interfejs typu server-to-server. Każde wywołanie autoryzujesz kluczem API, a odpowiedzi mają stabilny, wersjonowany kształt. Bazowy adres jest w Twojej domenie tenanta:
https://{twoj-slug}.navyflame.com/api/public/v1Pełną, maszynową specyfikację (OpenAPI 3.1) pobierzesz pod adresem /openapi-public-v1.yaml i zaimportujesz do Postmana, Insomnii lub dowolnego klienta OpenAPI.
Szybki start
Zacznij od utworzenia klucza w panelu (Konto - API) i sprawdzenia połączenia zapytaniem GET /me - nie wymaga żadnego zakresu, wystarczy ważny klucz. Zwraca Twój plan, limity i zakresy klucza.
curl https://{twoj-slug}.navyflame.com/api/public/v1/me \
-H "Authorization: Bearer nf_live_twoj_klucz"Przykładowa odpowiedź:
{
"tenant": "twoj-slug",
"keyPrefix": "nf_live_abc123",
"scopes": ["orders:read", "orders:write"],
"plan": "Professional",
"rateLimitPerMin": 3000,
"apiVersion": "v1"
}Uwierzytelnianie
Klucz przekazujesz w nagłówku Authorization jako token Bearer (rekomendowane). Dla narzędzi bez wsparcia Bearer działa alias X-API-Key:
Authorization: Bearer nf_live_twoj_klucz
# lub
X-API-Key: nf_live_twoj_kluczKlucze tworzysz, rotujesz i odwołujesz w panelu. Przechowujemy tylko skrót klucza (SHA-256) - pełną wartość zobaczysz raz przy utworzeniu. Klucz jest redagowany we wszystkich logach. Traktuj go jak hasło i nigdy nie umieszczaj po stronie przeglądarki.
Zakresy (scopes)
Każdy klucz ma przypisane zakresy. Zakres :write obejmuje odpowiadający mu :read. Brak wymaganego zakresu zwraca 403 missing_scope.
| Zakres | Uprawnia do |
|---|---|
| orders:read | Odczyt zamówień (lista, szczegóły, statystyki, historia statusów). |
| orders:write | Zmiana statusu, tworzenie zamówień, wyzwalanie fakturowania. |
| catalog:read | Odczyt katalogu: produkty, magazyny, lokalizacje, rezerwacje, dokumenty magazynowe, zestawy. |
| catalog:write | Pełny zapis katalogu: produkty (CRUD), stany i lokalizacje, magazyny, rezerwacje, dokumenty magazynowe, zestawy. |
| invoices:read | Odczyt faktur i statystyk faktur. |
| shipments:read | Odczyt przesyłek i statystyk wysyłek, plus odczyty pomocnicze kuriera (etykieta PDF, punkty odbioru, usługi, terminy nadania). |
| shipments:write | Lifecycle przesyłek: tworzenie, zakup etykiety kurierskiej (płatny u przewoźnika), anulowanie, odświeżanie trackingu, wysyłka numeru śledzenia do Allegro. |
| shipping:read | Odczyt konfiguracji wysyłki: reguły, strefy ze stawkami, opcje dostawy, nadpisania per produkt, plus kalkulator kosztów. |
| shipping:write | Zapis konfiguracji wysyłki: reguły, strefy i stawki per strefa, opcje dostawy, nadpisania wysyłki per produkt. |
| integrations:read | Odczyt listy konektorów konta (bez sekretów): klucz, id konfiguracji, nazwa, status włączenia i połączenia. Nigdy nie zwraca danych logowania. |
| offers:read | Odczyt ofert marketplace: mapowania produkt-kanał per produkt, mapowania kategorii oraz żywe odczyty z konektora (produkty, kategorie, parametry, podmioty GPSR). Żywe odczyty są płatne (liczą się do limitu API konektora), ale tylko do odczytu. |
| offers:write | Zapis ofert marketplace: mapowania kategorii (tworzenie, zbiorcze, przekierowanie, usuwanie, synchronizacja cache) oraz publikacja, synchronizacja, pull, odświeżanie statusu i import realnych ofert. Publikacja i sync są płatne (realne wywołanie do marketplace). |
| reports:read | Raporty sprzedaży, produktów i operacji + eksport CSV/XLSX. Dane wrażliwe biznesowo. |
| analytics:read | Analityka AI: prognozy zapasów, sugestie cen, anomalie, prognoza sprzedaży, wnioski. |
| monitoring:read | Monitoring integracji (webhooki, faktury, kolejka błędów) i zużycie konta. Detale zawierają dane osobowe. |
| monitoring:write | Ponowne przetwarzanie wpisu z kolejki błędów - odpala oryginalny proces (dla faktur wystawia realną fakturę; płatne). |
| customers:read | Klienci (agregacja z zamówień), statystyki, historia i eksport CSV. Pełne dane osobowe. |
| email:read | Szablony i logi e-mail. Logi zawierają adresy odbiorców i tematy. |
| email:write | Zapis szablonów e-mail (limit planu) oraz wysyłka wiadomości (płatna u dostawcy; dedykowany limit ~10/godz). |
| notifications:read | Powiadomienia w aplikacji i preferencje. |
| notifications:write | Tworzenie powiadomień w aplikacji (odbiorca musi być członkiem konta) i oznaczanie jako przeczytane. |
| alerts:read | Reguły alertów i historia wyzwoleń. |
| alerts:write | Zapis reguł alertów (kanał e-mail pośrednio generuje wysyłki). |
| postsale:read | Obsługa posprzedażowa: wiadomości, spory, zwroty, roszczenia (tylko odczyt). Dane osobowe kupujących. |
| postsale:write | Zapis posprzedaży bez ruchu środków: odpowiedzi w wątkach i sporach, decyzja w sporze, akceptacja/odrzucenie zwrotu (capability-gated per konektor). |
| postsale:refunds:write | Odrębny zakres pieniężny: realny zwrot środków kupującemu i zwrot prowizji. Wydzielony, aby wyciekły klucz bez niego nie ruszył pieniędzy. |
| templates:read | Odczyt szablonów opisów i szablonów produktów (z wariantami). |
| templates:write | Zapis szablonów opisów i produktów; zastosowanie szablonu tworzy produkt (wymaga też catalog:write). |
| ai:read | Odczyt ustawień AI i historii generowania treści. |
| ai:write | Generowanie i tłumaczenie treści przez AI (płatne u Twojego dostawcy). Zapis do produktu wymaga też catalog:write. |
Limity per plan
Limity są agregowane per konto (nie per klucz). Nagłówki X-RateLimit-Limit, X-RateLimit-Remaining i X-RateLimit-Reset na każdej odpowiedzi informują o stanie okna. Po przekroczeniu limitu otrzymasz 429 z nagłówkiem Retry-After.
| Plan | Klucze API | Zapytania | Webhooki |
|---|---|---|---|
| Basic | 5 | 1000 / min | 15 |
| Professional | 30 | 3000 / min | 50 |
| Enterprise | Bez limitu | Bez limitu | Bez limitu |
Zasoby i operacje
Odczyt (paginacja kursorowa, filtry, sortowanie):
GET /orders GET /orders/{id} GET /orders/stats
GET /orders/{id}/status-history
GET /warehouse-items GET /warehouse-items/{id}
GET /invoices GET /invoices/{id} GET /invoices/stats
GET /shipments GET /shipments/{id} GET /shipments/statsZapis:
PUT /orders/{id}/status # zmiana statusu (macierz przejść)
POST /orders # utworzenie zamówienia (source: api)
POST /orders/{id}/invoice # wyzwolenie fakturowania
PATCH /warehouse-items/{id}/stock # korekta stanu (set / adjust)Przykład - lista ostatnich zamówień:
curl "https://{twoj-slug}.navyflame.com/api/public/v1/orders?limit=25" \
-H "Authorization: Bearer nf_live_twoj_klucz"Przykład - korekta stanu magazynowego o -3 sztuki (atomowo):
curl -X PATCH \
"https://{twoj-slug}.navyflame.com/api/public/v1/warehouse-items/{id}/stock" \
-H "Authorization: Bearer nf_live_twoj_klucz" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f9a...-unikat" \
-d '{"operation":"adjust","quantity":-3}'Analityka, raporty i monitoring
Read-only zasoby analityczne (zakresy reports:read, analytics:read, monitoring:read). Kwoty w raportach i analityce to liczby (agregaty), w odróżnieniu od zasobów transakcyjnych, gdzie kwoty są tekstem z dwoma miejscami po przecinku.
GET /reports/sales GET /reports/sales/channels
GET /reports/sales/countries GET /reports/products/bestsellers
GET /reports/products/high-returns GET /reports/products/low-rotation
GET /reports/operations/sla GET /reports/operations/fulfillment
GET /reports/export/csv GET /reports/export/xlsx # pliki binarne
GET /ai-ops/status GET /ai-ops/stock-predictions
GET /ai-ops/price-optimizations GET /ai-ops/anomalies
GET /ai-ops/sales-forecast GET /ai-ops/insights # billable (LLM)
GET /monitoring/webhooks GET /monitoring/webhooks/{id}
GET /monitoring/invoice-links GET /monitoring/dlq
GET /monitoring/dlq/{id} GET /monitoring/stats
GET /usage # liczniki, zużycie miejsca, limity planuEksporty /reports/export/csv i /xlsx to wyjątek binarny od formatu JSON - zwracają plik z nagłówkiem Content-Disposition: attachment (CSV w UTF-8 z BOM, separator średnik). Błędy nadal zwracamy jako application/problem+json.
Detale /monitoring/webhooks/{id} i /monitoring/dlq/{id} zawierają surowy payload konektora (dane osobowe kupującego) - zakres monitoring:read jest oznaczony jako wrażliwy. Listy tych zasobów payloadu nie zwracają.
Przykład - podsumowanie sprzedaży z ostatnich 30 dni:
curl "https://{twoj-slug}.navyflame.com/api/public/v1/reports/sales?periodDays=30" \
-H "Authorization: Bearer nf_live_twoj_klucz"Klienci, e-maile, powiadomienia i obsługa posprzedażowa
Zasoby zawierające dane osobowe (zakresy customers:read, email:read, notifications:read, alerts:read, postsale:read). Tylko odczyt.
GET /customers GET /customers/{email}
GET /customers/stats GET /customers/{email}/orders
GET /customers/growth GET /customers/export # CSV
GET /email-templates(/{id}) GET /email-logs
GET /notifications(/{id}) GET /notifications/unread-count
GET /notification-preferences # wymaga ?userId=
GET /alert-rules(/{id}) GET /alert-rules/history
GET /post-sale/capabilities GET /post-sale/inbox
GET /post-sale/conversations(/{id})(/messages)
GET /post-sale/disputes(/{id})(/messages)
GET /post-sale/returns(/{id}) GET /post-sale/refundsKlient to byt wirtualny (agregacja z zamówień), adresowany adresem e-mail. Powiadomienia są tenant-wide (klucz API nie reprezentuje jednego użytkownika); opcjonalny ?userId= zawęża do odbiorcy, a preferencje go wymagają. Obsługa posprzedażowa czyta wyłącznie dane zapisane w systemie (bez wywołań do marketplace na Twój koszt); dostępność sprawdzisz w /post-sale/capabilities.
Zakresy customers:read, email:read i postsale:read udostępniają dane osobowe - nadawaj je tylko zaufanym integracjom i przetwarzaj zgodnie z RODO.
Katalog, szablony i AI
Pełny zapis katalogu (zakresy catalog:read / catalog:write). Operacje tworzące i nieodwracalne wymagają nagłówka Idempotency-Key - ponowienie z tym samym kluczem odtwarza zapisany wynik zamiast wykonać operację raz jeszcze.
# Produkty
POST/PUT/DELETE /warehouse-items(/{id}) POST /warehouse-items/{id}/backorder
GET /warehouse-items/by-barcode GET /warehouse-items/{id}/stock-history
# Magazyny i lokalizacje
GET/POST/PUT/DELETE /warehouses(/{id})
GET /warehouse-items/{id}/locations PUT /warehouse-items/{id}/locations/{warehouseId}
GET/PUT /warehouse-settings
# Rezerwacje i dokumenty magazynowe
GET/POST /reservations DELETE /reservations/{id}
GET/POST /stock-documents(/{id}) POST /stock-documents/{id}/lines
POST /stock-documents/{id}/commit POST /stock-documents/{id}/cancel
# Zestawy (bundle)
GET /bundles(/{id}) PUT /bundles/{id} DELETE /bundles/{id}Szablony opisów i produktów (zakresy templates:read / templates:write). Zastosowanie szablonu tworzy produkt, więc POST /product-templates/{id}/apply wymaga dodatkowo catalog:write.
GET/POST/PUT/DELETE /description-templates(/{id})
GET/POST/PUT/DELETE /product-templates(/{id})
PUT /product-templates/{id}/variants # zastąp komplet wariantów
POST /product-templates/{id}/variants # dodaj wariant
PATCH/DELETE /product-templates/{id}/variants/{variantId}
POST /product-templates/{id}/apply # + catalog:writeTreści AI (zakresy ai:read / ai:write). Generowanie i tłumaczenie to operacje płatne u Twojego dostawcy AI (klucz konfigurujesz w integracjach), dlatego Idempotency-Key jest wymagany - ponowienie odtwarza wynik, nie nalicza go ponownie. Zapis wyniku do produktu (applyToProduct / createNewProducts) wymaga dodatkowo catalog:write. Operacje wsadowe zwracają skrócony podgląd na pozycję - pełny tekst pobierzesz z /ai/generation-logs lub z produktu.
GET/PUT /ai/settings GET /ai/generation-logs
POST /ai/generate-description POST /ai/translate
POST /ai/batch-generate POST /ai/batch-translate # max 50 pozycji
POST /ai/preview-template # bez AI; templates:read + catalog:readPrzykład - utworzenie szablonu opisu (idempotentnie):
curl -X POST \
"https://{twoj-slug}.navyflame.com/api/public/v1/description-templates" \
-H "Authorization: Bearer nf_live_twoj_klucz" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1e-tpl-001" \
-d '{"name":"Opis premium","templateBody":"{{productName}} - {{price}} {{currency}}"}'Konfiguracja wysyłki
Konfiguracja wysyłki (zakresy shipping:read / shipping:write): reguły wysyłki, strefy ze stawkami, opcje dostawy i nadpisania per produkt, plus kalkulator kosztów. Operacje tworzące wymagają nagłówka Idempotency-Key. Kwoty i wagę w zapisie przekazujesz jako liczby (nie tekst). To konfiguracja, a nie obsługa kuriera - nadawanie przesyłek i etykiety pojawią się w osobnej fazie.
# Reguły wysyłki
GET/POST/PUT/DELETE /shipping-rules(/{id})
# Strefy i stawki (stawka należy do strefy właściciela)
GET/POST/PUT/DELETE /shipping-zones(/{id})
POST /shipping-zones/{id}/rates PUT/DELETE /shipping-zones/{id}/rates/{rateId}
# Opcje dostawy
GET/POST/PUT/DELETE /delivery-options(/{id})
# Nadpisania wysyłki per produkt
GET/POST /products/{productId}/shipping-overrides
PUT/DELETE /product-shipping-overrides/{id}
# Kalkulator kosztów (POST, ale wymaga tylko shipping:read)
POST /shipping/calculateNazwy nie są unikalne, więc nie ma konfliktu duplikatu (409). deliveryOptionId w stawce i nadpisaniu musi wskazywać Twoją opcję dostawy (inaczej 422), a stawka spoza Twojej strefy zwraca 404. Kalkulator zwraca listę opcji posortowaną rosnąco po koszcie.
Przykład - wyliczenie kosztów wysyłki do Polski:
curl -X POST \
"https://{twoj-slug}.navyflame.com/api/public/v1/shipping/calculate" \
-H "Authorization: Bearer nf_live_twoj_klucz" \
-H "Content-Type: application/json" \
-d '{"countryCode":"PL","orderValue":199.99,"totalWeightKg":1.5,"itemCount":2}'Przesyłki, etykiety i kurier
Lifecycle przesyłek (zakres shipments:write) oraz odczyty pomocnicze kuriera (zakres shipments:read): tworzysz przesyłkę, zamawiasz etykietę u przewoźnika, anulujesz, odświeżasz tracking i przekazujesz numer śledzenia do Allegro. Wagę, wymiary i kwoty przekazujesz jako liczby.
# Tworzenie przesyłki (status Draft; nie generuje kosztu)
POST /shipments # pojedynczo
POST /shipments/bulk # zbiorczo, max 100 (partial success)
# Etykieta u przewoźnika
POST /shipments/{id}/label # BILLABLE - zakup etykiety (Idempotency-Key wymagany)
GET /shipments/{id}/label # pobranie etykiety (PDF, binarny)
# Pozostały lifecycle
DELETE /shipments/{id} # anulowanie (u kuriera, jeśli wysłana)
POST /shipments/{id}/refresh-tracking
POST /shipments/{id}/push-tracking
# Odczyty pomocnicze (shipments:read)
GET /shipments/points # punkty odbioru (InPost)
GET /couriers/{provider}/services # usługi kuriera (Apaczka)
GET /shipments/allegro/delivery-services # usługi Allegro Delivery
POST /shipments/available-dates # terminy nadania (DHL; POST, ale shipments:read)Zamówienie etykiety jest płatne - kupuje realną przesyłkę u przewoźnika. Dlatego POST /shipments/{id}/label wymaga nagłówka Idempotency-Key: ponowienie z tym samym kluczem odtwarza zapisany wynik i nigdy nie kupuje etykiety drugi raz (zabezpieczenie działa po stronie serwera). Etykietę zamówisz tylko dla przesyłki w statusie Szkic. Pobranie etykiety (GET .../label) to wyjątek binarny - zwraca application/pdf, a nie JSON.
Konektor kuriera lub Allegro, który nie jest połączony, zwraca 403 not_supported (nigdy 500), a błąd po stronie przewoźnika lub Allegro - 502 bad_gateway. Odczyty pomocnicze dla nieobsługiwanego dostawcy zwracają { "supported": false } zamiast błędu. Anulowanie nie zmienia statusu lokalnego, jeśli przewoźnik odrzuci operację.
Przykład - zamówienie etykiety (idempotentnie, płatne):
curl -X POST \
"https://{twoj-slug}.navyflame.com/api/public/v1/shipments/{id}/label" \
-H "Authorization: Bearer nf_live_twoj_klucz" \
-H "Idempotency-Key: 6f9a...-label-001"Konektory i oferty marketplace
Odkrywanie konektorów (zakres integrations:read) oraz odczyty i zapisy ofert marketplace (zakresy offers:read / offers:write). Część operacji jest lokalna (z Twoich danych, bez kosztów), a część to żywe, płatne wywołania do konektora - oznaczone niżej.
Odkrywanie i lokalne odczyty (bez kosztów):
GET /connectors # lista konektorów (bez sekretów)
GET /warehouse-items/{id}/listings # oferty marketplace produktu (keyset)
GET /category-mappings # mapowania kategorii (keyset)GET /connectors zwraca ściśle ograniczony zestaw pól - key, configId, displayName, enabled i connected - i nigdy nie zwraca danych logowania (kluczy API, tokenów ani haseł konektora). Pole connected to wyliczony status: konektor jest włączony i ma zapisane poświadczenia. Wartość configId przekażesz jako filtr ?sourceConfigId= lub ?destConfigId= w mapowaniach kategorii.
Oferty produktu (/warehouse-items/{id}/listings) wiążą pozycję magazynową z ofertą w kanale (zewnętrzne ID, cena i status po stronie marketplace, ewentualne nadpisanie ceny per kanał). Pole lastSyncError jest oczyszczane z wzorców poświadczeń, które błąd konektora mógłby zawierać.
Przykład - lista konektorów konta:
curl "https://{twoj-slug}.navyflame.com/api/public/v1/connectors" \
-H "Authorization: Bearer nf_live_twoj_klucz"Żywe odczyty marketplace (zakres offers:read) wykonują realne wywołanie do konektora - są płatne (liczą się do limitu API konektora), ale wyłącznie do odczytu (nie publikują ani nie zmieniają oferty). Konektor niepołączony zwraca 403 not_supported (nigdy 500), błąd po stronie marketplace - 502 bad_gateway. Kształt danych zależy od konektora.
GET /marketplace/{connectorKey}/products
GET /marketplace/{connectorKey}/products/{externalProductId}
GET /marketplace/{connectorKey}/categories?q=fraza
GET /marketplace/{connectorKey}/categories/{categoryId}/parameters
GET /marketplace/{connectorKey}/responsible-producers
GET /marketplace/{connectorKey}/responsible-personsZapis mapowań kategorii (zakres offers:write) to zapisy lokalne - żadne z nich nie publikuje ani nie zmienia realnej oferty widocznej dla kupującego (publikację realnej oferty opisano niżej). POST /category-mappings wymaga nagłówka Idempotency-Key (duplikat -> 409); sync odświeża lokalny cache kategorii z konektora (płatne, ale idempotentne).
POST /category-mappings # utwórz (Idempotency-Key wymagany; duplikat -> 409)
POST /category-mappings/bulk # zbiorczo (max 1000; duplikaty pomijane)
PUT /category-mappings/{id} # przekieruj mapowanie na inny cel
DELETE /category-mappings/{id} # usuń mapowanie
POST /category-mappings/sync # odśwież lokalny cache kategorii (płatne, idempotentne)Publikacja i synchronizacja realnych ofert (zakres offers:write) tworzy lub aktualizuje ofertę widoczną dla kupującego w kanale - operacje płatne (realne wywołanie do marketplace). publish i sync wymagają nagłówka Idempotency-Key (retry z tym samym kluczem odtwarza zapisaną odpowiedź zamiast ponawiać płatne wywołanie). publish zwraca 409, gdy produkt jest już opublikowany na tym konektorze (lub publikacja jest w toku) - wtedy użyj sync. Konektor niepołączony -> 403 not_supported, błąd po stronie marketplace -> 502 bad_gateway.
Ważne przy błędzie 502 na publikacji: timeout lub błąd 5xx marketplace jest niejednoznaczny - oferta mogła powstać. Retry z tym samym Idempotency-Key odtworzy to samo 502 (nie opublikuje ponownie). Zweryfikuj ofertę w kanale i ponów z nowym Idempotency-Key dopiero wtedy, gdy wiesz, że oferta nie powstała.
POST /warehouse-items/{id}/publish/{connectorKey} # opublikuj ofertę (płatne; Idempotency-Key wymagany)
POST /warehouse-items/{id}/sync/{connectorKey} # zaktualizuj ofertę (płatne; Idempotency-Key wymagany)
POST /warehouse-items/{id}/pull/{connectorKey} # pobierz ofertę z kanału do katalogu
POST /warehouse-items/{id}/refresh-status/{connectorKey} # odśwież status jednej oferty
POST /warehouse-items/refresh-status # zbiorczo (max 100 produktów)
PUT /warehouse-items/{id}/listings/{connectorKey}/pricing # cena per kanał (lokalnie, bez wywołania)Import oferty do magazynu (POST /catalog/import) tworzy pozycję magazynową z produktu marketplace. Wymaga dwóch zakresów naraz - offers:write oraz catalog:write(brak jednego -> 403 missing_scope) - i nagłówka Idempotency-Key. Duplikat SKU lub kodu kreskowego -> 409 conflict.
POST /catalog/import # import produktu marketplace -> pozycja magazynowa (offers:write + catalog:write)Zapis: powiadomienia, alerty, e-mail i obsługa posprzedażowa
Zapis komunikacji, ponownego przetwarzania i obsługi posprzedażowej (zakresy notifications:write, alerts:write, email:write, monitoring:write, postsale:write i postsale:refunds:write). Operacje tworzące i nieodwracalne wymagają nagłówka Idempotency-Key; operacje naturalnie idempotentne (oznaczanie jako przeczytane, toggle) honorują go opcjonalnie.
# Powiadomienia (notifications:write)
POST /notifications # utwórz (odbiorca musi być członkiem konta; Idempotency-Key wymagany)
POST /notifications/{id}/read # oznacz jedno jako przeczytane
POST /notifications/read-all # oznacz wszystkie (wymaga ?userId=)
# Alerty (alerts:write)
POST /alert-rules # utwórz regułę (Idempotency-Key wymagany)
PUT/DELETE /alert-rules/{id} # aktualizuj / usuń
POST /alert-rules/{id}/toggle # włącz / wyłącz
# E-mail (email:write)
POST/PUT/DELETE /email-templates(/{id}) # szablony (limit planu; duplikat nazwy -> 409)
POST /emails/send # BILLABLE - realna wysyłka (Idempotency-Key wymagany)Tworzenie powiadomienia sprawdza, czy recipientUserId jest członkiem konta (nie-członek -> 422, niepewna weryfikacja -> 503) - klucz API nie może zasypać skrzynki dowolnego użytkownika. Szablony e-mail podlegają limitowi planu (Basic 10, Professional 24, Enterprise bez limitu) -> 403 plan_limit, a duplikat nazwy -> 409. Wysyłka e-mail (POST /emails/send) jest płatna i objęta dedykowanym limitem ~10 na godzinę per konto (429); dostawca bez konfiguracji -> 403 not_supported, błąd transportu -> 502 bad_gateway. Reguła alertu z kanałem email lub both pośrednio generuje wysyłki przy wyzwoleniu.
Ponowne przetwarzanie kolejki błędów (zakres monitoring:write) odpala oryginalny proces wpisu DLQ - dla źródeł fakturowania wystawia realną fakturę, więc jest płatne i destrukcyjne, a Idempotency-Key jest wymagany. Retriable są tylko trzy źródła (shopify_to_wfirma_pipeline, shopify, wfirma_invoice) - inne zwracają 422; niedostępny Temporal -> 503. Powtórzenie jest idempotentne po deterministycznym identyfikatorze procesu (zwraca alreadyRunning).
POST /monitoring/dlq/{id}/retry # BILLABLE - odpala oryginalny proces (Idempotency-Key wymagany)Obsługa posprzedażowa (zakres postsale:write): odpowiadasz w wątkach i sporach, zmieniasz status sporu, akceptujesz lub odrzucasz zwrot. Własność wątku, sporu lub zwrotu jest sprawdzana przed wywołaniem kanału (cudzy lub nieistniejący identyfikator -> 404), a operacje są capability-gated per konektor - brak danej zdolności lub metody zwraca 403 not_supported (nigdy 500). Błąd kanału -> 502 bad_gateway.
# Obsługa posprzedażowa bez ruchu środków (postsale:write)
POST /post-sale/conversations/{id}/messages # odpowiedz kupującemu (Idempotency-Key wymagany)
POST /post-sale/conversations/{id}/read # oznacz wątek przeczytany
POST /post-sale/disputes/{id}/messages # odpowiedz w sporze (Idempotency-Key wymagany)
POST /post-sale/disputes/{id}/status # decyzja w sporze (patrz izolacja pieniędzy)
POST /post-sale/returns/{id}/accept # zaakceptuj zwrot
POST /post-sale/returns/{id}/reject # odrzuć zwrot
# Zwrot środków - ODRĘBNY zakres pieniężny (postsale:refunds:write)
POST /post-sale/refunds/issue # REALNY zwrot środków kupującemu
POST /post-sale/refunds/commission-claim # zwrot prowizjiIzolacja pieniędzy. Zwrot środków ma odrębny zakres postsale:refunds:write, wydzielony od postsale:write, tak aby wyciekły klucz bez tego zakresu nie mógł ruszyć pieniędzy. Trasa POST /post-sale/disputes/{id}/status należy do postsale:write, ale jeśli decyzja przenosi środki do kupującego (obecne partialRefund albo status ACCEPTED_REFUND / ACCEPTED_PARTIAL_REFUND), klucz musi dodatkowo nieść postsale:refunds:write - inaczej żądanie zwraca 403 missing_scope i nic się nie wykonuje.
Ponawianie zwrotów. refunds/issue i commission-claim są idempotentne po stronie kanału (Twój Idempotency-Key staje się identyfikatorem operacji na kanale) - na 502 ponów z tym samym kluczem, a kanał zdeduplikuje. Natomiast decyzja sporu przenosząca środki nie ma idempotencji po stronie kanału - na niepewny błąd zweryfikuj wynik w kanale sprzedaży i ponów dopiero z nowym Idempotency-Key (to samo 502 jest zwracane dla tego samego klucza).
Przykład - realny zwrot środków (idempotentnie, płatne):
curl -X POST \
"https://{twoj-slug}.navyflame.com/api/public/v1/post-sale/refunds/issue" \
-H "Authorization: Bearer nf_live_twoj_klucz" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f9a...-refund-001" \
-d '{"connectorKey":"shopify","instanceId":"shop-1","orderExternalId":"1234","amount":49.99,"currency":"PLN"}'Pełny wykaz operacji (per zasób)
Kompletny, nawigowalny indeks wszystkich publicznych endpointów v1 pogrupowanych per zasób. To jest warstwa dla człowieka - pełne, polowe schematy żądań i odpowiedzi (179 schematów) znajdziesz w specyfikacji OpenAPI. Każdy żyjący endpoint jest tu wymieniony.
- Zakres - wymagany zakres klucza. Zakres
:writeobejmuje odpowiadający mu:read. Zapisa + boznacza cross-scope (potrzebne oba naraz). - Idem. -
K!= nagłówekIdempotency-Keywymagany;K?= honorowany (opcjonalny); puste = nie dotyczy (odczyt). - Błędy - kluczowe kody poza uniwersalnymi
401,403,429(oraz500/503, które mogą wystąpić wszędzie).
Meta
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /me | (brak) | - | Introspekcja klucza: plan, limity, zakresy. Nie wymaga zakresu. | - |
Zamówienia
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /orders | orders:read | - | Lista zamówień (keyset; filtry status / źródło / data / szukaj). | 422 |
POST /orders | orders:write | K! | Utwórz zamówienie (source=api); kwoty liczy serwer. | 409,413,415,422 |
GET /orders/{id} | orders:read | - | Szczegóły zamówienia. | 404 |
PUT /orders/{id}/status | orders:write | K? | Zmień status (macierz przejść; writeback do Allegro). | 404,415,422 |
POST /orders/{id}/invoice | orders:write | K! | Wyzwól fakturowanie (asynchroniczne). | 404,409,422 |
GET /orders/stats | orders:read | - | Statystyki zamówień (liczniki per status + przychód Paid). | 422 |
GET /orders/{id}/status-history | orders:read | - | Historia realnych przejść statusu zamówienia. | 404,422 |
Katalog - produkty
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /warehouse-items | catalog:read | - | Lista produktów (keyset; filtr status / sku / barcode). | 422 |
POST /warehouse-items | catalog:write | K! | Utwórz produkt magazynowy. | 409,413,415,422 |
GET /warehouse-items/{id} | catalog:read | - | Szczegóły produktu (z wariantami). | 404 |
PUT /warehouse-items/{id} | catalog:write | K! | Zaktualizuj produkt. | 404,409,413,415,422 |
DELETE /warehouse-items/{id} | catalog:write | K! | Zarchiwizuj produkt (miękkie usunięcie). | 404,409,422 |
PATCH /warehouse-items/{id}/stock | catalog:write | K? | Ustaw / skoryguj stan (set / adjust, atomowo). | 404,415,422 |
GET /warehouse-items/by-barcode | catalog:read | - | Znajdź produkt lub wariant po kodzie kreskowym. | 404,422 |
GET /warehouse-items/{id}/stock-history | catalog:read | - | Historia zmian stanu produktu (keyset). | 404,422 |
POST /warehouse-items/{id}/backorder | catalog:write | K! | Włącz / wyłącz backorder produktu. | 404,409,415,422 |
Katalog - magazyny i lokalizacje
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /warehouses | catalog:read | - | Lista magazynów / lokalizacji. | - |
POST /warehouses | catalog:write | K! | Utwórz magazyn / lokalizację. | 409,415,422 |
PUT /warehouses/{id} | catalog:write | K! | Zaktualizuj magazyn. | 404,409,415,422 |
DELETE /warehouses/{id} | catalog:write | K! | Usuń magazyn. | 404,409,422 |
GET /warehouse-items/{id}/locations | catalog:read | - | Stan produktu w rozbiciu na lokalizacje. | 404 |
PUT /warehouse-items/{id}/locations/{warehouseId} | catalog:write | K! | Ustaw stan produktu w danej lokalizacji. | 404,409,415,422 |
GET /warehouse-settings | catalog:read | - | Ustawienia automatyzacji magazynu. | - |
PUT /warehouse-settings | catalog:write | K! | Zmień ustawienia automatyzacji magazynu. | 409,415,422 |
Katalog - rezerwacje i dokumenty magazynowe
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /reservations | catalog:read | - | Lista rezerwacji stanu (keyset). | 422 |
POST /reservations | catalog:write | K! | Zarezerwuj stan produktu. | 404,409,415,422 |
DELETE /reservations/{id} | catalog:write | K! | Zwolnij rezerwację. | 404,409 |
GET /stock-documents | catalog:read | - | Lista dokumentów magazynowych (keyset). | 422 |
POST /stock-documents | catalog:write | K! | Utwórz dokument magazynowy (szkic). | 409,415,422 |
GET /stock-documents/{id} | catalog:read | - | Szczegóły dokumentu (z pozycjami). | 404 |
POST /stock-documents/{id}/lines | catalog:write | K! | Dodaj pozycję do dokumentu. | 404,409,415,422 |
DELETE /stock-documents/{id}/lines/{lineId} | catalog:write | K! | Usuń pozycję z dokumentu. | 404,409,422 |
POST /stock-documents/{id}/commit | catalog:write | K! | Zatwierdź dokument (zastosuj stan). | 404,409,422 |
POST /stock-documents/{id}/cancel | catalog:write | K! | Anuluj dokument magazynowy. | 404,409,422 |
Katalog - zestawy
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /bundles | catalog:read | - | Lista zestawów (keyset). | 422 |
GET /bundles/{id} | catalog:read | - | Szczegóły zestawu (komponenty + stan wyliczony). | 404 |
PUT /bundles/{id} | catalog:write | K! | Ustaw komponenty zestawu. | 404,409,415,422 |
DELETE /bundles/{id} | catalog:write | K! | Usuń zestaw (wyczyść komponenty). | 404,409,422 |
Szablony (opisów i produktów)
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /description-templates | templates:read | - | Lista szablonów opisów (keyset). | 422 |
POST /description-templates | templates:write | K! | Utwórz szablon opisu. | 409,413,415,422 |
GET /description-templates/{id} | templates:read | - | Szczegóły szablonu opisu. | 404 |
PUT /description-templates/{id} | templates:write | K? | Zaktualizuj szablon opisu. | 404,409,413,415,422 |
DELETE /description-templates/{id} | templates:write | K? | Usuń szablon opisu. | 404 |
GET /product-templates | templates:read | - | Lista szablonów produktów (keyset). | 422 |
POST /product-templates | templates:write | K! | Utwórz szablon produktu. | 409,413,415,422 |
GET /product-templates/{id} | templates:read | - | Szczegóły szablonu produktu (z wariantami). | 404 |
PUT /product-templates/{id} | templates:write | K? | Zaktualizuj szablon produktu. | 404,409,413,415,422 |
DELETE /product-templates/{id} | templates:write | K? | Usuń szablon produktu. | 404 |
PUT /product-templates/{id}/variants | templates:write | K? | Zamień komplet wariantów szablonu (bulk). | 404,409,413,415,422 |
POST /product-templates/{id}/variants | templates:write | K! | Dodaj wariant do szablonu. | 404,409,415,422 |
PATCH /product-templates/{id}/variants/{variantId} | templates:write | K? | Zaktualizuj wariant szablonu. | 404,409,415,422 |
DELETE /product-templates/{id}/variants/{variantId} | templates:write | K? | Usuń wariant szablonu. | 404 |
POST /product-templates/{id}/apply | templates:write + catalog:write | K! | Utwórz produkt z szablonu (cross-scope). | 404,409,422 |
AI - generowanie treści
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /ai/settings | ai:read | - | Globalne ustawienia generowania AI. | - |
PUT /ai/settings | ai:write | K? | Zmień globalne ustawienia AI. | 409,415,422 |
GET /ai/generation-logs | ai:read | - | Historia wywołań AI (keyset). | 422 |
POST /ai/generate-description | ai:write | K! | Wygeneruj opis produktu (billable). | 404,409,415,422 |
POST /ai/translate | ai:write | K! | Przetłumacz produkt (billable). | 404,409,415,422 |
POST /ai/batch-generate | ai:write | K! | Wygeneruj opisy wsadowo (billable; max 50). | 409,413,415,422 |
POST /ai/batch-translate | ai:write | K! | Przetłumacz wsadowo (billable; max 50). | 409,413,415,422 |
POST /ai/preview-template | templates:read + catalog:read | - | Podgląd szablonu z danymi produktu (bez LLM; cross-scope). | 404,413,415,422 |
Analityka AI (AI-Ops)
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /ai-ops/status | analytics:read | - | Status konfiguracji AI + pokrycie danymi. | - |
GET /ai-ops/stock-predictions | analytics:read | - | Prognoza wyczerpania zapasów per SKU (cache 5 min). | 422 |
GET /ai-ops/price-optimizations | analytics:read | - | Sugestie cenowe z historii zmian cen (cache 5 min). | 422 |
GET /ai-ops/anomalies | analytics:read | - | Anomalie vs średnia krocząca (cache 5 min). | 422 |
GET /ai-ops/sales-forecast | analytics:read | - | Prognoza sprzedaży (regresja; days = horyzont). | 422 |
GET /ai-ops/insights | analytics:read | - | Wnioski (billable LLM tenanta; cache 30 min; fallback regułowy). | - |
Faktury
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /invoices | invoices:read | - | Lista faktur (keyset; issueDate desc). | 422 |
GET /invoices/{id} | invoices:read | - | Szczegóły faktury (z pozycjami i KSeF). | 404 |
GET /invoices/stats | invoices:read | - | Statystyki faktur (KPI lifetime). | - |
Przesyłki i kurier
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /shipments | shipments:read | - | Lista przesyłek (keyset). | 422 |
GET /shipments/{id} | shipments:read | - | Szczegóły przesyłki (z historią trackingu). | 404 |
GET /shipments/stats | shipments:read | - | Statystyki przesyłek (liczniki per status). | - |
POST /shipments | shipments:write | K! | Utwórz przesyłkę (status Szkic; bez kosztu). | 409,415,422 |
POST /shipments/bulk | shipments:write | K! | Utwórz przesyłki zbiorczo (max 100, partial success). | 409,413,415,422 |
POST /shipments/{id}/label | shipments:write | K! | Zamów etykietę kurierską (billable - realny koszt). | 404,409 |
GET /shipments/{id}/label | shipments:read | - | Pobierz etykietę kurierską (PDF, binarny). | 404,409,502 |
DELETE /shipments/{id} | shipments:write | K! | Anuluj przesyłkę (u kuriera, jeśli wysłana). | 404,409,502 |
POST /shipments/{id}/refresh-tracking | shipments:write | K? | Odśwież status i tracking u kuriera. | 404,409,502 |
POST /shipments/{id}/push-tracking | shipments:write | K! | Wyślij numer śledzenia do zamówienia w marketplace, z którego pochodzi (Allegro, TikTok Shop). | 404,400,502 |
POST /shipments/{id}/push-to-allegro | shipments:write | K! | To samo, ale wyłącznie dla Allegro. Zachowane dla zgodności wstecznej - w nowych integracjach używaj push-tracking. | 404,409,422,502 |
POST /shipments/available-dates | shipments:read | - | Dostępne terminy nadania (DHL; POST-but-read). | 415,422,502 |
GET /shipments/points | shipments:read | - | Punkty odbioru / paczkomaty (InPost). | 502 |
GET /couriers/{provider}/services | shipments:read | - | Lista usług kuriera (Apaczka). | 502 |
GET /shipments/allegro/delivery-services | shipments:read | - | Lista usług Allegro Delivery. | 502 |
Konfiguracja wysyłki
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /shipping-rules | shipping:read | - | Lista reguł wysyłki (keyset). | 422 |
POST /shipping-rules | shipping:write | K! | Utwórz regułę wysyłki. | 409,415,422 |
GET /shipping-rules/{id} | shipping:read | - | Szczegóły reguły wysyłki. | 404 |
PUT /shipping-rules/{id} | shipping:write | K? | Zaktualizuj regułę wysyłki. | 404,409,415,422 |
DELETE /shipping-rules/{id} | shipping:write | K? | Usuń regułę wysyłki. | 404 |
GET /shipping-zones | shipping:read | - | Lista stref wysyłki (z zagnieżdżonymi stawkami). | 422 |
POST /shipping-zones | shipping:write | K! | Utwórz strefę wysyłki. | 409,415,422 |
GET /shipping-zones/{id} | shipping:read | - | Szczegóły strefy (z zagnieżdżonymi stawkami). | 404 |
PUT /shipping-zones/{id} | shipping:write | K? | Zaktualizuj strefę wysyłki. | 404,409,415,422 |
DELETE /shipping-zones/{id} | shipping:write | K? | Usuń strefę wysyłki. | 404 |
POST /shipping-zones/{id}/rates | shipping:write | K! | Dodaj stawkę do strefy. | 404,409,415,422 |
PUT /shipping-zones/{id}/rates/{rateId} | shipping:write | K? | Zaktualizuj stawkę w strefie. | 404,409,415,422 |
DELETE /shipping-zones/{id}/rates/{rateId} | shipping:write | K? | Usuń stawkę ze strefy. | 404 |
GET /delivery-options | shipping:read | - | Lista opcji dostawy (keyset). | 422 |
POST /delivery-options | shipping:write | K! | Utwórz opcję dostawy. | 409,415,422 |
GET /delivery-options/{id} | shipping:read | - | Szczegóły opcji dostawy. | 404 |
PUT /delivery-options/{id} | shipping:write | K? | Zaktualizuj opcję dostawy. | 404,409,415,422 |
DELETE /delivery-options/{id} | shipping:write | K? | Usuń opcję dostawy. | 404 |
GET /products/{productId}/shipping-overrides | shipping:read | - | Nadpisania wysyłki dla produktu (keyset). | 404,422 |
POST /products/{productId}/shipping-overrides | shipping:write | K! | Utwórz nadpisanie wysyłki dla produktu. | 404,409,415,422 |
PUT /product-shipping-overrides/{id} | shipping:write | K? | Zaktualizuj nadpisanie wysyłki produktu. | 404,409,415,422 |
DELETE /product-shipping-overrides/{id} | shipping:write | K? | Usuń nadpisanie wysyłki produktu. | 404 |
POST /shipping/calculate | shipping:read | - | Wylicz opcje i koszt wysyłki (POST-but-read). | 415,422 |
Klienci
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /customers | customers:read | - | Lista klientów (agregacja po e-mailu; keyset). | 422 |
GET /customers/stats | customers:read | - | Statystyki klientów (KPI). | - |
GET /customers/growth | customers:read | - | Przyrost klientów w czasie (szereg miesięczny). | 422 |
GET /customers/export | customers:read | - | Eksport klientów do CSV (binarny). | 422 |
GET /customers/{email} | customers:read | - | Szczegóły klienta (agregat + adresy). | 404 |
GET /customers/{email}/orders | customers:read | - | Zamówienia klienta (keyset). | 404,422 |
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /email-templates | email:read | - | Lista szablonów e-mail (keyset). | 422 |
GET /email-templates/{id} | email:read | - | Szczegóły szablonu e-mail. | 404 |
GET /email-logs | email:read | - | Lista logów wysłanych e-maili (keyset; PII). | 422 |
POST /email-templates | email:write | K! | Utwórz szablon e-mail (limit planu). | 409,413,415,422 |
PUT /email-templates/{id} | email:write | K? | Zaktualizuj szablon e-mail. | 404,409,413,415,422 |
DELETE /email-templates/{id} | email:write | K? | Usuń szablon e-mail. | 404,409 |
POST /emails/send | email:write | K! | Wyślij wiadomość e-mail (billable; ~10/godz). | 409,413,415,422,502 |
Powiadomienia
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /notifications | notifications:read | - | Lista powiadomień tenant-wide (keyset; ?userId zawęża). | 422 |
GET /notifications/{id} | notifications:read | - | Szczegóły powiadomienia. | 404 |
GET /notifications/unread-count | notifications:read | - | Liczba nieprzeczytanych powiadomień. | 422 |
GET /notification-preferences | notifications:read | - | Preferencje powiadomień (wymaga ?userId=). | 422 |
POST /notifications | notifications:write | K! | Utwórz powiadomienie (odbiorca = członek konta). | 413,415,422 |
POST /notifications/{id}/read | notifications:write | K? | Oznacz powiadomienie jako przeczytane. | 404,409 |
POST /notifications/read-all | notifications:write | K? | Oznacz wszystkie jako przeczytane (wymaga ?userId=). | 409,422 |
Alerty
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /alert-rules | alerts:read | - | Lista reguł alertów (keyset). | 422 |
GET /alert-rules/history | alerts:read | - | Historia wyzwoleń alertów (keyset). | 422 |
GET /alert-rules/{id} | alerts:read | - | Szczegóły reguły alertu. | 404 |
POST /alert-rules | alerts:write | K! | Utwórz regułę alertu. | 413,415,422 |
PUT /alert-rules/{id} | alerts:write | K? | Zaktualizuj regułę alertu. | 404,413,415,422 |
DELETE /alert-rules/{id} | alerts:write | K? | Usuń regułę alertu. | 404,409 |
POST /alert-rules/{id}/toggle | alerts:write | K? | Włącz / wyłącz regułę alertu. | 404,409,422 |
Obsługa posprzedażowa
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /post-sale/capabilities | postsale:read | - | Mapa zdolności posprzedaży per instancja konektora. | - |
GET /post-sale/inbox | postsale:read | - | Zbiorczy inbox (podsumowanie wątków i sporów). | - |
GET /post-sale/conversations | postsale:read | - | Lista wątków (keyset). | 422 |
GET /post-sale/conversations/{id} | postsale:read | - | Szczegóły wątku. | 404 |
GET /post-sale/conversations/{id}/messages | postsale:read | - | Wiadomości w wątku (keyset). | 404,422 |
GET /post-sale/disputes | postsale:read | - | Lista sporów / reklamacji (keyset). | 422 |
GET /post-sale/disputes/{id} | postsale:read | - | Szczegóły sporu. | 404 |
GET /post-sale/disputes/{id}/messages | postsale:read | - | Wiadomości w sporze (keyset). | 404,422 |
GET /post-sale/returns | postsale:read | - | Lista zwrotów (keyset). | 422 |
GET /post-sale/returns/{id} | postsale:read | - | Szczegóły zwrotu. | 404 |
GET /post-sale/refunds | postsale:read | - | Lista zwrotów środków (keyset). | 422 |
POST /post-sale/conversations/{id}/messages | postsale:write | K! | Odpowiedz kupującemu w wątku. | 404,413,415,422,502 |
POST /post-sale/conversations/{id}/read | postsale:write | K? | Oznacz wątek jako przeczytany. | 404,409 |
POST /post-sale/disputes/{id}/messages | postsale:write | K! | Odpowiedz w sporze. | 404,413,415,422,502 |
POST /post-sale/disputes/{id}/status | postsale:write | K! | Zmień status sporu (ruch środków wymaga refunds:write). | 404,413,415,422,502 |
POST /post-sale/returns/{id}/accept | postsale:write | K! | Zaakceptuj zwrot. | 404,409,502 |
POST /post-sale/returns/{id}/reject | postsale:write | K! | Odrzuć zwrot. | 404,413,415,422,502 |
Zwroty środków (izolowany zakres pieniężny)
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
POST /post-sale/refunds/issue | postsale:refunds:write | K! | Realny zwrot środków kupującemu (channel-idempotentne). | 413,415,422,502 |
POST /post-sale/refunds/commission-claim | postsale:refunds:write | K! | Zgłoś zwrot prowizji. | 413,415,422,502 |
Raporty
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /reports/sales | reports:read | - | Raport sprzedaży (szereg czasowy + agregaty, marża). | 422 |
GET /reports/sales/channels | reports:read | - | Podział sprzedaży na kanały. | 422 |
GET /reports/sales/countries | reports:read | - | Podział sprzedaży na kraje. | 422 |
GET /reports/products/bestsellers | reports:read | - | Bestsellery (sprzedaż + marża brutto). | 422 |
GET /reports/products/high-returns | reports:read | - | Produkty z wysokim wskaźnikiem zwrotów. | 422 |
GET /reports/products/low-rotation | reports:read | - | Produkty z niską rotacją. | 422 |
GET /reports/operations/sla | reports:read | - | Metryki SLA realizacji. | 422 |
GET /reports/operations/fulfillment | reports:read | - | Czas realizacji per kanał. | 422 |
GET /reports/export/csv | reports:read | - | Eksport raportu do CSV (binarny). | 422 |
GET /reports/export/xlsx | reports:read | - | Eksport raportu do XLSX (binarny). | 422 |
Monitoring i zużycie
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /monitoring/webhooks | monitoring:read | - | Lista przychodzących webhooków (bez payloadu). | 422 |
GET /monitoring/webhooks/{id} | monitoring:read | - | Szczegół webhooka (surowy payload - PII). | 404 |
GET /monitoring/invoice-links | monitoring:read | - | Powiązania fakturowania (zamówienie -> faktura). | 422 |
GET /monitoring/dlq | monitoring:read | - | Kolejka błędów (dead-letter, bez payloadu). | 422 |
GET /monitoring/dlq/{id} | monitoring:read | - | Szczegół wpisu DLQ (oryginalny payload - PII). | 404 |
GET /monitoring/stats | monitoring:read | - | Zbiorcze statystyki integracji. | - |
GET /usage | monitoring:read | - | Zużycie konta (liczniki, miejsce, limity planu). | - |
POST /monitoring/dlq/{id}/retry | monitoring:write | K! | Ponów wpis DLQ (billable; odpala oryginalny workflow). | 404,409,422 |
Konektory i oferty marketplace
| Operacja | Zakres | Idem. | Cel | Błędy |
|---|---|---|---|---|
GET /connectors | integrations:read | - | Lista konektorów tenanta (projekcja bez sekretów). | - |
GET /warehouse-items/{id}/listings | offers:read | - | Oferty marketplace jednego produktu (keyset). | 404,422 |
GET /category-mappings | offers:read | - | Lista mapowań kategorii (keyset). | 422 |
POST /category-mappings | offers:write | K! | Utwórz mapowanie kategorii (lokalnie). | 409,413,415,422 |
POST /category-mappings/bulk | offers:write | K? | Zbiorczo utwórz mapowania (max 1000). | 409,413,415,422 |
PUT /category-mappings/{id} | offers:write | K? | Przekieruj mapowanie na inny cel. | 404,409,413,415,422 |
DELETE /category-mappings/{id} | offers:write | K? | Usuń mapowanie kategorii. | 404,409 |
POST /category-mappings/sync | offers:write | K? | Odśwież lokalny cache kategorii (billable). | 409,413,415,422,502 |
GET /marketplace/{connectorKey}/products | offers:read | - | Żywa lista produktów z konektora (billable). | 422,502 |
GET /marketplace/{connectorKey}/products/{externalProductId} | offers:read | - | Żywy pojedynczy produkt z konektora (billable). | 502 |
GET /marketplace/{connectorKey}/categories | offers:read | - | Żywe wyszukiwanie kategorii konektora (billable). | 502 |
GET /marketplace/{connectorKey}/categories/{categoryId}/parameters | offers:read | - | Żywe parametry kategorii (billable). | 502 |
GET /marketplace/{connectorKey}/responsible-producers | offers:read | - | Żywa lista producentów GPSR (billable). | 502 |
GET /marketplace/{connectorKey}/responsible-persons | offers:read | - | Żywa lista osób odpowiedzialnych GPSR (billable). | 502 |
POST /warehouse-items/{id}/publish/{connectorKey} | offers:write | K! | Opublikuj ofertę produktu (billable, realna oferta). | 404,409,413,415,422,502 |
POST /warehouse-items/{id}/sync/{connectorKey} | offers:write | K! | Zaktualizuj opublikowaną ofertę (billable). | 404,409,413,415,422,502 |
POST /warehouse-items/{id}/pull/{connectorKey} | offers:write | K? | Pobierz ofertę z konektora do katalogu (billable). | 404,409,502 |
POST /warehouse-items/{id}/refresh-status/{connectorKey} | offers:write | K? | Odśwież status jednej oferty (billable). | 404,409,502 |
POST /warehouse-items/refresh-status | offers:write | K? | Zbiorczo odśwież status ofert (max 100). | 409,413,415,422 |
PUT /warehouse-items/{id}/listings/{connectorKey}/pricing | offers:write | K? | Ustaw cenę per kanał (lokalnie, bez wywołania). | 404,409,413,415,422 |
POST /catalog/import | offers:write + catalog:write | K! | Importuj produkt marketplace do magazynu (cross-scope). | 409,413,415,422 |
Paginacja i filtry
Listy stronicujemy kursorowo (bez offsetu). Odpowiedź niesie pagination.nextCursor - przekaż go w parametrze cursor, aby pobrać kolejną stronę. Parametr updatedSince (data-czas ISO ze strefą) zwraca rekordy zmienione od danej chwili. Dla pull-synchronizacji odpytuj z oknem nakładki i deduplikuj po id.
GET /orders?limit=50&cursor=eyJjIjoi...&updatedSince=2026-07-01T00:00:00ZIdempotencja
Operacje zapisu chroni nagłówek Idempotency-Key (dowolny unikat, rekomendowany UUID, do 255 znaków). Jest wymagany na POST /orders i POST /orders/{id}/invoice, a honorowany na PUT i PATCH.
- Powtórka z tym samym kluczem i tą samą treścią zwraca zapisany wynik (nagłówek
Idempotency-Replayed: true) - bez podwójnego efektu. - Ten sam klucz z inną treścią zwraca
409 idempotency_conflict. - Równoległy duplikat w trakcie przetwarzania zwraca
409 idempotency_in_progresszRetry-After. - Klucze wygasają po 24 godzinach.
Przykłady w kodzie
Gotowe fragmenty w trzech wariantach: curl, JavaScript (fetch, Node 20+) i Python (biblioteka requests). Warianty JS i Python zakładają stałe BASE (adres bazowy) i KEY (klucz z bezpiecznego magazynu), ustawione w przykładzie uwierzytelniania.
Uwierzytelnianie (Bearer i X-API-Key)
curl
# Bearer (rekomendowane)
curl https://{twoj-slug}.navyflame.com/api/public/v1/me \
-H "Authorization: Bearer nf_live_twoj_klucz"
# Alias X-API-Key (narzędzia bez wsparcia Bearer)
curl https://{twoj-slug}.navyflame.com/api/public/v1/me \
-H "X-API-Key: nf_live_twoj_klucz"JavaScript
const BASE = "https://moj-sklep.navyflame.com/api/public/v1";
const KEY = process.env.NAVYFLAME_API_KEY;
const res = await fetch(BASE + "/me", {
headers: { Authorization: "Bearer " + KEY },
});
if (!res.ok) throw new Error("HTTP " + res.status);
const me = await res.json();
console.log(me.plan, me.scopes);Python
import os, requests
BASE = "https://moj-sklep.navyflame.com/api/public/v1"
KEY = os.environ["NAVYFLAME_API_KEY"]
r = requests.get(BASE + "/me", headers={"Authorization": "Bearer " + KEY})
r.raise_for_status()
me = r.json()
print(me["plan"], me["scopes"])Paginacja kursorowa (pętla + deduplikacja)
curl
curl "https://{twoj-slug}.navyflame.com/api/public/v1/orders?limit=100&updatedSince=2026-07-01T00:00:00Z" \
-H "Authorization: Bearer nf_live_twoj_klucz"
# odpowiedź niesie pagination.nextCursor -> przekaż jako &cursor=... w kolejnym wywołaniuJavaScript
async function* paginate(path) {
let cursor = null;
do {
const url = new URL(BASE + path);
url.searchParams.set("limit", "100");
if (cursor) url.searchParams.set("cursor", cursor);
const res = await fetch(url, {
headers: { Authorization: "Bearer " + KEY },
});
if (res.status === 429) {
const wait = Number(res.headers.get("Retry-After") || 1);
await new Promise((r) => setTimeout(r, wait * 1000));
continue;
}
if (!res.ok) throw new Error("HTTP " + res.status);
const page = await res.json();
for (const row of page.data) yield row;
cursor = page.pagination.nextCursor;
} while (cursor);
}
const seen = new Set();
for await (const order of paginate("/orders?updatedSince=2026-07-01T00:00:00Z")) {
if (seen.has(order.id)) continue; // deduplikacja po id
seen.add(order.id);
// ... przetwórz zamówienie
}Python
import time
def paginate(path, params=None):
params = dict(params or {})
params["limit"] = 100
while True:
r = requests.get(BASE + path, params=params,
headers={"Authorization": "Bearer " + KEY})
if r.status_code == 429:
time.sleep(int(r.headers.get("Retry-After", "1")))
continue
r.raise_for_status()
page = r.json()
for row in page["data"]:
yield row
cursor = page["pagination"]["nextCursor"]
if not cursor:
break
params["cursor"] = cursor
seen = set()
for order in paginate("/orders", {"updatedSince": "2026-07-01T00:00:00Z"}):
if order["id"] in seen: # deduplikacja po id
continue
seen.add(order["id"])
# ... przetwórz zamówienieIdempotentny zapis (Idempotency-Key + backoff)
curl
curl -X POST "https://{twoj-slug}.navyflame.com/api/public/v1/orders" \
-H "Authorization: Bearer nf_live_twoj_klucz" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 3f1c9a20-7b2e-4c6d-9f10-000000000001" \
-d '{"customer":{"name":"Jan Kowalski"},"lineItems":[{"title":"Kubek 300 ml","sku":"KUB-300-BIA","quantity":2,"unitPrice":"39.99","taxRate":"23"}],"currency":"PLN"}'JavaScript
import { randomUUID } from "node:crypto";
async function createOrder(body) {
const key = randomUUID(); // ten sam klucz przy każdym ponowieniu
for (let attempt = 0; attempt < 5; attempt++) {
const res = await fetch(BASE + "/orders", {
method: "POST",
headers: {
Authorization: "Bearer " + KEY,
"Content-Type": "application/json",
"Idempotency-Key": key,
},
body: JSON.stringify(body),
});
if (res.status === 429 || res.status === 502 || res.status === 503) {
const wait = Number(res.headers.get("Retry-After") || 2 ** attempt);
await new Promise((r) => setTimeout(r, wait * 1000));
continue; // przejściowe - ponów z tym samym kluczem
}
if (res.status === 409) {
const problem = await res.json();
if (problem.code === "idempotency_in_progress") {
await new Promise((r) => setTimeout(r, 1000));
continue;
}
throw new Error("konflikt idempotencji: " + problem.code); // inne body
}
if (!res.ok) throw new Error("HTTP " + res.status);
return res.json(); // 201 lub odtworzone (Idempotency-Replayed: true)
}
throw new Error("wyczerpano proby ponowienia");
}Python
import time
from uuid import uuid4
def create_order(body):
key = str(uuid4()) # ten sam klucz przy każdym ponowieniu
for attempt in range(5):
r = requests.post(BASE + "/orders", json=body, headers={
"Authorization": "Bearer " + KEY,
"Idempotency-Key": key,
})
if r.status_code in (429, 502, 503):
time.sleep(int(r.headers.get("Retry-After", 2 ** attempt)))
continue # przejściowe - ponów z tym samym kluczem
if r.status_code == 409:
code = r.json().get("code")
if code == "idempotency_in_progress":
time.sleep(int(r.headers.get("Retry-After", "1")))
continue
raise RuntimeError("konflikt idempotencji: " + str(code))
r.raise_for_status()
return r.json() # 201 lub odtworzone
raise RuntimeError("wyczerpano proby ponowienia")Weryfikację podpisu webhooka (JavaScript i Python) znajdziesz w sekcji Webhooki wychodzące.
Format błędów
Błędy zwracamy zgodnie z RFC 9457 (application/problem+json). Każdy niesie stabilny code i requestId do korelacji ze wsparciem.
{
"type": "https://navyflame.com/dokumentacja/api/bledy#validation_failed",
"title": "Walidacja nie powiodła się",
"status": 422,
"detail": "Nieprawidłowe dane wejściowe zamówienia.",
"code": "validation_failed",
"requestId": "req_abc123",
"errors": [{ "field": "lineItems[0].unitPrice", "message": "Kwota >= 0 (jako string)." }]
}| Kod | HTTP | Kiedy | Co zrobić |
|---|---|---|---|
| unauthorized | 401 | Brak, nieprawidłowy, wygasły lub odwołany klucz API. | Sprawdź nagłówek Authorization / X-API-Key. Jeśli klucz odwołany lub wygasły - utwórz nowy w panelu. |
| missing_scope | 403 | Klucz nie ma wymaganego zakresu (np. orders:write) - także cross-scope, gdy operacja wymaga dwóch zakresów. | Nadaj brakujący zakres, rotując klucz z pełnym zestawem zakresów. Zakresów istniejącego klucza nie da się zmienić w miejscu. |
| plan_limit | 403 | Plan nie obejmuje API, wyczerpano limit planu lub subskrypcja wygasła / została anulowana. | Odnów lub podnieś plan. API wraca automatycznie po aktywacji (propagacja limitu do IE w ciągu ok. 5 minut). |
| not_supported | 403 | Operacja wymaga konektora kuriera lub marketplace, który nie jest połączony (capability gate; nigdy 500). | Podłącz i włącz właściwy konektor w panelu (Integracje). Dostępność sprawdzisz w /post-sale/capabilities lub /connectors. |
| not_found | 404 | Zasób nie istnieje w Twoim koncie (lub należy do innego tenanta - nieodróżnialne, anti-IDOR). | Zweryfikuj identyfikator. Cudzy identyfikator zawsze wygląda jak nieistniejący. |
| conflict | 409 | Konflikt stanu zasobu: oferta już opublikowana, duplikat SKU / kodu kreskowego / nazwy, brak stanu, dokument nie w statusie Szkic. | Rozwiąż konflikt: przy publikacji użyj sync zamiast publish; zmień SKU / nazwę; sprawdź status zasobu. |
| idempotency_conflict | 409 | Ten sam Idempotency-Key użyty z inną treścią żądania. | Użyj nowego Idempotency-Key dla nowej treści. Ten sam klucz musi nieść identyczne body. |
| idempotency_in_progress | 409 | Żądanie z tym kluczem jest właśnie przetwarzane (równoległy duplikat). | Poczekaj wg nagłówka Retry-After i ponów z tym samym kluczem. |
| payload_too_large | 413 | Treść żądania przekracza 2 MB. | Zmniejsz body (np. mniejsze partie w operacjach wsadowych). |
| unsupported_media_type | 415 | Zapis bez nagłówka Content-Type: application/json. | Ustaw nagłówek Content-Type: application/json na operacjach zapisu. |
| validation_failed | 422 | Błędne dane wejściowe: zła wartość, niedozwolone przejście statusu, zły cursor, naive datetime bez strefy. | Popraw dane wg pola errors w odpowiedzi (field + message). |
| rate_limited | 429 | Przekroczono limit (planu per konto, per-IP, in-flight lub dedykowany limit wysyłki e-mail). | Zwolnij tempo, uszanuj Retry-After i zastosuj wykładniczy backoff. Sprawdź nagłówki X-RateLimit-*. |
| internal | 500 | Błąd po stronie NavyFlame. | Ponów z backoffem. Przy powtarzalnym błędzie zgłoś requestId do wsparcia. |
| bad_gateway | 502 | Błąd usługi zewnętrznej (przewoźnik, Allegro lub inny marketplace) - traktuj jak przejściowy. | Ponów z backoffem. Przy zapisie ponawiaj z tym samym Idempotency-Key (kanał zdeduplikuje). Zob. uwagi o publikacji i zwrotach. |
| service_unavailable | 503 | Restart, wdrożenie lub konfiguracja jeszcze niegotowa (ciągłe wdrożenia). | Ponów z backoffem - to stan przejściowy. |
Kody 500 (internal) i 503 (service_unavailable) mogą wystąpić na każdej operacji i nie są deklarowane per endpoint. Wdrożenia są ciągłe - klient powinien traktować sporadyczne 502/503 jako przejściowe (ponowienie z backoffem), a operacje zapisu zabezpieczać nagłówkiem Idempotency-Key. Nagłówek type w problem+json wskazuje na kotwicę tej sekcji (np. #validation_failed).
Webhooki wychodzące
Subskrybujesz zdarzenie i podajesz adres HTTPS, a my wysyłamy tam podpisane powiadomienie. Zdarzenia v1: order.synced, invoice.issued, shipment.status_updated, catalog.updated. Każda dostawa niesie nagłówki X-NavyFlame-Event, X-NavyFlame-Delivery-Id i X-NavyFlame-Signature. Sukces to odpowiedź 2xx w ciągu 5 sekund; przy niepowodzeniu ponawiamy z rosnącym odstępem przez ok. 24 godziny, a historię dostaw widzisz w panelu.
Kształt ładunku (wspólna koperta):
{
"id": "evt_9f4c2f6a-...",
"type": "order.synced",
"apiVersion": "v1",
"occurredAt": "2026-07-07T12:00:00Z",
"tenant": "twoj-slug",
"origin": { "channel": "api", "apiKeyPrefix": "nf_live_abc123" },
"data": { "order": { }, "isNew": true }
}Pole origin.channel (api | panel | sync | automation) pozwala przerwać pętlę echa - jeśli sam wywołałeś zmianę kluczem API, rozpoznasz to po apiKeyPrefix i pominiesz zdarzenie. Odbiorca deduplikuje po id zdarzenia oraz nagłówku X-NavyFlame-Delivery-Id (gwarancja at-least-once, bez gwarancji kolejności).
Katalog zdarzeń (v1)
Zamknięta lista zdarzeń v1 - nowe typy to zmiana addytywna, więc odbiornik musi ignorować nieznane pola i typy. Każde zdarzenie niesie wspólną kopertę (powyżej); treść specyficzna dla typu jest w polu data:
order.synced - Po zapisaniu zamówienia, tylko przy realnej zmianie danych (nowe zamówienie lub przejście statusu). Pole isNew rozróżnia nowe od zaktualizowanego.
{
"id": "evt_9f4c2f6a-1b2c-4d3e-8a9b-000000000001",
"type": "order.synced",
"apiVersion": "v1",
"occurredAt": "2026-07-09T12:00:00Z",
"tenant": "moj-sklep",
"origin": { "channel": "sync" },
"data": {
"order": { "id": "0e6b7c...", "orderNumber": "2026/07/000123",
"status": "Processing", "totalPrice": "129.99", "currency": "PLN" },
"isNew": false
}
}invoice.issued - Po wystawieniu faktury w systemie księgowym tenanta.
{
"id": "evt_1a2b3c4d-5e6f-4a7b-8c9d-000000000002",
"type": "invoice.issued",
"apiVersion": "v1",
"occurredAt": "2026-07-09T12:03:00Z",
"tenant": "moj-sklep",
"origin": { "channel": "automation" },
"data": {
"invoice": { "id": "7a1c9e...", "number": "FV/2026/07/45",
"status": "Issued", "grossAmount": "129.99", "currency": "PLN" }
}
}shipment.status_updated - Po zmianie statusu przesyłki u przewoźnika. Pole previousStatus niesie poprzedni status (lub null).
{
"id": "evt_2b3c4d5e-6f7a-4b8c-9d0e-000000000003",
"type": "shipment.status_updated",
"apiVersion": "v1",
"occurredAt": "2026-07-09T12:10:00Z",
"tenant": "moj-sklep",
"origin": { "channel": "sync" },
"data": {
"shipment": { "id": "b2d9f1...", "courierProvider": "inpost",
"status": "InTransit", "trackingNumber": "6800000000001" },
"previousStatus": "PickedUp"
}
}catalog.updated - Po zmianie produktu lub stanu. Zmiany pojedyncze jako per-item; operacje jawnie masowe (import hurtowni, bulk) jako jedno zdarzenie zbiorcze (bulk: true).
{
"id": "evt_3c4d5e6f-7a8b-4c9d-0e1f-000000000004",
"type": "catalog.updated",
"apiVersion": "v1",
"occurredAt": "2026-07-09T12:15:00Z",
"tenant": "moj-sklep",
"origin": { "channel": "api", "apiKeyPrefix": "nf_live_abc123" },
"data": {
"warehouseItemId": "c4e1a2...", "sku": "KUB-300-BIA",
"changeType": "updated", "stockQuantity": 42
}
}
// Wariant zbiorczy (data):
// { "bulk": true, "source": "wholesale-import", "itemsChanged": 128 }Weryfikacja podpisu
Nagłówek X-NavyFlame-Signature ma postać t=<unix>,v1=<hex>, gdzie v1 = HMAC-SHA256(sekret, "<t>." + surowe_body). Nagłówek może zawierać kilka par v1= (okno rotacji sekretu - stary i nowy sekret podpisują równolegle przez 24 h) - zaakceptuj dowolną pasującą. Sprawdzaj zgodność znacznika czasu (tolerancja 300 s), aby chronić się przed powtórką.
JavaScript (Node)
import crypto from "node:crypto";
function verify(signatureHeader, rawBody, secret) {
const parts = Object.create(null);
const sigs = [];
for (const p of String(signatureHeader).split(",")) {
const [k, v] = p.split("=");
if (k === "t") parts.t = v;
if (k === "v1" && v) sigs.push(v);
}
if (!parts.t || sigs.length === 0) return false;
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const computed = crypto
.createHmac("sha256", secret)
.update(parts.t + "." + rawBody)
.digest("hex");
return sigs.some(
(s) =>
s.length === computed.length &&
crypto.timingSafeEqual(
Buffer.from(computed, "hex"),
Buffer.from(s, "hex"),
),
);
}Python
import hashlib, hmac, time
def verify(signature_header, raw_body, secret):
t = None
sigs = []
for part in signature_header.split(","):
k, _, v = part.partition("=")
if k == "t":
t = v
elif k == "v1" and v:
sigs.append(v)
if not t or not sigs:
return False
if abs(time.time() - int(t)) > 300: # ochrona przed powtórką
return False
computed = hmac.new(
secret.encode(), (t + "." + raw_body).encode(), hashlib.sha256
).hexdigest()
return any(hmac.compare_digest(computed, s) for s in sigs)Weryfikuj podpis na surowym ciele żądania (bajty przed parsowaniem JSON) - ponowne serializowanie zmieni bajty i podpis się nie zgodzi. raw_body / rawBody to dokładne bajty odebrane w ciele POST, przed dekodowaniem JSON.
Recepta na Zapier i Make
- W Zapier utwórz Zap z triggerem Webhooks by Zapier - Catch Hook (w Make: moduł Custom Webhook). Skopiuj wygenerowany adres.
- W panelu NavyFlame (Konto - API - Webhooki) dodaj subskrypcję: wybierz zdarzenie i wklej adres jako cel. Sekret podpisu zobaczysz raz - zapisz go.
- Użyj przycisku Wyślij test w panelu, aby potwierdzić, że scenariusz odbiera ładunek.
- (Zalecane) Dodaj krok weryfikacji podpisu powyższą funkcją, zanim zaufasz danym.
RODO
Ładunki webhooków niosą dane osobowe kupujących. Konfigurując subskrypcję (wybór adresu docelowego, np. Zapier - zwykle transfer poza EOG) występujesz jako administrator tych danych, a subskrypcja jest Twoim udokumentowanym poleceniem przetwarzania. Propagacja usunięcia lub anonimizacji danych kupującego do systemów zasilonych przez API i webhooki jest po Twojej stronie.
Przewodniki
Szybki start (od klucza do pierwszego wywołania)
- W panelu (Konto - API) utwórz klucz z potrzebnymi zakresami. Klucz zobaczysz tylko raz - zapisz go w bezpiecznym magazynie sekretów.
- Potwierdź połączenie:
GET /me(nie wymaga zakresu). Zwraca plan, limity i zakresy klucza. - Wykonaj pierwsze wywołanie w docelowym zasobie, np.
GET /orders?limit=25.
Pull-synchronizacja (updatedSince + okno nakładki + dedupe)
- Odpytuj z
updatedSince = ostatni_sync - okno_nakładki(np. 5 minut). Semantyka jest inclusive (>=), precyzja milisekundowa. - Paginuj kursorowo aż
pagination.nextCursorbędzienull. - Deduplikuj po
id- samo>=nie chroni przed rekordem, którego transakcja commitowała po Twoim odczycie (stąd okno nakładki). - Zapisz najwyższy
updatedAtze strony jako punkt startu następnego przebiegu. - Po przywróceniu konta z kopii zapasowej wykonaj pełny resync - nie polegaj na
updatedSince(i utwórz nowe klucze).
Zapier i Make (webhook do akcji)
- W Zapier utwórz trigger Webhooks by Zapier - Catch Hook (w Make: Custom Webhook) i skopiuj wygenerowany adres.
- W panelu (Konto - API - Webhooki) dodaj subskrypcję: wybierz zdarzenie, wklej adres jako cel, zapisz sekret (pokazany raz).
- Kliknij Wyślij test w panelu, aby potwierdzić odbiór ładunku.
- Dodaj krok weryfikacji podpisu (patrz sekcja Webhooki), zanim zaufasz danym.
- Do wywołań zwrotnych do API użyj modułu HTTP / Custom Request z nagłówkiem
Authorization: Bearer.
Rotacja klucza i sekretu webhooka (okno 24 h)
- Klucz API: rotacja w panelu zwraca nowy token raz; stary działa jeszcze 24 h (zero-downtime) - podmień go w integracji w tym oknie. Odwołanie (revoke) jest skuteczne natychmiast.
- Sekret webhooka: rotacja ma okno overlap - stary i nowy sekret podpisują równolegle przez 24 h. Nagłówek podpisu może nieść wiele par
v1=, więc akceptowanie dowolnej pasującej sprawia, że rotacja nie jest zmianą łamiącą. - Po restore z backupu klucze API są automatycznie odwoływane - utwórz nowe i wykonaj pełny resync.
Obsługa limitów (Retry-After + backoff)
- Odczytaj limit planu z
GET /me(rateLimitPerMin) lubGET /usage. Limity są agregowane per konto, nie per klucz. - Każda odpowiedź niesie
X-RateLimit-Limit,X-RateLimit-RemainingiX-RateLimit-Reset- steruj tempem na bieżąco. - Na
429uszanujRetry-After(sekundy) i zastosuj wykładniczy backoff. Trzymaj współbieżność poniżej limitu in-flight (20 równoległych żądań per konto). - Enterprise ma limit per-minuta wyłączony; per-IP flood guard i cap współbieżności działają zawsze (ochrona infrastruktury, nie plan).
Wersjonowanie i zmiany
Wersja jest w ścieżce (/api/public/v1). Zmiany addytywne (nowe pola, nowe endpointy, nowe typy zdarzeń) nie łamią zgodności - Twój klient musi ignorować nieznane pola. Zmiany łamiące zapowiadamy z wyprzedzeniem: wpis w changelogu, e-mail do właścicieli aktywnych kluczy oraz nagłówki Deprecation i Sunset.
Changelog
Historia wersji v1 (numer wersji = kolejna faza rozbudowy). Wszystkie zmiany są addytywne - nie usunęliśmy ani nie zmieniliśmy znaczenia żadnego endpointu ani pola. Aktualna wersja specyfikacji OpenAPI: v1.9.0.
| Wersja | Faza | Co doszło (addytywnie) |
|---|---|---|
| v1.0 | GA | Rdzeń API: /me, zamówienia (odczyt + zapis + fakturowanie), magazyn (odczyt + PATCH stanu), faktury (odczyt), przesyłki (odczyt). Webhooki: order.synced, invoice.issued, shipment.status_updated, catalog.updated. Paginacja keyset, idempotencja, błędy RFC 9457. |
| v1.1 | Faza A | Analityka read-only: raporty sprzedaży / produktów / operacji (+ eksport CSV/XLSX), AI-Ops, monitoring, zużycie oraz statystyki i historia statusów zamówień. |
| v1.2 | Faza B | Dane osobowe read-only: klienci, szablony i logi e-mail, powiadomienia i preferencje, reguły alertów, obsługa posprzedażowa. |
| v1.3 | Faza C | Zapis katalogu: produkty (CRUD), magazyny i lokalizacje, rezerwacje, dokumenty magazynowe, zestawy, szablony (opisów i produktów) oraz treści AI (billable). |
| v1.4 | Faza D1 | Zapis konfiguracji wysyłki: reguły, strefy ze stawkami, opcje dostawy, nadpisania per produkt oraz kalkulator kosztów. |
| v1.5 | Faza D2 | Lifecycle przesyłek i kurier: tworzenie (pojedynczo i zbiorczo), zakup etykiety (billable), anulowanie, tracking, push do Allegro oraz odczyty pomocnicze kuriera (etykieta PDF, punkty, usługi, terminy). |
| v1.6 | Faza E1 | Odkrywanie konektorów (bez sekretów) oraz lokalne odczyty ofert marketplace i mapowań kategorii. |
| v1.7 | Faza E2 | Żywe, płatne odczyty marketplace (produkty, kategorie, GPSR) oraz zapis mapowań kategorii (+ synchronizacja cache). |
| v1.8 | Faza E3 | Publikacja, synchronizacja, pull, import i cennik per kanał realnych ofert marketplace (billable). |
| v1.9 | Faza F | Zapis komunikacji i posprzedaży: powiadomienia, alerty, e-mail (wysyłka billable), ponowne przetwarzanie DLQ oraz obsługa posprzedażowa i zwroty środków (izolowany zakres postsale:refunds:write). |
Wersjonowanie jest w ścieżce: zmiana łamiąca trafiłaby do /v2 z równoległym wsparciem v1 przez min. 6 miesięcy od ogłoszenia (wpis w changelogu, e-mail do właścicieli aktywnych kluczy oraz nagłówki Deprecation i Sunset).
Dobre praktyki
- Testuj połączenie na
GET /meprzed pierwszą integracją. - Zawsze dołączaj
Idempotency-Keydo operacji zapisu i ponawiaj przejściowe błędy z backoffem. - Po przywróceniu konta z kopii zapasowej wykonaj pełną resynchronizację (nie polegaj na
updatedSince) i utwórz nowe klucze - stare są po restore unieważniane. - Do pull-synchronizacji używaj
updatedSincez oknem nakładki i deduplikuj poid.
Najczęściej zadawane pytania
Zaloguj się do panelu, wejdź w Konto - API i utwórz klucz z potrzebnymi zakresami. Klucz zobaczysz tylko raz - zapisz go bezpiecznie. Pierwszy test wykonaj na GET /me, aby potwierdzić połączenie i zobaczyć swój plan oraz limity.
Klucz API służy do wywołań przychodzących - Twój system odpytuje NavyFlame o dane lub wykonuje operacje. Webhook to powiadomienie wychodzące - to NavyFlame wysyła do Ciebie sygnał o zdarzeniu (np. nowe zamówienie), gdy tylko ono nastąpi.
Do odbierania webhooków użyj modułu Webhooks (Zapier) lub Custom Webhook (Make) - podaj adres jako cel subskrypcji w panelu. Do wywołań API użyj modułu HTTP / Custom Request z nagłówkiem Authorization: Bearer. Weryfikację podpisu opisujemy w sekcji Webhooki.
Nie, jeśli użyjesz nagłówka Idempotency-Key. Powtórzenie żądania z tym samym kluczem zwróci ten sam wynik bez podwójnego efektu. Nagłówek jest wymagany przy tworzeniu zamówień i wyzwalaniu fakturowania.
API zwraca 403 z kodem plan_limit do czasu odnowienia. Po przywróceniu konta z kopii zapasowej klucze API są automatycznie unieważniane (utwórz nowe) i zalecamy pełną resynchronizację danych zamiast polegania na updatedSince.
Gotowy, aby zintegrować swój system?
Załóż konto, utwórz klucz API w panelu i zacznij od GET /me.
Załóż konto