Příjem dokumentů
Dokumenty zaslané účastníkům vašich koncových uživatelů přistanou ve schránce (inboxu) daného účastníka. Webhook vám dá vědět, že něco přišlo; dokument pak stáhnete ve formátu, který váš software čte, a potvrdíte jeho převzetí.
Čtení schránky patří do Document API, proto vyžaduje klíč přijímajícího koncového uživatele, ne váš partnerský klíč. Pokud váš software běží centrálně, vyberte podle participantId z webhooku klíč správného koncového uživatele.
Schránka
Každý účastník má schránku s dokumenty, které přijal a vy jste je zatím nepotvrdili, seřazenými od nejstaršího.
curl -s "$DOCUMENT_API/v1/inbox/9929:CZ87654321?limit=100" -H "X-Api-Key: $END_USER_KEY"
limitje 1–500, výchozí 50. Zpracované dokumenty potvrďte a zavolejte znovu pro další stránku.- Každá položka má stejnou podobu jako stav přenosu:
transmissionId,state,counterpartyId(odesílatel),documentTypeId,validationReport,createdAt. - Účastník, který nepatří volajícímu koncovému uživateli, vrací
404.
Nevalidní dokumenty
Dokument, který při příjmu neprojde validací Peppol, vám je přesto doručen, se stavem state: "Invalid" a s validationReport. Odesílatel dostal potvrzení o převzetí a vzápětí odmítnutí (Message Level Status RE) s chybami, takže ví, že má poslat opravený dokument. Platný dokument Redque odesílateli potvrdí (AB). Co Redque odesílateli odpověděl, si stáhnete přes GET /v1/inbox/{participantId}/{transmissionId}/message-status/document.
U slovenských koncových uživatelů Redque k přijaté faktuře podá daňové hlášení za příjemce. Jeho stav a dokumenty najdete v GET /v1/inbox/{participantId}/{transmissionId}/tax-reports (viz Daňová hlášení).
Stažení dokumentu
curl -s "$DOCUMENT_API/v1/inbox/9929:CZ87654321/$TRANSMISSION_ID/document?format=Isdoc" \
-H "X-Api-Key: $END_USER_KEY" -o invoice.isdoc
Parametr format je povinný a rozlišuje velikost písmen. Tentýž dokument můžete stáhnout v libovolném formátu a kolikrát chcete; převádí se při každém požadavku.
format | Vrací |
|---|---|
Isdoc | ISDOC 6.0.2, application/xml. Obsahuje v rozšíření celou fakturu podle EN 16931, takže se při zpětném převodu nic neztratí. |
Ubl | Přesně ty bajty, které přišly přes Peppol, UBL podle Peppol BIS Billing 3.0. Vždy k dispozici. |
CanonicalJson | Model EN 16931 od Redque jako JSON, application/json. |
Pokud dokument nelze konvertovat do požadovaného formátu, odpověď je 422 s vysvětlením; stáhněte ho jako Ubl. Při archivaci přijatých faktur uchovávejte Ubl jako právní originál.
Potvrzení převzetí
curl -s -X POST "$DOCUMENT_API/v1/inbox/9929:CZ87654321/$TRANSMISSION_ID/ack" -H "X-Api-Key: $END_USER_KEY"
Potvrďte dokument, jakmile je bezpečně uložen ve vašem systému. Zmizí z výpisu schránky, ale stáhnout ho lze dál. Potvrzení je idempotentní a vrací 204.
Webhooky
Odběry webhooků patří vám, partnerovi, a pokrývají všechny vaše koncové uživatele. Vytvoříte je partnerským klíčem:
curl -s -X POST "$PARTNER_API/v1/webhooks" -H "X-Api-Key: $PARTNER_KEY" -H "Content-Type: application/json" \
-d '{ "url": "https://example.com/peppol/webhook" }'
{ "subscriptionId": "a41e…", "url": "https://example.com/peppol/webhook", "active": true, "createdAt": "…", "secret": "q0b9…" }
secret podepisuje každé doručení a vrací se pouze v této odpovědi. URL musí být HTTPS. GET /v1/webhooks vypíše vaše odběry, DELETE /v1/webhooks/{subscriptionId} odběr deaktivuje. Pro změnu secret vytvořte nový odběr a pak smažte starý.
Události
| Událost | Kdy |
|---|---|
document.received | Některému z vašich účastníků dorazil dokument. state je Dispatched, nebo Invalid, pokud neprošel validací. |
transmission.status | Dokument, který jste odeslali, přešel do stavu Delivered, Failed, Rejected nebo Recorded (jen daňové hlášení, odběratel mimo Peppol). Dokument odmítnutý už v odpovědi API (422) událost nevyvolá. |
transmission.message_status | Přístupový bod příjemce odpověděl na dokument, který jste odeslali (Message Level Status). Podrobnosti v messageStatus u přenosu. |
tax_report.status | Daňové hlášení k dokumentu (odeslanému i přijatému) změnilo stav: odesláno, potvrzeno nebo odmítnuto úřadem, nebylo potřeba, selhalo. Podrobnosti v GET /v1/documents/{id}/tax-reports. |
Každá událost je JSON POST. Dokumenty nikdy nejsou součástí události: stáhněte je přes API.
POST /peppol/webhook HTTP/1.1
Content-Type: application/json
X-Redque-Event: document.received
X-Redque-Delivery: 5c7d2a0e-…
X-Redque-Timestamp: 1791976351
X-Redque-Signature: v1=8f2c…
{
"eventType": "document.received",
"transmissionId": "e3a1…",
"direction": "Inbound",
"state": "Dispatched",
"participantId": "9929:cz87654321",
"counterpartyId": "9929:cz12345678",
"documentTypeId": "busdox-docid-qns::urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##…::2.1",
"instanceIdentifier": "…",
"occurredAt": "2026-10-14T09:15:02+00:00",
"validationSuccess": true
}
participantIdje účastník vašeho koncového uživatele: udocument.receivedpříjemce, utransmission.statusodesílatel.counterpartyIdje protistrana.lastErrorje uveden, pokud nějaká chyba nastala, například uFailed.
Doručování a opakování
- Odpovězte libovolným stavem
2xx, zpracování proveďte až potom. - Jakákoli jiná odpověď nebo žádná odpověď vede k opakování v prodlužujících se intervalech — 30 sekund a pak dvojnásobek až do 6 hodin.
- Doručení může přijít víckrát.
X-Redque-Deliveryje napříč opakováními jednoho doručení stejné. - Události nemusí dorazit ve správném pořadí. Spoléhejte na
state, případně si aktuální stav načtěte z API. - Webhooky jsou pouze notifikace. Schránka drží každý dokument, dokud ho nepotvrdíte, takže se nic neztratí, ani když je váš endpoint nedostupný.
Ověření podpisu
Každé doručení je podepsáno secretem vašeho odběru: X-Redque-Signature je v1= následované hexadecimálním (malá písmena) HMAC-SHA256 z {X-Redque-Timestamp}.{surové tělo}. Podpis ověřujte na surových bajtech ještě před parsováním JSON, porovnávejte v konstantním čase a odmítejte staré časové značky, abyste zabránili přehrání.
Node.js
import crypto from "node:crypto";
// rawBody: tělo požadavku jako Buffer, před parsováním JSON.
export function verifyRedqueWebhook(secret, headers, rawBody, toleranceSeconds = 300) {
const timestamp = headers["x-redque-timestamp"];
const signature = headers["x-redque-signature"] ?? "";
if (!timestamp || Math.abs(Date.now() / 1000 - Number(timestamp)) > toleranceSeconds) return false;
const expected = "v1=" + crypto.createHmac("sha256", secret)
.update(Buffer.concat([Buffer.from(timestamp + "."), rawBody]))
.digest("hex");
return expected.length === signature.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
C#
using System.Security.Cryptography;
using System.Text;
static bool VerifyRedqueWebhook(string secret, string timestamp, string signature, byte[] rawBody, TimeSpan tolerance)
{
if (!long.TryParse(timestamp, out var unix) ||
Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - unix) > tolerance.TotalSeconds)
return false;
byte[] payload = [.. Encoding.UTF8.GetBytes(timestamp + "."), .. rawBody];
var expected = "v1=" + Convert.ToHexStringLower(HMACSHA256.HashData(Encoding.UTF8.GetBytes(secret), payload));
return CryptographicOperations.FixedTimeEquals(Encoding.ASCII.GetBytes(expected), Encoding.ASCII.GetBytes(signature));
}
Spolehlivý postup příjmu
- Při
document.received: ověřte podpis, odpovězte200a zařaďteparticipantIdatransmissionIddo fronty. - Stáhněte dokument ve svém formátu a jako
Ublpro archiv. Uložte obojí. - Potvrďte převzetí.
- Pravidelně procházejte schránky všech účastníků, abyste zaručili doručení i v případě zmeškaného webhooku.