Ako to funguje
Tri základné scenáre použitia SAPI rozhrania.
1 Odosielanie faktúry
2 Prijímanie faktúry
3 Životný cyklus tokenu
Rýchly štart
Za 2 minúty odošlite prvú faktúru.
Použite sandbox credentials
Získajte token
curl -X POST https://epostak.sk/api/auth/token \ -H "Content-Type: application/json" \ -d '{"client_id":"test_98b486a08b3e3d7f","client_secret":"sk_test_e888be545de8bf6e132e5934b790761cdabc65b67595b3a6","grant_type":"client_credentials"}'
import requests resp = requests.post("https://epostak.sk/api/auth/token", json={ "client_id": "test_98b486a08b3e3d7f", "client_secret": "sk_test_e888be545de8bf6e132e5934b790761cdabc65b67595b3a6", "grant_type": "client_credentials" }) token = resp.json()["access_token"]
const resp = await fetch("https://epostak.sk/api/auth/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ client_id: "test_98b486a08b3e3d7f", client_secret: "sk_test_e888be545de8bf6e132e5934b790761cdabc65b67595b3a6", grant_type: "client_credentials" }) }); const { access_token } = await resp.json();
$resp = json_decode(file_get_contents( "https://epostak.sk/api/auth/token", false, stream_context_create(["http" => [ "method" => "POST", "header" => "Content-Type: application/json", "content" => json_encode([ "client_id" => "test_98b486a08b3e3d7f", "client_secret" => "sk_test_e888be545de8bf6e132e5934b790761cdabc65b67595b3a6", "grant_type" => "client_credentials" ]) ]]) )); $token = $resp->access_token;
using var client = new HttpClient(); var body = new StringContent( JsonSerializer.Serialize(new { client_id = "test_98b486a08b3e3d7f", client_secret = "sk_test_e888be545de8bf6e132e5934b790761cdabc65b67595b3a6", grant_type = "client_credentials" }), Encoding.UTF8, "application/json" ); var resp = await client.PostAsync("https://epostak.sk/api/auth/token", body); var json = await resp.Content.ReadFromJsonAsync<TokenResponse>(); var token = json.access_token;
HttpClient client = HttpClient.newHttpClient(); String json = """ {"client_id":"test_98b486a08b3e3d7f","client_secret":"sk_test_e888be545de8bf6e132e5934b790761cdabc65b67595b3a6","grant_type":"client_credentials"} """; HttpRequest req = HttpRequest.newBuilder() .uri(URI.create("https://epostak.sk/api/auth/token")) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(json)) .build(); HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandlers.ofString()); JsonObject obj = JsonParser.parseString(resp.body()).getAsJsonObject(); String token = obj.get("access_token").getAsString();
Odošlite faktúru
curl -X POST https://epostak.sk/api/document/send \ -H "Authorization: Bearer $TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "X-Peppol-Participant-Id: 0245:0000000001" \ -H "Content-Type: application/json" \ -d '{"metadata":{"documentId":"INV-001","documentTypeId":"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1","processId":"urn:fdc:peppol.eu:2017:poacc:billing:01:1.0","senderParticipantId":"0245:0000000001","receiverParticipantId":"0245:0000000002","creationDateTime":"2026-03-31T10:00:00Z"},"payload":"<Invoice xmlns=\\"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2\\">...</Invoice>","payloadFormat":"XML"}'
Testovacie prostredie (Sandbox)
Otestujte integráciu end-to-end bez produkčných dát.
Firma A — odosielateľ
| Parameter | Hodnota |
|---|---|
| Peppol ID | 0245:0000000001 |
| Client ID | test_98b486a08b3e3d7f |
| Client Secret | sk_test_e888be545de8bf6e132e5934b790761cdabc65b67595b3a6 |
Firma B — prijímateľ
| Parameter | Hodnota |
|---|---|
| Peppol ID | 0245:0000000002 |
| Client ID | test_02b1c35552f99f1c |
| Client Secret | sk_test_94e7d84efbf9000c2c0f3970c909750a8797a44a9a31e41e |
Postup krok za krokom
X-Peppol-Participant-Id: 0245:0000000001, v metadata receiverParticipantId: "0245:0000000002"X-Peppol-Participant-Id: 0245:0000000002Podporované typy dokumentov a poznámky
Podporované typy pre testovanie:
| Poznámka |
|---|
| Testovacie prostredie používa Peppol testbed |
| BuyerReference (BT-10) je povinný |
| Idempotency-Key musí byť unikátny UUID |
API Referencia
Interaktívna dokumentácia. Kliknite na endpoint pre detail a vyskúšanie.
Autentifikácia
OAuth2 client_credentials flow s JWT tokenmi.
Prihláste sa s vašimi API kľúčmi. Pošlite client_id a client_secret, dostanete prístupový token (platí 15 minút) a obnovovací token (platí 30 dní).
Request Body
| Parameter | Typ | Popis | |
|---|---|---|---|
| client_id | string | Povinný | Váš klientský identifikátor |
| client_secret | string | Povinný | Váš tajný kľúč |
| grant_type | string | Povinný | Vzdy "client_credentials" |
| scope | string | Nepovinný | Rozsah oprávnení, napr. "document:send document:receive" |
Odpovede
Príklad odpovede — 200 OK
{
"access_token": "eyJ...",
"refresh_token": "ref_...",
"token_type": "Bearer",
"expires_in": 900,
"scope": "document:send document:receive"
}Vyskúšajte
Skontrolujte či je váš prístupový token ešte platný, kedy expiruje, a či ho treba obnoviť.
Headers
| Header | Typ | Popis | |
|---|---|---|---|
| Authorization | string | Povinný | Bearer <access_token> |
Odpovede
Vyskúšajte
Keď vám vyprší prístupový token, pošlite obnovovací token a dostanete nový pár. Starý obnovovací token prestane platiť — pre väčšiu bezpečnosť.
Request Body
| Parameter | Typ | Popis | |
|---|---|---|---|
| refresh_token | string | Povinný | Platný refresh token |
Odpovede
Vyskúšajte
Zrušte platnosť refresh tokenu (napr. keď sa odhlasujete). Môžete zavolať opakovane — nič sa nestane.
Request Body
| Parameter | Typ | Popis | |
|---|---|---|---|
| token | string | Povinný | Refresh token na zneplatnenie |
| token_type_hint | string | Nepovinný | Enum: "refresh_token" |
Odpovede
Príklad odpovede — 200 OK
{
"revoked": true
}Vyskúšajte
Dokumenty
Odosielanie a prijímanie Peppol dokumentov (faktúr, dobropisov).
Odošlite faktúru alebo dobropis cez Peppol sieť. Pošlite XML a my ho doručíme príjemcovi. Header Idempotency-Key zabráni duplicitnému odoslaniu ak zavoláte dvakrát.
Povinné Headers
| Header | Popis |
|---|---|
| Authorization | Bearer <access_token> |
| Idempotency-Key | UUID — zabraňuje duplicitnému odoslaniu |
| X-Peppol-Participant-Id | Vaše Peppol ID, napr. 0245:0000000001 |
Request Body
| Parameter | Typ | Popis |
|---|---|---|
| metadata | object | documentId, documentTypeId, processId, senderParticipantId, receiverParticipantId, creationDateTime |
| payload | string | UBL XML obsah faktúry |
| payloadFormat | string | "XML" |
| payloadEncoding | string | Nepovinný, default "UTF-8" |
| checksum | string | Nepovinný, SHA-256 hex digest payloadu |
Odpovede
Príklad odpovede — 202 Accepted
{
"providerDocumentId": "bec4f875-996f-4794-b42e-8f3b5b2f1ba4",
"status": "ACCEPTED", /* alebo "RECEIVED" | "REJECTED" */
"receivedAt": "2026-03-31T10:00:00.000Z",
"timestamp": "2026-03-31T10:00:00.000Z"
}Príklad curl
curl -X POST https://epostak.sk/api/document/send \ -H "Authorization: Bearer $TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "X-Peppol-Participant-Id: 0245:0000000001" \ -H "Content-Type: application/json" \ -d '{ "metadata": { "documentId": "INV-2026-001", "documentTypeId": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1", "processId": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0", "senderParticipantId": "0245:0000000001", "receiverParticipantId": "0245:0000000002", "creationDateTime": "2026-03-31T10:00:00Z" }, "payload": "<Invoice xmlns=\"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2\">...</Invoice>", "payloadFormat": "XML" }'
Pozrite sa aké dokumenty vám prišli cez Peppol. Ak ich je veľa, stránkujte pomocou pageToken.
Query parametre
| Parameter | Typ | Default | Popis |
|---|---|---|---|
| limit | int | 20 | 1-100 |
| status | string | — | RECEIVED alebo ACKNOWLEDGED |
| pageToken | string | — | Token pre ďalšiu stránku |
Povinné Headers
| Header | Popis |
|---|---|
| Authorization | Bearer <access_token> |
| X-Peppol-Participant-Id | Vaše Peppol ID, napr. 0245:0000000001 |
Odpovede
Príklad odpovede — 200 OK
{
"documents": [
{
"documentId": "48b703c6-6fbb-4cfa-90e3-736b1d6fa2ec",
"documentTypeId": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1",
"processId": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
"senderParticipantId": "iso6523-actorid-upis::0245:0000000001",
"receiverParticipantId": "iso6523-actorid-upis::0245:0000000002",
"creationDateTime": "2026-03-31T10:00:00.000Z",
"status": "RECEIVED"
}
],
"nextPageToken": "eyJsYXN0SWQiOiI0OGI3MDNjNiJ9"
}Príklad curl
curl "https://epostak.sk/api/document/receive?status=RECEIVED" \ -H "Authorization: Bearer $TOKEN" \ -H "X-Peppol-Participant-Id: 0245:0000000002"
Stiahnite si celý dokument aj s XML obsahom.
Povinné Headers
| Header | Popis |
|---|---|
| Authorization | Bearer <access_token> |
| X-Peppol-Participant-Id | Vaše Peppol ID |
Odpovede
Príklad odpovede — 200 OK
{
"metadata": {
"documentId": "48b703c6-6fbb-4cfa-90e3-736b1d6fa2ec",
"documentTypeId": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1",
"processId": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
"senderParticipantId": "iso6523-actorid-upis::0245:0000000001",
"receiverParticipantId": "iso6523-actorid-upis::0245:0000000002",
"creationDateTime": "2026-03-31T10:00:00.000Z"
},
"payload": "<Invoice xmlns=\"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2\">...</Invoice>",
"payloadFormat": "XML"
}Príklad curl
curl https://epostak.sk/api/document/receive/{documentId} \ -H "Authorization: Bearer $TOKEN" \ -H "X-Peppol-Participant-Id: 0245:0000000002"
Potvrdíte, že ste dokument prevzali a spracovali. Môžete zavolať opakovane — nič sa nestane.
Povinné Headers
| Header | Popis |
|---|---|
| Authorization | Bearer <access_token> |
| X-Peppol-Participant-Id | Vaše Peppol ID |
Odpovede
Príklad odpovede — 200 OK
{
"documentId": "48b703c6-6fbb-4cfa-90e3-736b1d6fa2ec",
"status": "ACKNOWLEDGED",
"acknowledgedDateTime": "2026-03-31T10:00:07.664Z"
}Príklad curl
curl -X POST https://epostak.sk/api/document/receive/{documentId}/acknowledge \ -H "Authorization: Bearer $TOKEN" \ -H "X-Peppol-Participant-Id: 0245:0000000002"
Integračné príklady
Kompletné príklady implementácie SAPI klienta v rôznych jazykoch.
# pip install requests import requests import uuid BASE = "https://epostak.sk/api" CLIENT_ID = "test_98b486a08b3e3d7f" CLIENT_SECRET = "sk_test_e888be545de8bf6e132e5934b790761cdabc65b67595b3a6" class EpostakClient: def __init__(self): self.token = None self.refresh_token = None def authenticate(self): """Ziskanie pristupoveho tokenu""" resp = requests.post(f"{BASE}/auth/token", json={ "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET, "grant_type": "client_credentials" }) resp.raise_for_status() data = resp.json() self.token = data["access_token"] self.refresh_token = data["refresh_token"] return data def _headers(self, peppol_id): return { "Authorization": f"Bearer {self.token}", "X-Peppol-Participant-Id": peppol_id } def send_invoice(self, xml_payload, metadata, peppol_id): """Odoslanie faktury cez Peppol""" resp = requests.post(f"{BASE}/document/send", headers={**self._headers(peppol_id), "Idempotency-Key": str(uuid.uuid4())}, json={"metadata": metadata, "payload": xml_payload, "payloadFormat": "XML"}) return resp.json() def get_received(self, peppol_id, status="RECEIVED"): """Zoznam prijatých dokumentov""" resp = requests.get(f"{BASE}/document/receive", headers=self._headers(peppol_id), params={"status": status}) return resp.json() def acknowledge(self, doc_id, peppol_id): """Potvrdenie prijatia dokumentu""" resp = requests.post( f"{BASE}/document/receive/{doc_id}/acknowledge", headers=self._headers(peppol_id)) return resp.json() def renew(self): """Obnovenie tokenov""" resp = requests.post(f"{BASE}/auth/renew", json={"refresh_token": self.refresh_token}) data = resp.json() self.token = data["access_token"] self.refresh_token = data["refresh_token"] return data # Pouzitie: client = EpostakClient() client.authenticate() # Odoslanie faktury result = client.send_invoice( xml_payload="<Invoice>...</Invoice>", metadata={"documentId": "INV-001", ...}, peppol_id="0245:0000000001") # Kontrola prijatých docs = client.get_received("0245:0000000001") for doc in docs["documents"]: print(doc["documentId"]) client.acknowledge(doc["documentId"], "0245:0000000001")
// Node.js / browser (fetch API) const BASE = "https://epostak.sk/api"; class EpostakClient { #token = null; #refreshToken = null; async authenticate(clientId, clientSecret) { const resp = await fetch(`${BASE}/auth/token`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ client_id: clientId, client_secret: clientSecret, grant_type: "client_credentials" }) }); const data = await resp.json(); this.#token = data.access_token; this.#refreshToken = data.refresh_token; return data; } #headers(peppolId) { return { "Authorization": `Bearer ${this.#token}`, "X-Peppol-Participant-Id": peppolId, "Content-Type": "application/json" }; } async sendInvoice(xmlPayload, metadata, peppolId) { const resp = await fetch(`${BASE}/document/send`, { method: "POST", headers: { ...this.#headers(peppolId), "Idempotency-Key": crypto.randomUUID() }, body: JSON.stringify({ metadata, payload: xmlPayload, payloadFormat: "XML" }) }); return resp.json(); } async getReceived(peppolId, status = "RECEIVED") { const resp = await fetch( `${BASE}/document/receive?status=${status}`, { headers: this.#headers(peppolId) } ); return resp.json(); } async acknowledge(docId, peppolId) { const resp = await fetch( `${BASE}/document/receive/${docId}/acknowledge`, { method: "POST", headers: this.#headers(peppolId) } ); return resp.json(); } async renew() { const resp = await fetch(`${BASE}/auth/renew`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ refresh_token: this.#refreshToken }) }); const data = await resp.json(); this.#token = data.access_token; this.#refreshToken = data.refresh_token; return data; } } // Pouzitie: const client = new EpostakClient(); await client.authenticate("test_98b486a08b3e3d7f", "sk_test_e888be545de8bf6e132e5934b790761cdabc65b67595b3a6"); const docs = await client.getReceived("0245:0000000001"); for (const doc of docs.documents) { await client.acknowledge(doc.documentId, "0245:0000000001"); }
// PHP 8+ s cURL class EpostakClient { private $base = "https://epostak.sk/api"; private ?string $token = null; private ?string $refreshToken = null; public function authenticate(string $clientId, string $secret): array { $data = $this->post("/auth/token", [ "client_id" => $clientId, "client_secret" => $secret, "grant_type" => "client_credentials" ]); $this->token = $data["access_token"]; $this->refreshToken = $data["refresh_token"]; return $data; } public function sendInvoice(string $xml, array $meta, string $peppolId): array { return $this->post("/document/send", [ "metadata" => $meta, "payload" => $xml, "payloadFormat" => "XML" ], $peppolId, bin2hex(random_bytes(16))); } public function getReceived(string $peppolId, string $status = "RECEIVED"): array { return $this->get("/document/receive?status={$status}", $peppolId); } public function acknowledge(string $docId, string $peppolId): array { return $this->post("/document/receive/{$docId}/acknowledge", [], $peppolId); } private function post(string $path, array $body, ?string $peppolId = null, ?string $idem = null): array { $headers = ["Content-Type: application/json"]; if ($this->token) $headers[] = "Authorization: Bearer {$this->token}"; if ($peppolId) $headers[] = "X-Peppol-Participant-Id: {$peppolId}"; if ($idem) $headers[] = "Idempotency-Key: {$idem}"; $ch = curl_init($this->base . $path); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => $headers, CURLOPT_POSTFIELDS => json_encode($body), CURLOPT_RETURNTRANSFER => true ]); $resp = curl_exec($ch); curl_close($ch); return json_decode($resp, true); } private function get(string $path, string $peppolId): array { $opts = ["http" => ["header" => "Authorization: Bearer {$this->token}\r\nX-Peppol-Participant-Id: {$peppolId}"]]; return json_decode(file_get_contents( $this->base . $path, false, stream_context_create($opts)), true); } } // Pouzitie: $client = new EpostakClient(); $client->authenticate("test_98b486a08b3e3d7f", "sk_test_e888be545de8bf6e132e5934b790761cdabc65b67595b3a6"); $docs = $client->getReceived("0245:0000000001");
// C# / .NET 8+ using System.Net.Http.Json; public class EpostakClient : IDisposable { private readonly HttpClient _http = new(); private string? _token, _refreshToken; const string Base = "https://epostak.sk/api"; public async Task<TokenResponse> AuthenticateAsync(string clientId, string secret) { var resp = await _http.PostAsJsonAsync($"{Base}/auth/token", new { client_id = clientId, client_secret = secret, grant_type = "client_credentials" }); resp.EnsureSuccessStatusCode(); var data = await resp.Content.ReadFromJsonAsync<TokenResponse>(); _token = data.AccessToken; _refreshToken = data.RefreshToken; return data; } public async Task<JsonElement> SendInvoiceAsync( string xml, object metadata, string peppolId) { var req = new HttpRequestMessage(HttpMethod.Post, $"{Base}/document/send"); req.Headers.Add("Authorization", $"Bearer {_token}"); req.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString()); req.Headers.Add("X-Peppol-Participant-Id", peppolId); req.Content = JsonContent.Create(new { metadata, payload = xml, payloadFormat = "XML" }); var resp = await _http.SendAsync(req); return await resp.Content.ReadFromJsonAsync<JsonElement>(); } public void Dispose() => _http.Dispose(); } public record TokenResponse( [property: JsonPropertyName("access_token")] string AccessToken, [property: JsonPropertyName("refresh_token")] string RefreshToken, [property: JsonPropertyName("expires_in")] int ExpiresIn );
// Java 17+ (java.net.http) import java.net.http.*; import com.google.gson.*; public class EpostakClient { private static final String BASE = "https://epostak.sk/api"; private final HttpClient http = HttpClient.newHttpClient(); private String token, refreshToken; public JsonObject authenticate(String clientId, String secret) throws Exception { String body = new Gson().toJson(Map.of( "client_id", clientId, "client_secret", secret, "grant_type", "client_credentials")); HttpRequest req = HttpRequest.newBuilder() .uri(URI.create(BASE + "/auth/token")) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(body)) .build(); HttpResponse<String> resp = http.send(req, HttpResponse.BodyHandlers.ofString()); JsonObject json = JsonParser.parseString(resp.body()) .getAsJsonObject(); this.token = json.get("access_token").getAsString(); this.refreshToken = json.get("refresh_token").getAsString(); return json; } public JsonObject getReceived(String peppolId) throws Exception { HttpRequest req = HttpRequest.newBuilder() .uri(URI.create(BASE + "/document/receive?status=RECEIVED")) .header("Authorization", "Bearer " + token) .header("X-Peppol-Participant-Id", peppolId) .GET().build(); HttpResponse<String> resp = http.send(req, HttpResponse.BodyHandlers.ofString()); return JsonParser.parseString(resp.body()).getAsJsonObject(); } }
# Ruby (net/http) require "net/http" require "json" require "securerandom" class EpostakClient BASE = URI("https://epostak.sk/api") def authenticate(client_id, client_secret) data = post("/auth/token", { client_id: client_id, client_secret: client_secret, grant_type: "client_credentials" }) @token = data["access_token"] @refresh = data["refresh_token"] data end def send_invoice(xml, metadata, peppol_id) post("/document/send", { metadata: metadata, payload: xml, payloadFormat: "XML" }, peppol_id, SecureRandom.uuid) end def get_received(peppol_id, status: "RECEIVED") get("/document/receive?status=#{status}", peppol_id) end def acknowledge(doc_id, peppol_id) post("/document/receive/#{doc_id}/acknowledge", {}, peppol_id) end private def post(path, body, peppol_id = nil, idem = nil) uri = URI(BASE.to_s + path) req = Net::HTTP::Post.new(uri) req["Content-Type"] = "application/json" req["Authorization"] = "Bearer #{@token}" if @token req["X-Peppol-Participant-Id"] = peppol_id if peppol_id req["Idempotency-Key"] = idem if idem req.body = body.to_json resp = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) } JSON.parse(resp.body) end end
Chybové kódy
Všetky chyby vracajú jednotný JSON formát s kľúčom error obsahujúcim category, code, message a correlation_id.