API

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/v1

Peł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_klucz

Klucze 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.

ZakresUprawnia do
orders:readOdczyt zamówień (lista, szczegóły, statystyki, historia statusów).
orders:writeZmiana statusu, tworzenie zamówień, wyzwalanie fakturowania.
catalog:readOdczyt katalogu: produkty, magazyny, lokalizacje, rezerwacje, dokumenty magazynowe, zestawy.
catalog:writePełny zapis katalogu: produkty (CRUD), stany i lokalizacje, magazyny, rezerwacje, dokumenty magazynowe, zestawy.
invoices:readOdczyt faktur i statystyk faktur.
shipments:readOdczyt przesyłek i statystyk wysyłek, plus odczyty pomocnicze kuriera (etykieta PDF, punkty odbioru, usługi, terminy nadania).
shipments:writeLifecycle przesyłek: tworzenie, zakup etykiety kurierskiej (płatny u przewoźnika), anulowanie, odświeżanie trackingu, wysyłka numeru śledzenia do Allegro.
shipping:readOdczyt konfiguracji wysyłki: reguły, strefy ze stawkami, opcje dostawy, nadpisania per produkt, plus kalkulator kosztów.
shipping:writeZapis konfiguracji wysyłki: reguły, strefy i stawki per strefa, opcje dostawy, nadpisania wysyłki per produkt.
integrations:readOdczyt listy konektorów konta (bez sekretów): klucz, id konfiguracji, nazwa, status włączenia i połączenia. Nigdy nie zwraca danych logowania.
offers:readOdczyt 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:writeZapis 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:readRaporty sprzedaży, produktów i operacji + eksport CSV/XLSX. Dane wrażliwe biznesowo.
analytics:readAnalityka AI: prognozy zapasów, sugestie cen, anomalie, prognoza sprzedaży, wnioski.
monitoring:readMonitoring integracji (webhooki, faktury, kolejka błędów) i zużycie konta. Detale zawierają dane osobowe.
monitoring:writePonowne przetwarzanie wpisu z kolejki błędów - odpala oryginalny proces (dla faktur wystawia realną fakturę; płatne).
customers:readKlienci (agregacja z zamówień), statystyki, historia i eksport CSV. Pełne dane osobowe.
email:readSzablony i logi e-mail. Logi zawierają adresy odbiorców i tematy.
email:writeZapis szablonów e-mail (limit planu) oraz wysyłka wiadomości (płatna u dostawcy; dedykowany limit ~10/godz).
notifications:readPowiadomienia w aplikacji i preferencje.
notifications:writeTworzenie powiadomień w aplikacji (odbiorca musi być członkiem konta) i oznaczanie jako przeczytane.
alerts:readReguły alertów i historia wyzwoleń.
alerts:writeZapis reguł alertów (kanał e-mail pośrednio generuje wysyłki).
postsale:readObsługa posprzedażowa: wiadomości, spory, zwroty, roszczenia (tylko odczyt). Dane osobowe kupujących.
postsale:writeZapis posprzedaży bez ruchu środków: odpowiedzi w wątkach i sporach, decyzja w sporze, akceptacja/odrzucenie zwrotu (capability-gated per konektor).
postsale:refunds:writeOdrę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:readOdczyt szablonów opisów i szablonów produktów (z wariantami).
templates:writeZapis szablonów opisów i produktów; zastosowanie szablonu tworzy produkt (wymaga też catalog:write).
ai:readOdczyt ustawień AI i historii generowania treści.
ai:writeGenerowanie 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.

PlanKlucze APIZapytaniaWebhooki
Basic51000 / min15
Professional303000 / min50
EnterpriseBez limituBez limituBez 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/stats

Zapis:

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 planu

Eksporty /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/refunds

Klient 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:write

Treś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:read

Przykł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/calculate

Nazwy 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-persons

Zapis 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 prowizji

Izolacja 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 :write obejmuje odpowiadający mu :read. Zapis a + b oznacza cross-scope (potrzebne oba naraz).
  • Idem. - K! = nagłówek Idempotency-Key wymagany; K? = honorowany (opcjonalny); puste = nie dotyczy (odczyt).
  • Błędy - kluczowe kody poza uniwersalnymi 401, 403, 429 (oraz 500/503, które mogą wystąpić wszędzie).

Meta

