My App

Invoice Submission (Single)

Submit invoices to KSeF — JSON, raw XML, and synchronous submission with automatic session management.


Submission Methods Overview

#EndpointInputModeResponseBest for
1POST /api/invoices/submit-syncJSONSync201 + referenceSimple integrations, real-time
2POST /api/invoices/submit-raw-xmlXMLSync201 + referenceERP with own XML generation
3POST /api/invoicesJSONAsync (Kafka)202 + invoice_idHigh volume, fire-and-forget
4POST /api/invoices/queue-raw-xmlXMLAsync (Kafka)202 + invoice_idERP with own XML, high volume

Sync = Gateway sends to KSeF, waits for reference number, returns it in response.
Async = Gateway queues to Kafka, returns immediately. Worker processes in background. Poll for status.

Session management is automatic. The Gateway opens/reuses KSeF sessions transparently. You don't need to call Sessions endpoints before submitting — only ensure a credential exists (Tokens & Certificates).


JSON Invoice Schema (InvoiceCreate)

Used by endpoints #1 and #3. The Gateway generates FA(3) XML from this JSON.

{
  "company_id": "22919080-f3fe-4aff-8d71-f6493afc956a",
  "invoice_type_code": "VAT",
  "invoice_number": "FV/2026/03/001",
  "invoice_date": "2026-03-14",
  "sale_date": "2026-03-14",
  "seller": {
    "nip": "8133793363",
    "name": "Bizneto Mirosław Dykiel",
    "street": "Mieszka I 38",
    "city": "Rzeszów",
    "postal_code": "35-308",
    "country": "PL"
  },
  "buyer": {
    "nip": "8132952463",
    "name": "Test Buyer Sp. z o.o.",
    "street": "ul. Testowa 1",
    "city": "Warszawa",
    "postal_code": "00-001",
    "country": "PL"
  },
  "items": [{
    "position": 1,
    "name": "Usługa integracji KSeF",
    "quantity": "1",
    "unit": "szt",
    "unit_price": "5000.00",
    "vat_rate": "23",
    "net_amount": "5000.00",
    "vat_amount": "1150.00",
    "gross_amount": "6150.00"
  }],
  "summary": {
    "net_total": "5000.00",
    "vat_total": "1150.00",
    "gross_total": "6150.00"
  },
  "tax_breakdowns": [{
    "name": "PTU",
    "category": "S",
    "percent": "23",
    "taxable_base": "5000.00",
    "tax_amount": "1150.00"
  }],
  "currency": "PLN"
}

Required Fields

FieldTypeMaps to XMLDescription
company_idUUID—Company UUID (must match seller NIP)
invoice_type_codestringFa/RodzajFakturyVAT, KOR, ZAL, ROZ, UPR, KOR_ZAL, KOR_ROZ
invoice_numberstringFa/P_2Invoice number
invoice_datedateFa/P_1Issue date (YYYY-MM-DD)
sale_datedateFa/P_6Sale/delivery date
sellerPartyPodmiot1Seller info (NIP must match company)
buyerPartyPodmiot2Buyer info
items[]arrayFa/FaWierszLine items (min 1)
summaryobjectFa/P_13_*, P_14_*, P_15Totals
tax_breakdowns[]arrayFa/P_13_*, P_14_*VAT breakdown by rate

Optional Fields

FieldTypeMaps to XMLDescription
currencystringFa/KodWalutyISO 4217, default: PLN
exchange_ratenumberFa/KursWalutyRequired if non-PLN currency
payment_datedateFa/TerminPlatnosci/TerminPayment due date
descriptionstringStopka/Informacje/StopkaFakturyFooter text (max 3500 chars)
type_operationstring—services (default) or goods
amended_ksef_numberstringFa/NrKSeFFaKorygowanejFor corrections (KOR)
amended_datedate—Original invoice date
amended_numberstring—Original invoice number
amend_typestringFa/P_15ZKCorrection effect: 1=original date, 2=correction date, 3=other

