Fakturnia Developers Szybki start Dokumentacja API English

Uwierzytelnianie

API Fakturnia korzysta z uwierzytelniania w modelu OAuth 2.0 client credentials. Aplikacja wymienia parę client_id / client_secret na krótko żyjący token Bearer (JWT), a następnie dołącza ten token do każdego żądania.

REST API wymaga planu MAX. Konta API, wszystkie endpointy /external/v1 i webhooki są modułem planu MAX. Bez aktywnego planu endpoint tokenu odpowiada 403 z error: "access_denied" i error_code: "SUBSCRIPTION_REQUIRED", a wywołanie z tokenem wydanym wcześniej kończy się 403 SUBSCRIPTION_REQUIRED. Po wygaśnięciu planu integracja przestaje działać do czasu jego przedłużenia; webhooki nie są wtedy wysyłane. Konta pracownicze i uprawnienia w aplikacji nie mają na to wpływu: token działa zawsze jako właściciel konta.

Uzyskiwanie poświadczeń

Utwórz aplikację API w sekcji Inne → Integracje → REST API. Każda aplikacja posiada:

  • client_id (publiczny identyfikator, np. client_5c62e069…),
  • client_secret (sekret, przechowuj go wyłącznie po stronie serwera),
  • zestaw uprawnień scope, które ograniczają zakres działań aplikacji.

Możesz prowadzić wiele aplikacji (np. po jednej na każdą integrację) i niezależnie unieważniać dowolną z nich. Unieważnienie działa natychmiast: tokeny wydane wcześniej dostają 401 UNAUTHORIZED przy kolejnym wywołaniu, nie dopiero po wygaśnięciu. Dla aplikacji możesz też ustawić listę dozwolonych adresów IP; wywołanie z innego adresu kończy się 403 FORBIDDEN.

Dane API są przypisane do środowiska. Poświadczenia z środowiska testowego (https://sandbox.app.fakturnia.pl) działają wyłącznie wobec https://sandbox.api.fakturnia.pl, a poświadczenia produkcyjne wyłącznie wobec https://prod.api.fakturnia.pl. Zacznij od sandboxa, a na produkcję przełącz się dopiero po przetestowaniu integracji.

Żądanie tokenu

curl -s https://prod.api.fakturnia.pl/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{ "grant_type": "client_credentials", "client_id": "...", "client_secret": "..." }'
{ "access_token": "eyJ…", "token_type": "Bearer", "expires_in": 3600, "scope": "documents:create documents:read" }

Tokeny są ważne przez expires_in sekund. Buforuj i ponownie wykorzystuj token aż do momentu zbliżającego się wygaśnięcia, zamiast żądać nowego przy każdym wywołaniu. Po wygaśnięciu API odpowiada 401 TOKEN_EXPIRED: pobierz nowy token i ponów żądanie.

Endpoint tokenu odpowiada zgodnie z OAuth 2.0: 400 invalid_request / unsupported_grant_type przy błędnym żądaniu, 401 invalid_client przy błędnych danych (bez rozróżniania, czy client_id istnieje), 403 access_denied z error_code: "SUBSCRIPTION_REQUIRED" bez planu MAX oraz 403 access_denied bez error_code, gdy żądanie przychodzi z adresu IP spoza listy dozwolonych dla aplikacji.

let cached: { token: string; exp: number } | null = null;

async function getToken(): Promise<string> {
  const now = Date.now();
  if (cached && cached.exp - now > 60_000) return cached.token;
  const res = await fetch('https://prod.api.fakturnia.pl/v1/oauth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      grant_type: 'client_credentials',
      client_id: process.env.FAKTURNIA_CLIENT_ID,
      client_secret: process.env.FAKTURNIA_CLIENT_SECRET,
    }),
  });
  const json = await res.json();
  cached = { token: json.access_token, exp: now + json.expires_in * 1000 };
  return cached.token;
}

Używanie tokenu

Authorization: Bearer <access_token>

Brakujący lub nieprawidłowy token zwraca 401 z kodem UNAUTHORIZED, wygasły 401 TOKEN_EXPIRED. Prawidłowy token bez wymaganego zakresu uprawnień scope zwraca 403 z kodem NO_PERMISSIONS, a errors[0] mówi, którego scope brakuje. Kolejność sprawdzeń: token, stan konta API, adres IP (lista dozwolonych), plan MAX, dopiero potem scope.

Zakresy uprawnień (scope)

Każdy punkt końcowy deklaruje wymagany przez siebie scope. Żądaj wyłącznie tych zakresów uprawnień, których potrzebuje Twoja integracja.

Zasób Zakresy (scope)
Dokumenty documents:browse · documents:read · documents:create · documents:update · documents:delete · documents:download · documents:send-to-ksef · documents:update-payment-status · documents:update-external-reference
Klienci clients:browse · clients:read · clients:create · clients:update · clients:delete
Produkty products:browse · products:read · products:create · products:update · products:delete
Magazyn warehouse:browse · warehouse:create · warehouse:update · warehouse:delete · warehouse:stock:read · warehouse:adjust · warehouse:wz:create · warehouse:documents:create
Pracownicy employees:browse · employees:create · employees:update · employees:delete
Dokumenty cykliczne recurring:browse · recurring:read · recurring:toggle
KSeF ksef:read · ksef:configure · ksef:test
Ustawienia settings:read · settings:update
Webhooki webhooks:read · webhooks:create · webhooks:update · webhooks:delete
Konta pocztowe email-accounts:browse · email-accounts:read
Aktywność activity:read
Firma gus:company:read

Dokładny scope dla każdego punktu końcowego jest podany w dokumentacji API.

Lista kontrolna bezpieczeństwa

  • Przechowuj client_secret po stronie serwera. Nigdy nie umieszczaj go w przeglądarkach, aplikacjach mobilnych ani publicznych repozytoriach.
  • Przechowuj tokeny w pamięci lub krótko żyjącym buforze. Wygasają one, więc ich długotrwałe utrwalanie zwiększa ryzyko bez żadnej korzyści.
  • Używaj wyłącznie protokołu HTTPS. API odrzuca połączenia nieszyfrowane.
  • Natychmiast rotuj sekret w przypadku jego wycieku (unieważnij aplikację i utwórz nową); unieważnienie odcina także tokeny już wydane.
  • Ogranicz źródłowe adresy IP aplikacji, jeśli integracja działa z serwera o stałym adresie.
  • Ograniczaj uprawnienia: integracja, która jedynie odczytuje dane, nie powinna posiadać documents:create.

Sprawdzenie tokenu

GET /auth/me zwraca tożsamość oraz przyznane zakresy uprawnień powiązane z bieżącym tokenem. Użyj go po wdrożeniu integracji, żeby potwierdzić, że token działa i ma właściwe uprawnienia, albo przy debugowaniu, do której aplikacji należy dany token. Endpoint wymaga jedynie ważnego tokenu, bez dodatkowego scope'a.

curl -s https://prod.api.fakturnia.pl/external/v1/auth/me \
  -H "Authorization: Bearer $TOKEN"
{
  "success": true,
  "data": {
    "clientId": "507f1f77bcf86cd799439011",
    "name": "Integracja z e-Sklepem",
    "scopes": ["documents:read", "clients:browse"],
    "userId": "507f1f77bcf86cd799439012"
  }
}