OperacjaZakresIdem.CelBłędy
GET /me(brak)-Introspekcja klucza: plan, limity, zakresy. Nie wymaga zakresu.-

Zamówienia

OperacjaZakresIdem.CelBłędy
GET /ordersorders:read-Lista zamówień (keyset; filtry status / źródło / data / szukaj).422
POST /ordersorders:writeK!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}/statusorders:writeK?Zmień status (macierz przejść; writeback do Allegro).404,415,422
POST /orders/{id}/invoiceorders:writeK!Wyzwól fakturowanie (asynchroniczne).404,409,422
GET /orders/statsorders:read-Statystyki zamówień (liczniki per status + przychód Paid).422
GET /orders/{id}/status-historyorders:read-Historia realnych przejść statusu zamówienia.404,422

Katalog - produkty

OperacjaZakresIdem.CelBłędy
GET /warehouse-itemscatalog:read-Lista produktów (keyset; filtr status / sku / barcode).422
POST /warehouse-itemscatalog:writeK!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:writeK!Zaktualizuj produkt.404,409,413,415,422
DELETE /warehouse-items/{id}catalog:writeK!Zarchiwizuj produkt (miękkie usunięcie).404,409,422
PATCH /warehouse-items/{id}/stockcatalog:writeK?Ustaw / skoryguj stan (set / adjust, atomowo).404,415,422
GET /warehouse-items/by-barcodecatalog:read-Znajdź produkt lub wariant po kodzie kreskowym.404,422
GET /warehouse-items/{id}/stock-historycatalog:read-Historia zmian stanu produktu (keyset).404,422
POST /warehouse-items/{id}/backordercatalog:writeK!Włącz / wyłącz backorder produktu.404,409,415,422

Katalog - magazyny i lokalizacje

OperacjaZakresIdem.CelBłędy
GET /warehousescatalog:read-Lista magazynów / lokalizacji.-
POST /warehousescatalog:writeK!Utwórz magazyn / lokalizację.409,415,422
PUT /warehouses/{id}catalog:writeK!Zaktualizuj magazyn.404,409,415,422
DELETE /warehouses/{id}catalog:writeK!Usuń magazyn.404,409,422
GET /warehouse-items/{id}/locationscatalog:read-Stan produktu w rozbiciu na lokalizacje.404
PUT /warehouse-items/{id}/locations/{warehouseId}catalog:writeK!Ustaw stan produktu w danej lokalizacji.404,409,415,422
GET /warehouse-settingscatalog:read-Ustawienia automatyzacji magazynu.-
PUT /warehouse-settingscatalog:writeK!Zmień ustawienia automatyzacji magazynu.409,415,422

Katalog - rezerwacje i dokumenty magazynowe

OperacjaZakresIdem.CelBłędy
GET /reservationscatalog:read-Lista rezerwacji stanu (keyset).422
POST /reservationscatalog:writeK!Zarezerwuj stan produktu.404,409,415,422
DELETE /reservations/{id}catalog:writeK!Zwolnij rezerwację.404,409
GET /stock-documentscatalog:read-Lista dokumentów magazynowych (keyset).422
POST /stock-documentscatalog:writeK!Utwórz dokument magazynowy (szkic).409,415,422
GET /stock-documents/{id}catalog:read-Szczegóły dokumentu (z pozycjami).404
POST /stock-documents/{id}/linescatalog:writeK!Dodaj pozycję do dokumentu.404,409,415,422
DELETE /stock-documents/{id}/lines/{lineId}catalog:writeK!Usuń pozycję z dokumentu.404,409,422
POST /stock-documents/{id}/commitcatalog:writeK!Zatwierdź dokument (zastosuj stan).404,409,422
POST /stock-documents/{id}/cancelcatalog:writeK!Anuluj dokument magazynowy.404,409,422

Katalog - zestawy

OperacjaZakresIdem.CelBłędy
GET /bundlescatalog:read-Lista zestawów (keyset).422
GET /bundles/{id}catalog:read-Szczegóły zestawu (komponenty + stan wyliczony).404
PUT /bundles/{id}catalog:writeK!Ustaw komponenty zestawu.404,409,415,422
DELETE /bundles/{id}catalog:writeK!Usuń zestaw (wyczyść komponenty).404,409,422

Szablony (opisów i produktów)