Party (seller/buyer)

FieldTypeRequiredDescription
nipstring✅10-digit Polish NIP
namestring✅Legal name
streetstring✅Street + number
citystring✅City
postal_codestring✅Format: XX-XXX
countrystring❌ISO alpha-2, default PL

Line Item

FieldTypeRequiredMaps toDescription
positionint✅NrWierszaFaLine number (from 1)
namestring✅P_7Item/service description
quantitydecimal✅P_8AQuantity
unitstring✅P_8BUnit: szt, godz, kg, m2...
unit_pricedecimal✅P_9ANet unit price
vat_ratestring✅P_1223, 8, 5, 0, zw, np, oo
net_amountdecimal✅P_11Net total for line
vat_amountdecimal✅P_11VatVAT for line
gross_amountdecimal✅—Gross total for line
pkwiustring❌PKWiUClassification code
cnstring❌CNCombined Nomenclature

Tax Breakdown

FieldTypeRequiredDescription
categorystring✅S=Standard, E=Exempt, Z=Zero, O=Reverse charge, AE=RC EU
percentdecimal✅VAT rate (23, 8, 5, 0)
taxable_basedecimal✅Net amount for this rate
tax_amountdecimal✅VAT amount for this rate
namestring❌Default: PTU
commentstring❌Exemption reason etc.

VAT Rate Mapping

Ratevat_ratecategoryXML net fieldXML VAT field
23%23SP_13_1P_14_1
8%8SP_13_2P_14_2
5%5SP_13_3P_14_3
0% domestic0ZP_13_6—
ExemptzwEP_13_7—
Reverse chargenpO / AEP_13_9—

Endpoint #1: Submit Sync (JSON)

POST /api/invoices/submit-sync
Authorization: Bearer {token}
Content-Type: application/json

Request: Full InvoiceCreate JSON (see section 2).

Response (201):

{
  "invoice_id": "698ac8e1-2355-4e08-bda1-b29054263fee",
  "company_id": "22919080-f3fe-4aff-8d71-f6493afc956a",
  "status": "sending",
  "invoice_type_code": "VAT",
  "invoice_number": "FV/TEST/2026/03/001",
  "invoice_date": "2026-03-14",
  "sale_date": "2026-03-14",
  "created_at": "2026-03-14T09:44:27.189297Z",
  "sent_at": "2026-03-14T09:44:27.353080Z",
  "ksef_reference_number": "20260314-EE-21715A2000-D05678D784-5A",
  "fingerprint": "a7bd1e6d37f5a07bd18f9ee5f16388e4cc731bd9fe57f2c90b500ecb0887c8e3",
  "identifier": "https://ksef-demo.mf.gov.pl/client-app/invoice/8133793363/2026-03-14/p70ebTf1oHvRj57l8WOI5MxzG9n...",
  "qr_code": "iVBORw0KGgo...(base64 PNG)",
  "qr_label": "OFFLINE",
  "xml_url": "/api/invoices/698ac8e1-.../xml",
  "qr_url": "/api/invoices/698ac8e1-.../qr"
}

What happens: Gateway validates JSON → generates FA(3) XML → opens/reuses KSeF session → encrypts with AES-256-CBC → sends to KSeF → returns reference number. Background worker then polls for KSeF number.


Endpoint #2: Submit Raw XML (Sync)

POST /api/invoices/submit-raw-xml
Authorization: Bearer {token}
Content-Type: application/json

Request:

{
  "company_id": "22919080-f3fe-4aff-8d71-f6493afc956a",
  "xml_content": "<?xml version='1.0' encoding='UTF-8'?><Faktura xmlns=\"http://crd.gov.pl/wzor/2025/06/25/13775/\">...</Faktura>"
}

Response (201):

{
  "status": "submitted",
  "invoice_id": "1d69f57c-3c5e-4928-840c-9920e787adcc",
  "ksef_response": {
    "referenceNumber": "20260314-EE-220FD3B000-D0580027F0-3D"
  },
  "xml_hash": "f5edddd131138c0cdb2876416e6ab878ffd99b21071b225462cd9a4ae7365123",
  "xml_size": 1919
}

