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": 300,
"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). |
| orders:write | Zmiana statusu, tworzenie zamówień, wyzwalanie fakturowania. |
| catalog:read | Odczyt produktów magazynowych. |
| catalog:write | Korekta stanu magazynowego. |
| invoices:read | Odczyt faktur. |
| shipments:read | Odczyt przesyłek. |
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 | 2 | 60 / min | 5 |
| Professional | 10 | 300 / min | 25 |
| Enterprise | Bez limitu | 1000 / min | Bez limitu |
Zasoby i operacje
Odczyt (paginacja kursorowa, filtry, sortowanie):
GET /orders GET /orders/{id}
GET /warehouse-items GET /warehouse-items/{id}
GET /invoices GET /invoices/{id}
GET /shipments GET /shipments/{id}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}'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.
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 |
|---|---|---|
| unauthorized | 401 | Brak lub nieprawidłowy klucz API. |
| missing_scope | 403 | Klucz nie ma wymaganego zakresu (np. orders:write). |
| plan_limit | 403 | Subskrypcja wygasła lub plan nieaktywny. |
| not_found | 404 | Zasób nie istnieje w Twoim koncie. |
| idempotency_conflict | 409 | Ten sam Idempotency-Key użyty z inną treścią. |
| idempotency_in_progress | 409 | Żądanie z tym kluczem jest właśnie przetwarzane (ponów). |
| payload_too_large | 413 | Treść żądania przekracza 2 MB. |
| unsupported_media_type | 415 | Brak nagłówka Content-Type: application/json. |
| validation_failed | 422 | Błędne dane wejściowe (szczegóły w polu errors). |
| rate_limited | 429 | Przekroczono limit zapytań (patrz Retry-After). |
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.
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.
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) - zaakceptuj dowolną pasującą. Sprawdzaj zgodność znacznika czasu (tolerancja 300 s), aby chronić się przed powtórką.
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"),
),
);
}Weryfikuj podpis na surowym ciele żądania (bajty przed parsowaniem JSON) - ponowne serializowanie zmieni bajty i podpis się nie zgodzi.
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.
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.
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.
Najczesciej 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