OperacjaZakresIdem.CelBłędy
GET /description-templatestemplates:read-Lista szablonów opisów (keyset).422
POST /description-templatestemplates:writeK!Utwórz szablon opisu.409,413,415,422
GET /description-templates/{id}templates:read-Szczegóły szablonu opisu.404
PUT /description-templates/{id}templates:writeK?Zaktualizuj szablon opisu.404,409,413,415,422
DELETE /description-templates/{id}templates:writeK?Usuń szablon opisu.404
GET /product-templatestemplates:read-Lista szablonów produktów (keyset).422
POST /product-templatestemplates:writeK!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:writeK?Zaktualizuj szablon produktu.404,409,413,415,422
DELETE /product-templates/{id}templates:writeK?Usuń szablon produktu.404
PUT /product-templates/{id}/variantstemplates:writeK?Zamień komplet wariantów szablonu (bulk).404,409,413,415,422
POST /product-templates/{id}/variantstemplates:writeK!Dodaj wariant do szablonu.404,409,415,422
PATCH /product-templates/{id}/variants/{variantId}templates:writeK?Zaktualizuj wariant szablonu.404,409,415,422
DELETE /product-templates/{id}/variants/{variantId}templates:writeK?Usuń wariant szablonu.404
POST /product-templates/{id}/applytemplates:write + catalog:writeK!Utwórz produkt z szablonu (cross-scope).404,409,422

AI - generowanie treści

OperacjaZakresIdem.CelBłędy
GET /ai/settingsai:read-Globalne ustawienia generowania AI.-
PUT /ai/settingsai:writeK?Zmień globalne ustawienia AI.409,415,422
GET /ai/generation-logsai:read-Historia wywołań AI (keyset).422
POST /ai/generate-descriptionai:writeK!Wygeneruj opis produktu (billable).404,409,415,422
POST /ai/translateai:writeK!Przetłumacz produkt (billable).404,409,415,422
POST /ai/batch-generateai:writeK!Wygeneruj opisy wsadowo (billable; max 50).409,413,415,422
POST /ai/batch-translateai:writeK!Przetłumacz wsadowo (billable; max 50).409,413,415,422
POST /ai/preview-templatetemplates:read + catalog:read-Podgląd szablonu z danymi produktu (bez LLM; cross-scope).404,413,415,422

Analityka AI (AI-Ops)

OperacjaZakresIdem.CelBłędy
GET /ai-ops/statusanalytics:read-Status konfiguracji AI + pokrycie danymi.-
GET /ai-ops/stock-predictionsanalytics:read-Prognoza wyczerpania zapasów per SKU (cache 5 min).422
GET /ai-ops/price-optimizationsanalytics:read-Sugestie cenowe z historii zmian cen (cache 5 min).422
GET /ai-ops/anomaliesanalytics:read-Anomalie vs średnia krocząca (cache 5 min).422
GET /ai-ops/sales-forecastanalytics:read-Prognoza sprzedaży (regresja; days = horyzont).422
GET /ai-ops/insightsanalytics:read-Wnioski (billable LLM tenanta; cache 30 min; fallback regułowy).-

Faktury

OperacjaZakresIdem.CelBłędy
GET /invoicesinvoices:read-Lista faktur (keyset; issueDate desc).422
GET /invoices/{id}invoices:read-Szczegóły faktury (z pozycjami i KSeF).404
GET /invoices/statsinvoices:read-Statystyki faktur (KPI lifetime).-

Przesyłki i kurier

OperacjaZakresIdem.CelBłędy
GET /shipmentsshipments:read-Lista przesyłek (keyset).422
GET /shipments/{id}shipments:read-Szczegóły przesyłki (z historią trackingu).404
GET /shipments/statsshipments:read-Statystyki przesyłek (liczniki per status).-
POST /shipmentsshipments:writeK!Utwórz przesyłkę (status Szkic; bez kosztu).409,415,422
POST /shipments/bulkshipments:writeK!Utwórz przesyłki zbiorczo (max 100, partial success).409,413,415,422
POST /shipments/{id}/labelshipments:writeK!Zamów etykietę kurierską (billable - realny koszt).404,409
GET /shipments/{id}/labelshipments:read-Pobierz etykietę kurierską (PDF, binarny).404,409,502
DELETE /shipments/{id}shipments:writeK!Anuluj przesyłkę (u kuriera, jeśli wysłana).404,409,502
POST /shipments/{id}/refresh-trackingshipments:writeK?Odśwież status i tracking u kuriera.404,409,502
POST /shipments/{id}/push-trackingshipments:writeK!Wyślij numer śledzenia do zamówienia w marketplace, z którego pochodzi (Allegro, TikTok Shop).404,400,502
POST /shipments/{id}/push-to-allegroshipments:writeK!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-datesshipments:read-Dostępne terminy nadania (DHL; POST-but-read).415,422,502
GET /shipments/pointsshipments:read-Punkty odbioru / paczkomaty (InPost).502
GET /couriers/{provider}/servicesshipments:read-Lista usług kuriera (Apaczka).502
GET /shipments/allegro/delivery-servicesshipments:read-Lista usług Allegro Delivery.502

