3 API3.1
Rulare de probă: POST /validate
Rulează aceleași verificări ca transmiterea. Nu stochează și nu trimite nimic.
- În sandbox
În cuvinte simple
O rulare de probă verifică o factură așa cum ar face-o o transmitere reală, fără să trimită nimic, astfel încât un partener să poată găsi orice problemă înainte ca factura unui client să plece undeva.
POST /validate rulează aceleași verificări ca o transmitere și răspunde cu un raport. Nu pune nimic în coadă și nu trimite nimic. Apelul necesită o cheie cu domeniul submit. Corpul cererii este JSON, de cel mult 5 MB.
Sfat
Începeți de aici când mapați un client nou.
Cererea
| Câmp | Semnificație |
|---|---|
invoice_ref | Obligatoriu. ID-ul propriu al documentului în ERP, de cel mult 100 de caractere. Apare în fiecare eveniment de stare. |
route | Obligatoriu. DE-XRECHNUNG, PEPPOL, FR-PA, PL-KSEF sau RO-EFACTURA. |
document | O factură în modelul canonic. Trimiteți acest câmp sau un export, nu pe amândouă. |
export, connector | Un export ERP așa cum l-a scris ERP-ul, cu connector setat pe business-central sau sap-b1. Trimiteți acest câmp sau un document, nu pe amândouă. Pe un alt canal decât Germania, raportul începe cu un nivel mapping. mapping_version alege o altă versiune decât cea activă (consultați versiunile de mapare). |
formats | Documentele de generat, acolo unde canalul permite o alegere. Germania: oricare dintre xrechnung-ubl (implicit), xrechnung-cii și zugferd; KoSIT rulează o dată pentru fiecare format, iar pentru PDF rulează în plus Mustang și veraPDF. Franța: ubl, cii sau facturx. |
environment | Opțional. Trebuie să corespundă mediului cheii dumneavoastră. |
erp_totals | Totalurile calculate de ERP-ul dumneavoastră: payable_amount, currency și, opțional, tax_amount, ca șiruri de caractere. Dacă diferă de totalurile pe care serviciul le calculează din liniile facturii, raportul conține o constatare EI-TOTALS-MISMATCH pe erp_totals.payable_amount. |
Lista completă a câmpurilor este în referință.
O factură care trece verificările
Cererea exemplu este validate-de-ok.json, o factură germană fictivă. Raportul are valid: true, un document cu SHA-256-ul său și patru niveluri trecute.
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"
}
]
}O factură care nu trece verificările
Aceeași factură fără numele vânzătorului, validate-de-missing-seller-name.json. O rulare de probă răspunde tot 200. valid este false, iar fiecare constatare indică câmpul și cine îl corectează. Cele două linii evidențiate sunt cele de urmărit: code din catalog și field din datele clientului.
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"
}
]
}Citirea raportului
validestetruedoar când toate nivelurile au trecut.layersrulează în ordine:schema,mapping,pre-check, apoi validatoarele proprii ale canalului, numite după ce a rulat (de exempluKoSIT-XRechnung-3.0.2).- Fiecare constatare are un
codedin catalog, câmpulfield,who_fixes(ussauerp), unfix_hint, unmessageși nivelulsource. Pagina Erori și catalogul enumeră toate codurile. documentsenumeră ce s-a generat, cu SHA-256-ul fiecărui document și, pentru un fișier de cel mult 2 MiB, cu octeții săi încontent_base64. Apare când factura este validă.
Alte răspunsuri
| Cod | Semnificație |
|---|---|
200 | Un raport, pentru o factură validă sau nu. |
400 | Cererea nu poate fi citită: nu este JSON, un câmp este greșit sau sunt prezente atât document, cât și export. |
401 | Lipsește cheia sau cheia este necunoscută. |
403 | Cheia nu are domeniul submit. |
413 | Corpul cererii depășește 5 MB (payload-too-large). |
422 | Un număr peste limite, de exemplu unul de peste 40 de caractere (EI-SCHEMA, cu indicarea câmpului). Orice altă constatare vine în raportul 200. |
429 | Prea multe cereri pentru cheie. Așteptați numărul de secunde din Retry-After. |
503 | Toate validatoarele sunt ocupate (busy). Reîncercați după numărul de secunde din 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
}