Fakturnia Developers Szybki start Dokumentacja API English

Tworzenie dokumentów

To kompletny przewodnik po POST /external/v1/documents, jedynym endpoincie, którego potrzebujesz, aby wystawić fakturę, proformę, zaliczkę, rozliczenie, korektę lub zamówienie. Opisuje każde pole żądania, sposób ustalania stron transakcji, logikę zależną od typu dokumentu oraz adnotacje KSeF. Reguły obliczeń kwot i pełną mapę typów znajdziesz w Typy dokumentów i kwoty; tutaj skupiamy się na tym, jak zbudować poprawne żądanie.

Jeśli dopiero zaczynasz, najpierw przejdź Szybki start. Pełny, generowany maszynowo schemat każdego pola jest w Dokumentacji API.

Zanim zaczniesz

  • Scope: tworzenie dokumentów wymaga uprawnienia documents:create. Zobacz Uwierzytelnianie.
  • Słowniki to źródło prawdy: zamiast wpisywać wartości enumów na sztywno, pobierz je raz z GET /external/v1/dictionaries. Endpoint zwraca aktualne listy: typy dokumentów, metody i statusy płatności, stawki VAT, kody GTU, waluty, kody krajów, procedury marży, typy zwolnienia z VAT oraz nagłówki dat. Dzięki temu Twoja integracja nie rozjedzie się, gdy dodamy nową pozycję.
  • Idempotencja: każde tworzenie warto wysyłać z nagłówkiem Idempotency-Key, żeby ponowienie po przerwanej sieci nie utworzyło duplikatu. Szczegóły w Idempotentność.

Pełny spis wartości. Wszystkie enumy (typy dokumentów, stawki VAT, waluty, kody krajów, GTU, procedury marży, …) opisuje strona Słowniki, a na żywo pobierzesz je z GET /dictionaries. Słownik zwraca dokładnie te typy dokumentów, które przyjmuje ten endpoint.

Minimalne żądanie

Sam endpoint utworzy dokument już przy documentType, issueDate, nabywcy z nip i name oraz jednej pozycji. To jednak nie wystarczy do realnego obiegu: żeby faktura przeszła wysyłkę do KSeF, nabywca musi mieć pełny adres (street, postalCode, city, countryCode). Dlatego za minimum sensowne uznajemy przykład z adresem. Sprzedawca jest dobierany automatycznie z profilu Twojej firmy.

curl -s -X POST https://prod.api.fakturnia.pl/external/v1/documents \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7c1f1d6e-0b2a-4a1e-9b1a-2a4e9b1a2a4e" \
  -d '{
    "documentType": "FakturaVAT",
    "issueDate": "2026-06-04",
    "buyer": {
      "nip": "5261040828",
      "name": "Acme Corp Sp. z o.o.",
      "street": "Marszałkowska 1",
      "postalCode": "00-001",
      "city": "Warszawa",
      "countryCode": "PL"
    },
    "products": [
      { "name": "Usługa programistyczna", "unitOfMeasure": "szt.", "quantity": 1, "netPrice": 100, "vatRate": 23 }
    ]
  }'

Adres nabywcy a KSeF. Bez adresu dokument utworzy się i pobierzesz go jako PDF, ale wysyłka do KSeF zostanie odrzucona. Jeśli wystawiasz faktury z myślą o KSeF, traktuj adres nabywcy jako wymagany. Dla osoby fizycznej (type: "person") podaj firstName i lastName zamiast name.

Wszystko poza tym jest opcjonalne i ma rozsądne wartości domyślne. Poniżej rozkładamy żądanie na części.

Numerowanie dokumentów

Numer dokumentu składa się z trzech części: symbolu, numeru kolejnego (documentNo) i części datowej (numberingFormat). Najczęstszy układ to numer, a po nim data:

{symbol}{documentNo}{numberingFormat}