Konfiguracja wysyłki

OperacjaZakresIdem.CelBłędy
GET /shipping-rulesshipping:read-Lista reguł wysyłki (keyset).422
POST /shipping-rulesshipping:writeK!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:writeK?Zaktualizuj regułę wysyłki.404,409,415,422
DELETE /shipping-rules/{id}shipping:writeK?Usuń regułę wysyłki.404
GET /shipping-zonesshipping:read-Lista stref wysyłki (z zagnieżdżonymi stawkami).422
POST /shipping-zonesshipping:writeK!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:writeK?Zaktualizuj strefę wysyłki.404,409,415,422
DELETE /shipping-zones/{id}shipping:writeK?Usuń strefę wysyłki.404
POST /shipping-zones/{id}/ratesshipping:writeK!Dodaj stawkę do strefy.404,409,415,422
PUT /shipping-zones/{id}/rates/{rateId}shipping:writeK?Zaktualizuj stawkę w strefie.404,409,415,422
DELETE /shipping-zones/{id}/rates/{rateId}shipping:writeK?Usuń stawkę ze strefy.404
GET /delivery-optionsshipping:read-Lista opcji dostawy (keyset).422
POST /delivery-optionsshipping:writeK!Utwórz opcję dostawy.409,415,422
GET /delivery-options/{id}shipping:read-Szczegóły opcji dostawy.404
PUT /delivery-options/{id}shipping:writeK?Zaktualizuj opcję dostawy.404,409,415,422
DELETE /delivery-options/{id}shipping:writeK?Usuń opcję dostawy.404
GET /products/{productId}/shipping-overridesshipping:read-Nadpisania wysyłki dla produktu (keyset).404,422
POST /products/{productId}/shipping-overridesshipping:writeK!Utwórz nadpisanie wysyłki dla produktu.404,409,415,422
PUT /product-shipping-overrides/{id}shipping:writeK?Zaktualizuj nadpisanie wysyłki produktu.404,409,415,422
DELETE /product-shipping-overrides/{id}shipping:writeK?Usuń nadpisanie wysyłki produktu.404
POST /shipping/calculateshipping:read-Wylicz opcje i koszt wysyłki (POST-but-read).415,422

Klienci

OperacjaZakresIdem.CelBłędy
GET /customerscustomers:read-Lista klientów (agregacja po e-mailu; keyset).422
GET /customers/statscustomers:read-Statystyki klientów (KPI).-
GET /customers/growthcustomers:read-Przyrost klientów w czasie (szereg miesięczny).422
GET /customers/exportcustomers:read-Eksport klientów do CSV (binarny).422
GET /customers/{email}customers:read-Szczegóły klienta (agregat + adresy).404
GET /customers/{email}/orderscustomers:read-Zamówienia klienta (keyset).404,422

E-mail

OperacjaZakresIdem.CelBłędy
GET /email-templatesemail:read-Lista szablonów e-mail (keyset).422
GET /email-templates/{id}email:read-Szczegóły szablonu e-mail.404
GET /email-logsemail:read-Lista logów wysłanych e-maili (keyset; PII).422
POST /email-templatesemail:writeK!Utwórz szablon e-mail (limit planu).409,413,415,422
PUT /email-templates/{id}email:writeK?Zaktualizuj szablon e-mail.404,409,413,415,422
DELETE /email-templates/{id}email:writeK?Usuń szablon e-mail.404,409
POST /emails/sendemail:writeK!Wyślij wiadomość e-mail (billable; ~10/godz).409,413,415,422,502

