# Typy dokumentów i kwoty

To strona, którą warto przeczytać, zanim zaczniesz budować obsługę fakturowania. Wyjaśnia ona, **jakie typy dokumentów istnieją**, **co przesyłasz** oraz dokładnie **jak obliczane są kwoty**, co do grosza. Poprawne wyliczenia pieniężne to sedno sprawy, dlatego reguły są opisane precyzyjnie.

## Złota zasada: ty przesyłasz ceny, my obliczamy wartości

Dla każdej pozycji przesyłasz **cenę jednostkową** oraz **stawkę VAT**. Resztę oblicza backend. Nigdy nie wyliczasz `amountOfVat` ani `grossValue` samodzielnie i nie powinieneś, ponieważ serwer jest jedynym źródłem prawdy, a Twoje liczby tylko by się rozjeżdżały.

| Przesyłasz | Znaczenie |
|---|---|
| `quantity` | ilość w pozycji (wymagane) |
| `netPrice` **lub** `grossPrice` | cena jednostkowa przed/po VAT (jedna z nich) |
| `vatRate` | stawka VAT (liczba taka jak `23` lub kod specjalny) |
| `discount` | opcjonalne, procent `0–100` |

Backend zwraca, dla każdej pozycji:

| Pole | Sposób obliczenia |
|---|---|
| `netValue` | `round2(quantity × netPrice × (1 − discount/100))` |
| `amountOfVat` | `round2(netValue × rate / 100)` |
| `grossValue` | `round2(netValue + amountOfVat)` |

Jeśli zamiast tego przesyłasz `grossPrice`, obliczenia przebiegają „w dół”: najpierw `grossValue`, następnie `netValue = round2(gross / (1 + rate/100))` oraz `amountOfVat = round2(gross − netValue)`.

### Zaokrąglanie jest w górę (half-up), do grosza

Wszystkie kwoty są zaokrąglane do 2 miejsc po przecinku metodą **zaokrąglania połówek w górę (round half-up)**:

```
round2(x) = Math.round((x + Number.EPSILON) * 100) / 100
```

Zatem `0.345 → 0.35` (a nie `0.34`). Kolejność działań ma znaczenie na granicy zaokrąglenia: VAT to `round2((net × rate) / 100)`, nigdy `net × (rate/100)`. Dla niektórych wartości obie metody różnią się o grosz. Ten sam algorytm działa w naszej bibliotece `fakturnia-shared`, więc dokument utworzony przez API jest identyczny, co do grosza, z dokumentem utworzonym w aplikacji webowej.

> **W każdej pozycji `netValue + amountOfVat` zawsze równa się `grossValue`.** Po zsumowaniu w obrębie dokumentu `netSum + vatSum === grossSum`. Jeśli kiedykolwiek zobaczysz rozbieżność o jeden grosz, jest to błąd. Zgłoś go.

## Stawki VAT

`vatRate` przyjmuje procentową wartość liczbową ze słownika lub **kod specjalny**. Stawki liczbowe: `23, 22, 8, 7, 5, 4, 3`. Kody specjalne (VAT = 0, netto = brutto):

| Kod | Znaczenie |
|---|---|
| `zw` | zwolnione (zwolnione) |
| `np I`, `np II` | nie podlega (nie podlega) |
| `oo` | odwrotne obciążenie (odwrotne obciążenie) |
| `0 WDT` | wewnątrzwspólnotowa dostawa towarów |
| `0 EX` | eksport |
| `0 KR` | krajowa 0% |

Nie istnieje samo `0` ani samo `np`; używaj powyższych kodów. Nieznana stawka zwraca `400 VALIDATION_ERROR`.

## Typy dokumentów

Przez API dostępnych jest dziesięć typów dokumentów. Pięć typów dawnych (legacy) celowo nie zostało udostępnionych (zamiast nich używaj adnotacji, patrz niżej).

