3 API3.1
Probelauf: POST /validate
Führt dieselben Prüfungen aus wie eine Übermittlung. Speichert und sendet nichts.
- In der Sandbox
In einfachen Worten
Ein Probelauf prüft eine Rechnung so, wie es eine echte Übermittlung tun würde, und sendet nichts, damit ein Partner jedes Problem findet, bevor die Rechnung eines Kunden irgendwohin geht.
POST /validate führt dieselben Prüfungen aus wie eine Übermittlung und antwortet mit einem Bericht. Er reiht nichts in die Warteschlange ein und sendet nichts. Der Aufruf braucht einen Schlüssel mit dem Scope submit. Der Body ist JSON, bis zu 5 MB.
Tipp
Beginnen Sie hier, wenn Sie einen neuen Kunden mappen.
Die Anfrage
| Feld | Bedeutung |
|---|---|
invoice_ref | Pflicht. Die eigene Beleg-ID des ERP, bis zu 100 Zeichen. Erscheint in jedem Statusereignis wieder. |
route | Pflicht. DE-XRECHNUNG, PEPPOL, FR-PA, PL-KSEF oder RO-EFACTURA. |
document | Eine Rechnung im kanonischen Modell. Senden Sie dieses Feld oder einen export, nicht beides. |
export, connector | Ein ERP-Export, so wie das ERP ihn geschrieben hat, mit connector auf business-central oder sap-b1. Senden Sie dieses Feld oder ein document, nicht beides. Bei einem anderen Übermittlungsweg als Deutschland beginnt der Bericht mit einer Prüfstufe mapping. mapping_version wählt eine andere Version als die Live-Version (siehe Mapping-Versionen). |
formats | Die Dokumente, die erstellt werden, wo der Übermittlungsweg eine Wahl lässt. Deutschland: eine beliebige Auswahl aus xrechnung-ubl (Standard), xrechnung-cii und zugferd; KoSIT läuft einmal je Format, und für das PDF laufen zusätzlich Mustang und veraPDF. Frankreich: ubl, cii oder facturx. |
environment | Optional. Es muss der Umgebung Ihres Schlüssels entsprechen. |
erp_totals | Die Summen, die Ihr ERP berechnet hat: payable_amount, currency und optional tax_amount, als Strings. Weichen sie von den Summen ab, die der Service aus den Positionen berechnet, enthält der Bericht einen Befund EI-TOTALS-MISMATCH zu erp_totals.payable_amount. |
Die vollständige Feldliste steht in der Referenz.
Eine Rechnung, die besteht
Die Beispielanfrage ist validate-de-ok.json, eine erfundene deutsche Rechnung. Der Bericht enthält valid: true, ein Dokument mit seinem SHA-256 und vier bestandene Prüfstufen.
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"
}
]
}Eine Rechnung, die durchfällt
Dieselbe Rechnung ohne den Namen des Verkäufers, validate-de-missing-seller-name.json. Auch dann antwortet ein Probelauf mit 200. valid ist false, und jeder Befund nennt das Feld und sagt, wer den Fehler behebt. Die beiden hervorgehobenen Zeilen sind die wichtigen: der code aus dem Katalog und das field in den Daten des Kunden.
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"
}
]
}Den Bericht lesen
validist nur danntrue, wenn jede Prüfstufe bestanden ist.layerslaufen in dieser Reihenfolge:schema,mapping,pre-check, dann die eigenen Validatoren des Übermittlungswegs, benannt nach dem, was lief (zum BeispielKoSIT-XRechnung-3.0.2).- Jeder Befund hat einen
codeaus dem Katalog, dasfield,who_fixes(usodererp), einenfix_hint, einemessageund insourcedie Prüfstufe. Fehler und Katalog listet jeden Code auf. documentslistet auf, was erstellt wurde, mit seinem SHA-256 und, bei einer Datei bis 2 MiB, ihren Bytes incontent_base64. Es ist vorhanden, wenn die Rechnung gültig ist.
Andere Antworten
| Status | Bedeutung |
|---|---|
200 | Ein Bericht, gültig oder nicht. |
400 | Die Anfrage kann nicht gelesen werden: kein JSON, ein Feld ist falsch, oder sowohl document als auch export sind vorhanden. |
401 | Kein Schlüssel oder ein unbekannter Schlüssel. |
403 | Dem Schlüssel fehlt der Scope submit. |
413 | Der Body ist größer als 5 MB (payload-too-large). |
422 | Eine Zahl jenseits der Grenzen, etwa eine mit mehr als 40 Zeichen (EI-SCHEMA, mit dem Namen des Feldes). Jeder andere Befund steht im Bericht mit 200. |
429 | Zu viele Anfragen für den Schlüssel. Warten Sie Retry-After Sekunden. |
503 | Jeder Validator ist ausgelastet (busy). Versuchen Sie es nach Retry-After Sekunden erneut. |
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
}