3 API3.3
XML indienen: POST /invoices/xml
XML in UBL, CII of FA(3).
- In de sandbox
In gewone woorden
Deze aanroep dient een factuur in die al als kant-en-klaar XML-bestand bestaat. Ze krijgt een veiligheidscontrole en de eigen validators van het verzendkanaal, en gaat naar de wachtrij als ze slaagt.
POST /invoices/xml neemt een kant-en-klaar UBL-, CII- of FA(3)-bestand aan. Er gebeurt geen mapping. De dienst controleert het bestand op veiligheid en type, voert de officiële validators voor het verzendkanaal uit, zet het daarna in de wachtrij en verzendt het ongewijzigd. Voor FA(3) zijn de controles het schema plus de bestands- en datumregels van KSeF.
Opmerking
Een 202 betekent dat het bestand de veiligheidscontrole heeft doorstaan en in de wachtrij staat. Stuur de factuur om een bestand te controleren voordat u het verzendt als JSON naar POST /validate.
Het verzoek
| Onderdeel | Betekenis |
|---|---|
Queryparameter route | Verplicht. Een van de vijf verzendkanalen. |
Queryparameter invoice_ref | Verplicht. De eigen document-ID van het ERP, maximaal 100 tekens. |
Queryparameter client | Optioneel. De eigen sleutel van een eindklant mag het weglaten of de eigen eindklant noemen. |
Header Idempotency-Key | Verplicht, 8 tot 100 tekens. |
Header Content-Type | application/xml of text/xml. application/pdf wordt op dezelfde manier opgeslagen en in de wachtrij gezet. |
Welk bestand elk verzendkanaal aanneemt:
| Verzendkanaal | Accepteert |
|---|---|
DE-XRECHNUNG | UBL, CII |
FR-PA | UBL, CII |
PEPPOL | UBL |
RO-EFACTURA | UBL |
PL-KSEF | FA(3) |
Een geaccepteerd bestand
Het voorbeeld is fa3-pl-ksef.xml, een Pools FA(3)-bestand met verzonnen partijen. De status is 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"
}Een bestand dat twee keer is gestuurd
Hetzelfde bestand dat opnieuw wordt gestuurd voor dezelfde eindklant en hetzelfde verzendkanaal, is de factuur die al in bezit is. Het antwoord bevat duplicate_of, de ID van de eerste factuur, en er wordt niets nieuws verzonden. Een indiening die eindigde op rejected, validation_failed of cancelled telt niet mee, dus het bestand kan opnieuw worden gestuurd.
Geweigerde bestanden
XML die welgevormd is maar geen factuur, krijgt 422 met 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
}Een bestand met een DOCTYPE krijgt 422 met EI-XML-DTD, voordat een validator het leest. Een bestand dat niet welgevormd is, krijgt 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
}Een contenttype dat geen XML of PDF is, krijgt 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
}Een ontbrekende of te korte Idempotency-Key krijgt 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
}Antwoorden
| Status | Betekenis |
|---|---|
202 | Geaccepteerd en in de wachtrij gezet. Location bevat de URL van de factuur. |
400 | Een queryparameter of de Idempotency-Key ontbreekt of is fout. |
401 | Geen sleutel, of een onbekende sleutel. |
403 | De sleutel mist de scope submit, of noemt een andere eindklant (forbidden). |
409 | De sleutel werd gebruikt met een andere body (idempotency-conflict), of het eerste verzoek ermee loopt nog (request-in-progress). |
413 | De body is groter dan 5 MB (payload-too-large). |
415 | Het contenttype is geen XML of PDF (unsupported-media). |
422 | Een geweigerd bestand: EI-XML-DTD, EI-XML-SYNTAX of EI-XML-TYPE. |
429 | Te veel aanvragen voor de sleutel. Wacht het aantal seconden in Retry-After. |
503 | Een ander verzoek voor hetzelfde document wordt nog opgeslagen (busy). Probeer het opnieuw na het aantal seconden in Retry-After. |