Powiadomienia

OperacjaZakresIdem.CelBłędy
GET /notificationsnotifications:read-Lista powiadomień tenant-wide (keyset; ?userId zawęża).422
GET /notifications/{id}notifications:read-Szczegóły powiadomienia.404
GET /notifications/unread-countnotifications:read-Liczba nieprzeczytanych powiadomień.422
GET /notification-preferencesnotifications:read-Preferencje powiadomień (wymaga ?userId=).422
POST /notificationsnotifications:writeK!Utwórz powiadomienie (odbiorca = członek konta).413,415,422
POST /notifications/{id}/readnotifications:writeK?Oznacz powiadomienie jako przeczytane.404,409
POST /notifications/read-allnotifications:writeK?Oznacz wszystkie jako przeczytane (wymaga ?userId=).409,422

Alerty

OperacjaZakresIdem.CelBłędy
GET /alert-rulesalerts:read-Lista reguł alertów (keyset).422
GET /alert-rules/historyalerts:read-Historia wyzwoleń alertów (keyset).422
GET /alert-rules/{id}alerts:read-Szczegóły reguły alertu.404
POST /alert-rulesalerts:writeK!Utwórz regułę alertu.413,415,422
PUT /alert-rules/{id}alerts:writeK?Zaktualizuj regułę alertu.404,413,415,422
DELETE /alert-rules/{id}alerts:writeK?Usuń regułę alertu.404,409
POST /alert-rules/{id}/togglealerts:writeK?Włącz / wyłącz regułę alertu.404,409,422

Obsługa posprzedażowa

OperacjaZakresIdem.CelBłędy
GET /post-sale/capabilitiespostsale:read-Mapa zdolności posprzedaży per instancja konektora.-
GET /post-sale/inboxpostsale:read-Zbiorczy inbox (podsumowanie wątków i sporów).-
GET /post-sale/conversationspostsale:read-Lista wątków (keyset).422
GET /post-sale/conversations/{id}postsale:read-Szczegóły wątku.404
GET /post-sale/conversations/{id}/messagespostsale:read-Wiadomości w wątku (keyset).404,422
GET /post-sale/disputespostsale:read-Lista sporów / reklamacji (keyset).422
GET /post-sale/disputes/{id}postsale:read-Szczegóły sporu.404
GET /post-sale/disputes/{id}/messagespostsale:read-Wiadomości w sporze (keyset).404,422
GET /post-sale/returnspostsale:read-Lista zwrotów (keyset).422
GET /post-sale/returns/{id}postsale:read-Szczegóły zwrotu.404
GET /post-sale/refundspostsale:read-Lista zwrotów środków (keyset).422
POST /post-sale/conversations/{id}/messagespostsale:writeK!Odpowiedz kupującemu w wątku.404,413,415,422,502
POST /post-sale/conversations/{id}/readpostsale:writeK?Oznacz wątek jako przeczytany.404,409
POST /post-sale/disputes/{id}/messagespostsale:writeK!Odpowiedz w sporze.404,413,415,422,502
POST /post-sale/disputes/{id}/statuspostsale:writeK!Zmień status sporu (ruch środków wymaga refunds:write).404,413,415,422,502
POST /post-sale/returns/{id}/acceptpostsale:writeK!Zaakceptuj zwrot.404,409,502
POST /post-sale/returns/{id}/rejectpostsale:writeK!Odrzuć zwrot.404,413,415,422,502

Zwroty środków (izolowany zakres pieniężny)

OperacjaZakresIdem.CelBłędy
POST /post-sale/refunds/issuepostsale:refunds:writeK!Realny zwrot środków kupującemu (channel-idempotentne).413,415,422,502
POST /post-sale/refunds/commission-claimpostsale:refunds:writeK!Zgłoś zwrot prowizji.413,415,422,502

Raporty

