3 API3.3
Przesłanie XML: POST /invoices/xml
XML w formacie UBL, CII lub FA(3).
- W sandboxie
Prostymi słowami
To wywołanie przesyła fakturę, która istnieje już jako gotowy plik XML. Plik przechodzi kontrolę bezpieczeństwa i walidatory właściwe dla kanału, a jeśli je przejdzie, trafia do kolejki.
POST /invoices/xml przyjmuje gotowy plik UBL, CII lub FA(3). Plik nie jest mapowany. Usługa sprawdza bezpieczeństwo i typ pliku, uruchamia oficjalne walidatory właściwe dla kanału, a potem umieszcza plik w kolejce i wysyła go w niezmienionej postaci. Dla FA(3) kontrole to schemat oraz reguły KSeF dotyczące pliku i dat.
Uwaga
202 oznacza, że plik przeszedł kontrolę bezpieczeństwa i jest w kolejce. Aby sprawdzić plik przed wysłaniem, należy wysłać fakturę jako JSON do POST /validate.
Żądanie
| Część | Znaczenie |
|---|---|
Parametr zapytania route | Wymagany. Jeden z pięciu kanałów przesyłania. |
Parametr zapytania invoice_ref | Wymagany. Własny identyfikator dokumentu w ERP, maksymalnie 100 znaków. |
Parametr zapytania client | Opcjonalny. Klucz klienta może pominąć ten parametr albo podać własnego klienta. |
Nagłówek Idempotency-Key | Wymagany, od 8 do 100 znaków. |
Nagłówek Content-Type | application/xml lub text/xml. application/pdf jest zapisywany i umieszczany w kolejce w ten sam sposób. |
Jaki plik przyjmuje każdy kanał:
| Kanał | Przyjmuje |
|---|---|
DE-XRECHNUNG | UBL, CII |
FR-PA | UBL, CII |
PEPPOL | UBL |
RO-EFACTURA | UBL |
PL-KSEF | FA(3) |
Przyjęty plik
Przykład to fa3-pl-ksef.xml, polski plik FA(3) z fikcyjnymi stronami transakcji. Stan to queued.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PL-KSEF&invoice_ref=INV-2026-0042" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/xml" \
-H "Idempotency-Key: order-2026-0042" \
--data-binary @fa3-pl-ksef.xmlimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PL-KSEF&invoice_ref=INV-2026-0042"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/xml")
.header("Idempotency-Key", "order-2026-0042")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("fa3-pl-ksef.xml")))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}import { readFile } from 'node:fs/promises';
const response = await fetch('https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PL-KSEF&invoice_ref=INV-2026-0042', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/xml',
'Idempotency-Key': 'order-2026-0042',
},
body: await readFile('fa3-pl-ksef.xml'),
});
console.log(response.status);
console.log(await response.text());{
"links": {
"self": "/invoices/inv_d249e33382ce2911876b7295",
"events": "/invoices/inv_d249e33382ce2911876b7295/events"
},
"id": "inv_d249e33382ce2911876b7295",
"state": "queued"
}Plik wysłany dwa razy
Ten sam plik wysłany ponownie dla tego samego klienta i kanału to faktura, którą już mamy. Odpowiedź zawiera duplicate_of, identyfikator pierwszej faktury, a nic nowego nie jest wysyłane. Przesłanie, które zakończyło się stanem rejected, validation_failed lub cancelled, się nie liczy, więc plik można wysłać ponownie.
Odrzucone pliki
Dla poprawnie sformułowanego XML, który nie jest fakturą, usługa zwraca 422 z kodem EI-XML-TYPE.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0051" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/xml" \
-H "Idempotency-Key: order-2026-0051" \
--data-binary @not-an-invoice.xmlimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0051"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/xml")
.header("Idempotency-Key", "order-2026-0051")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("not-an-invoice.xml")))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}import { readFile } from 'node:fs/promises';
const response = await fetch('https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0051', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/xml',
'Idempotency-Key': 'order-2026-0051',
},
body: await readFile('not-an-invoice.xml'),
});
console.log(response.status);
console.log(await response.text());{
"type": "https://eurinvoice.com/problems/validation-failed",
"title": "The invoice did not pass the checks",
"errors": [
{
"code": "EI-XML-TYPE",
"fix_hint": "Send the invoice itself, in the format agreed for the route.",
"who_fixes": "erp",
"source": "XML-safety",
"message": "The file is not an invoice in a format this route accepts. Please send the invoice in the agreed format."
}
],
"status": 422
}Dla pliku z deklaracją DOCTYPE usługa zwraca 422 z kodem EI-XML-DTD, zanim odczyta go jakikolwiek walidator. Dla pliku, który nie jest poprawnie sformułowany, zwraca EI-XML-SYNTAX.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0052" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/xml" \
-H "Idempotency-Key: order-2026-0052" \
--data-binary @with-doctype.xmlimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0052"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/xml")
.header("Idempotency-Key", "order-2026-0052")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("with-doctype.xml")))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}import { readFile } from 'node:fs/promises';
const response = await fetch('https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0052', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/xml',
'Idempotency-Key': 'order-2026-0052',
},
body: await readFile('with-doctype.xml'),
});
console.log(response.status);
console.log(await response.text());{
"type": "https://eurinvoice.com/problems/validation-failed",
"title": "The invoice did not pass the checks",
"errors": [
{
"code": "EI-XML-DTD",
"fix_hint": "Export the invoice without the DOCTYPE line. If the ERP adds one on purpose, raise it with the ERP vendor: no e-invoicing format uses it.",
"who_fixes": "erp",
"source": "XML-safety",
"message": "The invoice file contains a DOCTYPE declaration, which e-invoices never use, so we refused it for security before reading it. Export it again without the DOCTYPE line."
}
],
"status": 422
}Dla typu treści innego niż XML lub PDF usługa zwraca 415.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0053" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: text/plain" \
-H "Idempotency-Key: order-2026-0053" \
--data-binary @hello.txtimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0053"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "text/plain")
.header("Idempotency-Key", "order-2026-0053")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("hello.txt")))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}import { readFile } from 'node:fs/promises';
const response = await fetch('https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0053', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'text/plain',
'Idempotency-Key': 'order-2026-0053',
},
body: await readFile('hello.txt'),
});
console.log(response.status);
console.log(await response.text());{
"type": "https://eurinvoice.com/problems/unsupported-media",
"title": "Not UBL, CII or FA(3)",
"status": 415
}Gdy brakuje Idempotency-Key albo jest on zbyt krótki, usługa zwraca 400.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0054" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/xml" \
--data-binary @ubl-peppol.xmlimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0054"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/xml")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("ubl-peppol.xml")))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}import { readFile } from 'node:fs/promises';
const response = await fetch('https://api-sandbox-eu.eurinvoice.com/invoices/xml?route=PEPPOL&invoice_ref=INV-2026-0054', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/xml',
},
body: await readFile('ubl-peppol.xml'),
});
console.log(response.status);
console.log(await response.text());{
"detail": "Idempotency-Key must be between 8 and 100 characters.",
"type": "https://eurinvoice.com/problems/bad-request",
"title": "The request could not be read",
"status": 400
}Odpowiedzi
| Status | Znaczenie |
|---|---|
202 | Przyjęty i umieszczony w kolejce. Location zawiera adres URL faktury. |
400 | Brakuje parametru zapytania lub nagłówka Idempotency-Key albo któryś z nich jest błędny. |
401 | Brak klucza lub nieznany klucz. |
403 | Klucz nie ma zakresu submit albo wskazuje innego klienta (forbidden). |
409 | Klucz został użyty z inną treścią (idempotency-conflict) albo jego pierwsze żądanie jeszcze trwa (request-in-progress). |
413 | Treść przekracza 5 MB (payload-too-large). |
415 | Typ treści nie jest ani XML, ani PDF (unsupported-media). |
422 | Odrzucony plik: EI-XML-DTD, EI-XML-SYNTAX lub EI-XML-TYPE. |
429 | Zbyt wiele żądań dla klucza. Należy odczekać liczbę sekund podaną w Retry-After. |
503 | Inne żądanie dotyczące tego samego dokumentu jest jeszcze zapisywane (busy). Należy ponowić po liczbie sekund podanej w Retry-After. |