| Typ | Czym jest | Wymagane dodatkowe pola |
|---|---|---|
| `Faktura` | Faktura poza KSeF, dla podmiotów zwolnionych z VAT (dostępna do końca 2026) | - |
| `FakturaVAT` | Faktura VAT, odpowiednik faktury podstawowej w KSeF | - |
| `FakturaProforma` | Proforma | - |
| `FakturaProformaBezVAT` | Proforma bez VAT | - |
| `FakturaZaliczka` | Faktura zaliczkowa | `linkedOrderId`, `advancePaymentAmount` |
| `FakturaRozliczeniowa` | Faktura rozliczeniowa (końcowa) | `linkedAdvanceInvoiceIds` |
| `FakturaKorygujaca` | Faktura korygująca | `correctedInvoiceId` |
| `FakturaKorygujacaZaliczkowa` | Korekta faktury zaliczkowej | `correctedInvoiceId`, `correctionAdvanceAmountAfter` |
| `FakturaKorygujacaRozliczeniowa` | Korekta faktury rozliczeniowej | `correctedInvoiceId`, `correctionSettlementAmountAfter` |
| `Zamowienie` | Zamówienie | - |

> **KSeF i przyszłość typów faktur.** `FakturaVAT` to odpowiednik *faktury podstawowej* w KSeF. `Faktura` to dokument, który nie trafia do KSeF, dedykowany podmiotom zwolnionym z VAT — dostępny do końca 2026 roku. Od 1 stycznia 2027 typ `Faktura` przestanie być dostępny, a `FakturaVAT` stanie się typem `FakturaPodstawowa`; przez pewien czas będzie można używać obu typów (tryb legacy). Obecnie używaj wyłącznie `FakturaVAT` jako odpowiednika faktury podstawowej.

## Adnotacje

Szczególne tryby rozliczenia VAT nie są osobnymi typami dokumentów. Zgodnie z KSeF FA(3) ustawiasz je w obiekcie `annotations` na dokumencie, niezależnie od jego typu. Dostępne opcje:

| Adnotacja | Pole | Znaczenie |
|---|---|---|
| Mechanizm podzielonej płatności (MPP) | `isSplitPayment` | Oznacza fakturę jako MPP. Wyklucza się z metodą kasową. Osobne konto VAT możesz podać w polach płatności (`vatAccountNumber` i pokrewne). |
| Odwrotne obciążenie | `isReverseCharge` | Podatek rozlicza nabywca. |
| Metoda kasowa | `isCashMethod` | Rozliczenie VAT w momencie zapłaty. Wyklucza się z MPP. |
| Samofakturowanie | `isSelfInvoicing` | Fakturę wystawia nabywca w imieniu sprzedawcy. |
| Procedura marży | `marginProcedure` | Obiekt `{ enabled, procedureId }`. Identyfikatory procedur (biuro podróży, towary używane, dzieła sztuki, antyki) znajdziesz w słowniku [`marginProcedures`](/docs/dictionaries#procedury-marzy-marginprocedures). |
| Zwolnienie z VAT | `vatExemption` | Obiekt `{ enabled, exemptionType, legalBasis, showOnDocument }`. Typy `A`/`B`/`C` opisuje słownik [`vatExemptionTypes`](/docs/dictionaries#typy-zwolnienia-z-vat-vatexemptiontypes). |

Sprzeczne kombinacje (np. MPP razem z metodą kasową) zwracają `422 ANNOTATIONS_VALIDATION_ERROR` (patrz [Błędy](/docs/errors)). Pełny opis pól każdej adnotacji wraz z przykładami żądań znajdziesz w [Tworzenie dokumentów → Adnotacje](/docs/creating-documents#adnotacje-annotations).

## Informacje dodatkowe: faktura do paragonu

Obok adnotacji KSeF FA(3) przewiduje sekcję „Informacje dodatkowe" (`additionalInfo`). Obecnie API udostępnia w niej jedno pole:

| Pole | Znaczenie |
|---|---|
| `additionalInfo.isInvoiceToReceipt` | Faktura do paragonu (art. 109 ust. 3d ustawy o VAT). |

Ustawienie `isInvoiceToReceipt: true` na dokumencie `FakturaVAT` dodaje flagę `<FP>1</FP>` w dokumencie wysyłanym do KSeF oraz adnotację „Faktura do paragonu" na PDF. To nadal zwykła faktura VAT, a nie osobny typ dokumentu; kwoty liczone są tak samo. KSeF nie przewiduje pola na numer paragonu, więc API również go nie przyjmuje. Szczegóły znajdziesz w [Tworzenie dokumentów → Informacje dodatkowe](/docs/creating-documents#informacje-dodatkowe-additionalinfo).

## Faktury standardowe

`Faktura`, `FakturaVAT`, `FakturaProforma`, `FakturaProformaBezVAT`, `Zamowienie` są obliczane bezpośrednio z ich pozycji: `grossSum = Σ grossValue` i tak dalej. Nic zaskakującego.

## Faktury zaliczkowe (`FakturaZaliczka`)

Faktura zaliczkowa księguje **przedpłatę na poczet zamówienia** (`Zamowienie`). **Nie** jest sumą pozycji zamówienia; jej wartością jest `advancePaymentAmount`.

- Przekazujesz `linkedOrderId` (istniejące `Zamowienie`) oraz `advancePaymentAmount`.
- Backend dzieli zaliczkę **proporcjonalnie pomiędzy stawki VAT zamówienia** i ten podział staje się pozycjami faktury.
- Dlatego `grossSum === advancePaymentAmount`, przy czym `netSum` / `vatSum` wynikają z podziału proporcjonalnego.

```json
{
  "documentType": "FakturaZaliczka",
  "issueDate": "2026-06-04",
  "buyerId": "681a…",
  "linkedOrderId": "6820…",
  "advancePaymentAmount": 615
}
```

Zaliczka nie może przekroczyć wartości brutto zamówienia (`422 ADVANCE_EXCEEDS_ORDER_VALUE`).

## Faktury rozliczeniowe (`FakturaRozliczeniowa`)

Faktura rozliczeniowa (końcowa) zamyka zamówienie po jednej lub kilku zaliczkach. Jej wartość brutto to **kwota pozostała do zapłaty**, a nie pełna suma pozycji.

- Przekazujesz `linkedAdvanceInvoiceIds` (rozliczane faktury zaliczkowe) oraz pełne `products`.
- Backend oblicza `settlementAmount = max(0, Σ products.gross − Σ advances.gross)` (chyba że ustawisz `isSettlementAmountManual: true` i podasz `settlementAmount`).
- `grossSum === settlementAmount`; `netSum` / `vatSum` pochodzą z proporcjonalnego podziału tej kwoty pomiędzy stawki VAT produktów.

Zatem jeśli Twoje pozycje sumują się do 6 150 brutto, a powiązane zaliczki do 2 460, to `grossSum` faktury rozliczeniowej wynosi `3 690`, a nie `6 150`.

## Korekty

> **Pełna instrukcja wystawiania korekt przez API** znajduje się w artykule [Korygowanie dokumentów](/docs/correcting-documents) — trzy typy korekt, wyzerowanie faktury i reguły proporcjonalnego VAT.

Korekta przedstawia dokument na nowo. **`products` to pełny stan „po” korekcie**, cały dokument w postaci, jaką powinien mieć po korekcie. Backend oblicza różnicę; nie przesyłasz pozycji „+/−”.

- **`FakturaKorygujaca`**: sumy to **różnica pozycji**: `Σ after − Σ corrected`. Aby anulować dokument, prześlij te same pozycje z `quantity: 0`.
- **`FakturaKorygujacaZaliczkowa`** koryguje zaliczkę. Sumy to **różnica kwoty zaliczki**: `grossSum = correctionAdvanceAmountAfter − advancePaymentAmountBefore`, z VAT wynikającym z różnicy obu podziałów proporcjonalnych.
- **`FakturaKorygujacaRozliczeniowa`** koryguje rozliczenie. `grossSum = correctionSettlementAmountAfter − settlementAmountBefore`, VAT proporcjonalnie.

```json
{
  "documentType": "FakturaKorygujaca",
  "issueDate": "2026-06-04",
  "correctedInvoiceId": "681a…",
  "correctionReason": "Zmiana ilości",
  "products": [
    { "name": "Usługa", "unitOfMeasure": "szt.", "quantity": 2, "netPrice": 100, "vatRate": 23 }
  ]
}
```

> **Dlaczego ma to znaczenie dla integratorów.** Wartości `grossSum` dla faktur zaliczkowych, rozliczeniowych i korekt *nie* są równe `Σ products`. Jeśli odwzorowujesz sumy faktur we własnym systemie, pobieraj je z odpowiedzi API, nie wyliczaj ich ponownie z pozycji.

## Płatność i daty

| Pole | Uwagi |
|---|---|
| `paymentMethodId` | `1` Gotówka · `2` Karta · `3` Bon · `4` Czek · `5` Kredyt · `6` Przelew · `7` Płatność mobilna |
| `paymentStatusId` | `0` Opłacone (wymaga `additionalPaymentDate`) · `1` Do zapłaty (wymaga `paymentDeadlineDate`) |
| `bankAccounts[]` | dla przelewu; pierwsze staje się rachunkiem głównym, pozostałe są wyświetlane jako dodatkowe |
| `issueDate`, `subDate`, `subDateTo` | data wystawienia / data albo okres sprzedaży (ISO `YYYY-MM-DD`) |
| `paymentInstallments`, `paymentDeadlineTerm` | raty i termin opisowy faktury do zapłaty, patrz [Tworzenie dokumentów](/docs/creating-documents#raty-paymentinstallments) |
| `exchangeRate`, `exchangeRateDate`, `exchangeRateTable` | kurs NBP z dnia roboczego przed obowiązkiem podatkowym, jego dzień i tabela |

Zapłatę, która wpłynęła po wystawieniu, oznaczasz przez `PATCH /documents/{id}/payment-status` z `receivedPayment: RECEIVED` i opcjonalnym `paymentDate` (dzień wpłaty, `YYYY-MM-DD`; domyślnie dzisiejszy dzień w Polsce, nie może być z przyszłości). Przy metodzie kasowej to dzień powstania obowiązku podatkowego (art. 21 ust. 1 ustawy o VAT). `GET /documents/{id}` zwraca go w `payment.receivedPaymentDate`.

## Usuwanie i edycja dokumentów

To, czy dokument można jeszcze zmienić lub usunąć, zależy od jego statusu w KSeF. `DELETE /documents/{id}` oraz aktualizacje dokumentu działają według tej samej reguły:

- Gdy dokument ma już **numer KSeF** (został zatwierdzony w KSeF), jest ostateczny. Usunięcie lub edycja zwraca `400 KSEF_CONFIRMED`.
- Gdy dokument jest **wysłany do KSeF i oczekuje na potwierdzenie**, jest zablokowany. Usunięcie lub edycja zwraca `400 KSEF_SENT`.
- Jeśli wysyłka do KSeF **się nie powiodła** (dokument niesie błąd KSeF), blokada znika. Możesz usunąć dokument albo poprawić go i wysłać ponownie.

Dokumenty, które nigdy nie zostały wysłane do KSeF, zawsze można usunąć lub edytować. Stan dokumentu sprawdzisz przez `GET /documents/{id}/ksef-status` zanim spróbujesz go zmienić.

## Zweryfikuj przed zatwierdzeniem

`POST /documents/validate` uruchamia pełny proces (numerację, sumy, ustalenie stron) i zwraca podgląd **bez zapisywania**. Użyj go, aby pokazać użytkownikom ekran potwierdzenia lub przeprowadzić próbne uruchomienie integracji.

Zobacz [dokumentację API](/api), aby poznać pełny schemat żądania i wszystkie pola.
