Sending transactions

Send each invoice or credit note as one document to POST /transactions, with all its lines inside it. Invoice fields go on the document once. Lines carry only what can differ within an invoice.

Batches are fine

Send as many documents in one call as fit, up to 500 lines or 5 MB. A whole month sent in a run of calls after month-end close is fine, and so is one document per call as invoices are posted. Both use the same endpoint and are processed the same way. Each document in a call is accepted or refused on its own, so one bad document never holds back the rest.

Document fields

Field Required Notes
client_ref yes Your id for the client legal entity
document_id yes Your permanent id for the document. Never reused. A credit note has its own
document_type yes invoice or credit_note
source_updated_at yes When the document last changed in your ERP. Orders versions
action yes upsert or void
invoice_number yes As printed. On a credit note, its own number
invoice_date yes On a credit note, its own date
currency yes Invoice currency
tax_jurisdiction yes The country of the client's VAT registration the document falls under. For OSS and IOSS, the registration country, not the consumer's. See Tax codes
counterparty_name yes The other party: the customer on a sale, the supplier on a purchase
counterparty_country yes Where the customer or supplier is established
lines yes At least one
counterparty_vat_number when the tax code needs it With country prefix. Needed for B2B cross-border and reverse charge
tax_point_date when it differs from the invoice date The date of supply or payment. PL and CZ use it to set the period
original_invoice_number, original_invoice_date on a credit note, whenever it credits one invoice The invoice being credited. Links the two
e_invoice_reference when e-invoiced The clearance id, for example KSeF (PL) or SDI (IT)
ship_from_country, ship_to_country goods that cross a border Where the goods left from and arrived. For OSS goods, ship_to_country is the consumer's country

Line fields

Field Required Notes
line_id yes Your id for the line, for example the ERP entry id, or its sequence number. Unique within the document and kept the same across versions
net yes As printed. Usually negative on a credit note, and negative on a discount line
vat yes The VAT charged on the line, as printed. Zero when none
vat_rate yes Percent: 23, not 0.23
tax_code yes A VAT IT tax code, or your own code where VAT IT keeps the mapping for that client
goods_or_services yes goods or services
tax_jurisdiction rarely Only when this line falls under a different registration than the document
ship_from_country, ship_to_country rarely Only when this line's goods moved between different countries than the document's, for example an invoice shipped from two warehouses
  • Gross is never sent. It is always net plus VAT.
  • Amounts are signed as printed. Send each line with the sign it has in your ERP. A discount line on an invoice is negative, and a line on a credit note that reverses a discount is positive.
  • Item lines or tax summary lines. Both are accepted. Line vat must add up to the invoice's VAT per rate. Where your ERP rounds at invoice level, put the rounding difference on one line.
  • One tax per line. Countries with more than one tax on a line come later, without breaking this shape.

How signs are checked

VAT IT checks the sign of the document, not of each line. It adds up the lines' net and their vat:

document_type Sum of net Sum of vat
invoice zero or more zero or more
credit_note zero or less zero or less

If either sum has the wrong sign, the document is refused with total_sign_invalid. VAT IT works these totals out from the lines, so you never send them.

Example

{
  "documents": [
    {
      "client_ref": "KD-10042",
      "document_id": "INV-2026-000981",
      "document_type": "invoice",
      "source_updated_at": "2026-11-02T09:12:44Z",
      "action": "upsert",
      "invoice_number": "FV/2026/11/981",
      "invoice_date": "2026-11-02",
      "tax_point_date": "2026-10-30",
      "currency": "PLN",
      "tax_jurisdiction": "PL",
      "counterparty_name": "Nowak Sp. z o.o.",
      "counterparty_country": "PL",
      "counterparty_vat_number": "PL7010001454",
      "e_invoice_reference": "5252248481-20261102-ABC123-45",
      "lines": [
        {"line_id": "1", "net": "10000.00", "vat": "2300.00", "vat_rate": "23", "tax_code": "sale_domestic", "goods_or_services": "goods"},
        {"line_id": "2", "net": "500.00", "vat": "40.00", "vat_rate": "8", "tax_code": "sale_domestic", "goods_or_services": "goods"}
      ]
    }
  ]
}

The values are illustrative only.

The response

Whenever the body can be read, the call returns 200 with one result per document, in the order sent.

outcome Meaning
accepted Stored. Processing follows in the next cycle
duplicate Same key and body as before. The original result is returned
refused Not stored. Fix it and resend with a newer source_updated_at

A document is accepted or refused as a whole. If one of its lines is refused, the document is refused, and the other documents in the call are unaffected. Fix the refused one and resend it alone: resending the others is harmless.

Reading the result

The reads are optional. If you only send, the response to each call is enough: fix and resend the documents it refused.

  • GET /transactions/{client_ref}/{document_id} shows each line's status, errors, warnings and the returns it feeds.
  • GET /transactions?client_ref=...&updated_since=... lists every document that changed. Poll it to stay in step. Every status, validity and filing change moves updated_at.
  • GET /transactions?client_ref=...&level=line&validity=error lists every line in error, without reading whole documents.
  • To reconcile a period, filter GET /transactions by invoice_date_from, invoice_date_to and status, and compare with your ledger.