Dokumentácia

Pre vývojárov: API referencia

REST API portálu a národné rozhranie SAPI-SK 1.0: autentifikácia, firmy, doklady, webhooky, chyby a limity.

Úvod

Verteco API je REST nad HTTPS. Request aj response sú JSON (UTF-8). Začnite vytvorením účtu, potom API tokenu, a urobte prvé volanie do minúty. Všetky cesty sú relatívne voči základnej URL nižšie.

Celé testovacie prostredie nájdete na test.peppol.verteco.digital. Správa sa rovnako ako produkcia, navyše má testovacie nástroje (FS webhook, verifikačný token, odstránenie firmy) a simulovaný výber poskytovateľa namiesto portálu Finančnej správy.

Base URL
https://peppol.verteco.digital/api/v1
Verzia
v1 (v ceste). Spätne nekompatibilné zmeny prídu pod novou verziou.
Protokol
HTTPS only · TLS 1.2+ · TLS A+
Formát
application/json (UTF-8)
Auth
cookie session (portál) alebo Bearer token (server-to-server)
Časy
ISO-8601 (UTC), napr. 2026-06-03T09:40:27Z

Certifikovaný AP

Reálny Peppol Access Point (Seat ID PSK001128), nie reseller. Prešli sme OpenPeppol conformance (19/19), v produkcii.

Validné doklady

Server-side validácia EN 16931 + Peppol BIS 3.0 Schematron pri každom prijatom AJ odosielanom doklade. Doklad si viete overiť aj vopred: verejný validátor beží na /validator (a ako API na POST /api/v1/public/peppol-validate); chyby vraciame s konkrétnym pravidlom (napr. BR-CO-15).

Multi-tenant

Jeden účet a jeden token pre N firiem, ideálne pre SaaS, ERP a účtovníkov.

SK TDD automaticky

Daňové hlásenie (corner-5 / TDD) na Finančnú správu generujeme a odosielame za vás.

Strojové rozhranie (OpenAPI 3.1): /api/v1/openapi.json. Importujte do Postman, otvorte v Swagger Editore, alebo si cez openapi-generator vygenerujte typovaného klienta v ľubovoľnom jazyku (TS, Java, PHP, Python…). Pokrýva portálové API aj SAPI-SK.

Rýchly štart

Účet aj API token si vytvoríte v portáli (cez prehliadač). Integrácia potom beží výhradne cez API token. Registráciu, prihlásenie ani heslá vaša appka nerieši.

  1. 1

    Vytvorte si účet v portáli

    Zaregistrujte sa e-mailom a potvrďte ho odkazom z e-mailu.
  2. 2

    Vygenerujte API token

    V portáli API tokeny → Vytvoriť. Token vpt_… sa zobrazí iba raz. Uložte si ho bezpečne.
  3. 3

    Urobte prvé volanie

    Token použite v hlavičke Authorization:
    javascript
    const res = await fetch('https://peppol.verteco.digital/api/v1/companies', {
    headers: { Authorization: 'Bearer vpt_8f2a…' },
    });
    const companies = await res.json();

Testovacie prostredie (sandbox)

Testovacie doklady sa po 60 dňoch automaticky mažú – prostredie je na skúšanie, nie na archiváciu. Ostrého portálu sa retencia netýka.

Okrem SAPI mock sandboxu (nižšie) prevádzkujeme aj plnohodnotné testovacie prostredie, kompletnú kópiu tohto portálu s oddelenými dátami, kde si celý tok (registrácia → firma → odoslanie → prijatie → notifikácie) vyskúšate end-to-end bez akéhokoľvek dopadu na ostrú prevádzku.

Registrácia
bez potvrdzovacieho e-mailu; účet je použiteľný okamžite
Schválenie firmy
automatické, priamo v rozhraní alebo cez API (bez výberu na portáli Finančnej správy, bez prihlásenia na portál FS); hneď po vytvorení firmy s IČ DPH môžete odosielať aj prijímať
Registrácia v sieti
automatická do testovacej siete Peppol. Pozor na dve vrstvy identifikátora: API a portál používajú rovnaký formát ako produkcia (peppolParticipantId = 0245:<číslice DIČ>, váš integračný kód sa nemení); do testovacieho SMP/SML sa firma technicky zapisuje ako 9950:SK<DIČ>, lebo schéma 0245 vyžaduje overovací kód Finančnej správy, ktorý v teste neexistuje. V produkcii sa registruje 0245:<číslice DIČ> do ostrej siete až po výbere poskytovateľa na portáli Finančnej správy (prihlásenie cez eID alebo prihlasovacími údajmi)
Validácia
reálna: EN 16931 + Peppol BIS 3.0 pravidlá, rovnaké ako v ostrej prevádzke
Doručenie
reálne cez testovaciu sieť Peppol (AS4, testovací certifikát, testovacie SML/SMP): príjemcovi registrovanému v testovacej sieti sa faktúra doručí ako prijatá (vrátane e-mailu, PDF a webhooku); do ostrej siete nič neodchádza
Doručenka
reálna MLS doručenka z testovacej siete
E-maily
reálne odchádzajú (na adresy, ktoré zadáte), s prefixom [TEST]
Cena
zadarmo, bez limitov na skúšanie

Funguje tam všetko čo tu: portál, REST API, SAPI-SK 1.0, e-shop pluginy aj webhooky. Stačí v integrácii vymeniť doménu za test.peppol.verteco.digital a použiť tokeny vytvorené v testovacom prostredí. Ideálne na vývoj integrácie, CI testy a zaškolenie účtovníkov pred ostrým nasadením.

Pozn.: edge ochrana testovacej domény blokuje generické hlavičky User-Agent: Python-urllib a User-Agent: Java/1.8.x (predvolený User-Agent HttpsURLConnection v Jave 8) odpoveďou HTTP 403 „error code: 1010“ ešte pred naším API; ostrá doména peppol.verteco.digital ich prepúšťa. Stačí nastaviť vlastný User-Agent: v Jave buď parametrom JVM -Dhttp.agent=moja-app/1.0 (bez zmeny kódu; Java pripojí „Java/1.8“, výsledný „moja-app/1.0 Java/1.8.0_xxx“ ochrana prepúšťa, blokuje len hlavičku začínajúcu na „Java/1.8“), alebo na spojení conn.setRequestProperty("User-Agent", "moja-app/1.0"). Bežné klienty (requests, httpx, Java 11+, Apache HttpClient, okhttp, axios, Go, PHP, curl) fungujú bez zmeny.

Prečo sa firmy schvaľujú automaticky

Finančná správa nemá testovacie prostredie portálu VPDS: výber poskytovateľa na vpds.financnasprava.sk beží len v produkcii a overuje sa prihlásením na portál FS (eID alebo prihlasovacie údaje PFS), takže v ostrej prevádzke si nemôžete „vybrať" ľubovoľnú cudziu firmu. Aby ste napriek tomu vedeli integráciu otestovať, v testovacom prostredí tento krok simulujeme: každá firma, ktorú vytvoríte, sa schváli automaticky (bez výberu na FS), takže si viete založiť odosielateľa aj príjemcu a prejsť celý tok.

Na testovanie FS webhookov (výber poskytovateľa) máme vlastnú obdobu nástroja Finančnej správy: test.peppol.verteco.digital/sandbox-nastroje. Vygenerujete si tam platný verifikačný token (verifikačný údaj) v štýle FS a odošlete kompletný webhook na svoj endpoint, presne ako to robí portál FS pri reálnom výbere. Firmy vytvorené na testovanie viete zase odregistrovať (z portálu aj z testovacieho SMP), práve pre chýbajúci testovací režim na strane Finančnej správy.

