Correcting documents
You issue corrections with the same endpoint as any other document, POST /external/v1/documents, using one of three types:
FakturaKorygujaca— correction of a regular invoice,FakturaKorygujacaZaliczkowa— correction of an advance invoice,FakturaKorygujacaRozliczeniowa— correction of a settlement invoice.
Every correction requires correctedInvoiceId (the id of the corrected invoice). It may carry correctionCause (the cause: an event after the sale or an error on the invoice), which decides the correction type in KSeF, and correctionReason (a description of the reason), see Cause of a correction and its effect in KSeF. Corrections are sent to KSeF like regular invoices (the KOR kind), see Sending to KSeF.
Shared numbering (per KSeF). All three correction types share one numbering counter. Whichever correction you issue, the next numbers come from the same pool within the period (e.g. the month). Numbering rules are described in Creating documents.
The delta principle: you send the "after" state
In every correction you send the target state of the document after the correction, and the backend computes the difference against the corrected invoice. You do not send "+/−" line items. The correction totals (netSum, vatSum, grossSum) are a delta and can be negative (when the correction lowers the value). Take them from the API response, don't recompute them.
A further correction of the same invoice
A document has at most one correction. You issue the next change as a correction of the latest correction (correctedInvoiceId is that correction's id). Its "before" state is then the state after the previous correction, so the amounts do not count it twice: after an invoice of 1000 PLN net and a correction down to 900 PLN, the next correction down to 700 PLN is −200 PLN net, not −300 PLN.
A new correction of a document that already has a correction gets 409 CORRECTED_INVOICE_HAS_CORRECTION. The message in errors[0] gives the number and the id of the latest correction of the chain, the one to correct:
{
"success": false,
"message": "CORRECTED_INVOICE_HAS_CORRECTION",
"errors": ["Dokument FV/1/07/2026 ma już korektę. Ostatnia korekta to KOR/1/08/2026 (id 6820a1b2c3d4e5f6a7b8c9d1): kolejną zmianę wystaw jako korektę tej korekty, żeby stan przed korektą uwzględniał poprzednie zmiany."]
}
PUT and PATCH answer the same when you change a correction's correctedInvoiceId to a document that already has another correction.
In KSeF a correction of a correction names the original invoice in DaneFaKorygowanej (its number, issue date and KSeF number, or the NrKSeFN marker when it was issued outside KSeF), while its "before" lines and amounts follow the state after the previous correction. This is what the KSeF 2.0 manual, part II, section 2.13.3 asks for. On the printout "Korygowany dokument" is the original invoice and "Poprzednia korekta" names the correction the "before" state comes from.
Original invoice without a KSeF number
When the original invoice has no KSeF number, the correction goes to KSeF with the NrKSeFN marker, that is as a correction of an invoice issued outside KSeF. Fakturnia neither holds nor refuses such a send. On an account connected to KSeF, POST /documents/validate then gives one of these codes in preview.warnings:
| Code | When | What to do |
|---|---|---|
CORRECTION_ORIGINAL_KSEF_PENDING |
The original invoice was sent or waits in the queue and has no KSeF number yet. | Send the correction once the invoice has its number. |
CORRECTION_ORIGINAL_NOT_SENT_TO_KSEF |
The original invoice is issued today and was not sent. | Send the invoice first, then the correction. A correction sent earlier is not linked in KSeF to the invoice sent later. |
CORRECTION_ORIGINAL_OUTSIDE_KSEF |
The original invoice can no longer go to KSeF: Fakturnia sends an invoice only on its issue day, and some types never go to KSeF. | Nothing. The NrKSeFN marker matches the facts. |
Each entry has a code and a Polish message you can show to the user. The list is empty when there is nothing to note.
Cause of a correction and its effect in KSeF
A correction can say why you issue it. That decides the TypKorekty field of the XML sent to KSeF and the period in which the correction enters the app's reports (VAT register, JPK_V7, KPiR).
| Field | Values | Meaning |
|---|---|---|
correctionCause |
after_sale, mistake, null |
after_sale: an event after the sale (discount, return of goods, complaint, price or quantity changed after the sale). mistake: an error on the corrected invoice (price, quantity, VAT rate, amount or data, including an invoice issued to the wrong buyer or issued twice). |
correctionType |
1, 2, 3, null |
TypKorekty set by hand: 1 effect on the date the original invoice was recorded, 2 on the issue date of the correction, 3 on another date. Leave it out and Fakturnia works it out. |
correctionReason |
text, at most 256 characters | The reason printed on the PDF and sent to KSeF (PrzyczynaKorekty). Optional. |
correctionEffectDate |
YYYY-MM-DD, null |
The day the correction takes effect for VAT when it is neither the date of the corrected invoice nor the date of the correction. For an increase after the sale it is the day the cause arose, e.g. a price rise was agreed (art. 29a ust. 17); with correctionType: 3 the day of the effect. KSeF has no field for it; the VAT report and JPK_V7 place the correction on this day. |
correctionConfirmationDate |
YYYY-MM-DD, null |
A decreasing correction issued outside KSeF (e.g. to a consumer): the day the buyer's confirmation of receipt arrived. The decrease counts in the period of the confirmation (art. 29a ust. 13a), and the VAT report places it there. |
When you leave out correctionType, Fakturnia works out TypKorekty when it sends the correction to KSeF:
correctionCause |
What the correction does to the amounts | TypKorekty |
|---|---|---|
after_sale or none |
raises the tax base, correctionEffectDate in another month than the correction |
3 |
after_sale or none |
any other case | 2 |
mistake |
raises the tax base or changes no amount | 1 |
mistake |
lowers the tax base | 2 |
mistake |
takes the whole invoice to zero (wrong buyer, duplicate) | 1 |
mistake |
raises one rate and lowers another | 3 |
The rule follows the Polish VAT Act: an increase belongs to the period its cause arose in (art. 29a ust. 17), so for an error the period of the original invoice and for an event after the sale the day in correctionEffectDate, a decrease issued in KSeF to the period of the correction (art. 29a ust. 13 and 14), and a correction to zero of an invoice that should not exist to the period of the original invoice (Ministry of Finance, 20 May 2026). In income tax an error correction goes back to the period of the original invoice (art. 14 ust. 1m of the PIT Act).
{
"documentType": "FakturaKorygujaca",
"issueDate": "2026-10-06",
"correctedInvoiceId": "681a3b2c4d5e6f7a8b9c0d1e",
"correctionCause": "mistake",
"correctionReason": "Wrong unit price",
"products": [
{ "name": "Service", "unitOfMeasure": "pcs", "quantity": 1, "netPrice": 150, "vatRate": 23 }
]
}
This correction fixes an error and raises the tax base, so it goes to KSeF with TypKorekty 1.
What the fields affect:
- KSeF.
TypKorektyin the correction's XML. WithoutcorrectionCauseandcorrectionTypewe send2, as before, so existing integrations keep working unchanged. - Reports in the app. The VAT register and JPK_V7 place a correction with
TypKorekty1 in the period of the corrected invoice, and the KPiR places a correction with themistakecause in the revenue period of the corrected invoice. Both periods get a notice about the move. - Reading.
GET /documents/{id}and thedocument.createdanddocument.updatedwebhooks return both fields:nullwhen not given, andcorrectionType: nullmeans the type is worked out. - Changing.
PUTandPATCHaccept both fields until the correction is sent to KSeF. On documents that are not corrections the fields are ignored. - Sale date and period. A correction without
subDatetakes the sale date or period of the corrected invoice: FA(3) is filled in as it stands after the correction, and the supply happened when the original invoice says. A correction of an advance invoice has no sale date. - Exchange rate. A correction without
exchangeRatetakes the corrected invoice's rate with its NBP day and table number (art. 31b ust. 1), also when you name the same currency. - Issue date. A correction cannot have an issue date earlier than the corrected invoice (
422 DOCUMENT_DATES_INVALID). - Validation. A value outside the dictionary and a reason longer than 256 characters are validation errors:
400 VALIDATION_ERRORonPOST,422 VALIDATION_ERRORonPUTandPATCH. A too long reason used to be rejected only by KSeF, when sending.
Invoice correction (FakturaKorygujaca)
The most common correction: a change of quantity, price, VAT rate or line data.
productsis the full state of the lines after the correction (the whole document as it should look after the change).- Totals:
grossSum = Σ(lines after) − grossSum of the corrected invoice(likewisenetSumandvatSum).
{
"documentType": "FakturaKorygujaca",
"issueDate": "2026-06-04",
"correctedInvoiceId": "681a3b2c4d5e6f7a8b9c0d1e",
"correctionReason": "Quantity change",
"products": [
{ "name": "Service", "unitOfMeasure": "szt.", "quantity": 2, "netPrice": 100, "vatRate": 23 }
]
}
Zeroing out / cancelling an invoice
To cancel a document (e.g. after an order is cancelled), issue a correction with the same lines but quantity: 0, keeping the netPrice/grossPrice from the original invoice. A line with quantity 0 has a value of 0, so the "after" state is 0 and the correction delta fully reverses the invoice down to zero.
{
"documentType": "FakturaKorygujaca",
"issueDate": "2026-06-04",
"correctedInvoiceId": "681a3b2c4d5e6f7a8b9c0d1e",
"correctionReason": "Order cancellation",
"products": [
{ "name": "Service", "unitOfMeasure": "szt.", "quantity": 0, "netPrice": 100, "vatRate": 23 }
]
}
You keep the unit price on purpose. KSeF expects the "after" line with the pre-correction price and a quantity of 0, not an empty line. The line value is derived from the quantity, so with
quantity: 0it is 0.
Advance invoice correction (FakturaKorygujacaZaliczkowa)
Corrects a previously issued advance invoice (a change to the advance amount or to the linked order's lines).
Required fields:
correctedInvoiceId— the corrected advance invoice (it must have a linked order andadvancePaymentAmount) or, for a further change, the latest advance correction of that invoice,products— the order lines after the correction (the basis of the proportional split),correctionAdvanceAmountAfter— the new advance amount after the correction (≥ 0).
Totals:
grossSum = correctionAdvanceAmountAfter − the advance before the correction(the advance invoice'sadvancePaymentAmount, or the previous advance correction'scorrectionAdvanceAmountAfter, whose lines are then the order before the correction),netSum/vatSumare the difference of the proportional VAT splits of both amounts (see How taxes are calculated).
{
"documentType": "FakturaKorygujacaZaliczkowa",
"issueDate": "2026-06-04",
"correctedInvoiceId": "6820a1b2c3d4e5f6a7b8c9d0",
"correctionReason": "Lower advance",
"correctionAdvanceAmountAfter": 500,
"products": [
{ "name": "Item A", "unitOfMeasure": "szt.", "quantity": 10, "netPrice": 100, "vatRate": 23 }
]
}
Settlement invoice correction (FakturaKorygujacaRozliczeniowa)
Corrects a settlement (final) invoice.
Required fields:
correctedInvoiceId— the corrected settlement invoice,products— the lines after the correction,correctionSettlementAmountAfter— the new settlement amount after the correction (≥ 0).
Totals:
grossSum = correctionSettlementAmountAfter − the settlement amount before the correction,netSum/vatSumare the difference of the proportional VAT splits (as above).
{
"documentType": "FakturaKorygujacaRozliczeniowa",
"issueDate": "2026-06-04",
"correctedInvoiceId": "6830a1b2c3d4e5f6a7b8c9d0",
"correctionReason": "Settlement correction",
"correctionSettlementAmountAfter": 1230,
"products": [
{ "name": "Item A", "unitOfMeasure": "szt.", "quantity": 10, "netPrice": 100, "vatRate": 23 }
]
}
Correcting an invoice downloaded from KSeF
A sales invoice issued in another system and downloaded from KSeF (source: "ksef", direction: "income") can be corrected like your own: pass its _id as correctedInvoiceId. The API reads its lines, totals and buyer address from the invoice XML itself (fetching it from KSeF when the invoice was never opened in the app), so the "before" state and the StanPrzed rows sent to KSeF match the original. In DaneFaKorygowanej the correction names the KSeF number of the original invoice.
Limits: only a sales invoice (a purchase invoice is corrected by its issuer) and only a plain VAT invoice; advance, settlement and correction invoices downloaded from KSeF carry no data in Fakturnia to build the "before" state from.
How taxes are calculated
A regular correction (FakturaKorygujaca) computes totals directly, as a difference of lines: (sum of lines after) − (sum of the corrected invoice), separately for net, VAT and gross.
Advance and settlement corrections work differently, because an advance and a settlement are a single gross amount that has to be split across VAT rates. A proportional split does this:
- The lines (the order's for an advance, the invoice's for a settlement) are grouped by VAT rate and summed by gross.
- Each rate gets a share of the amount proportional to its gross:
share = rate gross / total gross. The last rate gets the remainder, which removes rounding cents. - From the gross assigned to a rate, net and VAT are derived:
net = gross / (1 + rate/100),VAT = gross − net. Special rates (zw,oo,np …,0 …) have VAT = 0, net = gross.
A correction is the difference of two such splits: the split of the "after" amount minus the split of the "before" amount. That is why grossSum is simply the difference of the amounts, while netSum / vatSum follow from the difference of the proportional splits. Example: when an advance of 615 (rate 23%) drops to 500, grossSum = 500 − 615 = −115, and net and VAT are the difference of the two splits.
The proportional split is identical to the one used when issuing the advance or settlement invoice itself, so a correction always reconciles to the grosz against the original document.
Common errors
| Status | Code | Cause |
|---|---|---|
422 |
CORRECTED_INVOICE_REQUIRED |
Missing correctedInvoiceId. |
409 |
CORRECTED_INVOICE_HAS_CORRECTION |
The corrected document already has a correction. Correct its latest correction, whose number and id are in errors[0]. |
404 |
CORRECTED_INVOICE_NOT_FOUND |
The corrected invoice was not found. |
422 |
CORRECTION_ADVANCE_AMOUNT_REQUIRED |
Missing correctionAdvanceAmountAfter (≥ 0) for an advance correction. |
422 |
CORRECTION_ADVANCE_BASE_MISSING |
The corrected advance invoice has no linked order / advancePaymentAmount (or the corrected advance correction has no lines or correctionAdvanceAmountAfter). |
422 |
CORRECTION_SETTLEMENT_AMOUNT_REQUIRED |
Missing correctionSettlementAmountAfter (≥ 0) for a settlement correction. |
400 / 422 |
VALIDATION_ERROR |
correctionCause or correctionType outside the dictionary, correctionReason longer than 256 characters (400 on POST, 422 on PUT and PATCH). |
422 |
CORRECTED_INVOICE_NOT_INCOME |
The corrected invoice is a purchase invoice downloaded from KSeF; its issuer corrects it. |
422 |
CORRECTED_INVOICE_TYPE_MISMATCH |
The corrected invoice's type does not match the correction type; for an invoice downloaded from KSeF only a VAT invoice is allowed. |
422 |
CORRECTED_INVOICE_WITHOUT_POSITIONS |
The lines of the corrected invoice could not be read from KSeF (e.g. a KSeF outage); try again. |
What's next
- Creating documents — the full request anatomy and numbering.
- Document types & amounts — calculation rules and rounding.
- Sending to KSeF — send a correction to KSeF.
- Errors — codes and handling.