Pro SaaS, ERP a platformy
Vestavte Peppol e-fakturaci do svého produktu
Integrujete se jednou a obsluhujete neomezeně mnoho svých zákazníků. Vlastní certifikovaný slovenský Peppol Access Point, REST API, podepsané webhooky, veřejný sandbox a white-label v ceně. Tato stránka je kompletní technický návod: od registrace přes onboarding firem až po odesílání a příjem dokladů.
Architektura
Model integrace: jeden token, N vašich zákazníků
Model je proxy / multi-tenant: váš backend drží jeden API token (vpt_…) výhradně na serveru a každý váš zákazník je u nás jedna firma (tenant). Všechna volání dělá váš server. Token nikdy nepatří do prohlížeče ani do mobilní aplikace. Kterou firmu volání obsluhuje, určíte u dokladů hlavičkou X-Peppol-Participant-Id, u správy firem přímo ID firmy v cestě.
1 · Portálové REST API
Správa tenantů: založení firmy, ověření odesílání, webhooky, seznamy dokladů, stahování XML/PDF/doručenek, exporty. Auth: Authorization: Bearer vpt_… přímo.
2 · SAPI-SK 1.0
Národní standardizované rozhraní na samotné doklady: odesílání (i dávkové), příjem, stav doručení. Auth: OAuth2 client_credentials (client_id = UUID tokenu, client_secret = vpt_… token).
3 · Webhooky k vám
Při přijaté / odeslané faktuře voláme vaši URL podepsaným HMAC POSTem s retry a dead-letter frontou (per tenant, s vlastním secretem).
váš SaaS (backend) Verteco Peppol AP svět
────────────────── ───────────────── ────
POST /api/v1/companies ──────────────▶ založení tenanta
zákazník: výběr na FS (eID) ─────────▶ Finanční správa SR
◀── FS webhook: firma active + SMP reg.
POST /sapi/document/send ─────────────▶ validace → AS4 ──────────────────────▶ síť Peppol (příjemce)
◀── doručenka MLS (delivered/rejected)
◀── webhook invoice.received ────────── přijatá faktura ze sítě Peppol ◀────── odesílatelpeppolParticipantId); odesílání: po ověření Verifikačního údaje (firma je sending-verified). Odesílání je u nás fail-closed (doporučení Finanční správy poskytovatelům, § 76a odst. 2 zákona o DPH): bez ověřeného Verifikačního údaje API vrátí 403 sending_not_verified. Detaily v kroku 2.Krok 0
Účet a API klíč: registrace na naše endpointy
- 1. Vytvořte si účet na /register (e-mail + heslo, zdarma, bez vázanosti).
- 2. V dashboardu otevřete API tokeny (
/dashboard/tokens) a vytvořte token. Formát jevpt_+ 40 hex znaků; plaintext se zobrazí pouze jednou při vytvoření (my ukládáme jen SHA-256 hash). Spolu s tokenem si poznamenejte i jeho UUID. Je to zároveň OAuth2client_idpro SAPI-SK. - 3. Token má přístup jako váš účet: funguje pro všechny firmy, které spravujete (multi-tenant bez dalších klíčů). Zrušení tokenu v portálu okamžitě zastaví portálová volání i vydávání nových SAPI tokenů.
Ověření, že klíč funguje:
curl https://peppol.verteco.digital/api/v1/auth/me -H 'Authorization: Bearer vpt_8f2a…'
# → 200 { "id": "…", "email": "dev@vase-saas.cz", … }POST /api/v1/tokens → DELETE /api/v1/tokens/{id}). Už vydané SAPI access tokeny doběhnou do expirace (max 15 minut).Krok 1
Onboarding zákazníka = založení firmy přes API
Pro každého zákazníka založte firmu jedním voláním. Vrácené id si uložte ke svému tenantovi. Je to klíč pro všechna další volání.
curl -X POST https://peppol.verteco.digital/api/v1/companies \
-H 'Authorization: Bearer vpt_8f2a…' \
-H 'Content-Type: application/json' \
-d '{
"ico": "12345678",
"dic": "SK1234567890",
"legalName": "Firma zákazníka s.r.o.",
"street": "Príkladná 12",
"postalCode": "010 01",
"city": "Žilina",
"iban": "SK31 1200 0000 1987 4263 7541"
}'
# → 201 { "id": "9fa8fd81-…", "status": "pending_verification", "peppolParticipantId": null, … }
# (IČO/DIČ výše jsou ukázkové, použijte reálné údaje zákazníka)| Pole | Pravidla |
|---|---|
| ico | 8 číslic; povinné při založení; neměnné, jakmile je jednou nastaveno (400 ico_immutable); duplicita → 409 ico_taken |
| dic | IČ DPH / DIČ ve formátu SK + 10 číslic (u neplátců DPH „SK“ + DIČ); povinné; neměnné po nastavení (je to Peppol identita firmy) |
| legalName | povinné, max 500 znaků; po ověření Finanční správou se zamkne (400 company_verified_locked) |
| street / city / postalCode | volitelné (max 255 / 128 / 16 znaků) |
| country | volitelné, 2 znaky, default „SK“ |
| iban | volitelné, max 34 znaků; předvyplní se do faktur vytvářených v našem webovém rozhraní |
| registeredAddress | volitelné, max 1000 znaků (alternativa ke strukturované adrese) |
Tip: údaje firmy předvyplníte z Registru právnických osob (stejné API používá náš vlastní onboardingový formulář):
curl "https://peppol.verteco.digital/api/v1/lookup/company?ico=53412834" -H 'Authorization: Bearer vpt_8f2a…'
# → 200 { "name": "Verteco digital services, s. r. o.",
# "street": "Daniela Dlabača 21", "city": "Žilina", "zip": "010 01" }409 company_limit). Tým má standardně 25 členů, SaaS partnerům ho bezplatně rozšíříme, stačí napsat. Členy týmu (např. kolegy ze supportu) přidáte přes POST /api/v1/account/team/invite. Seznamy stránkujte: GET /companies?page=0&limit=100 (hlavičky X-Total-Count, X-Total-Pages).Krok 2
Aktivace u Finanční správy: příjem a odesílání
pending_verification ≠ živé v Peppolu. Podle výkladu Finanční správy (FAQ k eFaktúre, příklady 36 a 73) si firma poskytovatele pro příjem zvolí sama na portálu FS (jeden přijímací pošťák na DIČ); pro odesílání výběr slouží k získání verifikačního údaje a firma smí odesílat i přes více pošťáků. Jsou to dva nezávislé kroky:
Příjem faktur → status active
Zákazník vybere Verteco na portálu FS (jednorázově, přihlášením přes eID nebo přihlašovacími údaji PFS)
- Pošlete zákazníka na vpds.financnasprava.sk (výběr poskytovatele: Verteco), kde se přihlásí eID (slovensko.sk) a potvrdí výběr.
- Finanční správa nám pošle webhook s kryptograficky podepsaným souhlasem; ověříme ho automaticky.
- Firma se přepne na
status: "active", dostanepeppolParticipantId(formát0245:<číslice DIČ>) a automaticky ji zaregistrujeme do centrálního SK SMP; od té chvíle přijímá e-faktury. - Vy neděláte nic: dokončení zachytíte webhookem
company.activated, nebo pollingemGET /companies/{id}, dokud se nevyplnípeppolParticipantId(nastavuje se výhradně touto cestou).
Odesílání → sending-verified
Doložte Verifikační údaj přes API
Verifikační údaj (VÚ) je podepsaný řetězec, který firma dostane od Finanční správy při výběru poskytovatele (e-mailem / v portálu PDS). Zákazník vám ho vloží do vašeho UI a vy ho doložíte jedním voláním; my ověříme RSA podpis FS:
curl -X POST https://peppol.verteco.digital/api/v1/companies/{id}/verification \
-H 'Authorization: Bearer vpt_8f2a…' \
-H 'Content-Type: application/json' \
-d '{"token": "<verifikační údaj, 1024 hex znaků>"}'
# → 200 { "companyId": "…", "status": "active",
# "sendingVerified": true,
# "verificationMethod": "self", "verifiedAt": "…" }Neplatný podpis → 400 token_invalid. Chybějící DIČ → 400 company_dic_missing.
active i sending-verified a zaregistrovaná pro příjem. Samostatné doložení VÚ přes API zpřístupní pouze odesílání; registraci pro příjem (SMP) spouští až výběr na portálu FS. Doporučený flow pro SaaS: založit firmu přes API → poslat zákazníka na výběr na FS → hotovo.Krok 3
Příjem faktur: webhooky s podpisem HMAC nebo pull přes API
A · Push: webhook per tenant (doporučeno)
Každé firmě nastavte webhook URL (a volitelně notifikační e-mail) a vyzvedněte podpisový secret (vrátí se pouze jednou):
curl -X PUT https://peppol.verteco.digital/api/v1/companies/{id}/notifications \
-H 'Authorization: Bearer vpt_8f2a…' -H 'Content-Type: application/json' \
-d '{"webhookUrl": "https://vase-saas.cz/peppol/webhook", "notificationEmail": "zakaznik@firma.sk"}'
curl -X POST https://peppol.verteco.digital/api/v1/companies/{id}/webhook/secret -H 'Authorization: Bearer vpt_8f2a…'
# → 200 { "secret": "vpt_…" } ← uložte, zobrazí se pouze jednouPři přijaté faktuře pošleme na vaši URL POST (event invoice.received; při odeslané invoice.sent):
POST https://vase-saas.cz/peppol/webhook
Content-Type: application/json
X-Verteco-Event: invoice.received
X-Verteco-Signature: sha256=3f1a9c… ← HMAC-SHA256 nad surovým tělem
{
"event": "invoice.received",
"companyId": "9fa8fd81-…",
"companyDic": "SK2121358349",
"peppolParticipantId": "0245:2121358349",
"documentId": "574d4e52-…",
"invoiceNumber": "2027-0142",
"senderId": "0245:2120433843",
"supplierName": "Dodávateľ s.r.o.",
"receiverId": "0245:2121358349",
"issueDate": "2027-01-15",
"dueDate": "2027-01-29",
"deliveryDate": "2027-01-15",
"currency": "EUR",
"totalAmount": "1234.56",
"peppolMessageId": "a0b1c2d3-…"
}Partnerský podpisový klíč si nastavíte sami (zprostředkovatelé): PUT /api/v1/resellers/me/notification-webhook s tělem { "url": "https://…" } uloží URL, na kterou budeme události všech vašich zákaznických firem posílat, a při prvním nastavení vrátí podpisový klíč (secret); zobrazí se pouze jednou. Pozdější zobrazení vyžaduje heslo účtu (v portálu v detailu firmy, nebo POST …/notification-webhook/reveal s tělem { "password": "…" }); každé zobrazení se zapisuje do bezpečnostního logu s IP a časem a poslední vidíte v odpovědi GET. Autentizace je vaším portálovým účtem (session nebo Bearer token); klíč nikdy neposíláme e-mailem. To, že je firma zprostředkovatel, vidíte v API na jejím záznamu jako reseller: true (příznak whiteLabel označuje až firmy vašich zákazníků).
Ověření podpisu (Node.js):
import crypto from 'node:crypto';
function verifyVertecoWebhook(rawBody, signatureHeader, secret) {
// podpis = "sha256=" + hex( HMAC-SHA256(secret, surové tělo requestu) )
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
return signatureHeader?.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected));
}
// Důležité: počítejte HMAC nad SUROVÝM tělem (raw bytes), ne nad re-serializovaným JSONem.| Vlastnost doručování | Hodnota |
|---|---|
| Úspěch | jakákoli odpověď 2xx z vaší strany |
| Retry | 12 pokusů s odstupem od 30 sekund do 8 hodin (celkem přibližně 16 hodin), potom dead-letter s možností opakovaného doručení z portálu |
| Timeout | 15 s na pokus; přesměrování se nenásledují |
| URL | veřejná http(s) adresa; interní/privátní IP blokujeme (SSRF guard) |
| Deduplikace | retry posílá identické tělo; deduplikujte podle documentId |
| Test | POST /companies/{id}/webhook/test (pošle podepsaný event webhook.test s "test": true) |
B · Pull: SAPI-SK receive (alternativa nebo doplněk)
# seznam přijatých dokladů (inkrementálně přes ?since=)
curl "https://peppol.verteco.digital/sapi/document/receive?since=2027-01-01T00:00:00Z&limit=200" \
-H 'Authorization: Bearer <sapi_access_token>' \
-H 'X-Peppol-Participant-Id: 0245:2121358349'
# → { "documents": [ { "documentId": "…", "documentTypeId": "…",
# "senderParticipantId": "…", "receiverParticipantId": "…", … } ],
# "nextPageToken": "50" }
# detail včetně originálního XML přesně tak, jak přišlo ze sítě
curl https://peppol.verteco.digital/sapi/document/receive/{documentId} \
-H 'Authorization: Bearer <sapi_access_token>' -H 'X-Peppol-Participant-Id: 0245:2121358349'
# → { "metadata": { … }, "payload": "<Invoice …>", "payloadFormat": "XML" }
# potvrzení zpracování (idempotentní)
curl -X POST https://peppol.verteco.digital/sapi/document/receive/{documentId}/acknowledge \
-H 'Authorization: Bearer <sapi_access_token>' -H 'X-Peppol-Participant-Id: 0245:2121358349'K dokladům se dostanete i přes portálové API: GET /companies/{id}/documents?direction=received, stahování …/documents/{docId}/download?format=xml|html|mls, hromadné exporty …/documents/export.csv a …/documents/export.zip (originály XML). E-mailová notifikace firmě (pokud ji zapnete) nese fakturu jako PDF + originál XML v příloze, odesílatel nese jméno firmy a Reply-To směřuje na majitele účtu (chování připravené na white-label).
Krok 4
Odesílání faktur přes SAPI-SK: OAuth2, idempotence, doručenky
1 · Výměna tokenu (OAuth2 client_credentials)
curl -X POST https://peppol.verteco.digital/sapi/auth/token -H 'Content-Type: application/json' \
-d '{
"grant_type": "client_credentials",
"client_id": "<UUID vašeho API tokenu>",
"client_secret": "vpt_8f2a…"
}'
# → 200 { "access_token": "eyJ…", "token_type": "Bearer",
# "expires_in": 900, "refresh_token": "eyJ…" }
# access token platí 15 min (obnova přes POST /sapi/auth/renew, refresh 30 dní);
# GET /sapi/auth/token/status vrátí should_refresh: true < 3 min před expirací2 · Odeslání dokladu (UBL 2.1, Peppol BIS Billing 3.0)
curl -X POST https://peppol.verteco.digital/sapi/document/send \
-H 'Authorization: Bearer <sapi_access_token>' \
-H 'X-Peppol-Participant-Id: 0245:2121358349' \
-H 'Idempotency-Key: fa-2027-0142' \
-H 'Content-Type: application/json' \
-d '{
"metadata": {
"documentId": "FA-2027-0142",
"documentTypeId": "busdox-docid-qns::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": "cenbii-procid-ubl::urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
"senderParticipantId": "0245:2121358349",
"receiverParticipantId": "0245:2120433843"
},
"payload": "<?xml version=\"1.0\"?><Invoice …>…</Invoice>",
"payloadFormat": "XML",
"checksum": "<volitelné: SHA-256 hex payloadu>"
}'
# → 202 { "providerDocumentId": "<UUID u nás>", "status": "ACCEPTED", "receivedAt": "…", "timestamp": "…" }
# při "REJECTED" (neprošel validací / síť odmítla) nese odpověď i pole
# "detail" s konkrétním důvodem (např. porušená pravidla BR-CO-15, …)Idempotency-Key (doporučujeme číslo faktury nebo interní ID) chrání před duplicitním odesláním: opakované volání se stejným klíčem vrátí původní výsledek, nový klíč pro tutéž fakturu ji může poslat dvakrát. Probíhající send se stejným klíčem → 502 SAPI-PROC-001 (retryable: true, zkuste za chvíli); po transportním selhání (failed) retry se stejným klíčem doklad reálně pošle znovu. Stejný klíč pošle doklad znovu i tehdy, když ho odmítla naše kontrola před odesláním (REJECTED, do sítě nic neodešlo) nebo když skončil jako undeliverable (po opravě identifikátoru příjemce nebo po jeho registraci); postup včetně data vystavení opravené faktury je v dokumentaci pro vývojáře. Limit payloadu: 10 MB. Doklady před odesláním validujeme stejným rulesetem EN 16931 + Peppol BIS jako při příjmu; nevalidní doklad vrátí REJECTED s konkrétními pravidly (např. BR-CO-15).3 · Dávkové odesílání (až 100 dokladů)
curl -X POST https://peppol.verteco.digital/sapi/document/batch \
-H 'Authorization: Bearer <sapi_access_token>' -H 'X-Peppol-Participant-Id: 0245:2121358349' \
-H 'Content-Type: application/json' \
-d '{ "documents": [
{ "itemId": "fa-2027-0142", "idempotencyKey": "fa-2027-0142", "metadata": { … }, "payload": "…", "payloadFormat": "XML" },
…
] }'
# (schematický příklad: metadata má stejná pole jako při jednotlivém sendu)
# → 202 { "total": 100, "accepted": 98, "rejected": 1, "failed": 1,
# "results": [ { "itemId": "…", "ok": true, "providerDocumentId": "…", "status": "ACCEPTED" }, … ] }
# položky se zpracovávají sekvenčně; selhání jedné neovlivní ostatní4 · Stav doručení a doručenky (MLS)
Životní cyklus odeslaného dokladu: pending → submitted → delivered / rejected (potvrzené doručenkou MLS od Access Pointu příjemce) nebo failed (transportní selhání; retry se stejným Idempotency-Key), případně undeliverable (příjemce nemá adresu v síti Peppol: doklad jsme převzali a nahlásíme Finanční správě, nikomu se nedoručí). Stavy sledujte inkrementálně:
curl "https://peppol.verteco.digital/sapi/document/sent?since=2027-01-15T00:00:00Z" \
-H 'Authorization: Bearer <sapi_access_token>' -H 'X-Peppol-Participant-Id: 0245:2121358349'
# → { "documents": [ { "documentId": "574d4e52-…", "peppolMessageId": "a0b1c2d3-…",
# "status": "delivered", "statusDateTime": "…", … } ], … }
# documentId = providerDocumentId ze send odpovědi (UUID u nás); párujte podle něj
# nebo podle peppolMessageId; při "rejected" řádek nese i statusDetail s důvodem.
# ?since= zachytává i ZMĚNY STAVU (ne jen nové doklady); ideální pro polling každých pár minut
# doručenka (MLS ApplicationResponse XML), právní důkaz o doručení:
curl "https://peppol.verteco.digital/api/v1/companies/{id}/documents/{documentId}/download?format=mls" \
-H 'Authorization: Bearer vpt_8f2a…'POST /companies/{id}/documents/send s tělem { "xml": "…", "receiverParticipantId": "0245:…" } (beta: tvar odpovědi se ještě může měnit).Plná parita
Všechno, co má přímý zákazník, obsloužíte přes API
Váš tenant nemusí nikdy otevřít náš portál: každá funkce, kterou má přímý zákazník v dashboardu, existuje jako REST endpoint pod vaším tokenem. Přehled celé správcovské plochy (všechno Authorization: Bearer vpt_…, base /api/v1):
| Oblast | Endpointy |
|---|---|
| Firmy (tenanti) | GET/POST /companies · GET/PUT /companies/{id} · stránkování ?page&limit + X-Total-Count |
| Ověření odesílání | POST /companies/{id}/verification (Verifikační údaj) |
| Předvyplnění z registru | GET /lookup/company?ico= → název + adresa z RPO |
| Doklady | GET /companies/{id}/documents?direction=received|sent · GET …/documents/{docId} · POST …/documents/send · POST …/documents/send-test |
| Stahování a exporty | GET …/documents/{docId}/download?format=xml|html|mls · GET …/documents/export.csv · GET …/documents/export.zip (?direction&from&to) |
| Nastavení faktur | GET/PUT /companies/{id}/invoice-settings: číslování ({YYYY}{NNNN}), splatnost, předvolený IBAN a poznámka |
| Adresář odběratelů | GET/POST /companies/{id}/address-book · DELETE …/address-book/{entryId} (auto-save po úspěšném sendu) |
| Notifikace a webhooky | GET/PUT /companies/{id}/notifications · POST …/webhook/secret · POST …/webhook/test · události invoice.received / invoice.sent / invoice.delivered / invoice.rejected / company.activated / company.deactivated / company.smp_registered_elsewhere |
| Režim white-label | PUT /companies/{id} s { "whiteLabel": true }; platforma neposílá tenantovi žádné vlastní e-maily |
| Odregistrace white-label firmy | POST /companies/{id}/deregister s hlavičkami X-Company-Proof-Timestamp a X-Company-Proof (HMAC-SHA256 webhook secretem firmy, viz krok 4 níže); samoobslužnou firmu odregistruje jen přihlášený vlastník |
| Tým | GET /account/team · POST /account/team/invite · POST /account/team/accept |
| API klíče | GET/POST /tokens · DELETE /tokens/{id} |
| Doklady (SAPI-SK) | POST /sapi/document/send · POST …/batch · GET …/receive (+detail, acknowledge) · GET …/sent |
Neviditelná infrastruktura
Provoz white-label: tenant komunikuje jen s vámi
Cílový stav: váš zákazník používá váš produkt, vaši značku a váš support; my jsme neviditelná infrastruktura. Tři kroky, které to zajistí:
1 · Zapněte režim white-label na firmě
S
whiteLabel: trueplatforma neposílá tenantovi žádné vlastní e-maily (např. potvrzení výběru poskytovatele) a nepřebírá si jeho kontaktní adresu z výběru na FS. Komunikaci vedete vy, pod vlastní značkou.bashcurl -X PUT https://peppol.verteco.digital/api/v1/companies/{id} -H 'Authorization: Bearer vpt_8f2a…' \ -H 'Content-Type: application/json' \ -d '{"ico":"12345678","dic":"SK1234567890","legalName":"Firma zákazníka s.r.o.", "street":"Príkladná 12","postalCode":"010 01","city":"Žilina", "iban":"SK31 1200 0000 1987 4263 7541","whiteLabel":true}' # nejjednodušší je poslat whiteLabel už při POST /companies (založení firmy); # POZOR: PUT je plná aktualizace; pošlete všechna volitelná pole (adresa, IBAN), # vynechaná se vymažou2 · Notifikace řešte webhooky, ne našimi e-maily
V režimu white-label platforma neposílá e-maily o fakturách vůbec (pole
notificationEmailse ignoruje). Nastavte webhook a o přijaté faktuře se dozvíte přesinvoice.received. Obsah si stáhnete přes API (XML / tisknutelné HTML) a zákazníkovi pošlete vlastní e-mail z vlastní domény.3 · Dokončení výběru na FS zachytíte webhookem company.activated
Když zákazník dokončí výběr poskytovatele na portálu Finanční správy, pošleme na webhook firmy událost (nemusíte pollovat):
httpPOST https://vase-saas.cz/peppol/webhook X-Verteco-Event: company.activated X-Verteco-Signature: sha256=… { "event": "company.activated", "companyId": "9fa8fd81-…", "companyDic": "SK2121358349", "peppolParticipantId": "0245:2121358349", "status": "active", "verifiedAt": "2027-01-05T09:12:33Z" }Událost znamená: výběr kryptograficky ověřen, firma přepnuta na
status: "active", registrace do SK SMP odeslána; tenant je připraven přijímat i odesílat (Verifikační údaj přišel spolu s výběrem). Událost je at-least-once; zpracujte ji idempotentně a vždy se řiďte polemstatusv těle (posíláme ji jen pro reálně aktivované firmy; firma pozastavená administrátorem ji nedostane).4 · Když tenant firmu zruší: odregistrace přes API s důkazem webhook secretem
Odregistrace ze sítě je nevratná pro doručování faktur firmě, proto ji samotný API klíč nikdy neprovede (403
token_not_allowed). U white-label firmy, kterou jste založili vy, přidáte druhý faktor, který máte jen vy: aktuální webhook secret firmy (odpověď na POST …/webhook/secret). Časové razítko platí ±300 s, companyId je malými písmeny tak, jak ho vrací API. Nesprávný, expirovaný nebo neuplatnitelný důkaz vrátí 403company_proof_invalidbez bližšího důvodu; samoobslužnou firmu (bez whiteLabel) odregistruje nadále jen přihlášený vlastník.bash# secret = vpt_0123456789abcdef0123456789abcdef01234567 (webhook secret firmy) # companyId = 9fa8fd81-2c4e-4b7a-9d3e-5f6a7b8c9d0e # timestamp = 1760000000 (unix sekundy, ±300 s) # message = deregister:9fa8fd81-2c4e-4b7a-9d3e-5f6a7b8c9d0e:1760000000 # proof = hex(HMAC-SHA256(secret, message)) # = e7e21ebd72506453b95c4cbb87c5556a21d93a5539cc7de6b32a29b9d7090901 TS=$(date +%s) PROOF=$(printf '%s' "deregister:{id}:$TS" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" | awk '{print $NF}') curl -X POST https://peppol.verteco.digital/api/v1/companies/{id}/deregister \ -H 'Authorization: Bearer vpt_8f2a…' \ -H "X-Company-Proof-Timestamp: $TS" \ -H "X-Company-Proof: $PROOF" # 200 → firma ve stavu pending_verification + webhook company.deactivated; 403 company_proof_invalid → důkaz nesedí, # vypršel, firma není white-label nebo nemá webhook secret (důvod se nevrací)
Co tenant uvidí a co ne (upřímně)
Neviditelné pro tenanta
- · celé API, portál, dashboard (tenant je nikdy nepotřebuje)
- · e-maily: v režimu white-label od nás žádné nechodí
- · technická identita v síti (náš certifikát Access Pointu); vidí ji jen jiné Access Pointy
Krok, který zůstává na firmě
- · jednorázový výběr poskytovatele na portálu Finanční správy: zákazník tam vybírá „Verteco digital services“ ze státního seznamu certifikovaných poskytovatelů. Platí to stejně pro každého poskytovatele na trhu; pro příjem je to podle výkladu Finanční správy povinnost, pro odesílání tím firma získá verifikační údaj (FAQ FS, příklad 73).
- · Verifikační údaj od FS, který nám (přes vás) firma dokládá před odesíláním
I toto poslední okno se dá přebrandovat: Finanční správa umožňuje certifikovaným poskytovatelům registrovat partnery jako zprostředkovatele doručovací služby. Po zápisu si zákazník na vpds.financnasprava.sk vybírá přímo vaši značku ze seznamu. Žádost o zápis vygenerujete za pár minut na /sprostredkovatel.
Bezpečnost a zákonné požadavky
| Požadavek | Jak je splněn |
|---|---|
| Oprávnění odesílat (§ 76a odst. 2 písm. b zák. 222/2004) | fail-closed gate: bez kryptograficky ověřeného Verifikačního údaje od FS vrátí každý send 403; nedá se obejít ani přes API, ani přes batch |
| Souhlas firmy s poskytovatelem | výběr na portálu FS (přihlášení přes eID nebo přihlašovacími údaji PFS); FS nám ho doručí podepsaný (RSA-PSS); ověřujeme podpis, ne tvrzení |
| Ochrana osobních údajů | data faktur v EU (Frankfurt); zpracování podle VOP a zásad ochrany údajů (odkazy níže); webhooky podepisované HMAC, secrety se nedají zpětně přečíst |
| Důkaz o doručení | doručenka MLS (ApplicationResponse) přijatá ověřeným kanálem AS4 od Access Pointu příjemce, stažitelná přes API jako právní doklad o doručení |
| Daňové hlášení (TDD) | obstaráváme automaticky podle harmonogramu zpřístupnění rozhraní C5 FS; partner nic neimplementuje |
| Izolace tenantů | přístup jen přes členství ve firmě; API token má přísně stejná práva jako váš účet; SAPI kontroluje shodu odesílatele s autorizovaným participantem |
| ISO/IEC 27001 | certifikát zatím nemusí mít žádný poskytovatel (OpenPeppol ho vyžaduje od všech od 1. 10. 2027); naše certifikace ISO/IEC 27001:2022 probíhá u akreditovaného orgánu SKQS, s. r. o., Žilina (SNAS), vybraného v září 2026, certifikát plánujeme do 1. 7. 2027 |
Právní dokumenty: obchodní podmínky · ochrana osobních údajů. Smluvní vztah máte s námi vy jako partner; vůči svým zákazníkům vystupujete podle vlastních podmínek.
Vývoj a testování
Sandbox: veřejný, bez registrace
Celý kontrakt SAPI-SK si vyzkoušíte okamžitě s veřejnými přihlašovacími údaji client_id = sandbox / client_secret = sandbox. Sandbox validuje požadavky přesně jako produkce, ale nikdy nic nedoručí a nevidí reálná data; izolace je vynucená přímo v podepsaném tokenu.
# 1 · sandbox token
curl -X POST https://peppol.verteco.digital/sapi/auth/token -H 'Content-Type: application/json' \
-d '{"grant_type":"client_credentials","client_id":"sandbox","client_secret":"sandbox"}'
# 2 · mock send: plná validace kontraktu, nic se nedoručí
curl -X POST https://peppol.verteco.digital/sapi/document/send \
-H 'Authorization: Bearer <sandbox_token>' -H 'X-Peppol-Participant-Id: 0245:0000000000' \
-H 'Content-Type: application/json' \
-d '{"metadata":{"documentId":"TEST-1","documentTypeId":"…","senderParticipantId":"0088:sandbox-sender","receiverParticipantId":"0088:sandbox-receiver"},"payload":"<Invoice/>","payloadFormat":"XML"}'
# → 202 { "providerDocumentId": "sandbox-…", "status": "ACCEPTED", … }
# 3 · vzorový přijatý doklad
curl "https://peppol.verteco.digital/sapi/document/receive" -H 'Authorization: Bearer <sandbox_token>' -H 'X-Peppol-Participant-Id: 0245:0000000000'
curl "https://peppol.verteco.digital/sapi/document/receive/sandbox-doc-0001" -H 'Authorization: Bearer <sandbox_token>' -H 'X-Peppol-Participant-Id: 0245:0000000000'Doplňky k sandboxu: veřejný validátor e-faktur (stejná pravidla jako produkční AP), testovací webhook (POST /companies/{id}/webhook/test) a zkušební faktura přes reálnou síť na vlastní firmu (POST /companies/{id}/documents/send-test).
Bez autentizace
Veřejné API: ověření příjemce a validace dokladu
Ověření příjemce v síti Peppol
Před odesláním si ověřte, zda je příjemce registrovaný (živý lookup SML/SMP). Bere SK IČ DPH, DIČ i plné Peppol ID:
curl "https://peppol.verteco.digital/api/v1/public/peppol-check?id=SK2121358349"
# → { "registered": true, "participantId": "0245:2121358349",
# "smp": "…", "capabilities": ["Faktúra (BIS Billing)", …],
# "lastCheckedAt": "…" }Validace e-faktury (EN 16931 + Peppol BIS)
Stejný ruleset, jakým prochází každý doklad v našem Access Pointu, ideálně do CI nebo do vývoje mapování:
curl -X POST "https://peppol.verteco.digital/api/v1/public/peppol-validate" \
-H 'Content-Type: application/xml' --data-binary @faktura.xml
# → { "valid": false,
# "errors": ["BR-CO-15: Invoice total amount with VAT …"],
# "warnings": [] } (limit 3 MB)Robustnost
Rate limity, chybové odpovědi a velikostní limity
Rate limity (pevné 60sekundové okno)
| Rozsah | Limit | Klíč |
|---|---|---|
| /api/v1/** (portál) a /sapi/document/* | dynamický, s velkou rezervou | na API token |
| /sapi/auth/* a /api/v1/auth/* | přísnější (anti brute-force) | na IP adresu |
| /api/v1/public/** (checker, validátor) | přísnější | na IP adresu |
Každá odpověď nese hlavičky RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset; při překročení přijde 429 s hlavičkou Retry-After a tělem { "error": "rate_limited", "message": "Too many requests. Slow down." }. (Výjimka: /auth/me a /auth/logout jdou v běžném bucketu na token.) Aktuální hodnoty limitů čtěte vždy z hlaviček; jsou nastavené tak, aby jich běžný provoz včetně špiček nikdy nedosáhl. Při hromadném onboardingu / batch odesílání dávkujte s backoffem na 429. Potřebujete vyšší limit? Napište nám.
Dva tvary chyb
Portálové API (/api/v1/**)
{ "error": "ico_taken",
"message": "A company with this IČO already exists" }
// při validaci polí navíc:
{ "error": "validation_failed", "message": "Some fields are invalid",
"fields": { "dic": "IČ DPH musí byť 'SK' a 10 číslic" } }SAPI-SK (/sapi/**)
{ "error": {
"category": "AUTH",
"code": "SAPI-AUTH-003",
"message": "Sending is not enabled for this participant: a verified Verifikačný údaj is required.",
"retryable": false,
"correlation_id": "b4191dfc-…"
} }| Kód SAPI | HTTP | Význam |
|---|---|---|
| SAPI-AUTH-001 | 401 | neplatné / zrušené client credentials |
| SAPI-AUTH-002 | 401 | chybějící / neplatný / expirovaný Bearer token |
| SAPI-AUTH-003 | 403 / 401 | firma pro participanta neexistuje, nemáte k ní přístup, sender nesedí, chybí ověřený Verifikační údaj; nebo (při /auth/token a /auth/renew, 401) volající IP není na allowlistu API klíče nastaveném v portálu |
| SAPI-VAL-001 / 002 | 400 | neplatná pole / chybějící hlavička X-Peppol-Participant-Id |
| SAPI-RES-001 / 002 | 404 | doklad neexistuje / originál payload není archivován |
| SAPI-PROC-001 | 502 | dočasné selhání (retryable: true); zopakujte se stejným Idempotency-Key |
| SAPI-PROC-002 | 503 | dočasná infrastrukturní chyba (retryable: true); zopakujte se stejným Idempotency-Key |
| SAPI-PROC-500 | 500 | neočekávaná chyba (retryable: false); neopakujte, nahlaste nám correlation_id |
Velikostní limity
| Kde | Limit |
|---|---|
| SAPI payload (send / položka batch) | 10 MB na doklad; batch max 100 položek |
| Portálový send (pole xml) | 2 MB |
| Veřejný validátor | 3 MB |
| Seznamy (receive / sent / documents) | limit max 200 na stránku, default 50 |
Obchodní model
Přeprodej a white-label: jak se to počítá
Příjem bez archivu zdarma
Firma s vypnutým Archivem dat přijímá e-faktury zdarma do 1 000 faktur měsíčně, včetně daňového hlášení; obsah dokladů se u nás maže 14 dní po doručení. Firmy pod vaší značkou (white-label) se zakládají bez archivu.
Odesílání a Archiv dat od 2 €/měs
Platí se za IČO, které v měsíci odeslalo fakturu nebo mělo zapnutý Archiv dat (u nových firem v portálu předvoleně): 2 €/měs + DPH, strhává se z vašeho předplaceného kreditu vždy 1. den měsíce za ukončený měsíc (první čerpání 1. 2. 2027 za leden 2027). V ceně je archiv originálů v EU (1 GB), REST API, webhooky, konektory, více IČO, B2G i white-label.
0,01 € nad limit
Každá faktura (přijatá nebo odeslaná) nad 1 000 faktur měsíčně; žádný tvrdý strop, doručení nikdy neblokujeme.
Vaše marže = vaše věc
Svým zákazníkům fakturujete vy, podle vlastního ceníku. Nám platíte podle veřejného ceníku, bez skrytých partnerských poplatků.
White-label v ceně
Řešení pod vlastní značkou je součást balíčku: e-maily o fakturách nesou jméno firmy zákazníka, vaše UI je vaše.
Objemová dohoda
Při desítkách a stovkách firem připravíme objemovou dohodu a bezplatně zvýšíme limity účtu. Napište nám.
Go-live
Checklist před spuštěním
- ✓Účet + API token vytvořen, token bezpečně uložen na serveru (nikdy ve frontendu).
- ✓Onboarding flow: POST /companies + přesměrování zákazníka na výběr poskytovatele na portálu FS (eID).
- ✓Stavový polling: sledujete peppolParticipantId (signál, že firma přijímá) a příznak verified + status active před prvním odesláním.
- ✓Webhook endpoint: ověřuje X-Verteco-Signature (HMAC-SHA256 nad surovým tělem), odpovídá 2xx do 15 s, deduplikuje podle documentId.
- ✓Odesílání: Idempotency-Key na každém sendu, backoff na 429 a SAPI-PROC-001, polling /sapi/document/sent?since= na stavy doručení.
- ✓Mapování dokladů otestováno přes veřejný validátor a sandbox; první ostrý test přes send-test.
- ✓Ošetřené chybové stavy: 403 sending_not_verified, 409 ico_taken, verdikt REJECTED s důvodem.
- ✓Limity účtu navýšené podle počtu firem (napište nám při >10 firmách).
Otázky partnerů
Časté otázky SaaS a platforem
- Musí mít každý náš zákazník účet ve vašem portálu?
- Ne. Model je proxy: váš backend drží jeden API token a firmy zákazníků zakládáte a obsluhujete přes API ve svém účtu. Zákazník dělá jediný krok mimo váš produkt: jednorázový výběr poskytovatele na portálu Finanční správy (eID nebo přihlašovací údaje PFS). Podle výkladu FS je výběr povinný pro příjem; pro odesílání jím firma dodá verifikační údaj, který před odesláním vyžadujeme. Portálový účet u nás je pro ni volitelný bonus, ne podmínka.
- Jak zjistíme, že zákazník dokončil výběr na Finanční správě?
- Nejjednodušeji: nastavte firmě webhook a poslouchejte událost company.activated. Pošleme ji hned po kryptografickém ověření výběru, spolu s přiděleným peppolParticipantId. Alternativně polling: GET /api/v1/companies/{id}, kde spolehlivý signál dokončeného výběru (a tedy schopnosti přijímat) je vyplněné pole peppolParticipantId (nastavuje se výhradně po výběru na portálu FS). Samotný status active nestačí: nastaví ho i doložení Verifikačního údaje přes API, které zpřístupňuje pouze odesílání.
- Můžeme službu prodávat pod vlastní značkou (white-label)?
- Ano. Řešení pod vlastní značkou je součástí balíčku Odesílání a příjem, bez zvláštních partnerských poplatků. Firmě nastavíte whiteLabel: true a platforma jí neposílá žádné vlastní e-maily; notifikace odebíráte webhooky a komunikujete pod vlastní značkou. Vy určujete cenu pro své zákazníky a fakturujete jim sami; nám platíte podle veřejného ceníku.
- Jak otestujeme integraci bez reálných dokladů?
- Tři nástroje: veřejný SAPI sandbox (client_id i client_secret = "sandbox") s plnou validací kontraktu, který nikdy nic nedoručí; veřejný validátor e-faktur (POST /api/v1/public/peppol-validate) se stejnými pravidly EN 16931 + Peppol BIS jako produkční Access Point; a testovací webhook (POST /companies/{id}/webhook/test), který pošle podepsanou vzorovou událost na vaši URL.
- Co když zákazník posílá tisíce faktur měsíčně?
- Žádný tvrdý strop: nad 1 000 faktur měsíčně je každá další faktura 0,01 €. API podporuje dávkové odesílání (batch až 100 dokladů na volání) a inkrementální stahování přes parametr since. Při velkém objemu firem nebo dokladů připravíme objemovou dohodu.
- Jaké typy dokladů umíte přijímat a odesílat?
- Faktury a dobropisy Peppol BIS Billing 3.0 (UBL 2.1) včetně pravidel SK Billing, self-billing faktury a dobropisy a doručenky MLS. Slovenské daňové hlášení (TDD) k dokladům obstaráváme automaticky podle harmonogramu zpřístupnění rozhraní Finanční správy.
- Je API verzované a stabilní?
- Ano. Strojově čitelná specifikace OpenAPI 3.1 je na /api/v1/openapi.json a pokrývá portálové API i SAPI-SK. SAPI-SK je národní standardizované rozhraní, ne proprietární kontrakt, takže integrace není vendor lock-in. Změny děláme zpětně kompatibilně.
Začněte se sandboxem ještě dnes · ostrý účet máte za minutu
Související: kompletní dokumentace API · OpenAPI 3.1 · hotové e-shopové pluginy · pro účetní · ceník