What happens: Gateway parses XML (extracts P_2, P_1, P_6) → saves to DB → opens/reuses session → encrypts → sends to KSeF. Client is responsible for XML validity.


Endpoint #3: Submit Async JSON (Kafka)

POST /api/invoices
Authorization: Bearer {token}
Content-Type: application/json

Request: Same InvoiceCreate JSON as submit-sync.

Response (202 Accepted):

{
  "invoice_id": "5bf577a5-3335-4c63-a5e0-5d8248b10c67",
  "status": "queued",
  "invoice_number": "FV/ASYNC/2026/03/001"
}

Returns immediately. Invoice queued to Kafka topic invoice.submit. Worker picks it up, processes identically to sync. Poll GET /api/invoices/{id} for final status.


Endpoint #4: Queue Raw XML Async (Kafka)

POST /api/invoices/queue-raw-xml
Authorization: Bearer {token}
Content-Type: application/json

Request: Same RawXMLRequest as submit-raw-xml.

Response (202):

{
  "status": "queued",
  "invoice_id": "73591981-527c-49fb-bb05-e481f358c75d",
  "invoice_number": "FV/ASYNC-XML/2026/03/001",
  "message": "Invoice queued for async submission to KSeF. Poll GET /invoices/{invoice_id} for status."
}

Invoice Lifecycle

              ┌─────────────────────────────────────────────────┐
              │              SUBMISSION FLOW                     │
              │                                                 │
   JSON ──┐   │  ┌────────┐   ┌─────────┐   ┌────────────┐    │
   sync   ├──▶│  │SENDING │──▶│  KSeF    │──▶│REGISTERED  │    │
   XML    ┘   │  └────────┘   │  encrypt │   │ksef_number │    │
              │               │  + send  │   └────────────┘    │
   JSON ──┐   │  ┌────────┐  └────┬─────┘   ┌────────────┐    │
   async  ├──▶│  │QUEUED  │───────┘    ┌───▶│  FAILED    │    │
   XML    ┘   │  │(Kafka) │            │    │error_message│    │
              │  └────────┘            │    └────────────┘    │
              │                        │                       │
   incoming ──▶  ┌────────┐            │    ┌────────────┐    │
   webhook     │  │ DRAFT  │───submit──┘    │ CANCELLED  │    │
              │  └────────┘                 └────────────┘    │
              └─────────────────────────────────────────────────┘
StatusDescriptionFinal?Has ksef_number?
draftCreated via incoming webhook (auto_submit=false)❌❌
queuedIn Kafka queue, waiting for Worker❌❌
sendingWorker sending to KSeF❌❌
registeredRegistered in KSeF✅✅
failedError (check error_message)✅❌
cancelledCancelled/deleted before registration✅❌

Retrieval Endpoints

8.1 Get Invoice

GET /api/invoices/{invoice_id}
Authorization: Bearer {token}

Response (200):

{
  "invoice_id": "4fc06985-2b02-4389-8d89-40a9d1333883",
  "invoice_number": "FV/QR-TEST/2026/03/001",
  "status": "registered",
  "ksef_number": "8133793363-20260314-56B828800000-62",
  "ksef_url": "https://qr-demo.ksef.mf.gov.pl/client-app/invoice/.../verify-download",
  "identifier": "https://qr-demo.ksef.mf.gov.pl/invoice/8133793363/14-03-2026/Q6MltDPzEhCc...",
  "qr_label": "8133793363-20260314-56B828800000-62",
  "fingerprint": "43a325b433f312109ce02568c9844d07d1cff609745db61f168913136aa62fd4",
  "xml_url": "/api/invoices/4fc06985-.../xml",
  "qr_url": "/api/invoices/4fc06985-.../qr",
  "upo_url": "/api/invoice-status/4fc06985-.../download-upo",
  "created_at": "2026-03-14T11:19:58.885183Z",
  "sent_at": "2026-03-14T11:20:00.794107Z",
  "registered_at": "2026-03-14T11:20:14.107706Z"
}

