Guides & documentation

E-invoicing in Slovakia: simple and in plain language

From 1 January 2027, every VAT payer must issue and receive invoices electronically via the Peppol network. We are a certified provider (digital postman, digitálny poštár). Here you will find guides for businesses (what it is, how to register and how to invoice) and, further down, the technical documentation (API) for developers.

Peppol BIS 3.0EN 16931SAPI-SK 1.0Seat ID PSK001128Automatic SK TDD
webhook · invoice.received
POST https://vas-system.sk/peppol/webhook
X-Verteco-Signature: sha256=9f86d0…

{
  "event": "invoice.received",
  "companyId": "08dd…",
  "invoiceNumber": "2026001",
  "senderId": "0088:7300010000001",
  "currency": "EUR",
  "totalAmount": "120.00"
}
# → the received invoice goes straight into your system

What you will find here

The entire documentation on a single page. Pick what you are working on and jump straight to the section.

I use the portal (business owner, accountant)

I am connecting my own system (developer)

I offer services to clients (partner)

Getting started (for businesses)

You do not need to be a technician. If you are a sole trader, a limited company (s. r. o.) or an accountant, our portal in your browser is all you need: you receive and issue invoices by clicking, no programming required. This is how it works in three steps:

  1. 1

    Sign up (free of charge)

    Create an account with your e-mail on the registration page. Receiving invoices is free of charge (up to 1000 per month).

  2. 2

    Select us on the Financial Administration portal

    To be able to receive e-invoices, choose us as your certified provider (digital postman, digitálny poštár) on the FS portal (VPDS) of the Financial Administration of the Slovak Republic (Finančná správa, FS); the selection is confirmed via eID. We then register you in the Peppol network automatically and send you a login e-mail.

  3. 3

    Receive and issue invoices

    Received invoices arrive in the portal and by e-mail. You issue an invoice in the simple editor (like in Word), or duplicate an existing invoice in a few clicks. We send the tax report to the Financial Administration (TDD) on your behalf automatically.

Detailed guides (in Slovak, for beginners):

All guides in one place: E-invoicing Guide.

For developers

Technical documentation (API)

The following section is for developers who want to connect their own system (ERP, accounting software, an invoicing app) via the REST API. If you are a business owner and the portal is all you need, you can skip this section.

Introduction

The Verteco API is REST over HTTPS. Both request and response are JSON (UTF-8). Start by creating an account, then an API token, and make your first call within a minute. All paths are relative to the base URL below.

The complete test environment (sandbox) is available at test.peppol.verteco.digital. It behaves the same as production and additionally offers test tools (webhook of the Financial Administration of the Slovak Republic (Finančná správa, FS), verification token (Verifikačný údaj), company removal) and a simulated provider selection instead of the FS portal (VPDS).

Base URL
https://peppol.verteco.digital/api/v1
Version
v1 (in the path). Backward-incompatible changes will ship under a new version.
Protocol
HTTPS only · TLS 1.2+ · TLS A+
Format
application/json (UTF-8)
Auth
cookie session (portal) or Bearer token (server-to-server)
Timestamps
ISO-8601 (UTC), e.g. 2026-06-03T09:40:27Z

Certified AP

A real Peppol Access Point (Seat ID PSK001128), not a reseller. We passed OpenPeppol conformance (19/19) and are in production.

Valid documents

Server-side EN 16931 + Peppol BIS 3.0 Schematron validation of every received AND sent document. You can also validate a document in advance: the public validator runs at /validator (and as an API at POST /api/v1/public/peppol-validate); errors are returned with the specific rule (e.g. BR-CO-15).

Multi-tenant

One account and one token for N companies, ideal for SaaS, ERP and accountants.

SK TDD automatically

We generate and send the tax report (corner-5 / TDD) to the Financial Administration (FS) on your behalf.

Machine-readable interface (OpenAPI 3.1): /api/v1/openapi.json. Import it into Postman, open it in the Swagger Editor, or generate a typed client in any language (TS, Java, PHP, Python…) with openapi-generator. It covers both the portal API and SAPI-SK.

Quick start

You create both the account and the API token in the portal (via the browser). The integration then runs exclusively through the API token. Your app does not need to handle registration, login or passwords.

  1. 1

    Create an account in the portal

    Sign up with your e-mail and confirm it via the link in the e-mail.
  2. 2

    Generate an API token

    In the portal, go to API tokeny → Vytvoriť (API tokens → Create). The vpt_… token is shown only once. Store it securely.
  3. 3

    Make your first call

    Use the token in the Authorization header:
    javascript
    const res = await fetch('https://peppol.verteco.digital/api/v1/companies', {
      headers: { Authorization: 'Bearer vpt_8f2a…' },
    });
    const companies = await res.json();

Test environment (sandbox)

Test documents are deleted automatically after 60 days: the environment is for trying things out, not for archiving. This retention does not apply to the production portal.

In addition to the SAPI mock sandbox (below), we also operate a full-featured test environment, a complete copy of this portal with separate data, where you can try the entire flow (registration → company → sending → receiving → notifications) end-to-end without any impact on production.