OperacjaZakresIdem.CelBłędy
GET /reports/salesreports:read-Raport sprzedaży (szereg czasowy + agregaty, marża).422
GET /reports/sales/channelsreports:read-Podział sprzedaży na kanały.422
GET /reports/sales/countriesreports:read-Podział sprzedaży na kraje.422
GET /reports/products/bestsellersreports:read-Bestsellery (sprzedaż + marża brutto).422
GET /reports/products/high-returnsreports:read-Produkty z wysokim wskaźnikiem zwrotów.422
GET /reports/products/low-rotationreports:read-Produkty z niską rotacją.422
GET /reports/operations/slareports:read-Metryki SLA realizacji.422
GET /reports/operations/fulfillmentreports:read-Czas realizacji per kanał.422
GET /reports/export/csvreports:read-Eksport raportu do CSV (binarny).422
GET /reports/export/xlsxreports:read-Eksport raportu do XLSX (binarny).422

Monitoring i zużycie

OperacjaZakresIdem.CelBłędy
GET /monitoring/webhooksmonitoring:read-Lista przychodzących webhooków (bez payloadu).422
GET /monitoring/webhooks/{id}monitoring:read-Szczegół webhooka (surowy payload - PII).404
GET /monitoring/invoice-linksmonitoring:read-Powiązania fakturowania (zamówienie -> faktura).422
GET /monitoring/dlqmonitoring: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/statsmonitoring:read-Zbiorcze statystyki integracji.-
GET /usagemonitoring:read-Zużycie konta (liczniki, miejsce, limity planu).-
POST /monitoring/dlq/{id}/retrymonitoring:writeK!Ponów wpis DLQ (billable; odpala oryginalny workflow).404,409,422

Konektory i oferty marketplace

OperacjaZakresIdem.CelBłędy
GET /connectorsintegrations:read-Lista konektorów tenanta (projekcja bez sekretów).-
GET /warehouse-items/{id}/listingsoffers:read-Oferty marketplace jednego produktu (keyset).404,422
GET /category-mappingsoffers:read-Lista mapowań kategorii (keyset).422
POST /category-mappingsoffers:writeK!Utwórz mapowanie kategorii (lokalnie).409,413,415,422
POST /category-mappings/bulkoffers:writeK?Zbiorczo utwórz mapowania (max 1000).409,413,415,422
PUT /category-mappings/{id}offers:writeK?Przekieruj mapowanie na inny cel.404,409,413,415,422
DELETE /category-mappings/{id}offers:writeK?Usuń mapowanie kategorii.404,409
POST /category-mappings/syncoffers:writeK?Odśwież lokalny cache kategorii (billable).409,413,415,422,502
GET /marketplace/{connectorKey}/productsoffers: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}/categoriesoffers:read-Żywe wyszukiwanie kategorii konektora (billable).502
GET /marketplace/{connectorKey}/categories/{categoryId}/parametersoffers:read-Żywe parametry kategorii (billable).502
GET /marketplace/{connectorKey}/responsible-producersoffers:read-Żywa lista producentów GPSR (billable).502
GET /marketplace/{connectorKey}/responsible-personsoffers:read-Żywa lista osób odpowiedzialnych GPSR (billable).502
POST /warehouse-items/{id}/publish/{connectorKey}offers:writeK!Opublikuj ofertę produktu (billable, realna oferta).404,409,413,415,422,502
POST /warehouse-items/{id}/sync/{connectorKey}offers:writeK!Zaktualizuj opublikowaną ofertę (billable).404,409,413,415,422,502
POST /warehouse-items/{id}/pull/{connectorKey}offers:writeK?Pobierz ofertę z konektora do katalogu (billable).404,409,502
POST /warehouse-items/{id}/refresh-status/{connectorKey}offers:writeK?Odśwież status jednej oferty (billable).404,409,502
POST /warehouse-items/refresh-statusoffers:writeK?Zbiorczo odśwież status ofert (max 100).409,413,415,422
PUT /warehouse-items/{id}/listings/{connectorKey}/pricingoffers:writeK?Ustaw cenę per kanał (lokalnie, bez wywołania).404,409,413,415,422
POST /catalog/importoffers:write + catalog:writeK!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:00Z

Idempotencja

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_progress z Retry-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łaniu

JavaScript

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ówienie