8.2 List Invoices

GET /api/invoices?company_id={id}&invoice_status={status}&skip={n}&limit={n}
Authorization: Bearer {token}
ParameterTypeDescription
company_idUUIDFilter by company
invoice_statusstringdraft, queued, sending, registered, failed, cancelled
skipintOffset for pagination
limitintResults per page

Response (200):

{
  "total": 92,
  "skip": 0,
  "limit": 3,
  "invoices": [
    { "invoice_id": "...", "invoice_number": "INC/2026/03/002", "status": "registered", "ksef_number": "..." },
    { "invoice_id": "...", "invoice_number": "FV/WEBHOOK/2026/03/001", "status": "registered", "ksef_number": "..." }
  ]
}

8.3 Get Invoice XML

GET /api/invoices/{invoice_id}/xml
Authorization: Bearer {token}

Returns raw FA(3) XML (Content-Type: application/xml).

8.4 Get QR Code

GET /api/invoices/{invoice_id}/qr
Authorization: Bearer {token}

Returns PNG image (Content-Type: image/png). QR encodes the identifier URL.

8.5 Get UPO

GET /api/invoices/{invoice_id}/upo
Authorization: Bearer {token}

Returns UPO XML (Urzędowe Poświadczenie Odbioru — Official Receipt).


Invoice Actions

9.1 Submit Draft to KSeF

For invoices created via incoming webhook with auto_submit: false.

POST /api/invoices/{invoice_id}/submit
Authorization: Bearer {token}

Response (202): Invoice moves from draft → queued → processing pipeline.

Error (400): "Cannot submit invoice with status 'cancelled'. Only DRAFT invoices can be submitted."

9.2 Retry Failed Invoice

POST /api/invoices/{invoice_id}/retry
Authorization: Bearer {token}

Response (202): Invoice re-queued for submission.

Error (409): "Invoice already registered in KSeF: 8133793363-20260314-56B828800000-62"

9.3 Cancel / Delete Invoice

DELETE /api/invoices/{invoice_id}?hard={true|false}
Authorization: Bearer {token}
ParameterDefaultDescription
hardfalsefalse = soft delete (status → cancelled), true = physical delete

Response: 204 No Content

Registered invoices can be cancelled in the Gateway database (status → cancelled) but cannot be un-registered from KSeF. The KSeF number remains valid. Use corrective invoices (KOR) for corrections.


FA(3) XML Structure (for raw XML endpoints)

Namespace (CRITICAL)

<?xml version="1.0" encoding="UTF-8"?>
<Faktura xmlns="http://crd.gov.pl/wzor/2025/06/25/13775/"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xsd="http://www.w3.org/2001/XMLSchema">

Wrong namespace = silent rejection. Always use 2025/06/25/13775/.

Complete Tested Example