Registration
no confirmation e-mail; the account is usable immediately
Company approval
automatic, directly in the UI or via the API; there is no provider selection on the portal of the Financial Administration of the Slovak Republic (Finančná správa, FS) and no eID; right after creating a company with a VAT ID (IČ DPH) you can both send and receive
Network registration
automatic, into the Peppol test network. Note the two layers of the identifier: the API and the portal use the same format as production (peppolParticipantId = 0245:<DIČ digits>, where DIČ is the Slovak tax identification number; your integration code does not change); in the test SMP/SML the company is technically registered as 9950:SK<DIČ>, because the 0245 scheme requires a Financial Administration verification code that does not exist in the test environment. In production, 0245:<DIČ digits> is registered in the live Peppol network only after provider selection via eID
Validation
real: EN 16931 + Peppol BIS 3.0 rules, the same as in production
Delivery
simulated: the document never leaves the test server; if the recipient (VAT ID) exists in the test environment, the invoice is delivered to it as a received invoice (including the e-mail, PDF and webhook)
Delivery receipt (MLS)
simulated, explicitly marked as SANDBOX
E-mails
are really sent (to the addresses you enter), with the [TEST] prefix
Price
free, with no limits for testing

Everything that works here works there: the portal, the REST API, SAPI-SK 1.0, e-shop plugins and webhooks. Just switch the domain in your integration to test.peppol.verteco.digital and use the tokens created in the test environment. Ideal for integration development, CI tests and training accountants before the production rollout.

Note: the edge protection of the test domain blocks the generic headers User-Agent: Python-urllib and User-Agent: Java/1.8.x (the default User-Agent of HttpsURLConnection in Java 8) with HTTP 403 "error code: 1010" before the request even reaches our API; the production domain peppol.verteco.digitallets them through. Set your own User-Agent on every request (Java: conn.setRequestProperty("User-Agent", "my-app/1.0"); -Dhttp.agent alone is not enough, Java appends Java/1.8 to it). Common clients (requests, httpx, Java 11+, okhttp, axios, Go, PHP, curl) work unchanged.

Why companies are approved automatically

The Financial Administration has no test environment for the VPDS portal: provider selection on vpds.financnasprava.sk runs only in production and is verified via slovensko.sk (eID), so in production you cannot “select” an arbitrary company that is not your own. So that you can still test your integration, we simulate this step in the test environment: every company you create is approved automatically (without selection at FS), so you can set up both a sender and a recipient and go through the entire flow.

For testing FS webhooks (provider selection) we have our own counterpart to the Financial Administration tool: test.peppol.verteco.digital/sandbox-nastroje. There you can generate a valid FS-style verification token (Verifikačný údaj) and send a complete webhook to your endpoint, exactly as the FS portal does during a real selection. Companies created for testing can in turn be deregistered (from the portal and from the test SMP), precisely because of the missing test mode on the Financial Administration side.

The test environment is not part of the live Peppol network: companies are registered in a separate test network (test SMP/SML), nothing is sent to real endpoints, and its data may be wiped at any time. Do not use it for real invoices; for those, production is at peppol.verteco.digital, where registration in the live network is unlocked by provider selection on the Financial Administration portal confirmed via eID.

Guide for SaaS / platforms

If you run an invoicing app, an ERP or a platform and want to connect several of your customers (tenants) to Peppol through us, you integrate once and serve N companies. The model is a proxy: your backend holds one API token (vpt_…) server-side only (never in the browser), and each of your tenants = one company with us (one token → N companies). The extended public guide with sample code, webhook signatures and a go-live checklist: peppol.verteco.digital/saas.

  1. 1

    One token, server-side

    Create an API token and keep it in a secured backend environment. All calls are made by your server (Bearer), not by the customer's browser.
  2. 2

    Tenant onboarding = creating a company

    For each customer, call POST /companies with their company registration number (IČO) / VAT ID (IČ DPH); it returns { id, status: "pending_verification" }; store the id with the tenant (for details see Companies).
    bash
    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":"Firma s.r.o.",
           "street":"Príkladná 12","postalCode":"010 01","city":"Žilina","iban":"SK…"}'
  3. 3

    Activation in Peppol (a step the customer takes with the state)

    pending_verification ≠ live in Peppol. For a company to receive, the customer must select Verteco as their provider on the portal of the Financial Administration of the Slovak Republic (Finančná správa, FS), using eID; we then register the company in the SMP and its status changes to active. For a company to send, submit its verification token (Verifikačný údaj) via Sending verification (POST /companies/{id}/verification).
  4. 4

    Receiving invoices: webhook per tenant

    Set up a webhook (and/or e-mail) for each company and fetch the signing secret:
    bash
    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://vasa-saas.sk/peppol/webhook","notificationEmail":"…"}'
    
    curl -X POST https://peppol.verteco.digital/api/v1/companies/{id}/webhook/secret -H 'Authorization: Bearer vpt_8f2a…'
    # → { "secret": "…" }   (store it to verify X-Verteco-Signature)
    When an invoice is received, you get a signed POST (event invoice.received), durable with retry/dead-letter. For signature verification, the payload and the „Otestovať webhook" (Test webhook) button, see Notifications & webhooks.
  5. 5

    Sending invoices

    Send the invoice (UBL Peppol BIS 3.0) through the national interface SAPI-SK 1.0: POST /sapi/document/send (OAuth2 client_credentials, client_secret = your vpt_ token). We add the Slovak tax report (TDD/C5) automatically.
  6. 6

    Usage data for re-invoicing

    GET /companies/usage?month=YYYY-MM returns the counts of sent and received documents for each of your companies separately as well as in total, in exactly the units the price list is built on, so you can re-invoice your clients directly from it. Without the parameter it returns the current month; the period is half-open and the response explicitly contains the from/to fields so you do not have to guess the month boundary. Companies with no traffic are listed with zeros.
  7. 7

    Scaling and robustness

    Paginate lists: GET /companies?page&limit as well as GET /companies/{id}/documents?page&limit (with headers such as X-Total-Count and others). Respect the per-token rate limit: during bulk onboarding, batch with backoff on 429 (Retry-After) and handle 409 ico_taken (idempotently).
