3 API3.2
Predaja JSON-a: POST /invoices
Kanonski JSON ili izvoz iz ERP-a.
- U sandboxu
Jednostavnim riječima
Ovaj poziv predaje račun: ako prođe sve provjere, usluga ga stavlja u red čekanja, a ako ne prođe, odgovor navodi polje koje nije prošlo i ništa se ne stavlja u red čekanja.
POST /invoices provjerava račun jednako kao probna provjera. Ako prođe, usluga ga stavlja u red čekanja i odgovara 202 s ID-om. Ako provjera ne uspije, odgovor je 422 i ništa se ne stavlja u red čekanja. Za poziv su potrebni ključ s opsegom submit i Idempotency-Key.
Zahtjev
| Dio | Značenje |
|---|---|
Zaglavlje Idempotency-Key | Obavezno, od 8 do 100 znakova. |
invoice_ref | Obavezno. Vlastiti ID dokumenta u ERP-u, do 100 znakova. |
route | Neobavezno. Jedan od pet kanala slanja. Ako ga izostavite, usluga ga bira prema računu (zemlje prodavatelja i kupca, profil i spremljeni pristupni podaci klijenta). Ako nijedno pravilo ne odgovara, odgovor je 422, EI-ROUTE-UNDECIDED ili EI-ROUTE-PEPPOL-UNKNOWN. |
document | Jedan račun u kanonskom modelu. Pošaljite ovo polje ili export s connector, ali ne oba. |
export, connector | Izvoz iz ERP-a onakav kakav ga je ERP napisao, uz connector postavljen na business-central ili sap-b1. Usluga ga mapira aktivnom verzijom mapiranja konektora ili verzijom mapping_version koju navedete (pogledajte verzije mapiranja). Nalaz u mapiranju daje odgovor 422 i navodi polje ERP-a. Izvoz se čuva uz račun. |
formats | Neobavezno. Navedite najviše jedan: dokument koji se izrađuje, provjerava i šalje. |
environment | Neobavezno. Ako ga pošaljete, mora odgovarati okruženju vašeg ključa, inače je odgovor 400. |
client | Neobavezno. Vlastiti ključ klijenta može ga izostaviti ili navesti vlastitog klijenta; svaki drugi klijent dobiva 403. Ograničenja prijenosnih sustava računaju se po klijentu (pogledajte ograničenja). |
Tijelo je ograničeno na 5 MB. U produkciji se izvoz čita samo kad postavke konektora klijenta sadrže klijentove vlastite podatke o prodavatelju i plaćanju; bez njih odgovor je 422, connector-settings-missing, uz navod što nedostaje. Sandbox ga čita s primjerima podataka konektora.
Prihvaćeni račun
Primjer je submit-de.json. Location sadrži URL računa, a links upućuje na račun i njegove događaje. Stanje je queued: ništa nije poslano.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/invoices" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-2026-0001" \
--data-binary @submit-de.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/invoices"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.header("Idempotency-Key", "order-2026-0001")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("submit-de.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/invoices', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
'Idempotency-Key': 'order-2026-0001',
},
body: await readFile('submit-de.json'),
});
console.log(response.status);
console.log(await response.text());{
"links": {
"self": "/invoices/inv_936a93e38de84e7b0a1d7681",
"events": "/invoices/inv_936a93e38de84e7b0a1d7681/events"
},
"id": "inv_936a93e38de84e7b0a1d7681",
"state": "queued"
}Račun koji ne prođe provjeru
Isti poziv s uklonjenim nazivom prodavatelja, submit-de-missing-seller-name.json. Odgovor je dokument s opisom problema i popisom errors. Svaka pogreška je nalaz poput onih u izvješću probne provjere. Istaknuti redci su šifra i polje koje treba ispraviti.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/invoices" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-2026-0002" \
--data-binary @submit-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/invoices"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.header("Idempotency-Key", "order-2026-0002")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("submit-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/invoices', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
'Idempotency-Key': 'order-2026-0002',
},
body: await readFile('submit-de-missing-seller-name.json'),
});
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-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."
},
{
"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."
}
],
"status": 422
}Idempotentnost
- Isti ključ s istim tijelom ponovno vraća prvi odgovor, s istim ID-om.
- Isti ključ s drugačijim tijelom daje
409. - Sprema se i odgovor
422. Ispravljeni račun pošaljite s novim ključem. - Spremljeni odgovor čuva se dokle god se čuvaju podaci klijenta.
- Drugi zahtjev s ključem čiji je prvi zahtjev još u tijeku dobiva
409,request-in-progress. Ključ čiji zahtjev nikad nije dobio odgovor, jer se poslužitelj zaustavio, oslobađa se nakon 15 minuta.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/invoices" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-2026-0001" \
--data-binary @submit-de.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/invoices"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.header("Idempotency-Key", "order-2026-0001")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("submit-de.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/invoices', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
'Idempotency-Key': 'order-2026-0001',
},
body: await readFile('submit-de.json'),
});
console.log(response.status);
console.log(await response.text());{
"links": {
"self": "/invoices/inv_936a93e38de84e7b0a1d7681",
"events": "/invoices/inv_936a93e38de84e7b0a1d7681/events"
},
"id": "inv_936a93e38de84e7b0a1d7681",
"state": "queued"
}curl -X POST "https://api-sandbox-eu.eurinvoice.com/invoices" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-2026-0001" \
--data-binary @submit-de-changed.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/invoices"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.header("Idempotency-Key", "order-2026-0001")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("submit-de-changed.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/invoices', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
'Idempotency-Key': 'order-2026-0001',
},
body: await readFile('submit-de-changed.json'),
});
console.log(response.status);
console.log(await response.text());{
"type": "https://eurinvoice.com/problems/idempotency-conflict",
"title": "This Idempotency-Key was already used with a different body",
"status": 409
}Dokument koji ste već poslali
Dokument identičan aktivnom dokumentu, za istog klijenta i isti kanal, ponovno se prihvaća pod novim ključem. Odgovor sadrži duplicate_of, ID prvog računa, i ništa se novo ne stavlja u red čekanja.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/invoices" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-2026-0003" \
--data-binary @submit-de.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/invoices"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.header("Idempotency-Key", "order-2026-0003")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("submit-de.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/invoices', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
'Idempotency-Key': 'order-2026-0003',
},
body: await readFile('submit-de.json'),
});
console.log(response.status);
console.log(await response.text());{
"links": {
"self": "/invoices/inv_936a93e38de84e7b0a1d7681",
"events": "/invoices/inv_936a93e38de84e7b0a1d7681/events"
},
"id": "inv_936a93e38de84e7b0a1d7681",
"state": "queued",
"duplicate_of": "inv_936a93e38de84e7b0a1d7681"
}Odgovori
| Status | Značenje |
|---|---|
202 | Prihvaćeno i stavljeno u red čekanja ili duplikat aktivnog računa. |
400 | Tijelo nije valjan JSON, neko polje nije ispravno ili Idempotency-Key nedostaje ili nema od 8 do 100 znakova. |
401 | Nema ključa ili je ključ nepoznat. |
403 | Ključ nema opseg submit ili navodi drugog klijenta (forbidden). |
409 | Ključ je upotrijebljen s drugačijim tijelom (idempotency-conflict) ili je njegov prvi zahtjev još u tijeku (request-in-progress). |
413 | Tijelo je veće od 5 MB (payload-too-large). |
422 | Račun nije prošao provjeru. errors navodi što nije prošlo i tko to ispravlja. |
429 | Previše zahtjeva za ključ. Pričekajte onoliko sekundi koliko navodi Retry-After. |
503 | Drugi zahtjev za isti dokument još se sprema (busy). Ništa nije zapisano i ključ se može ponovno upotrijebiti. Pokušajte ponovno nakon onoliko sekundi koliko navodi Retry-After. |
Upozorenje
Nakon odgovora 202 račun nikad ne šaljete ponovno. Pogreške na strani prijenosnog sustava koje mogu proći ponavljamo prema vlastitom rasporedu, a trajno odbijanje ide na popis za obradu.