<?xml version="1.0" encoding="UTF-8"?>
<Faktura xmlns="http://crd.gov.pl/wzor/2025/06/25/13775/"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Naglowek>
    <KodFormularza kodSystemowy="FA (3)" wersjaSchemy="1-0E">FA</KodFormularza>
    <WariantFormularza>3</WariantFormularza>
    <DataWytworzeniaFa>2026-03-14T10:00:00Z</DataWytworzeniaFa>
    <SystemInfo>KSeF API Gateway v1.0.0</SystemInfo>
  </Naglowek>
  <Podmiot1>
    <DaneIdentyfikacyjne>
      <NIP>8133793363</NIP>
      <Nazwa>Bizneto Mirosław Dykiel</Nazwa>
    </DaneIdentyfikacyjne>
    <Adres>
      <KodKraju>PL</KodKraju>
      <AdresL1>Mieszka I 38</AdresL1>
      <AdresL2>35-308 Rzeszów</AdresL2>
    </Adres>
  </Podmiot1>
  <Podmiot2>
    <DaneIdentyfikacyjne>
      <NIP>8132952463</NIP>
      <Nazwa>Test Buyer Sp. z o.o.</Nazwa>
    </DaneIdentyfikacyjne>
    <Adres>
      <KodKraju>PL</KodKraju>
      <AdresL1>ul. Testowa 1</AdresL1>
      <AdresL2>00-001 Warszawa</AdresL2>
    </Adres>
    <JST>2</JST>
    <GV>2</GV>
  </Podmiot2>
  <Fa>
    <KodWaluty>PLN</KodWaluty>
    <P_1>2026-03-14</P_1>
    <P_2>FV/2026/03/001</P_2>
    <P_6>2026-03-14</P_6>
    <P_13_1>2500.00</P_13_1>
    <P_14_1>575.00</P_14_1>
    <P_15>3075.00</P_15>
    <Adnotacje>
      <P_16>2</P_16>
      <P_17>2</P_17>
      <P_18>2</P_18>
      <P_18A>2</P_18A>
      <Zwolnienie><P_19N>1</P_19N></Zwolnienie>
      <NoweSrodkiTransportu><P_22N>1</P_22N></NoweSrodkiTransportu>
      <P_23>2</P_23>
      <PMarzy><P_PMarzyN>1</P_PMarzyN></PMarzy>
    </Adnotacje>
    <RodzajFaktury>VAT</RodzajFaktury>
    <FaWiersz>
      <NrWierszaFa>1</NrWierszaFa>
      <P_7>Integracja API KSeF - pakiet Enterprise</P_7>
      <P_8A>szt</P_8A>
      <P_8B>1</P_8B>
      <P_9A>2500.00</P_9A>
      <P_11>2500.00</P_11>
      <P_11Vat>575.00</P_11Vat>
      <P_12>23</P_12>
    </FaWiersz>
  </Fa>
</Faktura>

XML Adnotacje Section (REQUIRED)

Missing <Adnotacje> = rejection. Default values for a standard VAT invoice:

<Adnotacje>
  <P_16>2</P_16>           <!-- cash method: 1=yes, 2=no -->
  <P_17>2</P_17>           <!-- self-billing: 1=yes, 2=no -->
  <P_18>2</P_18>           <!-- reverse charge: 1=yes, 2=no -->
  <P_18A>2</P_18A>         <!-- split payment: 1=yes, 2=no -->
  <Zwolnienie><P_19N>1</P_19N></Zwolnienie>
  <NoweSrodkiTransportu><P_22N>1</P_22N></NoweSrodkiTransportu>
  <P_23>2</P_23>           <!-- margin invoice: 1=yes, 2=no -->
  <PMarzy><P_PMarzyN>1</P_PMarzyN></PMarzy>
</Adnotacje>

XML Size Limits

LimitValue
Single invoice file1 MB
With attachments (batch)3 MB
DodatkowyOpis value256 chars
StopkaFaktury text3,500 chars

Common XML Validation Errors

ProblemCauseFix
Silent rejectionWrong namespaceUse 2025/06/25/13775/
Missing AdnotacjeSection requiredAdd full block with defaults
Empty <Stopka/>Empty element not allowedRemove or fill with content
<FormaPlatnosci>Text instead of codeUse: 1=cash, 2=transfer, 6=card
<DodatkowyOpis>Missing child elementsMust have both <Klucz> + <Wartosc>
NIP mismatchPodmiot1/NIP ≠ company.nipVerify seller NIP

Invoice Type Codes

CodeXML RodzajFakturyDescription
VATVATStandard VAT invoice
KORKORCorrective invoice
ZALZALAdvance payment invoice
ROZROZSettlement (final after advance)
UPRUPRSimplified invoice
KOR_ZALKOR_ZALCorrection of advance
KOR_ROZKOR_ROZCorrection of settlement

Error Responses