Two independent “gates”: active = the company receives (set after selecting Verteco with the Financial Administration via eID, or after successful verification of the verification token via POST /companies/{id}/verification); sending-verified = the company sends (after the verification token has been submitted via the API). The webhook for a received invoice is only sent once the company is active.

FS webhook for intermediaries (integration manual)

If you are registered as an intermediary (sprostredkovateľ) (application via /sprostredkovatel), the Financial Administration of the Slovak Republic (Finančná správa, FS) sends a notification to your webhook URL every time a client selects you on the FS portal (VPDS). This manual describes the exact contractas FS actually calls it in production (verified on live selections). FS does not publish its own public manual for the webhooks; this is what you need for the implementation.

1 · What the notification looks like + 2 · authenticity verification

🔒 The exact contract (payload, signature header) is shown after signing in

We keep integration details out of public HTML. Sign in with a free account and this part loads right here.

3 · What to do with it: forward the raw body to us

The recommended (and simplest) implementation is a raw-byte proxy: accept the POST, respond quickly, and forward the raw body bytes to your registration endpoint with us. That endpoint is created automatically once you fill in the /sprostredkovatel form, it is active immediately, and you can see its exact URL (with your key) after logging in via GET /api/v1/resellers/me:

text
POST https://peppol.verteco.digital/peppol/webhook/reseller/{vas-kluc}
Content-Type: application/json
(body = the unchanged raw bytes from FS)

We cryptographically verify the verification_token, automatically create the company under your partner account (white-label), register it in the central SK SMP, and from that moment on we deliver e-invoices to it. You may store the contact details from the payload for your own onboarding; nothing more is needed.

4 · Operating rules (important)

FS does not retry the webhook. If delivery fails, FS does not send the message again; it only writes it to the taxpayer's electronic mailbox. Your endpoint must therefore be permanently available, respond quickly (within a few seconds, ideally with 200 before doing any processing of your own), and persist every received body first, and only then process it. On our side we store every call in a permanent audit log, so a missed selection can be reconstructed together.
  • Idempotency: the same entity may repeat the selection; processing the same DIČ (Slovak tax identification number) must be safe (it is on our side).
  • Source IP: calls come from FS infrastructure (observed from 194.1.2.13); we recommend an IP allowlist only as a supplement, not as the sole protection (FS does not guarantee the range).
  • Response: return 200 even on an internal processing error (log the error yourself); FS does not evaluate anything else.
  • Deployment order: the webhook must be live before the application is filed with FS; the first selection may arrive shortly after publication.

A reference proxy implementation is ~30 lines (accept POST → store → forward the raw bytes). If you want to verify the whole chain before FS publishes you, send a test POST to your registration endpoint; it responds safely to unknown/unsigned content and creates nothing. Questions: Support.

5 · Terminating the intermediary agreement

The intermediary agreement can also be terminated directly from within the application: the owner of the partner account, in Nastavenia poštára (Postman settings), fills in a termination request (control question + confirmation of the consequences) and confirms the notice via a link sent to them by e-mail. Upon confirmation the notice is deemed delivered; the notice period is one month and runs from the 1st day of the following month (Art. 7.1 of the Terms and Conditions of Intermediation). We file the request for removal from the list of intermediaries with the Financial Administration ourselves within 5 business days after the agreement ends (Art. 7.3); our team receives the supporting record, nothing is sent to the intermediary's clients. An unconfirmed request can be cancelled in the application. Programmatically: GET/POST/DELETE /api/v1/resellers/me/termination.

Authentication

Your integration authenticates with an API token in the header Authorization: Bearer vpt_…. You create the token in the portal (API tokens); it has the format vpt_ + 40 hex characters, we store only its SHA-256 hash, and it has the same access as your account. Test it via /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 works)

With a missing or invalid token the API returns:

json
// 401 Unauthorized
{ "error": "unauthorized", "message": "Authentication required" }
The portal (browser) uses an internal session cookie (portal_session, JWT, 7 days); for a server-to-server integration you do not need it. Public without auth are /ping, /openapi.json and the endpoints under /public/* (the peppol-check lookup, the peppol-validate validator, see the section Public tools for details, and the service status via status); everything else requires a session or a Bearer token.

Conventions & formats

TypeFormatExample
idUUID (string)08dd6c1e-…
timestampsISO-8601 Instant (UTC)2026-06-03T09:40:27Z
issueDatedate (YYYY-MM-DD)2026-06-03
totalAmountdecimal number120.00
missing valuesnull (not an omitted field)"dic": null

Pagination & idempotency

/companies and /companies/{id}/documents support optional ?page&limit (the response remains a JSON array; the total count is in the X-Total-Count / X-Total-Pages headers). Without parameters they return the whole array, documents sorted by createdAt descending; /tokens always returns the whole array. The Idempotency-Key header is supported by the national interface SAPI-SK on POST /sapi/document/send; for programmatic sending, use exactly that.

Errors

Errors have a uniform shape with a machine-readable error code. Validation errors add a fields map (first error per field).

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

// validation error (400); field messages are returned in Slovak ("IČO musí byť 8 číslic" = "IČO must be 8 digits")
{ "error": "validation_failed", "message": "Some fields are invalid",
  "fields": { "ico": "IČO musí byť 8 číslic" } }

HTTP statuses

200 / 201 / 204
success (OK / Created / No Content)
400
invalid input (see error / fields)
401
missing or invalid authentication
403
insufficient permission (role)
404
the resource does not exist or you have no access to it
409
conflict (IČO / e-mail already exists)
429
rate limit exceeded

Complete error catalog

CodeHTTPWhen
validation_failed400the body failed validation (see fields)
unauthorized401missing or invalid API token
forbidden403the action requires the owner/admin role
company_not_found404the company does not exist or you are not a member of it
ico_taken409a company with this IČO (company registration number) already exists
ico_immutable400the IČO cannot be changed
company_dic_missing400sending verification without the company DIČ (Slovak tax identification number)
token_invalid400the verification token (Verifikačný údaj, signature) does not match
document_not_found404the document does not exist
token_not_found404the API token does not exist / is not yours
rate_limited429too many requests

Rate limits

The API is protected by rate limiting in a 60-second window (per instance). The limit and the remaining quota are returned in every response via headers; when exceeded, the API returns 429 Too Many Requests with Retry-After.

Regular calls
dynamic limit with a large headroom, per API token (or session, otherwise IP); the current value is returned in the RateLimit-Limit header
Auth (/auth/*)
stricter limit per IP (anti brute-force; except /auth/me and /auth/logout)
RateLimit-Limit
limit in the window
RateLimit-Remaining
how many requests remain
RateLimit-Reset
seconds until the window resets
Retry-After
seconds until the next attempt (on 429)
http
HTTP/2 429 Too Many Requests
RateLimit-Limit: <limit in the window>
RateLimit-Remaining: 0
RateLimit-Reset: 37
Retry-After: 37

{ "error": "rate_limited", "message": "Too many requests. Slow down." }

API tokens

Opaque vpt_… tokens for server-to-server access. The plaintext is shown only once at creation. Save it. We store only the SHA-256 hash and a 12-character prefix for display.

GET/tokenssession / token

List of your active tokens (without the secret), createdAt descending.

POST/tokenssession / token

Creates a token; returns the plaintext (once only).

FieldTypeRequiredDescription
namestringyestoken name, 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

Revokes the token. Returns 204.

Errors: token_not_found (404)

Companies

Companies, identified by company registration number (IČO) / VAT ID (IČ DPH), that you manage. Access is tied to membership: you only see companies you are a member of. The creator of a company becomes its owner.

GET/companiessession / token

List of companies you are a member of (with your role).

POST/companiessession / token

Adds a company; you become its owner, status = pending_verification.

FieldTypeRequiredDescription
icostringyesexactly 8 digits
dicstringyesformat SK + 10 digits (e.g. SK2121358349)
legalNamestringyeslegal (business) name, max 500
registeredAddressstringnoregistered office address, 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" }

Errors: ico_taken (409) · validation_failed (400)

GET/companies/{id}session / token

Company detail (you must be a member).

PUT/companies/{id}owner / admin

Updates a company. The IČO is immutable (it must equal the existing value).

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

The status field

pending_verification
after creation; sending is not yet unlocked
active
verified, sending unlocked

Member role

owner
company creator (full access)
admin
administrator (edits, webhooks, verification)
member
member (read)
viewer
read-only
Actions marked „owner / admin" are available to both the owner and admin roles (company manager).

Sending verification (verification token, Verifikačný údaj)

Before sending, the company must be verified using the verification token (Verifikačný údaj, VÚ), a signed token issued by the Financial Administration of the Slovak Republic (Finančná správa, FS). After successful verification, the status of the company changes to active and sending is unlocked.

POST/companies/{id}/verificationowner / admin

Self-verification of the verification token (Verifikačný údaj). On success, sets status to active.

FieldTypeRequiredDescription
tokenstringyesVÚ = hex signature (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" }

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

Documents

Log of Peppol documents (received and sent) for a company. It fills up as invoices flow through the Access Point. Tied to company membership, sorted by createdAt descending.

GET/companies/{id}/documentssession / token

List of the company's documents. Optional 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 of a single document.

Errors: document_not_found (404)

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

Standalone printable HTML of the invoice. ?inline=1 → displays in the browser, otherwise downloads.

Returns text/html, with Content-Disposition naming the file faktura-<číslo>.html (číslo = the invoice number).

SAPI-SK 1.0 (national interface)

SAPI-SK is the standardized national REST interface between a client/ERP system and an Access Point (sapi-sk.sk). We implement it in full. This means you are not tied to our proprietary API shape, and you write the integration once for any SAPI-SK Access Point.

Base URL
https://peppol.verteco.digital/sapi
Authentication
OAuth2 client_credentials → short-lived access token (JWT)
client_id
UUID of your API token (listed in the API tokens section / dashboard)
client_secret
the vpt_… token itself from the portal
Version
1.3 (10 operations: 4× auth, 6× documents)
The SAPI access token is signed with a separate key (it is neither the portal vpt_ token nor a session). Revoking the API token in the portal immediately invalidates both /auth/token and /auth/renew.

Sandbox (trial environment)

Want to try SAPI-SK without registering and without any risk? Use the public sandbox credentials. The sandbox validates requests exactly like production, but never sends anything to the Peppol network and does not work with real data; it returns realistic mock responses. Ideal for development, CI and integration onboarding.

client_id
sandbox
client_secret
sandbox
send
full contract validation + mock 202 (nothing is delivered)
receive
1 sample document sandbox-doc-0001 for testing parsing and acknowledge
curl
# 1) sandbox token (no registration required)
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 send: it is validated, but NOTHING is actually delivered
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) sample inbox + detail of the sample document
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 tokens are isolated: they never deliver to Peppol and never see real documents. For live sending, use the client_id/client_secret from the portal (below).

Authentication

POST/sapi/auth/tokenclient_credentials

Exchanges client_id + client_secret for an access token (15 min) and a refresh token (30 days). Store the token and use it for the full 15 minutes: requesting a new token on every call is unnecessary overhead (the request limit also counts calls to /auth/token).

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

Errors: SAPI-AUTH-001 (401) · SAPI-AUTH-003 (401: IP outside the key allowlist) · SAPI-VAL-001 (400)

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

Validity and expiry of the access token; should_refresh = true when less than 3 min remain.

POST/sapi/auth/renewrefresh token

Issues a new access + refresh token. Fails if the underlying API token has been revoked.

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

Always returns success (RFC 7009). The permanent kill switch is revoking the API token in the portal.

Sending a document

POST/sapi/document/sendBearer (access)

Sends a Peppol business document (UBL / BIS 3.0) to the recipient through our Access Point. Sending is fail-closed: the company must have a verified verification token (Verifikačný údaj).

Required headers:

HeaderDescription
AuthorizationBearer <access_token>
X-Peppol-Participant-Idthe participant you are sending on behalf of (e.g. 0245:2121358349, the digits of the DIČ (Slovak tax identification number) without the "SK" prefix)
Idempotency-Keyunique key; a repeated call returns the original result
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": "…" }
# when status is "REJECTED", the response also carries a "detail" field
# with the rejection reason (validation rules, e.g. BR-CO-15)
metadata vs. UBL: the fields in metadata are routing and technical fields: documentId is your internal identifier, not the invoice number. Business data (invoice number cbc:ID, issue date, due date, delivery date, currency, amount) is taken directly from the UBL payload; you do not send any of it in metadata, and UBL is always the source of truth for display in the portal and for webhooks.

Errors: SAPI-AUTH-002 (401) · SAPI-AUTH-003 (403) · SAPI-VAL-001 (400) · SAPI-PROC-001 (502) · SAPI-PROC-002 (503) · SAPI-PROC-500 (500: do not retry, report the correlation_id)

Receiving documents

GET/sapi/document/receiveBearer (access)

List of received documents (oldest first); the metadata also carries invoiceNumber, so you can identify a document without downloading the payload. Query: ?pageToken, ?limit (max 200), ?status (received / acknowledged; case-insensitive, any other value returns error SAPI-VAL-001), ?invoiceNumber (exact match on cbc:ID), ?since and ?until (ISO-8601 instant; window by time of receipt, e.g. documents from the last 5 days, bulk download for external archiving or reconstruction of accounting records), ?deliveryDateFrom and ?deliveryDateTo (ISO-8601 date; filter by the delivery date stated in the document). The X-Peppol-Participant-Id header is required.

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 including the payload (raw XML, exactly as it arrived via Peppol).

Errors: SAPI-RES-001 (404) · SAPI-RES-002 (404: payload not archived)

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

Confirms that your system has taken over the document. Idempotent.

Status of sent documents

GET/sapi/discovery?receiverId=0245:2121358349

Preflight before sending: is the recipient registered in the Peppol network, and which document types can they receive? The same SML/SMP lookup the Access Point performs; receiverId accepts a Peppol ID, a VAT ID (IČ DPH) or the bare DIČ. Response: {registered, participantId, smp, documentTypes, checkedAt}. The X-Peppol-Participant-Id header is not needed here.

GET/sapi/document/sentBearer (access)

Delivery status of sent documents: pending (being handed over to the network) → submitted → delivered / rejected (confirmed by the delivery receipt (MLS) from the recipient's AP); failed = transport error (a retry with the same Idempotency-Key sends again). Query: ?pageToken, ?limit, ?status (pending / submitted / sent / delivered / rejected / failed; case-insensitive, any other value returns error SAPI-VAL-001), ?invoiceNumber (exact match on cbc:ID: the status of a specific invoice in a single call), ?since and ?until (ISO-8601 instant; time window), ?deliveryDateFrom and ?deliveryDateTo (ISO-8601 date; filter by delivery date).

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 }

Errors: SAPI-AUTH-002 (401) · SAPI-AUTH-003 (403) · SAPI-VAL-001 (400: invalid since)

Batch sending

POST/sapi/document/batchBearer (access)

Up to 100 documents in a single call. Each item goes through the full single-send logic (idempotency via itemId + idempotencyKey, reservation, submit, verdict) and returns its own result; a failure of one item does not stop the others. Items are processed sequentially; retry failed items with the same 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": "…" } ] }

Errors: SAPI-AUTH-002 (401) · SAPI-AUTH-003 (403) · SAPI-VAL-001 (400: empty or oversized list)

Error model

All SAPI errors share a uniform envelope with a category, a stable code, a retryable flag and a correlation_id for support.

json
{ "error": {
    "category": "AUTH",
    "code": "SAPI-AUTH-001",
    "message": "Invalid client credentials.",
    "retryable": false,
    "correlation_id": "b4191dfc-…" } }
Note: when sending, we deliver the business document; the C2 side of the tax reporting (TDD) for sent documents is in preparation. Tax reporting on receipt (C3) is generated and submitted to the Financial Administration of the Slovak Republic (Finančná správa, FS) automatically.

Notifications & webhooks

For a received invoice we can notify the company by e-mail or by webhook (POST to your URL). Delivery is durable: it is stored in an outbound queue and delivered asynchronously (15 s timeout); on failure we retry up to 8× with exponential backoff (30 s → max 1 h), then dead-letter. An outage of your server therefore does not lose the notification; we deliver it on the next attempt. SSRF protection blocks loopback/local addresses; the webhook URL must be public.

GET/companies/{id}/notificationssession / token

Notification settings: { webhookUrl, notificationEmail, hasSecret }.

PUT/companies/{id}/notificationsowner / admin

Sets both channels (an empty string disables the given channel).

FieldTypeRequiredDescription
webhookUrlstringnoempty or http(s) URL, max 512
notificationEmailstringnovalid e-mail, max 256
GET/companies/{id}/webhooksession / token

Webhook configuration: { url, hasSecret } (without the secret).

PUT/companies/{id}/webhookowner / admin

Sets the webhook URL (auto-generates a signing secret if none exists yet).

FieldTypeRequiredDescription
urlstringyeshttp(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

Removes both the webhook URL and the secret. Returns 204.

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

Generates a new signing secret and returns it ONCE; store it for verifying X-Verteco-Signature.

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

Synchronously sends a test notification (event webhook.test, signed, SSRF-protected) to the stored URL and returns WHAT it sent and WHAT came back. The same is triggered by the „Otestovať webhook“ (Test webhook) button in the company detail.

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 if no webhook URL is stored

Webhook payload

For both a received (invoice.received) and a sent (invoice.sent) invoice we send a POST with this body; the event field distinguishes the type.

Two further events announce the network's verdict on an invoice you have sent: invoice.delivered (the recipient's Access Point confirmed delivery with a delivery receipt (MLS)) and invoice.rejected (rejected, either by the network or during validation before sending). They carry the identification of the document and the company (documentId, invoiceNumber, receiverId, peppolMessageId, companyDic, peppolParticipantId) plus status, statusDetail with the rejection reason, and statusDateTime. Thanks to them you do not need to poll for the status of sent invoices.

The company.activated event arrives when a customer completes provider selection on the portal (VPDS) of the Financial Administration of the Slovak Republic (Finančná správa, FS); body: event, companyId, companyDic, peppolParticipantId, status, verifiedAt. company.deactivated in turn arrives when a company is deregistered from the network (same body without verifiedAt); details in the guide /saas:

json
{
  "event": "invoice.received",
  "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"
}

The companyDic and peppolParticipantId fields identify the company the event relates to (important for partners that use a single webhook URL for all of their clients).

Network verdict on a sent invoice:

json
{
  "event": "invoice.delivered",          // or "invoice.rejected"
  "companyId": "08dd…",
  "companyDic": "SK2121358349",
  "peppolParticipantId": "0245:2121358349",
  "documentId": "…",
  "invoiceNumber": "2026001",
  "receiverId": "0245:2120049096",
  "peppolMessageId": "…",
  "status": "delivered",                 // or "rejected"
  "statusDetail": null,                  // for rejected: the rejection reason
  "statusDateTime": "2026-06-03T10:15:42Z"
}

Company activation after provider selection on the FS portal (VPDS):

json
{
  "event": "company.activated",          // company.deactivated has the same body without verifiedAt
  "companyId": "08dd…",
  "companyDic": "SK2121358349",
  "peppolParticipantId": "0245:2121358349",
  "status": "active",
  "verifiedAt": "2026-06-03T10:02:11Z"
}

The event name is also carried in the X-Verteco-Event header. Full list of events: invoice.received, invoice.sent, invoice.delivered, invoice.rejected, company.activated, company.deactivated and the test event webhook.test. We recommend setting an unknown event type aside and logging it; we always announce a new type in advance.

Partner notification webhook (intermediaries)

If you are a registered intermediary (sprostredkovateľ), you do not need to configure a webhook for each company separately: a single partner notification webhook receives all events of the companies under your partner account and takes precedence over the webhooks of individual companies. Your clients therefore configure nothing; you distinguish the company by companyDic / peppolParticipantId.

GET/resellers/me/notification-webhookintermediary account

Current configuration: { url, hasSecret, events, lastRevealedAt, lastRevealedIp } (the secret is not returned).

PUT/resellers/me/notification-webhookintermediary account

Sets an https URL (max 512). On the FIRST setup a signing secret is generated and returned ONCE in the response; subsequent URL changes keep the secret and do not return it. An empty URL removes both the webhook and the secret.

FieldTypeRequiredDescription
urlstringyeshttps URL, max 512; empty string = remove
json
// 200 OK (first setup)
{ "url": "https://vasa-appka.sk/peppol/events", "secret": "vpt_…", "hasSecret": true,
  "events": ["company.activated","company.deactivated","invoice.received","invoice.sent","invoice.delivered","invoice.rejected"] }
POST/resellers/me/notification-webhook/revealintermediary account + password

Re-displays the stored secret after confirmation with the account password ({ password }). Every reveal is audited and the last one is visible in GET.

The X-Verteco-Signature signature is computed the same way as for the company webhook (below), only with the partner secret.

Managing clients via the API (unilateral release and sending brake)

A client who leaves a partner usually does nothing, which is why these operations are unilateral and require no cooperation from the client. Invoice reception is not affected by them: it is tied to the company's registration in the central SMP, not to the managing account.

POST/resellers/me/clients/{companyId}/releaseintermediary account

Detaches the company from the partner account with immediate effect. The company passes under direct management by the platform; its registration, verification and invoice reception continue without interruption; from this moment on the partner is no longer billed for it. Irreversible from the partner's side.

POST/resellers/me/clients/{companyId}/pause-sendingintermediary account

Safeguard when ending a cooperation: blocks sending of the company's documents (SAPI returns 403 SAPI-AUTH-003 with the pause reason, the portal API 403 sending_paused); reception continues. Immediate effect.

POST/resellers/me/clients/{companyId}/resume-sendingintermediary account

Lifts the sending pause.

GET/resellers/me/terminationintermediary account

Status of a termination notice of the intermediary agreement filed from the application (204 = none; otherwise status awaiting_email / confirmed, contract end date contractEndsOn).

POST/resellers/me/terminationintermediary account (owner of the registration)

Files a request to terminate the agreement: body { confirmName: the exact name of the registered intermediary, reason?: string, acknowledged: true }. A confirmation link (48 h) is sent to the account owner's e-mail; the termination notice is served only once it is confirmed (Art. 7.1 of the Intermediary Terms, OP). 202 + status; 400 confirm_name_mismatch / acknowledgement_required; 409 termination_pending / termination_confirmed.

DELETE/resellers/me/terminationintermediary account

Cancels a request that has not yet been confirmed. A confirmed termination notice cannot be cancelled from the application (409); write to [email protected].

Partner billing model

In the partner console (and via GET/PUT /api/v1/resellers/me/billing) you choose the billing model (the choice is available only to registered intermediaries): per_company = €2 per month per actively sending company registration number (IČO), or per_document = €0.01 for every invoice sent by your companies (received documents are free) with a minimum monthly billing of €300 + VAT. A model change always takes effect from the 1st day of the following month (in the response pendingModel and pendingFrom); the response of both calls also returns a recalculation of the current month under both models, so you switch informed.

Recommended procedure for a terminated client (a cap on costs on your side): you can see current usage in GET /api/v1/companies/usage?month=YYYY-MM (sent/received breakdown per company, exactly for re-billing) and in GET /api/v1/resellers/me/clients (counts for the current month); in addition, an event is sent to the partner webhook for every document your companies send or receive, so you catch a "terminated" company at its very first document. Then simply call pause-sending or release.

Signature verification

If the company has a secret, we send the X-Verteco-Signature header in the form sha256=HMAC-SHA256(secret, raw body) (lowercase hex). Always compute the HMAC over the exact bytes of the body:

javascript
import crypto from 'node:crypto';

// rawBody = the exact bytes of the request body (not re-serialized 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));
}
You obtain the secret via POST /companies/{id}/webhook/secret; it returns it once (rotation generates a new one). Without a secret we do not send the X-Verteco-Signature header.

Bulk setup: one token, multiple companies

A single API token (bound to your account/e-mail) manages all companies it owns: whoever creates a company via POST /companies becomes its owner and can configure its webhook. The webhook is per company (its own URL and secret), so with the same token you can connect any number of companies:

bash
# 1) list of your companies (paginated, see Companies)
curl 'https://peppol.verteco.digital/api/v1/companies?page=0&limit=100' -H 'Authorization: Bearer vpt_8f2a…'

# 2) for EACH company {id}: set the webhook (and/or 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) fetch the signing secret (returned ONLY ONCE) and store it for signature verification
curl -X POST https://peppol.verteco.digital/api/v1/companies/{id}/webhook/secret -H 'Authorization: Bearer vpt_8f2a…'
# → { "secret": "…" }
  • The token must be owner/admin of the given company; for a company where it is only member/viewer, it returns 403 forbidden (no cross-tenant access).
  • You can give each company a different URL or the same one for all; in the payload you distinguish them by companyId (and receiverId).
  • With hundreds of companies, respect the per-token rate limit (the current value is returned in the RateLimit-Limit header); batch with backoff on 429 (Retry-After header).
  • The webhook is actually fired only once the company is active in Peppol (after selecting Verteco as provider with the Financial Administration) and therefore actually receives documents.

Data models

Fields of the objects returned by the API.

Company

FieldTypeRequiredDescription
idUUIDcompany identifier
icostringcompany registration number (IČO, 8 digits)
dicstring|nullVAT ID (IČ DPH)
legalNamestringlegal name
registeredAddressstring|nullregistered office address
peppolParticipantIdstring|nullPeppol participant (after registration)
statusstringpending_verification | active
rolestringowner | admin | member | viewer (your role)
createdAtInstantcreation time

Document

FieldTypeRequiredDescription
idUUIDdocument identifier
directionstringsent | received
peppolMessageIdstring|nullPeppol message ID
docTypeIdstring|nulldocument type (Peppol)
senderIdstring|nullsender (scheme:id)
receiverIdstring|nullreceiver (scheme:id)
invoiceNumberstring|nullinvoice number
issueDatedate|nullissue date
currencystring|nullcurrency (e.g. EUR)
totalAmountnumber|nulltotal amount
statusstringprocessing status
createdAtInstantrecord time

User · Token · Webhook

FieldTypeRequiredDescription
Userobject{ id: UUID, email: string }
Tokenobject{ id, name, prefix, lastUsedAt|null, createdAt }
Webhookobject{ url: string|null, hasSecret: boolean }

Slovak conventions from implementer practice

Beyond Peppol BIS Billing 3.0, Slovak ERP and invoicing software vendors are gradually converging on a shared interpretation of optional fields (the discussion takes place in a Slack channel run by the Financial Administration of the Slovak Republic, Finančná správa, FS). Below are the conventions our portal already respects today: all of them are valid BIS constructs, they pass through our API unchanged, and received documents display them in the human-readable preview and PDF as well.

  • Deduction of a taxed advance payment on a line: a negative line with cac:DocumentReference, where cbc:ID carries the number of the tax document for the received payment and cbc:DocumentTypeCode is 130 (BIS: invoice line object identifier, max. 1 per line). A received invoice with such a line is shown in our preview with the note „odpočet zálohy – daňový doklad č. …" (advance deduction, tax document no. …).
  • Tax document for a received payment: according to the Financial Administration FAQ, the code InvoiceTypeCode 388 (Tax invoice) is used. It passes both our API and validation; the deduction of an unpaid (untaxed) advance is expressed via cbc:PrepaidAmount.
  • Invoice cancellation: a credit note 381 (CreditNote) with cac:BillingReference to the original invoice, not a negative 380 invoice. Note: the network rejects code 384 for Slovak parties (rule PEPPOL-EN16931-P0112 allows it only between German entities); for an upward correction use debit note 383.
  • BT-83 PaymentID: Slovak practice is converging on the payer reference format /VS…/SS…/KS…; a bare variable symbol (variabilný symbol) is also common. Our processing passes the value through unchanged and displays it with the payment details.
  • Additional item data (batches, serial numbers, expiration dates) via cac:AdditionalItemProperty with established names such as BatchNumber, SerialNumber, ExpirationDate.
These are community conventions, not binding national rules: a receiving system must also handle a document that does not use them. As the discussion at the Financial Administration concludes, we will keep this section updated (watch /changelog).

Document attachments (BT-125)

Attachments (PDF, images) can be attached to an e-invoice as base64 in the cac:AdditionalDocumentReference element (BT-125). Our limit is 25 MB per attachment. Peppol does not define a single network-wide limit; individual providers set their own (FS FAQ 9/DPH/2025/IM, example no. 67), so for very large attachments also check the limit of the other party's provider.

Public tools (validation, recipient check)

Two helper endpoints without authentication: the same validation core and the same SML/SMP lookup our Access Point uses. They are suitable for CI and for pre-send checks; a stricter public rate limit applies to them.

POST/public/peppol-validatepublic

Validation of an e-invoice against EN 16931 + Peppol BIS Billing 3.0 (including Slovak rules), the same as the UI validator at /validator. Request body = the UBL 2.1 XML directly (Invoice / CreditNote, or the whole 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 = empty body (empty_document) or document over 3 MB (document_too_large)
GET/public/peppol-check?id=0245:2121358349public

Recipient check in the live Peppol network (SML/SMP lookup): is it registered and which document types can it receive? The id parameter accepts a Peppol ID (0245:…), a VAT ID (IČ DPH, SK…) or the bare DIČ (Slovak tax identification number). Authenticated equivalent for ERP pipelines: 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"], // Slovak labels: Invoice (BIS Billing), Credit note, Self-billing, MLS delivery receipts
  "lastCheckedAt": "2026-08-31T…Z"
}

Status (ping)

Public health-check endpoint, suitable for monitoring.

GET/pingpublic

Backend status.

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

A live overview of all components is available on the system status page.

Coming soon

The sending/receiving core (AS4) is complete and tested. The following per-company endpoints are being added; their shape may still change. Partners can get early access.
  • POST/companies/{id}/peppol/register· Manual registration in the Peppol SMP via the API. Today this happens automatically upon provider selection on the FS portal (VPDS) of the Financial Administration of the Slovak Republic (Finančná správa, FS).
POST /companies/{id}/documents/send is already available (beta: the response shape may still change); for stable programmatic sending we recommend SAPI-SK POST /sapi/document/send with Idempotency-Key.

Want early access to the integration, a sandbox, or have a question? Get in touch directly:

Miriama Mrkávková

Your Peppol contact

Miriama Mrkávková

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