3 API3.1
Proefrun: POST /validate
Voert dezelfde controles uit als een indiening. Slaat niets op en verzendt niets.
- In de sandbox
In gewone woorden
Een proefrun controleert een factuur zoals een echte indiening dat zou doen en verzendt niets, zodat een partner elk probleem kan vinden voordat de factuur van een eindklant ergens naartoe gaat.
POST /validate voert dezelfde controles uit als een indiening en antwoordt met een rapport. Het zet niets in de wachtrij en verzendt niets. De aanroep vereist een sleutel met de scope submit. De body is JSON, maximaal 5 MB.
Tip
Begin hier wanneer u een nieuwe eindklant mapt.
Het verzoek
| Veld | Betekenis |
|---|---|
invoice_ref | Verplicht. De eigen document-ID van het ERP, maximaal 100 tekens. Komt terug in elk statusbericht. |
route | Verplicht. DE-XRECHNUNG, PEPPOL, FR-PA, PL-KSEF of RO-EFACTURA. |
document | Eén factuur in het canonieke model. Stuur dit of een export, niet allebei. |
export, connector | Een ERP-export zoals het ERP hem schreef, met connector op business-central of sap-b1. Stuur dit of een document, niet allebei. Voor een ander verzendkanaal dan Duitsland begint het rapport met een laag mapping. mapping_version kiest een andere versie dan de live versie (zie mappingversies). |
formats | De documenten die worden opgebouwd waar het verzendkanaal een keuze laat. Duitsland: een of meer van xrechnung-ubl (de standaard), xrechnung-cii en zugferd; KoSIT draait één keer per formaat, en voor de PDF draaien ook Mustang en veraPDF. Frankrijk: ubl, cii of facturx. |
environment | Optioneel. Het moet overeenkomen met de omgeving van uw sleutel. |
erp_totals | De totalen die uw ERP berekende: payable_amount, currency en eventueel tax_amount, als strings. Als ze verschillen van de totalen die de dienst uit de factuurregels berekent, bevat het rapport een bevinding EI-TOTALS-MISMATCH op erp_totals.payable_amount. |
De volledige lijst van velden staat in de referentie.
Een factuur die slaagt
Het voorbeeldverzoek is validate-de-ok.json, een verzonnen Duitse factuur. Het rapport bevat valid: true, één document met zijn SHA-256 en vier lagen die geslaagd zijn.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/validate" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
--data-binary @validate-de-ok.jsonimport 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/validate"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("validate-de-ok.json")))
.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/validate', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
},
body: await readFile('validate-de-ok.json'),
});
console.log(response.status);
console.log(await response.text());{
"valid": true,
"route": "DE-XRECHNUNG",
"documents": [
{
"sha256": "e21ab9d5097022bea30bfa9f9fe0a4c7ca9afdbd672b0ce2f9150461db773625",
"kind": "xrechnung-ubl",
"content_base64": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgi... (7,092 characters, shortened for these docs)"
}
],
"layers": [
{
"findings": [],
"passed": true,
"layer": "schema"
},
{
"findings": [],
"passed": true,
"layer": "mapping"
},
{
"findings": [],
"passed": true,
"layer": "pre-check"
},
{
"findings": [],
"passed": true,
"layer": "kosit"
}
]
}Een factuur die niet slaagt
Dezelfde factuur zonder de naam van de verkoper, validate-de-missing-seller-name.json. Een proefrun antwoordt nog altijd 200. valid is false, en elke bevinding noemt het veld en wie het oplost. De twee gemarkeerde regels zijn die waar u naar moet kijken: de code uit de catalogus, en het field in de gegevens van de eindklant.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/validate" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
--data-binary @validate-de-missing-seller-name.jsonimport 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/validate"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("validate-de-missing-seller-name.json")))
.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/validate', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
},
body: await readFile('validate-de-missing-seller-name.json'),
});
console.log(response.status);
console.log(await response.text());{
"valid": false,
"route": "DE-XRECHNUNG",
"layers": [
{
"findings": [
{
"code": "EI-SCHEMA",
"field": "seller.name",
"related": [
{
"code": "Art.226(5)",
"source": "pre-check"
}
],
"fix_hint": "Read the JSON path in the error and correct the client mapping.",
"who_fixes": "us",
"source": "schema",
"message": "We could not read this invoice from your export. We are correcting our mapping; if a field is missing in the ERP we will tell you which one."
}
],
"passed": false,
"layer": "schema"
},
{
"findings": [],
"passed": true,
"layer": "mapping"
},
{
"findings": [
{
"code": "Art.226(5)",
"field": "seller.name",
"related": [
{
"code": "EI-SCHEMA",
"source": "schema"
}
],
"fix_hint": "Complete the party's name and address in the master data.",
"who_fixes": "erp",
"source": "pre-check",
"message": "A company name or street address is missing. Complete the company or customer record in the ERP."
}
],
"passed": false,
"layer": "pre-check"
}
]
}Het rapport lezen
validis alleentrueals elke laag is geslaagd.layersdraaien in volgorde:schema,mapping,pre-check, daarna de eigen validators van het verzendkanaal, genoemd naar wat er draaide (bijvoorbeeldKoSIT-XRechnung-3.0.2).- Elke bevinding heeft een
codeuit de catalogus, hetfield,who_fixes(usoferp), eenfix_hint, eenmessageen desource-laag. Fouten en de catalogus vermeldt elke code. documentsvermeldt wat er is aangemaakt, met de SHA-256 ervan en, voor een bestand van 2 MiB of minder, de bytes ervan incontent_base64. Het is aanwezig als de factuur geldig is.
Andere antwoorden
| Status | Betekenis |
|---|---|
200 | Een rapport, geldig of niet. |
400 | Het verzoek is niet leesbaar: geen JSON, een veld is fout, of document en export zijn allebei aanwezig. |
401 | Geen sleutel, of een onbekende sleutel. |
403 | De sleutel heeft de scope submit niet. |
413 | De body is groter dan 5 MB (payload-too-large). |
422 | Een getal buiten de limieten, bijvoorbeeld een van meer dan 40 tekens (EI-SCHEMA, met het veld). Elke andere bevinding staat in het rapport bij 200. |
429 | Te veel aanvragen voor de sleutel. Wacht het aantal seconden in Retry-After. |
503 | Elke validator is bezet (busy). Probeer het opnieuw na het aantal seconden in Retry-After. |
curl -X POST "https://api-sandbox-eu.eurinvoice.com/validate" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
--data-binary @not-json.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/validate"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("not-json.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/validate', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
},
body: await readFile('not-json.txt'),
});
console.log(response.status);
console.log(await response.text());{
"detail": "The request is not valid JSON.",
"type": "https://eurinvoice.com/problems/bad-request",
"title": "The request could not be read",
"status": 400
}