Idempotentny 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)." }]
}
KodHTTPKiedyCo zrobić
unauthorized401Brak, 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_scope403Klucz 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_limit403Plan 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_supported403Operacja 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_found404Zasó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.
conflict409Konflikt 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_conflict409Ten 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_progress409Żą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_large413Treść żądania przekracza 2 MB.Zmniejsz body (np. mniejsze partie w operacjach wsadowych).
unsupported_media_type415Zapis bez nagłówka Content-Type: application/json.Ustaw nagłówek Content-Type: application/json na operacjach zapisu.
validation_failed422Błę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_limited429Przekroczono 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-*.
internal500Błąd po stronie NavyFlame.Ponów z backoffem. Przy powtarzalnym błędzie zgłoś requestId do wsparcia.
bad_gateway502Błą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_unavailable503Restart, 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

  1. W Zapier utwórz Zap z triggerem Webhooks by Zapier - Catch Hook (w Make: moduł Custom Webhook). Skopiuj wygenerowany adres.
  2. W panelu NavyFlame (Konto - API - Webhooki) dodaj subskrypcję: wybierz zdarzenie i wklej adres jako cel. Sekret podpisu zobaczysz raz - zapisz go.
  3. Użyj przycisku Wyślij test w panelu, aby potwierdzić, że scenariusz odbiera ładunek.
  4. (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)

  1. W panelu (Konto - API) utwórz klucz z potrzebnymi zakresami. Klucz zobaczysz tylko raz - zapisz go w bezpiecznym magazynie sekretów.
  2. Potwierdź połączenie: GET /me (nie wymaga zakresu). Zwraca plan, limity i zakresy klucza.
  3. Wykonaj pierwsze wywołanie w docelowym zasobie, np. GET /orders?limit=25.

Pull-synchronizacja (updatedSince + okno nakładki + dedupe)

  1. Odpytuj z updatedSince = ostatni_sync - okno_nakładki (np. 5 minut). Semantyka jest inclusive (>=), precyzja milisekundowa.
  2. Paginuj kursorowo aż pagination.nextCursor będzie null.
  3. Deduplikuj po id - samo >= nie chroni przed rekordem, którego transakcja commitowała po Twoim odczycie (stąd okno nakładki).
  4. Zapisz najwyższy updatedAt ze strony jako punkt startu następnego przebiegu.
  5. 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)

  1. W Zapier utwórz trigger Webhooks by Zapier - Catch Hook (w Make: Custom Webhook) i skopiuj wygenerowany adres.
  2. W panelu (Konto - API - Webhooki) dodaj subskrypcję: wybierz zdarzenie, wklej adres jako cel, zapisz sekret (pokazany raz).
  3. Kliknij Wyślij test w panelu, aby potwierdzić odbiór ładunku.
  4. Dodaj krok weryfikacji podpisu (patrz sekcja Webhooki), zanim zaufasz danym.
  5. 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) lub GET /usage. Limity są agregowane per konto, nie per klucz.
  • Każda odpowiedź niesie X-RateLimit-Limit, X-RateLimit-Remaining i X-RateLimit-Reset - steruj tempem na bieżąco.
  • Na 429 uszanuj Retry-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.

WersjaFazaCo doszło (addytywnie)
v1.0GARdzeń 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.1Faza AAnalityka 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.2Faza BDane osobowe read-only: klienci, szablony i logi e-mail, powiadomienia i preferencje, reguły alertów, obsługa posprzedażowa.
v1.3Faza CZapis katalogu: produkty (CRUD), magazyny i lokalizacje, rezerwacje, dokumenty magazynowe, zestawy, szablony (opisów i produktów) oraz treści AI (billable).
v1.4Faza D1Zapis konfiguracji wysyłki: reguły, strefy ze stawkami, opcje dostawy, nadpisania per produkt oraz kalkulator kosztów.
v1.5Faza D2Lifecycle 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.6Faza E1Odkrywanie konektorów (bez sekretów) oraz lokalne odczyty ofert marketplace i mapowań kategorii.
v1.7Faza E2Żywe, płatne odczyty marketplace (produkty, kategorie, GPSR) oraz zapis mapowań kategorii (+ synchronizacja cache).
v1.8Faza E3Publikacja, synchronizacja, pull, import i cennik per kanał realnych ofert marketplace (billable).
v1.9Faza FZapis 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 /me przed pierwszą integracją.
  • Zawsze dołączaj Idempotency-Key do 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 updatedSince z oknem nakładki i deduplikuj po id.

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

Ta strona korzysta z plików cookies

Używamy plików cookies, aby zapewnić prawidłowe działanie strony, analizować ruch oraz personalizować treści. Dowiedz się więcej w naszej polityce prywatności.

Zarządzaj preferencjami