HTTPErrorCause
201—Invoice submitted (sync)
202—Invoice queued (async)
400Only DRAFT invoices can be submittedTrying to submit non-draft
400XML parse errorInvalid XML in raw-xml endpoint
401Not authenticatedMissing/expired JWT
403Access denied to this companyWrong tenant
409Invoice already registered in KSeFRetry on registered invoice
422Field requiredMissing required fields in JSON
422Validation errorTotals don't match, invalid NIP, etc.
503Circuit breaker openKSeF system unavailable

Endpoint Reference

Submission

MethodEndpointInputModeHTTP
POST/api/invoices/submit-syncJSONSync201
POST/api/invoices/submit-raw-xmlXMLSync201
POST/api/invoicesJSONAsync202
POST/api/invoices/queue-raw-xmlXMLAsync202

Retrieval

MethodEndpointDescription
GET/api/invoicesList invoices (filter, paginate)
GET/api/invoices/{id}Get invoice details + all links
GET/api/invoices/{id}/xmlDownload FA(3) XML
GET/api/invoices/{id}/qrDownload QR code (PNG)
GET/api/invoices/{id}/upoDownload UPO (XML)

Actions

MethodEndpointDescription
POST/api/invoices/{id}/submitSubmit draft to KSeF
POST/api/invoices/{id}/retryRetry failed invoice
DELETE/api/invoices/{id}Cancel/delete invoice

Complete Examples

JSON Sync (simplest)

TOKEN="your_jwt_token"
BASE="https://demo.ksefapi.com"

curl -s -X POST "$BASE/api/invoices/submit-sync" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "company_id": "22919080-f3fe-4aff-8d71-f6493afc956a",
    "invoice_type_code": "VAT",
    "invoice_number": "FV/2026/03/001",
    "invoice_date": "2026-03-14",
    "sale_date": "2026-03-14",
    "seller": {"nip":"8133793363","name":"Bizneto","street":"Mieszka I 38","city":"Rzeszów","postal_code":"35-308"},
    "buyer": {"nip":"8132952463","name":"Buyer","street":"ul. Test 1","city":"Warszawa","postal_code":"00-001"},
    "items": [{"position":1,"name":"Service","quantity":"1","unit":"szt","unit_price":"1000.00","vat_rate":"23","net_amount":"1000.00","vat_amount":"230.00","gross_amount":"1230.00"}],
    "summary": {"net_total":"1000.00","vat_total":"230.00","gross_total":"1230.00"},
    "tax_breakdowns": [{"category":"S","percent":"23","taxable_base":"1000.00","tax_amount":"230.00"}],
    "currency": "PLN"
  }' | jq '{invoice_id, status, ksef_reference_number}'

Raw XML Async (fire-and-forget)

# Prepare XML in variable or file
XML='<?xml version="1.0" encoding="UTF-8"?><Faktura xmlns="http://crd.gov.pl/wzor/2025/06/25/13775/">...</Faktura>'

# Submit (escaping handled by jq)
jq -n --arg cid "22919080-..." --arg xml "$XML" '{company_id: $cid, xml_content: $xml}' | \
curl -s -X POST "$BASE/api/invoices/queue-raw-xml" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d @- | jq .

# Poll for result
INVOICE_ID="returned_id"
sleep 5
curl -s "$BASE/api/invoices/$INVOICE_ID" \
  -H "Authorization: Bearer $TOKEN" | jq '{status, ksef_number}'

Test Results (2026-03-14, demo.ksefapi.com)

EndpointInvoiceStatusKSeF NumberTime
submit-sync (JSON)FV/TEST/.../001✅ registered...4B85A3000000-CE~18s
submit-raw-xml (XML)FV/RAW-XML/.../001✅ registered...4CCA28C00000-32~12s
POST /invoices (JSON async)FV/ASYNC/.../001✅ registered...4FFAA8C00000-2E~6s
queue-raw-xml (XML async)FV/ASYNC-XML/.../001✅ registered...506CA3000000-DB~5s

All 4 submission methods verified end-to-end. 92 total invoices in tenant.

Next steps:


On this page