Na przykład symbol FV/, numer 4 i format /MM/YYYY dla daty wystawienia 2026-05-07 dają FV/4/05/2026. Część datowa może też stać przed numerem — zależnie od wybranego formatu (patrz „Dostępne formaty" niżej).

Trzy elementy numeru

Element Pole Co to jest
Symbol symbol Prefiks, np. FV/, KOR/. Domyślnie z ustawień firmy dla danego typu dokumentu.
Numer kolejny documentNo Liczba całkowita ≥ 1. To ona rośnie w obrębie okresu.
Format numberingFormat Wzór części „datowej", np. /MM/YYYY. Domyślnie z ustawień, fallback /MM/YYYY.

W formacie podstawiane są tylko dwa tokeny: MM (miesiąc, dwie cyfry) i YYYY (rok), oba z daty wystawienia. Pozostałe znaki (ukośniki, myślniki, litery) wstawiane są dosłownie:

numberingFormat issueDate Część datowa Pełny numer (symbol FV/, nr 4)
/MM/YYYY 2026-05-07 /05/2026 FV/4/05/2026
/YYYY 2026-05-07 /2026 FV/4/2026
-MM-YYYY 2026-05-07 -05-2026 FV/4-05-2026

Dostępne formaty

Pozycja części datowej zależy od wzoru: w wariancie prefiksowym data stoi po numerze, w sufiksowym przed numerem. Oba są wspierane. W kolumnie „Układ" NUMER oznacza documentNo.

Miesięczne (zawierają MM):

Format Układ Przykład (symbol FV/, nr 4, 2026-05)
/MM/YYYY NUMER/MM/YYYY FV/4/05/2026
/YYYY/MM NUMER/YYYY/MM FV/4/2026/05
-MM-YYYY NUMER-MM-YYYY FV/4-05-2026
-YYYY-MM NUMER-YYYY-MM FV/4-2026-05
YYYY/MM/ YYYY/MM/NUMER FV/2026/05/4
MM/YYYY/ MM/YYYY/NUMER FV/05/2026/4
YYYY-MM- YYYY-MM-NUMER FV/2026-05-4
MM-YYYY- MM-YYYY-NUMER FV/05-2026-4

Roczne (tylko YYYY):

Format Układ Przykład (symbol FV/, nr 4, 2026)
/YYYY NUMER/YYYY FV/4/2026
-YYYY NUMER-YYYY FV/4-2026
YYYY/ YYYY/NUMER FV/2026/4
YYYY- YYYY-NUMER FV/2026-4

Domyślny format to /MM/YYYY. numberingFormat jest walidowany względem powyższej listy, więc nieznany wzór jest odrzucany z 400 VALIDATION_ERROR. Gdy podajesz documentNumber ręcznie, musi on odpowiadać układowi wybranego formatu (inaczej 422 NUMBER_MISMATCH).

Numeracja automatyczna (domyślnie)

Gdy nie podasz documentNo, numer nadaje backend:

  • symbol, numberingFormat i tryb numeracji są brane z ustawień Twojej firmy (każde z nich możesz nadpisać w żądaniu).
  • Tryb numeracji to miesięczny (domyślny) albo roczny (ustawienie numberingType). Decyduje, kiedy licznik się zeruje: miesięczny prowadzi osobny licznik dla każdego miesiąca (okres YYYY-MM), roczny dla każdego roku (okres YYYY).
  • Licznik jest atomowy i osobny dla każdej kombinacji firma + typ dokumentu + okres. Pierwszy dokument w okresie dostaje 1, kolejny 2, i tak dalej.
  • Korekty współdzielą jeden licznik: FakturaKorygujaca, FakturaKorygujacaZaliczkowa i FakturaKorygujacaRozliczeniowa numerują się wspólnie.

Trzymaj format zgodny z trybem. Przy numeracji miesięcznej format powinien zawierać MM (np. /MM/YYYY). Unikalność numeru jest sprawdzana w obrębie okresu wynikającego z formatu, więc użycie /YYYY przy trybie miesięcznym zlewa miesiące w jeden okres.

Numeracja ręczna

Aby narzucić własny numer, podaj documentNo (≥ 1). Backend złoży pełny numer z symbolu, numeru i części datowej zgodnie z układem wybranego formatu i sprawdzi, czy numer jest wolny: w swojej serii (typ dokumentu, format numeracji, miesiąc albo rok daty wystawienia) i na całym koncie, bo ten sam pełny numer nie może mieć dwóch dokumentów, także różnych typów albo z różnych miesięcy.

Opcjonalnie dołóż documentNumber (pełny string) jako asekurację: musi dokładnie odpowiadać temu, co backend złoży z symbol/documentNo/numberingFormat, inaczej dostaniesz 422 NUMBER_MISMATCH. To zabezpieczenie przed rozjechaniem się Twojego numeru z naszym.

{
  "documentType": "FakturaVAT",
  "issueDate": "2026-05-07",
  "symbol": "FV/",
  "documentNo": 4,
  "numberingFormat": "/MM/YYYY",
  "documentNumber": "FV/4/05/2026"
}

Numeracja ręczna nie rusza licznika automatycznego. Jeśli mieszasz oba tryby, pilnuj ciągłości numerów po swojej stronie, żeby nie powstały luki ani kolizje.

Pola numeracji

Pole Typ Wymagane Uwagi
symbol string nie Prefiks. Domyślnie z ustawień dla danego typu dokumentu.
documentNo number nie Numer kolejny ≥ 1. Pominięty → numeracja automatyczna.
numberingFormat string nie Wzór części datowej (tokeny MM, YYYY). Domyślnie z ustawień.
documentNumber string nie Pełny numer do walidacji 1:1 z documentNo.

Błędy numeracji

Status Kod Przyczyna
422 NUMBER_MISMATCH documentNumber nie pasuje do numeru, jaki API składa dla układu wybranego formatu (PREFIX {symbol}{documentNo}{date} albo SUFFIX {symbol}{date}{documentNo}).
409 DOCUMENT_NUMBER_EXISTS Numer jest zajęty w swojej serii albo inny dokument na koncie ma już ten sam pełny numer.

Anatomia żądania

Nagłówek dokumentu

Pole Typ Wymagane Uwagi
documentType string tak Jeden z dziesięciu typów (patrz Typy dokumentów). Niezmienny przy edycji.
issueDate string tak Data wystawienia, format ISO 8601 YYYY-MM-DD.
issuePlace string nie Miejsce wystawienia. Domyślnie z ustawień firmy.
currency string nie Kod waluty, domyślnie PLN. Lista w słowniku currencies.
exchangeRate number nie Kurs dla walut innych niż PLN: kurs średni NBP z ostatniego dnia roboczego przed powstaniem obowiązku podatkowego (zwykle przed datą sprzedaży), a gdy faktura jest wcześniejsza, przed datą wystawienia (art. 31a ustawy o VAT).
exchangeRateDate string nie Dzień tabeli NBP, z której jest exchangeRate (YYYY-MM-DD).
exchangeRateTable string nie Numer tabeli NBP, np. 190/A/NBP/2026. Drukowany na PDF obok kursu.
comments string nie Uwagi widoczne na dokumencie. W KSeF trafiają do stopki faktury: Stopka/Informacje/StopkaFaktury.
invoiceName string nie Nazwa wyświetlana dokumentu. Domyślnie generowana z typu i numeru.

Strony transakcji: sprzedawca, nabywca, odbiorca

To najczęstsze źródło pytań od integratorów, więc opiszemy je dokładnie.

Sprzedawca (seller) nigdy nie jest przesyłany w żądaniu. Zawsze pochodzi z profilu firmy uwierzytelnionego użytkownika (user.company): nazwa, NIP, VAT UE, REGON, KRS, BDO, adres oraz dane osobowe dla jednoosobowej działalności. Aby zmienić dane sprzedawcy, zaktualizuj profil firmy, nie żądanie. NIP nabywcy nie może być równy NIP sprzedawcy (422).

Nabywca (buyer) jest wymagany i przekazujesz go na jeden z dwóch sposobów:

  • buyerId (string): identyfikator istniejącego kontrahenta. Pobierz go z GET /external/v1/clients.
  • buyer (obiekt): osadzone dane. Backend wyszukuje zapisanego kontrahenta (po NIP, numerze VAT UE albo nazwie), a gdy go nie znajdzie, tworzy nowego kontrahenta z przekazanych pól. Dzięki temu nie musisz osobno zakładać kontrahenta przed wystawieniem faktury. Identyfikatory podlegają zasadom identyfikatorów kontrahenta: kontrahenta z innego kraju UE podaj jako "identifierType": "vatEu", "vatUE": "DE123456789", nie w nip. Ustalony typ i przeniesione numery zwraca data.warnings, a sprzeczne dane 422 PARTY_IDENTIFIER_INVALID.

Podaj buyerId albo buyer, nie oba naraz.

Odbiorca (receiver) jest opcjonalny i wskazuje odrębny podmiot, który faktycznie odbiera fakturę, inny niż nabywca. Typowy przypadek to struktury jednostek samorządu terytorialnego: nabywcą jest jednostka nadrzędna posiadająca NIP (np. Gmina), a odbiorcą jednostka podległa, która realnie otrzymuje fakturę (np. oddział urzędu albo Przedszkole Publiczne). Przekazujesz go tak samo jak nabywcę: receiverId lub osadzony obiekt receiver. Gdy pominiesz odbiorcę, faktura nie ma osobnego odbiorcy i odbiorcą pozostaje nabywca.

Odbiorca może być dodatkowo identyfikowany przez identyfikator wewnętrzny: ustaw identifierType na idWew i podaj idWew (format NIP-NNNNN, np. 5252248481-16006), co przydaje się m.in. dla jednostek samorządu terytorialnego (JST). Sprzedawca takiej opcji nie ma, w KSeF jest zawsze identyfikowany numerem NIP.

Obiekt kontrahenta (buyer / receiver)

Ten sam zestaw pól obowiązuje dla buyer i receiver. Wszystkie pola poza wskazaniem typu są opcjonalne, ale dla poprawnej faktury podaj dane identyfikujące i adresowe.

Pole Typ Uwagi
id string Identyfikator istniejącego kontrahenta (alternatywa dla buyerId/receiverId).
type string company (domyślnie) lub person. Określa, czy używasz name, czy firstName + lastName.
name string Nazwa firmy (dla company).
firstName, lastName string Imię i nazwisko (dla person).
nip string Polski NIP (10 cyfr; spacje, myślniki i prefiks PL są usuwane, sprawdzana jest cyfra kontrolna). Używany do wyszukania lub utworzenia kontrahenta. Zagraniczny numer VAT podaj w vatUE.
vatUE string Numer VAT UE z prefiksem kraju, np. DE123456789; zapisywany wielkimi literami, bez spacji.
pesel string PESEL osoby fizycznej.
regon, krs, bdo string Pozostałe identyfikatory rejestrowe.
street, postalCode, city string Adres.
country, countryCode string Kod ISO 3166-1 alpha-2 (np. PL, DE), domyślnie PL. Lista w słowniku countries. Do KSeF i PDF liczy się sam countryCode; nazwa country jest opcjonalna (na PDF i tak dobierana z kodu).
email, phoneNumber, www string Dane kontaktowe.
identifierType string Który identyfikator wskazuje stronę w KSeF: nip (pole nip), vatEu (vatUE), other (countryCode i otherTaxIdentifier), idWew (idWew, tylko odbiorca), none (brak). Bez niego API ustala typ z danych, zob. Identyfikatory kontrahenta.
otherTaxIdentifier string Identyfikator podatkowy przy identifierType: "other", do 50 znaków, razem z countryCode (w KSeF KodKraju + NrID).
idWew string Identyfikator wewnętrzny (format NIP-NNNNN, np. 5252248481-16006), używany gdy identifierType: "idWew". Może go mieć tylko odbiorca: w schemacie FA(3) IDWew istnieje wyłącznie dla odbiorcy (Podmiot3), nie dla nabywcy ani sprzedawcy.
fieldsToShow string[] Które pola pokazać na dokumencie, np. ["nip","regon"].

Przykład nabywcy będącego osobą fizyczną:

{
  "buyer": {
    "type": "person",
    "firstName": "Jan",
    "lastName": "Kowalski",
    "street": "Długa 5",
    "postalCode": "80-001",
    "city": "Gdańsk",
    "countryCode": "PL"
  }
}

Wskazówka. Jeśli wystawiasz wiele dokumentów temu samemu kontrahentowi, utwórz go raz przez API kontrahentów i potem przekazuj buyerId. Szybciej i bez ryzyka rozjechania danych przy literówce w nazwie.

Pozycje (products)

Tablica pozycji. Wymagana dla faktur standardowych, rozliczeniowych i korekt. Dla faktury zaliczkowej pozycje są wyliczane z powiązanego zamówienia, więc jej nie przesyłasz (patrz niżej).

Dla każdej pozycji przesyłasz cenę i stawkę VAT, a backend dolicza wartości. Nie wyliczaj netValue, amountOfVat ani grossValue samodzielnie - serwer jest jedynym źródłem prawdy. Dokładne wzory i zasady zaokrąglania opisuje Typy dokumentów i kwoty.

Pole Typ Wymagane Uwagi
name string tak Nazwa towaru lub usługi.
unitOfMeasure string tak Jednostka, np. szt., godz., kg. Dowolny tekst, sugerowane wartości w słowniku.
quantity number tak Ilość. Dla korekt dozwolone 0 (anulowanie pozycji).
vatRate number | string tak Stawka VAT (patrz Stawki VAT).
netPrice number tak* Cena jednostkowa netto.
grossPrice number tak* Cena jednostkowa brutto (alternatywa dla netPrice).
discount number nie Rabat procentowy 0-100.
gtu string nie Kod GTU (GTU_01 do GTU_13). Walidowany względem słownika.
pkwiu string nie Symbol PKWiU.
marginPurchaseValue number nie Tylko vatRate: "marza": kwota nabycia całej pozycji brutto w PLN. Patrz Procedura marży.
marginTaxRate number nie Tylko vatRate: "marza": stawka VAT od marży, 23, 8, 5 albo 0. Domyślnie 23.

* Podaj netPrice lub grossPrice. Jeśli przekazujesz grossPrice, obliczenia idą „w dół” od brutto.

Stawki VAT

vatRate przyjmuje liczbową stawkę procentową albo kod specjalny (string). Pełną listę z opisami zwraca słownik vatRates.

  • Stawki procentowe: 23, 22, 8, 7, 5, 4, 3.
  • Kody specjalne (VAT = 0, netto = brutto): zw (zwolnione), np I i np II (nie podlega), oo (odwrotne obciążenie), 0 KR (krajowa 0%), 0 WDT (wewnątrzwspólnotowa dostawa), 0 EX (eksport), marza (procedura marży, opis niżej).

Nie istnieje samo 0 ani samo np. Nieznana stawka zwraca 400 VALIDATION_ERROR.

Procedura marży

Faktura w procedurze marży (art. 119 ustawy o VAT dla biur podróży, art. 120 dla towarów używanych, dzieł sztuki, przedmiotów kolekcjonerskich i antyków) pokazuje nabywcy tylko kwoty brutto. Pozycję w marży oznaczasz stawką vatRate: "marza":

  • podaj grossPrice (cena brutto); netValue = grossValue, amountOfVat = 0,
  • dokument musi mieć annotations.marginProcedure z enabled: true i procedureId (1 biura podróży, 2 towary używane, 3 dzieła sztuki, 4 przedmioty kolekcjonerskie i antyki); bez tego 422 MARGIN_LINE_WITHOUT_PROCEDURE,
  • w KSeF pozycja nie ma stawki (P_12), a jej suma trafia do P_13_11,
  • na jednej fakturze możesz łączyć pozycje w marży ze zwykłymi stawkami (np. biuro podróży: usługi nabyte dla turysty w marży i własna usługa 23%).

Podatek należy się od marży, czyli różnicy między ceną a kwotą nabycia. Fakturnia liczy go do rejestru VAT i JPK_V7 (pola K_19 i K_20 dla 23%, MR_T lub MR_UZ), dlatego przy pozycji możesz podać:

  • marginPurchaseValue: kwota nabycia całej pozycji brutto w PLN (towar używany: cena zakupu; biuro podróży: koszty usług kupionych bezpośrednio dla turysty). Nie trafia na fakturę ani do KSeF. Bez niej raporty nie liczą VAT od marży tej pozycji i pokazują ostrzeżenie, a MCP ostrzega MARGIN_PURCHASE_MISSING. Kwotę możesz dopisać później przez PUT /documents/{id},
  • marginTaxRate: stawka VAT od marży, 23 (domyślnie), 8, 5 albo 0.

Kwotę nabycia możesz podać także po wystawieniu, również gdy faktura jest już w KSeF: PATCH /documents/{id}/margin-purchases z { "lines": [{ "index": 0, "marginPurchaseValue": 1500, "marginTaxRate": 23 }] }, gdzie index to pozycja w products (od 0). Zmieniają się tylko te dwa pola, treść faktury zostaje. Pominięty klucz zostawia zapisaną wartość, null ją czyści. Pozycja spoza procedury marży daje 422 MARGIN_LINE_NOT_FOUND, zła wartość 422 MARGIN_PURCHASES_INVALID. To samo robi narzędzie MCP updateDocumentMarginPurchases.

Gdy w PUT albo PATCH /documents/{id} wysyłasz pozycję w marży bez marginPurchaseValue i marginTaxRate, zostają wartości zapisane przy pozycji o tej samej nazwie.

VAT od marży = marża × stawka / (100 + stawka). Ujemna marża daje podatek 0 i nie zmniejsza marży z innych pozycji. W korekcie pominięte pola marży są przejmowane z korygowanej pozycji o tej samej nazwie, a kwota nabycia proporcjonalnie do ilości (zwrot jednej z trzech sztuk zmniejsza ją o jedną trzecią).

Pozycja w marży nie ma netto, więc w netSum dokumentu liczy się kwotą brutto (KSeF wykazuje ją osobno w P_13_11). Podgląd POST /documents/validate podaje tę sprzedaż w preview.totals.marginSaleSum, a netto zwykłych stawek to netSum minus marginSaleSum. Bez pozycji w marży marginSaleSum wynosi 0.

{
  "documentType": "FakturaVAT",
  "annotations": { "marginProcedure": { "enabled": true, "procedureId": 3 } },
  "products": [
    { "name": "Obraz olejny", "unitOfMeasure": "szt.", "quantity": 1, "grossPrice": 5000, "vatRate": "marza", "marginPurchaseValue": 3000, "marginTaxRate": 23 }
  ]
}

Płatność

Pole Typ Uwagi
paymentMethodId number 1 Gotówka · 2 Karta · 3 Bon · 4 Czek · 5 Kredyt · 6 Przelew · 7 Płatność mobilna
paymentStatusId number 0 Zapłacono · 1 Do zapłaty
paymentDeadlineDate string Termin płatności. Wymagany, gdy paymentStatusId = 1.
additionalPaymentDate string Data zapłaty. Wymagana, gdy paymentStatusId = 0.
additionalPaymentDateHeaderId number Nagłówek nad datą zapłaty (słownik paymentDateHeaders).
paymentDescription string Dodatkowy opis płatności.
showPaymentSection boolean Czy pokazać sekcję płatności na PDF. Domyślnie true.

Zapłaty częściowe (partialPayments)

Gdy do dnia wystawienia nabywca zapłacił część kwoty (albo całość w kilku wpłatach), przekaż listę wpłat. Trafiają one do KSeF jako ZaplataCzesciowa i na PDF jako informacja o wpłatach.

Pole Typ Znaczenie
partialPayments[].amount number kwota wpłaty brutto
partialPayments[].date string data wpłaty (YYYY-MM-DD), nie późniejsza niż issueDate
partialPayments[].paymentMethodId number forma wpłaty jak paymentMethodId (opcjonalna)

Reguły zależą od paymentStatusId:

  • 1 (Do zapłaty): suma wpłat musi być mniejsza niż kwota do zapłaty; reszta ma termin z paymentDeadlineDate.
  • 0 (Zapłacono): co najmniej dwie wpłaty o sumie równej kwocie do zapłaty; additionalPaymentDate nie jest wtedy wymagane.

Niezgodne wpłaty odpowiadają 422 PARTIAL_PAYMENTS_INVALID. Gdy faktura ma zapłaty częściowe, data zapłaty całości (additionalPaymentDate) nie trafia do KSeF: daty są przy wpłatach. W odpowiedzi payment zawiera partialPayments (pusta lista, gdy ich nie ma), paidAmount (zapłacono według treści faktury) i amountDue (pozostało do zapłaty), więc integracja nie musi tego liczyć.

{
  "paymentMethodId": 6,
  "paymentStatusId": 1,
  "paymentDeadlineDate": "2026-10-10",
  "partialPayments": [
    { "amount": 500, "date": "2026-09-20", "paymentMethodId": 6 }
  ]
}

Raty (paymentInstallments)

Faktura płatna w kilku terminach podaje raty: każda z datą i kwotą. W KSeF każda rata to osobny TerminPlatnosci, a kwoty rat trafiają do DodatkowyOpis (FA(3) nie ma pola na kwotę raty). Na PDF raty zastępują pojedynczy termin.

Pole Typ Znaczenie
paymentInstallments[].date string termin raty (YYYY-MM-DD)
paymentInstallments[].amount number kwota raty brutto, w walucie dokumentu

Reguły: tylko przy paymentStatusId = 1, co najmniej dwie raty, najwyżej 100, terminy po kolei i nie wcześniej niż issueDate, suma równa kwocie do zapłaty. Bez paymentDeadlineDate terminem płatności dokumentu jest pierwsza rata. Niezgodne raty odpowiadają 422 PAYMENT_INSTALLMENTS_INVALID. Pusta lista ([]) w PUT albo PATCH usuwa raty. Raty równe policzy za Ciebie API: patrz Równe raty.

{
  "paymentStatusId": 1,
  "paymentMethodId": 6,
  "paymentInstallments": [
    { "date": "2026-10-20", "amount": 615 },
    { "date": "2026-11-20", "amount": 615 }
  ]
}

Równe raty (paymentInstallmentsSplit)

Gdy raty mają być równe, nie licz kwot u siebie: podaj liczbę rat, a API podzieli kwotę do zapłaty po wyliczeniu sum dokumentu. Dokument dostaje zwykłe paymentInstallments (są w odpowiedzi, w podglądzie validate i w KSeF), a samego podziału API nie zapisuje.

Pole Typ Znaczenie
paymentInstallmentsSplit.count number liczba rat, od 2 do 100 (wymagana)
paymentInstallmentsSplit.firstDate string termin pierwszej raty (YYYY-MM-DD), nie wcześniej niż issueDate; domyślnie paymentDeadlineDate z żądania, a bez niego issueDate + 14 dni
paymentInstallmentsSplit.every string month (co miesiąc, domyślnie), week (co 7 dni) albo 14days (co 14 dni)

Jak API liczy raty:

  • Kwota do zapłaty (brutto, w walucie dokumentu; na fakturze rozliczeniowej kwota po rozliczeniu zaliczek) jest zamieniana na grosze raz, z zaokrągleniem połówki od zera.
  • Każda rata dostaje tyle samo groszy, a reszta z dzielenia trafia do ostatniej: 100,00 na 3 raty to 33,33 + 33,33 + 33,34. Suma rat zawsze równa się kwocie do zapłaty.
  • Raty miesięczne liczone są od pierwszej daty: 31 stycznia, 28 lutego, 31 marca.
  • Terminem płatności dokumentu (paymentDeadlineDate) staje się data pierwszej raty.

Reguły: tylko przy paymentStatusId = 1. Przy tworzeniu bez paymentStatusId dokument dostaje status Do zapłaty; status 0 (Zapłacono) odpowiada błędem. Nie łącz z paymentInstallments: raty o różnych kwotach (np. większa pierwsza rata) podaj w paymentInstallments. PATCH bez products dzieli kwotę zapisaną w dokumencie, a bez firstDate zaczyna od zapisanego terminu płatności. Kwota mniejsza niż grosz na ratę, zła liczba rat, data albo odstęp odpowiadają 422 PAYMENT_INSTALLMENTS_INVALID, z opisem w errors[0], np. „Kwota jest za mała na tyle rat.”. null oznacza brak podziału.

Żądanie (fragment POST /external/v1/documents, suma brutto 1 230,00 zł):

{
  "documentType": "FakturaVAT",
  "issueDate": "2026-10-07",
  "paymentMethodId": 6,
  "paymentStatusId": 1,
  "paymentInstallmentsSplit": { "count": 3, "firstDate": "2026-10-31", "every": "month" }
}

Odpowiedź (fragment data.document):

{
  "paymentDeadlineDate": "2026-10-31",
  "paymentInstallments": [
    { "date": "2026-10-31", "amount": 410 },
    { "date": "2026-11-30", "amount": 410 },
    { "date": "2026-12-31", "amount": 410 }
  ]
}

POST /external/v1/documents/validate zwraca te same raty w preview.paymentInstallments, więc możesz je pokazać przed wystawieniem.

Termin opisowy (paymentDeadlineTerm)

Termin płatności można też opisać słowami, np. „14 dni od dnia wystawienia faktury”. W KSeF trafia do TerminOpis, na PDF obok daty terminu.

Pole Typ Znaczenie
paymentDeadlineTerm.count number liczba jednostek, liczba całkowita od 1
paymentDeadlineTerm.unit string day, week albo month
paymentDeadlineTerm.event string od czego liczy się termin: issue (wystawienie faktury), invoice_delivery (doręczenie faktury), supply (dostawa towaru lub wykonanie usługi), acceptance (odbiór)

paymentDeadlineDate nadal podaje datę terminu; przy event: issue powinna wynikać z opisu. null w PUT albo PATCH usuwa opis.

Kilka wpłat na fakturze zaliczkowej (advanceReceipts)

Faktura zaliczkowa może dokumentować kilka wpłat otrzymanych przed jej wystawieniem (w KSeF ZaliczkaCzesciowa, przykład 16 z broszury MF). Każda wpłata to osobny moment powstania obowiązku podatkowego (art. 19a ust. 8 ustawy o VAT), więc raport VAT i JPK ujmują je osobno.

Pole Typ Znaczenie
advanceReceipts[].date string dzień otrzymania wpłaty, nie późniejszy niż issueDate
advanceReceipts[].amount number kwota wpłaty brutto
advanceReceipts[].exchangeRate number w walucie obcej: kurs NBP z dnia roboczego przed otrzymaniem wpłaty (wymagany)
advanceReceipts[].exchangeRateDate string dzień tabeli NBP tego kursu (opcjonalny)

Reguły: tylko FakturaZaliczka z paymentStatusId = 0, od dwóch do 31 wpłat, suma równa advancePaymentAmount. Data otrzymania zapłaty dokumentu to data ostatniej wpłaty. Niezgodne wpłaty odpowiadają 422 ADVANCE_RECEIPTS_INVALID.

Rachunki bankowe

Dla płatności przelewem (paymentMethodId = 6) podaj bankAccounts, chyba że masz domyślny rachunek w ustawieniach firmy. Pierwszy rachunek staje się głównym, pozostałe są wyświetlane jako dodatkowe.

Pole Typ Wymagane Uwagi
accountNumber string tak Numer rachunku / IBAN.
bank string nie Nazwa banku.
swift string nie Kod SWIFT dla przelewów zagranicznych.
accountDescription string nie Opis rachunku na dokumencie.
bankOwnAccountType number nie 1, 2 lub 3.

Dla mechanizmu podzielonej płatności możesz dodatkowo podać osobne konto VAT: vatAccountNumber, vatAccountBank, vatAccountSwift, vatAccountDescription. Samą adnotację MPP włączasz przez annotations.isSplitPayment (patrz niżej).

Daty sprzedaży

Pole Typ Uwagi
subDate string Data sprzedaży / dostawy / wykonania usługi (KSeF P_6), z subDateTo początek okresu. Dla typów KSeF i zamówień domyślnie równa issueDate. Korekta bez subDate przejmuje datę albo okres sprzedaży faktury korygowanej.
subDateTo string Koniec okresu sprzedaży, np. usługa za cały miesiąc (KSeF OkresFa). null w PUT albo PATCH wraca do jednej daty.
subDateHeaderId number Nagłówek nad datą sprzedaży (słownik additionalDateHeaders).
taxPointRule string Obowiązek podatkowy z chwilą wystawienia faktury (art. 19a ust. 5 ustawy o VAT): art19a5p3a usługi budowlane, art19a5p3b dostawa książek i prasy, art19a5p3c druk książek i prasy, art19a5p4 media, telekomunikacja, najem, dzierżawa, leasing, ochrona, stała obsługa prawna i biurowa. Nie trafia do KSeF; decyduje o okresie w raportach VAT i o dniu kursu waluty. null oznacza zwykłe zasady.

Daty dokumentu nie mogą sobie przeczyć. API odrzuca z 422 DOCUMENT_DATES_INVALID (komunikaty w errors):

  • okres sprzedaży, którego początek jest późniejszy niż koniec;
  • datę sprzedaży późniejszą o więcej niż 60 dni od daty wystawienia (art. 106i ust. 7; okresu rozliczeniowego to nie dotyczy);
  • datę zapłaty (additionalPaymentDate) późniejszą niż data wystawienia przy paymentStatusId = 0. Zapłatę, która wpłynęła po wystawieniu, oznacz przez PATCH /documents/{id}/payment-status z paymentDate;
  • korektę z datą wystawienia wcześniejszą niż faktura korygowana.

Termin płatności wcześniejszy niż data wystawienia jest dozwolony (spóźniona faktura może mieć termin, który już minął).

Adnotacje (annotations)

Adnotacje to nowoczesny sposób oznaczania szczególnych trybów rozliczenia VAT zgodny z KSeF FA(3). Zastępują dawne, osobne typy faktur (jak FakturaMPP czy FakturaVATMarza), których API celowo nie udostępnia.

Pole Typ Znaczenie
isSplitPayment boolean Mechanizm podzielonej płatności (MPP). Wyklucza się z isCashMethod.
isReverseCharge boolean Odwrotne obciążenie.
isCashMethod boolean Metoda kasowa. Wyklucza się z isSplitPayment.
isSelfInvoicing boolean Samofakturowanie.
marginProcedure obiekt Procedura marży.
vatExemption obiekt Zwolnienie z VAT.

Procedura marży (annotations.marginProcedure):

Pole Typ Uwagi
enabled boolean Włącza procedurę.
procedureId number Wymagane, gdy enabled = true. Wartości w słowniku marginProcedures (np. biuro podróży, towary używane, dzieła sztuki, antyki).

Zwolnienie z VAT (annotations.vatExemption):

Pole Typ Uwagi
enabled boolean Włącza zwolnienie.
exemptionType string A (przepis ustawy), B (dyrektywa 2006/112/WE) lub C (inna podstawa prawna).
legalBasis string Podstawa prawna jako tekst, np. art. 43 ust. 1 pkt 19 ustawy o VAT.
showOnDocument boolean Czy pokazać adnotację na PDF. Nie wpływa na dokument wysyłany do KSeF (zwolnienie i tak trafia do P_19/P_19A/P_19B/P_19C) — steruje wyłącznie wyświetlaniem na PDF.
{
  "annotations": {
    "isSplitPayment": true,
    "vatExemption": {
      "enabled": true,
      "exemptionType": "A",
      "legalBasis": "art. 113 ust. 1 ustawy o VAT"
    }
  }
}

Informacje dodatkowe (additionalInfo)

Sekcja KSeF FA(3) „Informacje dodatkowe” — osobna od adnotacji. Na razie udostępnia jedno pole:

Pole Typ Znaczenie
isInvoiceToReceipt boolean Faktura do paragonu (art. 109 ust. 3d ustawy o VAT).

Gdy ustawisz isInvoiceToReceipt: true, w dokumencie wysyłanym do KSeF zostaje ustawiona flaga <FP>1</FP>, a na PDF pojawia się adnotacja „Faktura do paragonu, o której mowa w art. 109 ust. 3d ustawy”. Typ dokumentu (RodzajFaktury) nie zmienia się — to zwykła faktura VAT z dodatkowym oznaczeniem, a nie osobny typ dokumentu. KSeF nie przewiduje pola na numer paragonu, więc API również go nie przyjmuje.

{
  "additionalInfo": {
    "isInvoiceToReceipt": true
  }
}

Podpisy (signatures)

Opcjonalne bloki podpisu na PDF.

{
  "signatures": {
    "issuerSignature": { "show": true, "value": "Jan Nowak" },
    "receiverSignature": { "show": false }
  }
}

Pozostałe pola

  • ksefJst (boolean): dokument dla jednostki samorządu terytorialnego na potrzeby KSeF.

Wartości domyślne z ustawień konta

Dokument wystawiony przez API wygląda tak samo jak nowy dokument z edytora w aplikacji: pola, których nie wyślesz, dostają wartości z ustawień konta. Pole wysłane jawnie zawsze wygrywa (także pusty tekst "" albo pusty obiekt {}), a useAccountDefaults: false wyłącza wszystkie wartości domyślne konta.

Pole Wartość domyślna
comments Uwagi z ustawień dokumentów.
issuePlace Miejsce wystawienia z ustawień, a gdy puste: miasto z adresu firmy.
signatures Pola podpisów według ustawienia podpisów; wystawia imię i nazwisko właściciela albo pracownika, który wystawia dokument.
annotations Automatyczne adnotacje (jeśli włączone): mechanizm podzielonej płatności z rachunkiem VAT (vatAccountNumber z rachunku oznaczonego jako VAT) i procedura marży. Korekty ich nie dostają.
annotations.vatExemption Pozycje ze stawką zw dostają podstawę zwolnienia z ustawień (typ A/B/C i podstawa prawna).
paymentMethodId 6 (przelew) z domyślnym rachunkiem.
paymentStatusId Domyślny status z ustawień: zapłacono (data zapłaty = data wystawienia) albo do zapłaty (termin = data wystawienia).
products[].vatRate Domyślna stawka VAT konta.
taxPointRule Domyślna reguła z ustawienia „Obowiązek podatkowy z datą wystawienia faktury” (Ustawienia → Autouzupełnianie), gdy jest włączone i ma wybraną regułę. Dotyczy faktur sprzedaży w KSeF poza korektami i fakturą zaliczkową; jawne taxPointRule: null jej nie dostaje.
sprzedawca Widoczne pola sprzedawcy z ustawień (fieldsToShow).
PKWiU na wydruku Według ustawienia wyświetlania PKWiU.

Odpowiedź POST /documents/validate wymienia każdą zastosowaną wartość w preview.appliedDefaults (kod, pole, zdanie do pokazania użytkownikowi), a preview.resolved pokazuje płatność, miejsce, uwagi i adnotacje po ich uwzględnieniu.

Korekty przejmują z korygowanej faktury nabywcę, odbiorcę, walutę z kursem i adnotacje (z rachunkiem VAT), jeśli ich nie wyślesz, więc buyerId jest dla nich opcjonalne. Faktury, do której istnieje korekta, nie zmienisz ani nie usuniesz (409 DOCUMENT_CORRECTED): zmianę wprowadza kolejna korekta. Po usunięciu ostatniej korekty faktura znowu jest edytowalna.

FakturaProformaBezVAT ma zawsze VAT 0 na pozycjach, jak w aplikacji, niezależnie od wysłanej stawki. FakturaZaliczka nie ma daty sprzedaży.

Typy dokumentów i ich pola

Endpoint przyjmuje dziesięć typów. Poniżej tylko pola dodatkowe wymagane dla danego typu; reguły obliczeń sum dla zaliczek, rozliczeń i korekt opisuje Typy dokumentów i kwoty.

Typ Czym jest Wymagane dodatkowo
Faktura Faktura poza KSeF (podmioty zwolnione, do końca 2026) -
FakturaVAT Faktura VAT (odpowiednik faktury podstawowej KSeF) -
FakturaProforma Proforma -
FakturaProformaBezVAT Proforma bez VAT -
FakturaZaliczka Faktura zaliczkowa linkedOrderId, advancePaymentAmount (bez products)
FakturaRozliczeniowa Faktura rozliczeniowa (końcowa) linkedAdvanceInvoiceIds, products
FakturaKorygujaca Faktura korygująca correctedInvoiceId, products (pełny stan „po”); nabywca z korygowanej faktury
FakturaKorygujacaZaliczkowa Korekta zaliczki correctedInvoiceId, correctionAdvanceAmountAfter
FakturaKorygujacaRozliczeniowa Korekta rozliczenia correctedInvoiceId, correctionSettlementAmountAfter
Zamowienie Zamówienie -

Pola powiązane z typami specjalnymi:

Pole Typ Dla
linkedOrderId string FakturaZaliczka: powiązane Zamowienie.
advancePaymentAmount number FakturaZaliczka: kwota zaliczki (≥ 0.01, ≤ wartość zamówienia).
linkedAdvanceInvoiceIds string[] FakturaRozliczeniowa: rozliczane faktury zaliczkowe.
settlementAmount number FakturaRozliczeniowa: kwota do rozliczenia (auto, chyba że isSettlementAmountManual).
isSettlementAmountManual boolean FakturaRozliczeniowa: wymusza ręczną settlementAmount.
correctedInvoiceId string Korekty: korygowana faktura.
correctionReason string Korekty: przyczyna (tekst).
correctionAdvanceAmountAfter number FakturaKorygujacaZaliczkowa: nowa kwota zaliczki po korekcie.
correctionSettlementAmountAfter number FakturaKorygujacaRozliczeniowa: nowa kwota rozliczenia po korekcie.

Sumy nie zawsze równają się Σ products. Dla zaliczek, rozliczeń i korekt grossSum wynika z osobnej logiki. Jeśli odwzorowujesz kwoty u siebie, bierz je z odpowiedzi API, nie wyliczaj ponownie. Pełne wzory w Typy dokumentów i kwoty.

Walidacja na sucho

POST /external/v1/documents/validate uruchamia pełny proces (numeracja, ustalenie stron, sumy) i zwraca podgląd bez zapisywania dokumentu. Idealne, by pokazać użytkownikowi ekran potwierdzenia albo przetestować integrację bez zaśmiecania konta.

Idempotencja

Wyślij nagłówek Idempotency-Key (zalecany UUID v4). Powtórzenie tego samego żądania z tym samym kluczem zwróci zapisaną odpowiedź zamiast tworzyć duplikat (cache 24 h). To samo żądanie z innym ciałem i tym samym kluczem zwróci błąd. Zobacz Idempotentność.

Najczęstsze błędy

Status Kod Przyczyna
400 VALIDATION_ERROR Niepoprawny lub brakujący typ, data, stawka VAT, struktura pól.
403 NO_PERMISSIONS Token bez scope documents:create.
404 DOCUMENT_NOT_FOUND Nieznany buyerId, receiverId, correctedInvoiceId lub linkedOrderId.
409 DOCUMENT_NUMBER_EXISTS Numer dokumentu już istnieje.
422 DOCUMENT_DATES_INVALID Daty dokumentu przeczą sobie albo ustawie o VAT (patrz Daty sprzedaży).
422 PAYMENT_INSTALLMENTS_INVALID Raty nie zgadzają się z kwotą, terminami albo statusem płatności, albo paymentInstallmentsSplit nie da się wykonać.
422 ADVANCE_RECEIPTS_INVALID Wpłaty zaliczki nie zgadzają się z kwotą zaliczki, datami albo kursami.
422 - Reguły domenowe: zaliczka większa niż zamówienie, isSplitPayment razem z isCashMethod, brak wymaganej daty płatności, NIP nabywcy równy NIP sprzedawcy.

Pełna lista kodów i koperta błędu są w Błędy.

Co dalej