Testovacie prostredie nie je súčasťou ostrej siete Peppol: firmy sa registrujú do oddelenej testovacej siete (testovacie SMP/SML), nič neodchádza na reálne endpointy a dáta v ňom môžu byť kedykoľvek premazané. Nepoužívajte ho na reálne faktúry; na tie je ostrá prevádzka na peppol.verteco.digital, kde registráciu do ostrej siete odomyká výber poskytovateľa na portáli Finančnej správy potvrdený prihlásením (eID alebo prihlasovacie údaje PFS).

Autentifikácia

Integrácia sa autentifikuje API tokenom v hlavičke Authorization: Bearer vpt_…. Token vytvoríte v portáli (API tokeny); má formát vpt_ + 40 hex znakov, ukladáme len jeho SHA-256 hash a má rovnaký prístup ako váš účet. Otestujte ho cez /auth/me:

curl
curl https://peppol.verteco.digital/api/v1/auth/me -H 'Authorization: Bearer vpt_8f2a…'
# 200 → { "id": "…", "email": "vy(at)firma.sk" }   (token funguje)

Pri chýbajúcom alebo neplatnom tokene API vráti:

json
// 401 Unauthorized
{ "error": "unauthorized", "message": "Authentication required" }
Portál (prehliadač) používa internú session cookie (portal_session, JWT, 7 dní); pri server-to-server integrácii ju nepotrebujete. Verejné bez auth sú /ping, /openapi.json a endpointy pod /public/* (overenie peppol-check, validátor peppol-validate – detail v sekcii Verejné nástroje – a stav služby status); všetko ostatné vyžaduje session alebo Bearer token.

Konvencie & formáty

TypFormátPríklad
idUUID (string)08dd6c1e-…
časové značkyISO-8601 Instant (UTC)2026-06-03T09:40:27Z
issueDatedátum (YYYY-MM-DD)2026-06-03
totalAmountdesatinné číslo120.00
chýbajúce hodnotynull (nie vynechané pole)"dic": null

Stránkovanie & idempotencia

/companies a /companies/{id}/documents podporujú voliteľné ?page&limit (odpoveď zostáva JSON pole; celkový počet nájdete v hlavičkách X-Total-Count / X-Total-Pages). Bez parametrov vrátia celé pole, doklady zoradené createdAt zostupne; /tokens vracia vždy celé pole. Hlavičku Idempotency-Key podporuje národné rozhranie SAPI-SK na POST /sapi/document/send; pre programové odosielanie použite práve to.

Chyby

Chyby majú jednotný tvar s machine-readable error kódom. Validačné chyby pridávajú mapu fields (prvá chyba na pole).

json
// business chyba
{ "error": "invalid_credentials", "message": "Invalid email or password" }

// validačná chyba (400)
{ "error": "validation_failed", "message": "Some fields are invalid",
"fields": { "ico": "IČO musí byť 8 číslic" } }

HTTP stavy

200 / 201 / 204
úspech (OK / vytvorené / bez obsahu)
400
neplatný vstup (pozri error / fields)
401
chýbajúca alebo neplatná autentifikácia
403
nedostatočné oprávnenie (rola)
404
zdroj neexistuje alebo naň nemáte prístup
405
nepodporovaná HTTP metóda pre danú cestu
409
konflikt (IČO / e-mail už existuje)
415
nepodporovaný Content-Type (XML endpointy očakávajú application/xml)
429
prekročený rate limit (hlavičky RateLimit-* a Retry-After, telo JSON rate_limited)
Naše API odpovedá vždy JSON-om s poľom error. Ak dostanete odpoveď bez JSON tela (HTML alebo text ako error code: 1010 so stavom 403, prípadne 502/504 pri nasadzovaní), neprišla z API, ale z infraštruktúry pred ním (edge ochrana, brána). Typická príčina 403/1010 je generický User-Agent knižnice (Python-urllib, Java/1.8.x na testovacej doméne), riešenie je v sekcii Testovacie prostredie.

Kompletný katalóg chýb

KódHTTPKedy
validation_failed400telo nesplnilo validáciu (pozri fields)
unauthorized401chýba alebo neplatný API token
forbidden403akcia vyžaduje rolu owner/admin
company_not_found404firma neexistuje alebo nie ste jej členom
ico_taken409firma s týmto IČO už existuje
ico_immutable400IČO sa nedá zmeniť
company_dic_missing400overenie odosielania bez DIČ firmy
token_invalid400verifikačný údaj (podpis) nesedí
document_not_found404doklad neexistuje
token_not_found404API token neexistuje / nie je váš
rate_limited429priveľa requestov

Rate limity

API je chránené rate limitingom v 60-sekundovom okne (per inštancia). Limit a zostatok vraciame v každej odpovedi cez hlavičky; pri prekročení vráti 429 Too Many Requests s Retry-After.

Bežné volania
dynamický limit s veľkou rezervou, na API token (alebo session, inak IP); aktuálnu hodnotu vracia hlavička RateLimit-Limit
Auth (/auth/*)
prísnejší limit na IP (anti brute-force; mimo /auth/me a /auth/logout)
RateLimit-Limit
limit v okne
RateLimit-Remaining
koľko ešte ostáva
RateLimit-Reset
sekúnd do resetu okna
Retry-After
sekúnd do ďalšieho pokusu (pri 429)
http
HTTP/2 429 Too Many Requests
RateLimit-Limit: <limit v okne>
RateLimit-Remaining: 0
RateLimit-Reset: 37
Retry-After: 37

{ "error": "rate_limited", "message": "Too many requests. Slow down." }
Praktické odpovede integrátorov:
  • Limity sú viazané na prihlasovací údaj, nie na IP: 300 volaní za minútu na API token (SAPI: na access token), auth endpointy 20 za minútu na IP a ochranný strop 600 za minútu na IP pre /api/v1. Serverovej integrácii za jednou IP to neprekáža; vyššie limity nastavíme na požiadanie, napíšte očakávanú špičku.
  • Polling je plnohodnotná cesta: GET /sapi/document/sent a /receive s ?since a ?until každých 1 až 5 minút; webhooky sú doplnok, nie podmienka.
  • Časové pečiatky: čas odoslania = statusDateTime stavu delivered v /sapi/document/sent (potvrdené doručenkou MLS), čas prijatia = creationDateTime v /sapi/document/receive; čas odovzdania hlásenia FS = fsReportedAt (webhook invoice.reported alebo pole fsReportedAt v udalostiach invoice.*); každý webhook nesie occurredAt a eventId.
  • PDF: cez API vraciame tlačiteľné HTML (…/html, portál ?format=html), z ktorého sa PDF tlačí v prehliadači alebo headless Chrome; samostatný PDF endpoint neexistuje.
  • C#/.NET a iné jazyky: klienta vygenerujte z OpenAPI (NSwag, Kiota, openapi-generator); vlastný NuGet balík nedodávame.

API tokeny

Opaque tokeny vpt_… pre server-to-server prístup. Plaintext sa zobrazí iba raz pri vytvorení. Uložte si ho. Ukladáme len SHA-256 hash a 12-znakový prefix na zobrazenie.

GET/tokenssession / token

Zoznam vašich aktívnych tokenov (bez secretu), createdAt zostupne.

POST/tokenssession / token

Vytvorí token; vráti plaintext (jediný raz).

PoleTypPovinnéPopis
namestringánonázov tokenu, max 128
curl
curl -X POST https://peppol.verteco.digital/api/v1/tokens -b cookies.txt \
-H 'Content-Type: application/json' -d '{"name":"moja-appka"}'
# 201 Created
{ "id":"…","name":"moja-appka","token":"vpt_8f2a…","prefix":"vpt_8f2a3b…","createdAt":"…" }
DELETE/tokens/{id}session / token

Zruší token. Vráti 204.

Chyby: token_not_found (404)

Firmy

Firmy (IČO / IČ DPH), ktoré spravujete. Prístup je viazaný na členstvo: vidíte len firmy, ktorých ste členom. Tvorca firmy sa stáva jej owner.

GET/companiessession / token

Zoznam firiem, ktorých ste členom (s vašou rolou).

POST/companiessession / token

Pridá firmu; stanete sa owner, status = pending_verification.

PoleTypPovinnéPopis
icostringánopresne 8 číslic
dicstringánoIČ DPH vo formáte SK + 10 číslic (napr. SK2121358349); neplatiteľ DPH pošle len 10 číslic DIČ, SK doplníme
legalNamestringánoobchodné meno, max 500
registeredAddressstringniesídlo, max 1000
curl
curl -X POST https://peppol.verteco.digital/api/v1/companies \
-H 'Authorization: Bearer vpt_8f2a…' -H 'Content-Type: application/json' \
-d '{"ico":"53412834","dic":"SK2121358349","legalName":"Verteco digital services, s. r. o."}'

# 201 Created
{ "id":"08dd…","ico":"53412834","dic":"SK2121358349","legalName":"…",
"registeredAddress":null,"peppolParticipantId":null,
"status":"pending_verification","role":"owner","createdAt":"2026-06-03T09:40:27Z" }

Chyby: ico_taken (409) · validation_failed (400)

GET/companies/{id}session / token

Detail firmy (musíte byť členom).

PUT/companies/{id}owner / admin

Úprava firmy. IČO je nemenné (musí sa rovnať existujúcemu).

Chyby: forbidden (403) · ico_immutable (400) · company_not_found (404)

Pole status

pending_verification
po vytvorení; odosielanie ešte nie je odomknuté
active
overená, odosielanie odomknuté

Rola člena

owner
tvorca firmy (plný prístup)
admin
správca (úpravy, webhooky, overenie)
member
člen (čítanie)
viewer
iba čítanie
Akcie „owner / admin" sú dostupné rolám owner aj admin (manažér firmy).

Overenie odosielania (Verifikačný údaj)

Pred odosielaním treba firmu overiť cez Verifikačný údaj (VÚ), podpísaný token od Finančnej správy. Po úspešnom overení sa status firmy zmení na active a odomkne sa odosielanie. V bežnom toku VÚ nikto neprepisuje: Finančná správa ho pošle na náš webhook v momente, keď si firma na portáli FS zvolí Verteco (alebo vášho sprostredkovateľa), a overenie prebehne automaticky. Tento endpoint je záložná cesta pre prípad, že VÚ máte z e-mailu FS a webhook nedorazil; neregistruje firmu do SMP.

POST/companies/{id}/verificationowner / admin

Self-verify Verifikačného údaja. Po úspechu nastaví status na active.

PoleTypPovinnéPopis
tokenstringánoVÚ = hex podpis (prod/pPFS 1024 hex, test/tPFS 768 hex)
curl
curl -X POST https://peppol.verteco.digital/api/v1/companies/{id}/verification \
-H 'Authorization: Bearer vpt_8f2a…' -H 'Content-Type: application/json' \
-d '{"token":"<1024-hex VÚ>"}'

# 200 OK
{ "companyId":"08dd…","status":"active","sendingVerified":true,
"verificationMethod":"self","verifiedAt":"2026-06-15T…Z" }

Chyby: company_dic_missing (400) · token_invalid (400) · forbidden (403)

Dokumenty

Log Peppol dokladov (prijatých a odoslaných) za firmu. Napĺňa sa, ako cez Access Point tečú faktúry. Viazané na členstvo vo firme, zoradené createdAt zostupne.

GET/companies/{id}/documentssession / token

Zoznam dokladov firmy. Voliteľný filter ?direction=sent|received.

curl
curl 'https://peppol.verteco.digital/api/v1/companies/{id}/documents?direction=received' \
-H 'Authorization: Bearer vpt_8f2a…'
# 200 OK
[ { "id":"…","direction":"received","peppolMessageId":"…","docTypeId":"…",
  "senderId":"0088:7300010000001","receiverId":"0245:2121358349",
  "invoiceNumber":"2026001","issueDate":"2026-06-03",
  "currency":"EUR","totalAmount":120.00,"status":"received","createdAt":"…" } ]
GET/companies/{id}/documents/{docId}session / token

Detail jedného dokladu.

Chyby: document_not_found (404)

GET/companies/{id}/documents/{docId}/downloadsession / token

Samostatné HTML faktúry na tlač. ?inline=1 → zobrazí v prehliadači, inak stiahne.

Vráti text/html, Content-Disposition s názvom faktura-<číslo>.html.

SAPI-SK 1.0 (národné rozhranie)

SAPI-SK je štandardizované národné REST rozhranie medzi klientskym/ERP systémom a Access Pointom (sapi-sk.sk). Implementujeme ho v plnom rozsahu. Vďaka tomu nie ste viazaní na náš proprietárny tvar API a integráciu napíšete raz pre ktorýkoľvek SAPI-SK Access Point.

Base URL
https://peppol.verteco.digital/sapi
Autentifikácia
OAuth2 client_credentials → krátkodobý access token (JWT)
client_id
UUID vášho API tokenu (zoznam v sekcii API tokeny / dashboard)
client_secret
samotný vpt_… token z portálu
Verzia
1.3 (10 operácií: 4× auth, 6× dokumenty)
SAPI access token je podpísaný samostatným kľúčom (nie je to portálový vpt_ token ani session). Zrušenie API tokenu v portáli okamžite zneplatní aj /auth/token aj /auth/renew.

Sandbox (skúšobné prostredie)

Chcete si SAPI-SK vyskúšať bez registrácie a bez rizika? Použite verejné sandbox prihlasovacie údaje. Sandbox validuje požiadavky presne ako ostrá prevádzka, ale nikdy nič neodošle na Peppol sieť a nepracuje s reálnymi dátami; vráti realistické mock odpovede. Ideálne na vývoj, CI a onboarding integrácie.

client_id
sandbox
client_secret
sandbox
send
plná validácia kontraktu + mock 202 (nič sa nedoručí)
receive
1 vzorový doklad sandbox-doc-0001 na test parsovania a acknowledge
curl
# 1) sandbox token (bez registrácie)
curl -X POST https://peppol.verteco.digital/sapi/auth/token \
-H 'Content-Type: application/json' \
-d '{ "client_id": "sandbox", "client_secret": "sandbox",
      "grant_type": "client_credentials" }'

# 2) mock odoslanie: zvaliduje sa, ale NIČ sa reálne nedoručí
curl -X POST https://peppol.verteco.digital/sapi/document/send \
-H 'Authorization: Bearer <sandbox access_token>' \
-H 'X-Peppol-Participant-Id: 0245:0000000000' \
-H 'Content-Type: application/json' \
-d '{ "metadata": { "documentId": "TEST-1",
        "documentTypeId": "urn:…::Invoice##…::2.1",
        "senderParticipantId": "0088:sandbox-sender",
        "receiverParticipantId": "0088:sandbox-receiver" },
      "payload": "<Invoice>…</Invoice>", "payloadFormat": "XML" }'
# 202 { "providerDocumentId": "sandbox-…", "status": "ACCEPTED", … }

# 3) vzorová schránka + detail vzorového dokladu
curl https://peppol.verteco.digital/sapi/document/receive \
-H 'Authorization: Bearer <sandbox access_token>'
curl https://peppol.verteco.digital/sapi/document/receive/sandbox-doc-0001 \
-H 'Authorization: Bearer <sandbox access_token>'
Sandbox tokeny sú izolované: nikdy nedoručia na Peppol a nevidia reálne doklady. Na ostré odosielanie použite client_id/client_secret z portálu (nižšie).

Autentifikácia

POST/sapi/auth/tokenclient_credentials

Vymení client_id + client_secret za access token (15 min) a refresh token (30 dní). Token si uložte a používajte ho celých 15 minút - nový token na každé volanie je zbytočná réžia (limit požiadaviek sa počíta aj na /auth/token).

curl
curl -X POST https://peppol.verteco.digital/sapi/auth/token \
-H 'Content-Type: application/json' \
-d '{ "client_id": "<UUID tokenu>", "client_secret": "vpt_8f2a…",
      "grant_type": "client_credentials" }'
# 200 OK
{ "access_token": "eyJhbGciOi…", "token_type": "Bearer",
"expires_in": 900, "refresh_token": "eyJhbGciOi…" }

Chyby: SAPI-AUTH-001 (401) · SAPI-AUTH-003 (401: IP mimo allowlistu kľúča) · SAPI-VAL-001 (400)

GET/sapi/auth/token/statusBearer (access)

Platnosť a expirácia access tokenu; should_refresh = true pri < 3 min do konca.

POST/sapi/auth/renewrefresh token

Vystaví nový access + refresh token. Zlyhá, ak bol podkladový API token zrušený.

json
// body
{ "refresh_token": "eyJhbGciOi…" }
POST/sapi/auth/revoke

Vždy vráti success (RFC 7009). Trvalý kill-switch = zrušenie API tokenu v portáli.

Odoslanie dokumentu

POST/sapi/document/sendBearer (access)

Odošle Peppol biznis dokument (UBL / BIS 3.0) príjemcovi cez náš Access Point. Odosielanie je fail-closed: firma musí mať overený Verifikačný údaj.

Povinné hlavičky:

HlavičkaPopis
AuthorizationBearer <access_token>
X-Peppol-Participant-Idúčastník, za ktorého odosielate (napr. 0245:2121358349, číslice DIČ bez „SK“)
Idempotency-Keyjedinečný kľúč na jedno odoslanie; opakované volanie vráti pôvodný výsledok a nikdy nedoručí dvakrát. Výnimka: ak bol prvý pokus odmietnutý ešte pred odoslaním (príjemca nie je v sieti Peppol, chyba validácie, neúplná požiadavka), rovnaký kľúč odoslanie zopakuje, takže „oprav a pošli znova“ funguje aj pod rovnakým číslom faktúry
curl
curl -X POST https://peppol.verteco.digital/sapi/document/send \
-H 'Authorization: Bearer eyJ…' \
-H 'X-Peppol-Participant-Id: 0245:2121358349' \
-H 'Idempotency-Key: 7b1f0e2a-…' \
-H 'Content-Type: application/json' \
-d '{ "metadata": {
        "documentId": "INV-2026-001",
        "documentTypeId": "urn:…::Invoice##…::2.1",
        "processId": "urn:…:bis:billing:3.0",
        "senderParticipantId": "0245:2121358349",
        "receiverParticipantId": "0088:7300010000001",
        "creationDateTime": "2026-06-17T10:00:00Z" },
      "payload": "<Invoice …>…</Invoice>",
      "payloadFormat": "XML" }'
# 202 Accepted
{ "providerDocumentId": "…", "status": "ACCEPTED",
"receivedAt": "2026-06-17T10:00:01Z", "timestamp": "…" }
# pri status "REJECTED" nesie odpoveď aj pole "detail"
# s dôvodom odmietnutia (validačné pravidlá, napr. BR-CO-15)
metadata vs. UBL: polia v metadata sú smerovacie a technické: documentId je váš interný identifikátor, nie číslo faktúry. Obchodné údaje (číslo faktúry cbc:ID, dátum vystavenia, splatnosť, dátum dodania, mena, suma) si preberáme priamo z UBL payloadu; nič z toho v metadata neposielate a UBL je vždy zdroj pravdy pre zobrazenie v portáli aj webhooky.

Chyby: SAPI-AUTH-002 (401) · SAPI-AUTH-003 (403) · SAPI-VAL-001 (400) · SAPI-PROC-001 (502) · SAPI-PROC-002 (503) · SAPI-PROC-500 (500: neopakovať, nahláste correlation_id)

HTTP kód vs. verdikt. Podľa národného kontraktu SAPI-SK odpovedá odoslanie vždy 202a verdikt nesie telo (status ACCEPTED alebo REJECTED). Ak chcete, aby verdikt niesol aj HTTP kód, pošlite hlavičku Prefer: handling=strict (RFC 7240): synchrónne odmietnutie sa vráti ako 422 so SAPI chybovou obálkou (SAPI-VAL-002 pri chybe validácie, SAPI-RES-003 keď príjemcovi nejde doručiť; details[] nesú providerDocumentId a detail) a odpoveď má Preference-Applied: handling=strict. Pri ACCEPTED sa nič nemení. Pred odovzdaním prístupovému bodu robíme rovnaký SML/SMP lookup ako on. Príjemca, ktorý v sieti Peppol vôbec nie je, znamená ACCEPTED s undeliverable: true: doklad sme prevzali a nahlásime ho Finančnej správe bez ohľadu na doručenie (§ 85o ods. 11, FS FAQ 9/DPH/2025/IM príklad 9), nikomu sa však nedoručí; na GET /sapi/document/sent má status undeliverable, webhook dostane invoice.undeliverable, e-mail nikomu neposielame a rovnaký Idempotency-Key ide po registrácii príjemcu odoslať znova. Príjemca, ktorý v sieti je, ale nepublikuje daný typ dokladu, dostane REJECTED okamžite, bez pokusu o doručenie. Pole retrying: true pri ACCEPTED znamená, že prvý pokus o doručenie zlyhal (napr. dočasne nedostupné SMP) a prístupový bod ho sám opakuje spravidla do 20 minút; detail nesie dôvod a konečný verdikt príde cez GET /sapi/document/sent alebo webhook.
POST/sapi/document/validateBearer (access)

Overí dokument bez odoslania: rovnaké pravidlá EN 16931 + Peppol BIS 3.0, aké prístupový bod uplatňuje pred odoslaním. Nič sa neukladá ani neodosiela; funguje aj so sandbox tokenom. Telo = JSON pár { payload, payloadFormat } ako pri /document/send, alebo priamo XML (Content-Type: application/xml). Limit 10 MB.

curl
curl -X POST https://peppol.verteco.digital/sapi/document/validate \
-H 'Authorization: Bearer eyJ…' \
-H 'Content-Type: application/xml' \
--data-binary @faktura.xml
# 200 OK
{ "valid": false,
  "errors": [ "BR-CO-15: Invoice total amount with VAT (BT-112) = … " ],
  "warnings": [],
  "checkedAt": "2026-09-10T12:00:00Z" }

Chyby: SAPI-AUTH-002 (401) · SAPI-VAL-001 (400: prázdne telo, neplatný JSON, payloadFormat iný než XML, > 10 MB) · SAPI-SYS-002 (502: validátor dočasne nedostupný, opakujte)

Príjem dokumentov

GET/sapi/document/receiveBearer (access)

Zoznam prijatých dokumentov (najstaršie prvé); metadáta nesú aj invoiceNumber, takže doklad identifikujete bez sťahovania payloadu. Query: ?pageToken, ?limit (max 200), ?status (received / acknowledged; bez ohľadu na veľkosť písmen, iná hodnota vráti chybu SAPI-VAL-001), ?invoiceNumber (presná zhoda s cbc:ID), ?since a ?until (ISO-8601 instant; okno podľa času prijatia – napr. doklady za posledných 5 dní, hromadné stiahnutie na externú archiváciu či rekonštrukciu účtovníctva), ?deliveryDateFrom a ?deliveryDateTo (ISO-8601 dátum; filter podľa dátumu dodania z dokladu). Hlavička X-Peppol-Participant-Id povinná.

json
// 200 OK
{ "documents": [ { "documentId":"…","documentTypeId":"…",
  "senderParticipantId":"0088:…","receiverParticipantId":"0245:…",
  "creationDateTime":"2026-06-17T…Z" } ],
"nextPageToken": "50" }
GET/sapi/document/receive/{documentId}Bearer (access)

Detail vrátane payloadu (raw XML, ako prišiel cez Peppol).

Chyby: SAPI-RES-001 (404) · SAPI-RES-002 (404: payload nearchivovaný)

POST/sapi/document/receive/{documentId}/acknowledgeBearer (access)

Potvrdí prevzatie dokumentu vaším systémom. Idempotentné.

GET/sapi/document/receive/{documentId}/xmlBearer (access)

Archívny odkaz (metadata.links.xml): samotný obchodný doklad ako XML súbor, rovnaký obsah ako payload v detaile.

GET/sapi/document/receive/{documentId}/htmlBearer (access)

Archívny odkaz (metadata.links.html): generický tlačiteľný náhľad faktúry (HTML).

GET/sapi/document/receive/{documentId}/pdfBearer (access)

Archívny odkaz (metadata.links.pdf): PDF dokladu. Ak dodávateľ vložil do XML vlastné PDF faktúry (BT-125), vraciame ten originál; inak PDF vygenerované z uloženého XML na požiadanie (PDF neukladáme). Hlavička X-Verteco-Pdf-Source: supplier | generated. 404 SAPI-RES-002 po výmaze obsahu, 503 pri výpadku renderera (skúste neskôr alebo použite /html).

GET/sapi/document/receive/{documentId}/attachments/{index}Bearer (access)

Archívny odkaz (metadata.links.attachments[].url): bajty jednej prílohy vloženej v doklade, napr. PDF originál dodávateľa. Vynútené stiahnutie.

POST/sapi/document/receive/{documentId}/public-linkBearer (access)

Odkaz bez prihlásenia (voliteľné): vydá NOVÝ náhodný kľúč k dokladu ({"rotate":true} nahradí existujúci). Vráti url (stránka), xmlUrl, htmlUrl, pdfUrl a expiresAt; kľúč sa zobrazí len raz. Firma musí mať zapnuté Sťahovanie faktúr bez autorizácie (403 SAPI-AUTH-004 inak). DELETE odkaz zruší.

Archív namiesto kópie: každý prijatý doklad nesie v metadátach pole links (xml, html, pdf, prílohy) a retention. Integrátor si k zaúčtovanému dokladu môže uložiť len odkaz a doklad stiahnuť až pri zobrazení; odkazy vyžadujú rovnaký Bearer token a hlavičku X-Peppol-Participant-Id. retention.mode = storage znamená, že firma má pre prijaté doklady zapnutý Archív dát a originál uchovávame počas celého trvania zmluvného vzťahu (VOP 11a.1). retention.mode = secure znamená, že firma prijaté doklady u nás nearchivuje: obsah sa nenávratne vymaže v retention.contentAvailableUntil, čo je plánovaný dátum výmazu uložený pri každom doklade (predvolene 14 dní od prijatia; lehota je zvlášť pre prijaté a odoslané doklady a každá zmena nastavenia sa pre existujúce doklady počíta odo dňa zmeny, nikdy skôr), a potom odkazy vracajú SAPI-RES-002; ak je contentAvailableUntil null pri mode secure, obsah zatiaľ držíme z povinnosti (nevykonané daňové hlásenie) a dátum výmazu nesľubujeme. Archív si vlastník firmy nastavuje na detaile firmy zvlášť pre prijaté a pre vystavené doklady. Odkazy bez autorizácie: ak firma na detaile firmy zapne „Sťahovanie faktúr bez autorizácie“, POST /sapi/document/receive/{id}/public-link vráti odkaz s vlastným náhodným kľúčom, ktorý otvorí doklad bez tokenu (url pre človeka, xmlUrl a htmlUrl pre programy). Kľúč je v odpovedi presne raz; odkaz platí najviac do contentAvailableUntil, dá sa zrušiť (DELETE) a po vypršaní vracia 410 s dôvodom, vtedy si vyžiadajte nový. Bez zapnutia v portáli odpovedá 403 SAPI-AUTH-004.
Odkazy bez prihlásenia: polia links.* vyžadujú Bearer vždy (sú to archívne odkazy). Keď má firma zapnuté „Sťahovanie faktúr bez autorizácie“ (detail firmy → Archív dát, alebo PUT /companies/{id}/public-links), detail dokladu nesie metadata.publicLink s hotovými adresami url, xmlUrl, htmlUrl a pdfUrl – rovnaká adresa pri každom čítaní a tá istá, ktorú vidí používateľ v portáli pri faktúre. Uložte si ju k zaúčtovanému dokladu; POST …/public-link potrebujete len na vynútenie nového kľúča. Pri vypnutej voľbe je publicLink.issued=false s reason=public_links_disabled. Odkaz je trvalý: platí, kým je obsah dokladu uložený (pri firme bez archivácie prijatých dokladov do retention.contentAvailableUntil), expiresAt je preto null (v SAPI odpovedi pole chýba); žiadne obnovovanie nie je potrebné. xmlUrl aj links.xml vracajú samotný doklad s koreňom Invoice/CreditNote bez transportnej SBDH obálky. pdfUrl aj links.pdf vracajú PDF, ktoré dodávateľ vložil do XML (BT-125), ak existuje, inak PDF vygenerované z XML; hlavička X-Verteco-Pdf-Source hovorí, ktoré (supplier | generated).

Stav odoslaných dokumentov

GET/sapi/discovery?receiverId=0245:2121358349

Preflight pred odoslaním: je príjemca registrovaný v sieti Peppol a aké typy dokladov vie prijať? Rovnaký SML/SMP lookup, aký robí Access Point; receiverId prijme Peppol ID, IČ DPH aj samotné DIČ. Odpoveď: {registered, participantId, smp, documentTypes, checkedAt}. Hlavička X-Peppol-Participant-Id tu nie je potrebná.

GET/sapi/document/sentBearer (access)

Stav doručenia odoslaných dokladov: pending (odovzdávame sieti) → submitted → delivered / rejected (potvrdené doručenkou MLS od AP príjemcu); failed = transportná chyba (retry s rovnakým Idempotency-Key pošle znova). Query: ?pageToken, ?limit, ?status (pending / submitted / sent / delivered / rejected / failed; bez ohľadu na veľkosť písmen, iná hodnota vráti chybu SAPI-VAL-001), ?invoiceNumber (presná zhoda s cbc:ID – stav konkrétnej faktúry jedným volaním), ?since a ?until (ISO-8601 instant; okno podľa času), ?deliveryDateFrom a ?deliveryDateTo (ISO-8601 dátum; filter podľa dátumu dodania).

json
// 200 OK
{ "documents": [ {
  "documentId": "…",
  "receiverParticipantId": "0245:1084695645",
  "peppolMessageId": "befc9112-…",
  "status": "delivered",
  "statusDateTime": "2026-07-09T14:52:31Z",
  "creationDateTime": "2026-07-09T14:52:12Z" } ],
"nextPageToken": null }

Chyby: SAPI-AUTH-002 (401) · SAPI-AUTH-003 (403) · SAPI-VAL-001 (400: neplatné since)

Hromadné odoslanie

POST/sapi/document/batchBearer (access)

Až 100 dokumentov v jednom volaní. Každá položka prejde plnou logikou jednotlivého odoslania (idempotencia cez itemId + idempotencyKey, rezervácia, submit, verdikt) a vráti vlastný výsledok; chyba jednej položky nezastaví ostatné. Položky sa spracúvajú sekvenčne; failed položky opakujte s rovnakým idempotencyKey.

json
// request
{ "documents": [ {
  "itemId": "fa-2026-001",
  "idempotencyKey": "fa-2026-001",
  "metadata": { "documentId": "2026001", "documentTypeId": "…", "processId": "…",
                "senderParticipantId": "0245:2121358349", "receiverParticipantId": "0245:1084695645" },
  "payload": "<Invoice …>", "payloadFormat": "XML" } ] }

// 202 Accepted
{ "total": 2, "accepted": 1, "rejected": 1, "failed": 0,
"results": [
  { "itemId": "fa-2026-001", "ok": true,  "providerDocumentId": "…", "status": "ACCEPTED" },
  { "itemId": "fa-2026-002", "ok": false, "errorCode": "SAPI-AUTH-003", "errorMessage": "…" } ] }

Chyby: SAPI-AUTH-002 (401) · SAPI-AUTH-003 (403) · SAPI-VAL-001 (400: prázdny/príliš veľký zoznam)

Model chýb

Všetky SAPI chyby majú jednotnú obálku s kategóriou, stabilným kódom, príznakom retryable a correlation_id na podporu.

json
{ "error": {
  "category": "AUTH",
  "code": "SAPI-AUTH-001",
  "message": "Invalid client credentials.",
  "retryable": false,
  "correlation_id": "b4191dfc-…" } }
Poznámka: pri odoslaní doručujeme biznis dokument; C2-strana daňového hlásenia (TDD) k odoslaným dokladom je v príprave. Daňové hlásenie pri príjme (C3) generujeme a podávame na Finančnú správu automaticky.

Notifikácie & webhooky

Pri prijatej faktúre vieme firmu upozorniť e-mailom alebo webhookom (POST na vašu URL). Doručenie je durable: ukladá sa do výstupnej fronty a doručuje asynchrónne (15 s timeout); pri zlyhaní opakujeme až 8× s exponenciálnym backoffom (30 s → max 1 h), potom dead-letter. Výpadok vášho servera teda notifikáciu nestratí, doručíme ju pri ďalšom pokuse. SSRF ochrana blokuje loopback/lokálne adresy; webhook URL musí byť verejná.

GET/companies/{id}/notificationssession / token

Nastavenia notifikácií: { webhookUrl, notificationEmail, hasSecret }.

PUT/companies/{id}/notificationsowner / admin

Nastaví oba kanály (prázdny reťazec = zruší daný kanál).

PoleTypPovinnéPopis
webhookUrlstringnieprázdne alebo http(s) URL, max 512
notificationEmailstringnieplatný e-mail, max 256
GET/companies/{id}/webhooksession / token

Konfigurácia webhooku: { url, hasSecret } (bez secretu).

PUT/companies/{id}/webhookowner / admin

Nastaví URL webhooku (auto-vygeneruje podpisový secret, ak ešte nie je).

PoleTypPovinnéPopis
urlstringánohttp(s) URL, max 512
curl
curl -X PUT https://peppol.verteco.digital/api/v1/companies/{id}/webhook \
-H 'Authorization: Bearer vpt_8f2a…' -H 'Content-Type: application/json' \
-d '{"url":"https://vas-system.sk/peppol/webhook"}'
# 200 OK { "url":"https://vas-system.sk/peppol/webhook", "hasSecret": true }
DELETE/companies/{id}/webhookowner / admin

Zruší webhook URL aj secret. Vráti 204.

POST/companies/{id}/webhook/secretowner / admin

Vygeneruje nový podpisový secret a vráti ho JEDENKRÁT; uložte si ho na overovanie X-Verteco-Signature.

json
// 200 OK
{ "secret": "vpt_8f2a…" }
POST/companies/{id}/webhook/testowner / admin

Pošle synchrónne testovaciu notifikáciu (event webhook.test, podpísanú, SSRF-chránenú) na uloženú URL a vráti, ČO poslala a ČO prišlo späť. To isté spustíte tlačidlom Otestovať webhook v detaile firmy.

json
// 200 OK
{
"sent":     { "url": "https://vas-system.sk/peppol/webhook", "event": "webhook.test",
              "signed": true, "payload": "{…}" },
"received": { "status": 200, "body": "OK", "durationMs": 142, "error": null }
}
// 400 webhook_not_configured, ak nie je uložená webhook URL

Payload webhooku

Pri prijatej (invoice.received) aj odoslanej (invoice.sent) faktúre pošleme POST s týmto telom; pole event rozlišuje typ.

Ďalšie dve udalosti oznamujú verdikt siete o faktúre, ktorú ste odoslali: invoice.delivered (príjemcov Access Point potvrdil doručenie doručenkou MLS) a invoice.rejected (odmietnutá, či už sieťou, alebo pri validácii ešte pred odoslaním); invoice.undeliverable hlási príjemcu bez záznamu v sieti Peppol (prevzaté, nahlásené FS, nedoručené). Nesú identifikáciu dokladu a firmy (documentId, invoiceNumber, receiverId, peppolMessageId, companyDic, peppolParticipantId) plus status, statusDetail s dôvodom odmietnutia a statusDateTime. Ak prvý pokus o doručenie zlyhal a prístupový bod ho sám opakuje (spravidla do hodiny), doklad ostáva submitted a statusDetail začína predponou network_retrying: ; po doručení príde delivered, po vzdaní rejected s predponou network_gave_up: . Vďaka nim nemusíte stav odoslaných faktúr zisťovať polovaním.

Udalosť company.activated príde, keď zákazník dokončí výber poskytovateľa na portáli Finančnej správy (telo: event, companyId, companyDic, peppolParticipantId, status, verifiedAt); company.deactivated zase pri odregistrovaní firmy zo siete (rovnaké telo bez verifiedAt). company.smp_registered_elsewhere príde, keď firma dokončila výber na portáli FS, ale jej záznam v národnom SMP drží iný poskytovateľ (telo ako pri company.activated plus action: "migration_code_required" a migrateUrl). Postup pre partnerov je v dokumentácii pre sprostredkovateľov. Kým zákazník nevloží migračný kód, sieť doručuje starému poskytovateľovi. Detaily v návode /saas:

json
{
"event": "invoice.received",
"eventId": "7f1c2d9e-4b1a-4e3d-9c1f-0a2b3c4d5e6f",
"occurredAt": "2026-09-03T15:04:05Z",
"companyId": "08dd…",
"documentId": "…",
"invoiceNumber": "2026001",
"senderId": "0088:7300010000001",
"supplierName": "Dodávateľ s.r.o.",
"receiverId": "0245:2121358349",
"issueDate": "2026-06-03",
"dueDate": "2026-06-17",
"deliveryDate": "2026-06-03",
"currency": "EUR",
"totalAmount": "120.00",
"peppolMessageId": "…",
"companyDic": "SK2121358349",
"peppolParticipantId": "0245:2121358349"
}

Polia companyDic a peppolParticipantId identifikujú firmu, ktorej sa udalosť týka (dôležité pre partnerov, ktorí majú jednu webhook URL pre všetkých svojich klientov).

Verdikt siete o odoslanej faktúre:

json
{
"event": "invoice.delivered",          // alebo "invoice.rejected"
"occurredAt": "2026-09-03T15:04:05Z",
"companyId": "08dd…",
"companyDic": "SK2121358349",
"peppolParticipantId": "0245:2121358349",
"documentId": "…",
"invoiceNumber": "2026001",
"receiverId": "0245:2120049096",
"peppolMessageId": "…",
"status": "delivered",                 // alebo "rejected"
"statusDetail": null,                  // pri rejected: dôvod odmietnutia
"statusDateTime": "2026-06-03T10:15:42Z"
}

Aktivácia firmy po výbere na portáli Finančnej správy:

json
{
"event": "company.activated",          // company.deactivated má rovnaké telo bez verifiedAt
"occurredAt": "2026-09-03T15:04:05Z",
"companyId": "08dd…",
"companyDic": "SK2121358349",
"peppolParticipantId": "0245:2121358349",
"status": "active",
"verifiedAt": "2026-06-03T10:02:11Z"
}

Názov udalosti nesie aj hlavička X-Verteco-Event. Úplný zoznam udalostí: invoice.received, invoice.sent, invoice.delivered, invoice.rejected, invoice.undeliverable, invoice.reported, company.activated, company.deactivated, company.smp_registered_elsewhere a testovací webhook.test. Neznámy typ udalosti odporúčame odložiť bokom a zalogovať; nový typ vždy vopred ohlásime. Každá udalosť nesie aj occurredAt (čas vzniku udalosti, ISO-8601 UTC), podľa ktorého udalosti radíte, a eventId (rovnaká hodnota aj v hlavičke X-Verteco-Delivery-Id): jedinečný pre každú udalosť a nemenný pri jej opakovaní, preto je to správny kľúč na dedupliáciu (peppolMessageId sa opakuje naprieč invoice.sent, invoice.delivered a invoice.reported). Udalosti invoice.* nesú aj časy sentAt, deliveredAt, receivedAt a fsReportedAt (ISO-8601 UTC, null kým skutočnosť nenastala). invoice.reported príde, keď bolo hlásenie Finančnej správe (TDD) k dokladu odovzdané doručovacej službe (§ 85o ods. 11), a to aj s odstupom dní pri výpadku zberného bodu C5. Formálne schémy všetkých udalostí sú v sekcii webhooks špecifikácie OpenAPI.

Partnerský notifikačný webhook, správa klientov (release, pause-sending) a fakturačný model sú dostupné len zapísaným sprostredkovateľom a sú opísané v časti Pre sprostredkovateľov.

Overenie podpisu

Ak má firma secret, posielame hlavičku X-Verteco-Signature v tvare sha256=HMAC-SHA256(secret, raw telo) (lowercase hex). Vždy počítajte HMAC nad presnými bajtmi tela:

javascript
import crypto from 'node:crypto';

// rawBody = presné bajty tela requestu (nie znova serializovaný JSON)
function verify(rawBody, header, secret) {
const expected = 'sha256=' +
  crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
return crypto.timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}

Hlavičky každého doručenia: X-Verteco-Event (názov udalosti), X-Verteco-Delivery-Id (= eventId v tele, rovnaké pri každom opakovaní), X-Verteco-Signature (HMAC vyššie) a paralelne hlavičky podľa štandardu Standard Webhooks: webhook-id (= eventId), webhook-timestamp (unix sekundy okamihu pokusu) a webhook-signature = v1,base64(HMAC-SHA256(secret, id + "." + timestamp + "." + telo)). Kľúčom sú bajty vášho secretu v UTF-8; knižnica standardwebhooks ho očakáva ako whsec_ + base64(secret). Odporúčaný postup: overte podpis, odmietnite doručenie s webhook-timestamp starším ako 5 minút (ochrana pred prehratím), spracúvajte idempotentne podľa eventId, odpovedzte 2xx do 15 sekúnd a ťažšie spracovanie odložte do vlastnej fronty. Neúspešné doručenie opakujeme 8× s odstupom 30 s až 1 h; potom skončí ako dead-letter s upozornením e-mailom a je viditeľné v Realtime logu. Produkčná webhook URL musí byť https://, v testovacom prostredí je dovolené aj http://.

Secret získate cez POST /companies/{id}/webhook/secret; vráti ho jedenkrát (rotácia vygeneruje nový). Bez secretu hlavičku X-Verteco-Signature neposielame.

Hromadné nastavenie: jeden token, viac firiem

Jeden API token (viazaný na váš účet/e-mail) spravuje všetky firmy, ktoré vlastní: kto firmu založí cez POST /companies, stáva sa jej ownerom a vie jej nastaviť webhook. Webhook je per firma (vlastná URL aj secret), takže rovnakým tokenom napojíte ľubovoľný počet firiem:

bash
# 1) zoznam vašich firiem (stránkovane, viď Firmy)
curl 'https://peppol.verteco.digital/api/v1/companies?page=0&limit=100' -H 'Authorization: Bearer vpt_8f2a…'

# 2) pre KAŽDÚ firmu {id}: nastavte webhook (a/alebo e-mail)
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://vas-system.sk/peppol/webhook","notificationEmail":"faktury@firma.sk"}'

# 3) vyzdvihnite podpisový secret (vráti sa LEN RAZ) a uložte si ho pre overovanie podpisu
curl -X POST https://peppol.verteco.digital/api/v1/companies/{id}/webhook/secret -H 'Authorization: Bearer vpt_8f2a…'
# → { "secret": "…" }
  • Token musí byť owner/admin danej firmy; pri firme, kde je len member/viewer, vráti 403 forbidden (žiadny cross-tenant zásah).
  • Každej firme môžete dať inú URL alebo všetkým rovnakú; v payloade ich rozlíšite podľa companyId (a receiverId).
  • Pri stovkách firiem rešpektujte rate-limit na token (aktuálnu hodnotu vracia hlavička RateLimit-Limit); dávkujte s backoffom na 429 (hlavička Retry-After).
  • Webhook reálne chodí, až keď je firma aktívna v Peppole (po výbere Verteco ako poskytovateľa u Finančnej správy) a teda skutočne prijíma doklady.

Dátové modely

Polia objektov vracaných API.

Company

PoleTypPovinnéPopis
idUUIDidentifikátor firmy
icostringIČO (8 číslic)
dicstring|nullIČ DPH
legalNamestringobchodné meno
registeredAddressstring|nullsídlo
peppolParticipantIdstring|nullúčastník v Peppol (po registrácii)
statusstringpending_verification | active
rolestringowner | admin | member | viewer (vaša rola)
createdAtInstantčas vytvorenia

Document

PoleTypPovinnéPopis
idUUIDidentifikátor dokladu
directionstringsent | received
peppolMessageIdstring|nullID Peppol správy
docTypeIdstring|nulltyp dokumentu (Peppol)
senderIdstring|nullodosielateľ (scheme:id)
receiverIdstring|nullpríjemca (scheme:id)
invoiceNumberstring|nullčíslo faktúry
issueDatedate|nulldátum vystavenia
currencystring|nullmena (napr. EUR)
totalAmountnumber|nullsuma
statusstringstav spracovania
createdAtInstantčas záznamu

User · Token · Webhook

PoleTypPovinnéPopis
Userobjekt{ id: UUID, email: string }
Tokenobjekt{ id, name, prefix, lastUsedAt|null, createdAt }
Webhookobjekt{ url: string|null, hasSecret: boolean }

Slovenské konvencie z praxe implementátorov

Nad rámec Peppol BIS Billing 3.0 sa slovenskí výrobcovia ERP a fakturačných systémov priebežne zhodujú na spoločnej interpretácii voliteľných polí (diskusia prebieha v Slack kanáli Finančnej správy). Nižšie sú konvencie, ktoré náš portál už dnes rešpektuje – všetko sú platné BIS konštrukcie, cez naše API prechádzajú bez zmeny a prijaté doklady ich zobrazujú aj v ľudsky čitateľnom náhľade a PDF.

  • Odpočet zdanenej zálohy na riadku: záporný riadok s cac:DocumentReference, kde cbc:ID nesie číslo daňového dokladu k prijatej platbe a cbc:DocumentTypeCode je 130 (BIS: invoice line object identifier, max. 1 na riadok). Prijatá faktúra s takýmto riadkom sa v našom náhľade zobrazí s poznámkou „odpočet zálohy – daňový doklad č. …".
  • Daňový doklad k prijatej platbe: podľa FAQ Finančnej správy sa používa InvoiceTypeCode 388 (Tax invoice). Naším API aj validáciou prechádza; odpočet neuhradenej (nezdanenej) zálohy sa vyjadruje cez cbc:PrepaidAmount.
  • Storno faktúry: dobropis 381 (CreditNote) s cac:BillingReference na pôvodnú faktúru – nie záporná faktúra 380. Pozor: kód 384 sieť pre slovenské strany odmieta (pravidlo PEPPOL-EN16931-P0112 ho povoľuje len medzi nemeckými subjektmi); na opravu nahor slúži ťarchopis 383.
  • BT-83 PaymentID: v SK praxi sa presadzuje tvar referencie platiteľa /VS…/SS…/KS…; samotný variabilný symbol je tiež bežný. Naše spracovanie hodnotu prenáša bez zmeny a zobrazuje ju pri platobných údajoch.
  • Doplnkové údaje položiek (šarže, sériové čísla, expirácie) cez cac:AdditionalItemProperty s ustálenými názvami ako BatchNumber, SerialNumber, ExpirationDate.
Ide o konvencie komunity, nie záväzné národné pravidlá – prijímajúci systém musí zvládnuť aj doklad, ktorý ich nepoužíva. Ako sa diskusia u Finančnej správy uzavrie, túto sekciu priebežne aktualizujeme (sledujte /changelog).

Prílohy dokladov (BT-125)

K e-faktúre je možné pripojiť prílohy (PDF, obrázky) ako base64 v elemente cac:AdditionalDocumentReference (BT-125). Náš limit je 25 MB na prílohu – Peppol jednotný celosieťový limit neurčuje, jednotliví poskytovatelia si ho stanovujú sami (FS FAQ 9/DPH/2025/IM, príklad č. 67), takže pri veľmi veľkých prílohách si overte aj limit poskytovateľa druhej strany.

Verejné nástroje (validácia, overenie príjemcu)

Dva pomocné endpointy bez autentifikácie – rovnaké validačné jadro a rovnaký SML/SMP lookup, aké používa náš Access Point. Hodia sa do CI aj do predodoslacích kontrol; platí na ne prísnejší verejný rate limit.

POST/public/peppol-validateverejné

Validácia e-faktúry proti EN 16931 + Peppol BIS Billing 3.0 (vrátane slovenských pravidiel) – to isté, čo UI validátor na /validator. Telo požiadavky = priamo UBL 2.1 XML (Invoice / CreditNote, prípadne celý Peppol SBD), Content-Type application/xml, limit 3 MB.

bash
curl -X POST https://peppol.verteco.digital/api/v1/public/peppol-validate \
-H "Content-Type: application/xml" \
--data-binary @faktura.xml
json
// 200 OK
{
"valid": false,
"errors": [
  "BR-CO-09: [BR-CO-09]-The Seller VAT identifier (BT-31) … shall have a prefix in accordance with ISO code…"
],
"warnings": []
}
// 400 = prázdne telo (empty_document) alebo dokument nad 3 MB (document_too_large)
GET/public/peppol-check?id=0245:2121358349verejné

Overenie príjemcu v produkčnej sieti Peppol (SML/SMP lookup): je registrovaný a aké typy dokladov vie prijať? Parameter id prijme Peppol ID (0245:…), IČ DPH (SK…) aj samotné DIČ. Autentifikovaná obdoba pre ERP pipeline: GET /sapi/discovery.

json
// 200 OK
{
"registered": true,
"participantId": "0245:2121358349",
"smp": "sml.peppol-smp.sk",
"capabilities": ["Faktúra (BIS Billing)", "Dobropis", "Self-billing", "MLS doručenky"],
"lastCheckedAt": "2026-08-31T…Z"
}

MCP server (AI asistenti)

Portál má vlastný server pre Model Context Protocol, otvorený štandard, cez ktorý sa AI asistenti (Claude Code, Claude Desktop, Cursor, VS Code Copilot a ďalší) pripájajú k externým systémom. Asistent sa prihlási bežným API kľúčom účtu a dostane šesť nástrojov; nikdy nevidí viac než ten účet a každé volanie je v API logu kľúča.

Adresa: https://peppol.verteco.digital/api/mcp. Transport: Streamable HTTP, JSON-RPC 2.0, bezstavovo (POST /api/mcp, žiadny SSE stream, GET vráti 405). Prihlásenie hlavičkou Authorization: Bearer <API kľúč>. Podporované metódy: initialize, ping, tools/list, tools/call, resources/list, prompts/list.

Nástroje

  • list_companies: firmy účtu s Peppol ID, stavom a rolou (začiatok každej konverzácie)
  • list_documents: odoslané/prijaté faktúry firmy s stavom doručenia a hlásenia FS, stránkované
  • get_document: detail faktúry vrátane doručenky MLS a hlásenia FS, voliteľne UBL XML (do 1 MB)
  • check_participant: živé overenie príjemcu v sieti Peppol (SML/SMP)
  • validate_document: validácia UBL proti EN 16931 + BIS 3.0 vrátane SK pravidiel
  • send_document: odoslanie faktúry za firmu, vyžaduje confirm = true a platí brána Verifikačného údaja

Pripojenie v Claude Code

bash
claude mcp add --transport http verteco-peppol https://peppol.verteco.digital/api/mcp \
  --header "Authorization: Bearer vpt_..."

Claude Desktop (cez most mcp-remote, potrebuje Node.js)

json
{
  "mcpServers": {
    "verteco-peppol": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://peppol.verteco.digital/api/mcp", "--header", "Authorization: Bearer vpt_..."]
    }
  }
}

Odoslanie faktúry je právne záväzné: nástroj bez confirm = true odmietne volanie a asistent má v inštrukciách servera pokyn vyžiadať si výslovný súhlas používateľa s konkrétnou faktúrou a príjemcom. Hotové konfigurácie pre Cursor a VS Code a tlačidlo na vytvorenie kľúča nájdete v portáli: API kľúče → záložka MCP server. API kľúče → MCP server

Stav (ping)

Verejný health-check endpoint, vhodný na monitoring.

GET/pingverejné

Stav backendu.

json
// 200 OK
{ "service": "peppol-portal-backend", "status": "ok", "timestamp": "2026-06-17T…Z" }

Živý prehľad všetkých komponentov nájdete na stránke stavu systémov.

Pripravujeme

Jadro odosielania/príjmu (AS4) je hotové a testované. Nasledujúce per-firma endpointy dopĺňame; ich tvar sa môže ešte zmeniť. Partneri môžu dostať skorý prístup.
  • POST/companies/{id}/peppol/register· Manuálna registrácia do Peppol SMP cez API (dnes prebieha automaticky pri výbere poskytovateľa na portáli FS).
POST /companies/{id}/documents/send je už dostupný (beta: tvar odpovede sa ešte môže meniť); pre stabilné programové odosielanie odporúčame SAPI-SK POST /sapi/document/send s Idempotency-Key.

Chcete skorý prístup k integrácii, sandbox alebo máte otázku? Ozvite sa priamo:

Miriama Mrkávková

Váš Peppol kontakt

Miriama Mrkávková

+421 944 488 269·peppol​@​verteco.digital