Вступ
API Verteco це REST поверх HTTPS. Запит і відповідь мають формат JSON (UTF-8). Почніть зі створення облікового запису, потім API-токена, і зробіть перший виклик протягом хвилини. Усі шляхи вказано відносно базової URL-адреси нижче.
Повне тестове середовище (sandbox) доступне на test.peppol.verteco.digital. Воно поводиться так само, як продуктивне середовище, і додатково пропонує тестові інструменти (вебхук Фінансової адміністрації Словаччини (Finančná správa, FS), верифікаційний токен (Verifikačný údaj), видалення компанії) та симульований вибір постачальника замість порталу FS (VPDS).
- Base URL
https://peppol.verteco.digital/api/v1- Версія
- v1 (у шляху). Зворотно несумісні зміни виходитимуть під новою версією.
- Протокол
- HTTPS only · TLS 1.2+ · TLS A+
- Формат
- application/json (UTF-8)
- Автентифікація
- cookie-сесія (портал) або Bearer-токен (server-to-server)
- Часові мітки
- ISO-8601 (UTC), напр. 2026-06-03T09:40:27Z
Сертифікований AP
Справжній Peppol Access Point (Seat ID PSK001128), а не реселер. Ми пройшли тести відповідності OpenPeppol (19/19) і працюємо в продуктивному режимі.
Валідні документи
Серверна валідація EN 16931 + Peppol BIS 3.0 Schematron кожного отриманого ТА відправленого документа. Документ можна перевірити й заздалегідь: публічний валідатор працює на /validator (і як API на POST /api/v1/public/peppol-validate); помилки повертаються з конкретним правилом (напр. BR-CO-15).
Multi-tenant
Один обліковий запис і один токен для N компаній, ідеально для SaaS, ERP і бухгалтерів.
SK TDD автоматично
Податковий звіт (corner-5 / TDD) до Фінансової адміністрації (FS) ми генеруємо та надсилаємо за Вас.
openapi-generator. Він охоплює як API порталу, так і SAPI-SK.Швидкий старт
Обліковий запис і API-токен Ви створюєте в порталі (через браузер). Далі інтеграція працює виключно через API-токен. Вашому застосунку не потрібно обробляти реєстрацію, вхід чи паролі.
- 1
Створіть обліковий запис у порталі
Зареєструйтеся за допомогою електронної пошти і підтвердьте її за посиланням з електронного листа. - 2
Згенеруйте API-токен
У порталі перейдіть до API tokeny → Vytvoriť (API-токени → Створити). Токенvpt_…показується лише один раз. Зберігайте його надійно. - 3
Зробіть перший виклик
Використайте токен у заголовкуAuthorization:javascriptconst res = await fetch('https://peppol.verteco.digital/api/v1/companies', { headers: { Authorization: 'Bearer vpt_8f2a…' }, }); const companies = await res.json();
Тестове середовище (sandbox)
Окрім SAPI mock sandbox (нижче), ми також підтримуємо повнофункціональне тестове середовище, повну копію цього порталу з окремими даними, де можна випробувати весь процес (реєстрація → компанія → відправлення → отримання → сповіщення) від початку до кінця без жодного впливу на продуктивне середовище.
- Реєстрація
- без листа з підтвердженням; обліковий запис можна використовувати одразу
- Схвалення компанії
- автоматичне, безпосередньо в інтерфейсі або через API; немає вибору постачальника на порталі Фінансової адміністрації Словаччини (Finančná správa, FS) і немає eID; одразу після створення компанії з номером платника ПДВ (IČ DPH) Ви можете як відправляти, так і отримувати
- Реєстрація в мережі
- автоматична, до тестової мережі Peppol. Зверніть увагу на два рівні ідентифікатора: API і портал використовують той самий формат, що й продуктивне середовище (
peppolParticipantId = 0245:<цифри DIČ>, де DIČ це словацький податковий ідентифікаційний номер; Ваш інтеграційний код не змінюється); у тестових SMP/SML компанія технічно реєструється як9950:SK<DIČ>, оскільки схема 0245 вимагає верифікаційного коду Фінансової адміністрації, якого в тестовому середовищі не існує. У продуктивному середовищі0245:<цифри DIČ>реєструється в робочій мережі Peppol лише після вибору постачальника через eID - Валідація
- реальна: правила EN 16931 + Peppol BIS 3.0, ті самі, що й у продуктивному середовищі
- Доставка
- симульована: документ ніколи не залишає тестовий сервер; якщо отримувач (номер платника ПДВ) існує в тестовому середовищі, рахунок доставляється йому як отриманий (включно з електронним листом, PDF і вебхуком)
- Підтвердження доставки (MLS)
- симульоване, явно позначене як SANDBOX
- Електронні листи
- справді надсилаються (на адреси, які Ви вводите), з префіксом
[TEST] - Ціна
- безкоштовно, без обмежень для тестування
Усе, що працює тут, працює і там: портал, REST API, SAPI-SK 1.0, плагіни для інтернет-магазинів і вебхуки. Достатньо змінити домен у Вашій інтеграції на test.peppol.verteco.digital і використовувати токени, створені в тестовому середовищі. Ідеально для розробки інтеграції, CI-тестів і навчання бухгалтерів перед продуктивним запуском.
Примітка: захист периметра (edge) тестового домену блокує загальні заголовки User-Agent: Python-urllib і User-Agent: Java/1.8.x (стандартний User-Agent HttpsURLConnection у Java 8) відповіддю HTTP 403 "error code: 1010" ще до того, як запит дійде до нашого API; продуктивний домен peppol.verteco.digitalїх пропускає. Встановіть власний User-Agent: у Java або прапорцем JVM -Dhttp.agent=my-app/1.0 (без зміни коду; Java додає "Java/1.8", і результат "my-app/1.0 Java/1.8.0_xxx" проходить, блокується лише заголовок, що починається з "Java/1.8"), або на з'єднанні через conn.setRequestProperty("User-Agent", "my-app/1.0"). Поширені клієнти (requests, httpx, Java 11+, Apache HttpClient, okhttp, axios, Go, PHP, curl) працюють без змін.
Чому компанії схвалюються автоматично
Фінансова адміністрація не має тестового середовища для порталу VPDS: вибір постачальника на vpds.financnasprava.sk працює лише в продуктивному середовищі та перевіряється через slovensko.sk (eID), тому в продуктивному середовищі Ви не можете «обрати» довільну компанію, яка не є Вашою. Щоб Ви все ж могли протестувати свою інтеграцію, у тестовому середовищі ми симулюємо цей крок: кожна створена Вами компанія схвалюється автоматично (без вибору у FS), тож Ви можете налаштувати як відправника, так і отримувача та пройти весь процес.
Для тестування вебхуків FS (вибір постачальника) ми маємо власний аналог інструменту Фінансової адміністрації: test.peppol.verteco.digital/sandbox-nastroje. Там можна згенерувати валідний верифікаційний токен (Verifikačný údaj) у стилі FS і надіслати повний вебхук на Ваш endpoint, точно так, як це робить портал FS під час реального вибору. Компанії, створені для тестування, натомість можна зняти з реєстрації (з порталу та з тестового SMP), саме через відсутність тестового режиму на боці Фінансової адміністрації.
Автентифікація
Ваша інтеграція автентифікується за допомогою API-токена в заголовку Authorization: Bearer vpt_…. Токен Ви створюєте в порталі (API-токени); він має формат vpt_ + 40 hex-символів, ми зберігаємо лише його SHA-256 хеш, і він має той самий доступ, що і Ваш обліковий запис. Перевірте його через /auth/me:
curl https://peppol.verteco.digital/api/v1/auth/me -H 'Authorization: Bearer vpt_8f2a…'
# 200 → { "id": "…", "email": "vy(at)firma.sk" } (token works)Якщо токен відсутній або недійсний, API повертає:
// 401 Unauthorized
{ "error": "unauthorized", "message": "Authentication required" }portal_session, JWT, 7 днів); для інтеграції server-to-server вона Вам не потрібна. Публічними без автентифікації є /ping, /openapi.json та endpoint-и під /public/* (перевірка peppol-check, валідатор peppol-validate, докладніше в розділі Публічні інструменти, і стан сервісу через status); усе інше вимагає сесії або Bearer-токена.Конвенції та формати
| Тип | Формат | Приклад |
|---|---|---|
id | UUID (string) | 08dd6c1e-… |
часові мітки | ISO-8601 Instant (UTC) | 2026-06-03T09:40:27Z |
issueDate | дата (YYYY-MM-DD) | 2026-06-03 |
totalAmount | десяткове число | 120.00 |
відсутні значення | null (а не пропущене поле) | "dic": null |
Пагінація та ідемпотентність
/companies і /companies/{id}/documents підтримують опціональні ?page&limit (відповідь залишається JSON-масивом; загальна кількість міститься в заголовках X-Total-Count / X-Total-Pages). Без параметрів вони повертають увесь масив, документи відсортовані за createdAt за спаданням; /tokens завжди повертає увесь масив. Заголовок Idempotency-Key підтримує національний інтерфейс SAPI-SK на POST /sapi/document/send; для програмного відправлення використовуйте саме його.Помилки
Помилки мають єдину структуру з машинозчитуваним кодом error. Помилки валідації додають мапу fields (перша помилка для кожного поля).
// 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-статуси
- 200 / 201 / 204
- успіх (OK / Created / No Content)
- 400
- недійсні вхідні дані (див. error / fields)
- 401
- відсутня або недійсна автентифікація
- 403
- недостатньо прав (роль)
- 404
- ресурс не існує або Ви не маєте до нього доступу
- 405
- HTTP-метод не підтримується для цього шляху
- 409
- конфлікт (IČO / електронна адреса вже існує)
- 415
- непідтримуваний Content-Type (XML endpoint-и очікують application/xml)
- 429
- перевищено ліміт запитів (заголовки RateLimit-* і Retry-After, тіло JSON rate_limited)
error. Відповідь без JSON-тіла (HTML або текст, як error code: 1010 зі статусом 403, або 502/504 під час розгортання) надійшла не від API, а від інфраструктури перед ним (захист периметра, шлюз). Типова причина 403/1010: загальний User-Agent бібліотеки (Python-urllib, Java/1.8.x на тестовому домені); рішення описано в розділі Тестове середовище.Повний каталог помилок
| Код | HTTP | Коли |
|---|---|---|
validation_failed | 400 | тіло не пройшло валідацію (див. fields) |
unauthorized | 401 | відсутній або недійсний API-токен |
forbidden | 403 | дія вимагає ролі owner/admin |
company_not_found | 404 | компанія не існує або Ви не є її учасником |
ico_taken | 409 | компанія з таким IČO (реєстраційним номером компанії) вже існує |
ico_immutable | 400 | IČO не можна змінити |
company_dic_missing | 400 | верифікація для відправлення без DIČ компанії (словацького податкового ідентифікаційного номера) |
token_invalid | 400 | верифікаційний токен (Verifikačný údaj, підпис) не збігається |
document_not_found | 404 | документ не існує |
token_not_found | 404 | API-токен не існує / не належить Вам |
rate_limited | 429 | надто багато запитів |
Ліміти запитів (rate limit)
API захищене обмеженням частоти запитів у 60-секундному вікні (на інстанс). Ліміт і залишок квоти повертаються в кожній відповіді через заголовки; при перевищенні API повертає 429 Too Many Requests із Retry-After.
- Звичайні виклики
- динамічний ліміт із великим запасом, на API-токен (або сесію, інакше IP); поточне значення повертається в заголовку RateLimit-Limit
- Auth (/auth/*)
- суворіший ліміт на IP (захист від brute-force; крім /auth/me і /auth/logout)
RateLimit-Limit- ліміт у вікні
RateLimit-Remaining- скільки запитів залишилося
RateLimit-Reset- секунд до скидання вікна
Retry-After- секунд до наступної спроби (при 429)
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-токени
Непрозорі (opaque) токени vpt_… для доступу server-to-server. Відкритий текст показується лише один раз при створенні. Збережіть його. Ми зберігаємо лише SHA-256 хеш і 12-символьний префікс для відображення.
/tokenssession / tokenСписок Ваших активних токенів (без секрету), createdAt за спаданням.
/tokenssession / tokenСтворює токен; повертає відкритий текст (лише один раз).
| Поле | Тип | Обовʼязкове | Опис |
|---|---|---|---|
name | string | так | назва токена, макс. 128 |
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":"…" }/tokens/{id}session / tokenВідкликає токен. Повертає 204.
Помилки: token_not_found (404)
Компанії
Компанії, ідентифіковані за реєстраційним номером (IČO) / номером платника ПДВ (IČ DPH), якими Ви керуєте. Доступ залежить від членства: Ви бачите лише компанії, учасником яких є. Творець компанії стає її owner.
/companiessession / tokenСписок компаній, учасником яких Ви є (з Вашою роллю).
/companiessession / tokenДодає компанію; Ви стаєте її owner, status = pending_verification.
| Поле | Тип | Обовʼязкове | Опис |
|---|---|---|---|
ico | string | так | рівно 8 цифр |
dic | string | так | формат SK + 10 цифр (напр. SK2121358349) |
legalName | string | так | юридична (комерційна) назва, макс. 500 |
registeredAddress | string | ні | адреса зареєстрованого офісу, макс. 1000 |
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" }Помилки: ico_taken (409) · validation_failed (400)
/companies/{id}session / tokenДеталі компанії (Ви маєте бути учасником).
/companies/{id}owner / adminОновлює компанію. IČO незмінне (має дорівнювати наявному значенню).
Помилки: forbidden (403) · ico_immutable (400) · company_not_found (404)
Поле status
pending_verification- після створення; відправлення ще не розблоковано
active- верифікована, відправлення розблоковано
Роль учасника
owner- творець компанії (повний доступ)
admin- адміністратор (редагування, вебхуки, верифікація)
member- учасник (читання)
viewer- лише читання
owner, так і admin (менеджер компанії).Верифікація для відправлення (верифікаційний токен, Verifikačný údaj)
Перед відправленням компанію необхідно верифікувати за допомогою верифікаційного токена (Verifikačný údaj, VÚ), підписаного токена, який видає Фінансова адміністрація Словаччини (Finančná správa, FS). Після успішної верифікації status компанії змінюється на active і відправлення розблоковується.
/companies/{id}/verificationowner / adminСамостійна верифікація верифікаційного токена (Verifikačný údaj). У разі успіху встановлює status на active.
| Поле | Тип | Обовʼязкове | Опис |
|---|---|---|---|
token | string | так | VÚ = hex-підпис (prod/pPFS 1024 hex, test/tPFS 768 hex) |
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" }Помилки: company_dic_missing (400) · token_invalid (400) · forbidden (403)
Документи
Журнал документів Peppol (отриманих і відправлених) для компанії. Він наповнюється в міру того, як рахунки проходять через Access Point. Залежить від членства в компанії, відсортовано за createdAt за спаданням.
/companies/{id}/documentssession / tokenСписок документів компанії. Опціональний фільтр ?direction=sent|received.
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":"…" } ]/companies/{id}/documents/{docId}session / tokenДеталі одного документа.
Помилки: document_not_found (404)
/companies/{id}/documents/{docId}/downloadsession / tokenОкремий HTML рахунка для друку. ?inline=1 → відображає в браузері, інакше завантажує.
Повертає text/html із Content-Disposition, де файл має назву faktura-<číslo>.html (číslo = номер рахунка).
SAPI-SK 1.0 (національний інтерфейс)
SAPI-SK це стандартизований національний REST-інтерфейс між клієнтською/ERP-системою та Access Point (sapi-sk.sk). Ми реалізуємо його повністю. Це означає, що Ви не залежите від нашої пропрієтарної форми API і пишете інтеграцію один раз для будь-якого SAPI-SK Access Point.
- Base URL
https://peppol.verteco.digital/sapi- Автентифікація
- OAuth2 client_credentials → короткостроковий access-токен (JWT)
- client_id
- UUID Вашого API-токена (наведений у розділі API-токени / dashboard)
- client_secret
- сам токен
vpt_…з порталу - Версія
- 1.3 (10 операцій: 4× auth, 6× документи)
vpt_, ні сесія). Відкликання API-токена в порталі негайно робить недійсними як /auth/token, так і /auth/renew.Sandbox (пробне середовище)
Хочете випробувати SAPI-SK без реєстрації і без жодного ризику? Використайте публічні облікові дані sandbox. Sandbox валідує запити точно так, як продуктивне середовище, але ніколи нічого не надсилає в мережу Peppol і не працює з реальними даними; він повертає реалістичні mock-відповіді. Ідеально для розробки, CI та онбордингу інтеграції.
- client_id
sandbox- client_secret
sandbox- send
- повна валідація контракту + mock 202 (ніщо не доставляється)
- receive
- 1 зразковий документ
sandbox-doc-0001для тестування парсингу та acknowledge
# 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>'client_id/client_secret з порталу (нижче).Автентифікація
/sapi/auth/tokenclient_credentialsОбмінює client_id + client_secret на access-токен (15 хв) і refresh-токен (30 днів). Збережіть токен і використовуйте його всі 15 хвилин: запит нового токена при кожному виклику є зайвими витратами (ліміт запитів враховує і виклики /auth/token).
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…" }Помилки: SAPI-AUTH-001 (401) · SAPI-AUTH-003 (401: IP поза списком дозволених адрес ключа) · SAPI-VAL-001 (400)
/sapi/auth/token/statusBearer (access)Дійсність і термін дії access-токена; should_refresh = true, коли залишається менше 3 хв.
/sapi/auth/renewrefresh tokenВидає новий access + refresh-токен. Не вдається, якщо базовий API-токен було відкликано.
// body
{ "refresh_token": "eyJhbGciOi…" }/sapi/auth/revoke–Завжди повертає успіх (RFC 7009). Постійний kill switch: відкликання API-токена в порталі.
Відправлення документа
/sapi/document/sendBearer (access)Відправляє бізнес-документ Peppol (UBL / BIS 3.0) отримувачу через наш Access Point. Відправлення працює за принципом fail-closed: компанія має мати верифікований верифікаційний токен (Verifikačný údaj).
Обов'язкові заголовки:
| Заголовок | Опис |
|---|---|
Authorization | Bearer <access_token> |
X-Peppol-Participant-Id | учасник, від імені якого Ви відправляєте (напр. 0245:2121358349, цифри DIČ (словацького податкового ідентифікаційного номера) без префікса "SK") |
Idempotency-Key | унікальний ключ; повторний виклик повертає початковий результат |
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 це маршрутизаційні та технічні поля: documentId це Ваш внутрішній ідентифікатор, а не номер рахунка. Бізнес-дані (номер рахунка cbc:ID, дата виставлення, термін оплати, дата постачання, валюта, сума) беруться безпосередньо з UBL payload; нічого з цього Ви не надсилаєте в metadata, і UBL завжди є джерелом істини для відображення в порталі та для вебхуків.Помилки: SAPI-AUTH-002 (401) · SAPI-AUTH-003 (403) · SAPI-VAL-001 (400) · SAPI-PROC-001 (502) · SAPI-PROC-002 (503) · SAPI-PROC-500 (500: не повторюйте, повідомте correlation_id)
Отримання документів
/sapi/document/receiveBearer (access)Список отриманих документів (найстаріші першими); метадані також містять invoiceNumber, тож документ можна ідентифікувати без завантаження payload. Query: ?pageToken, ?limit (макс. 200), ?status (received / acknowledged; без урахування регістру, будь-яке інше значення повертає помилку SAPI-VAL-001), ?invoiceNumber (точна відповідність cbc:ID), ?since і ?until (ISO-8601 instant; вікно за часом отримання, напр. документи за останні 5 днів, масове завантаження для зовнішнього архівування або відновлення бухгалтерського обліку), ?deliveryDateFrom і ?deliveryDateTo (ISO-8601 date; фільтр за датою постачання, вказаною в документі). Заголовок X-Peppol-Participant-Id обов'язковий.
// 200 OK
{ "documents": [ { "documentId":"…","documentTypeId":"…",
"senderParticipantId":"0088:…","receiverParticipantId":"0245:…",
"creationDateTime":"2026-06-17T…Z" } ],
"nextPageToken": "50" }/sapi/document/receive/{documentId}Bearer (access)Деталі включно з payload (сирий XML, точно так, як він надійшов через Peppol).
Помилки: SAPI-RES-001 (404) · SAPI-RES-002 (404: payload не архівовано)
/sapi/document/receive/{documentId}/acknowledgeBearer (access)Підтверджує, що Ваша система прийняла документ. Ідемпотентний.
Стан відправлених документів
/sapi/discovery?receiverId=0245:2121358349Попередня перевірка перед відправленням: чи зареєстровано отримувача в мережі Peppol і які типи документів він може отримувати? Той самий SML/SMP lookup, який виконує Access Point; receiverId приймає Peppol ID, номер платника ПДВ (IČ DPH) або сам DIČ. Відповідь: {registered, participantId, smp, documentTypes, checkedAt}. Заголовок X-Peppol-Participant-Id тут не потрібен.
/sapi/document/sentBearer (access)Стан доставки відправлених документів: pending (передається мережі) → submitted → delivered / rejected (підтверджено підтвердженням доставки (MLS) від AP отримувача); failed = транспортна помилка (повторна спроба з тим самим Idempotency-Key відправляє знову). Query: ?pageToken, ?limit, ?status (pending / submitted / sent / delivered / rejected / failed; без урахування регістру, будь-яке інше значення повертає помилку SAPI-VAL-001), ?invoiceNumber (точна відповідність cbc:ID: стан конкретного рахунка одним викликом), ?since і ?until (ISO-8601 instant; часове вікно), ?deliveryDateFrom і ?deliveryDateTo (ISO-8601 date; фільтр за датою постачання).
// 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 }Помилки: SAPI-AUTH-002 (401) · SAPI-AUTH-003 (403) · SAPI-VAL-001 (400: недійсний since)
Пакетне відправлення
/sapi/document/batchBearer (access)До 100 документів в одному виклику. Кожен елемент проходить повну логіку одиночного відправлення (ідемпотентність через itemId + idempotencyKey, резервування, submit, вердикт) і повертає власний результат; збій одного елемента не зупиняє інші. Елементи обробляються послідовно; невдалі елементи повторюйте з тим самим idempotencyKey.
// 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": "…" } ] }Помилки: SAPI-AUTH-002 (401) · SAPI-AUTH-003 (403) · SAPI-VAL-001 (400: порожній або надто великий список)
Модель помилок
Усі помилки SAPI мають єдину обгортку з категорією, стабільним кодом, прапорцем retryable і correlation_id для служби підтримки.
{ "error": {
"category": "AUTH",
"code": "SAPI-AUTH-001",
"message": "Invalid client credentials.",
"retryable": false,
"correlation_id": "b4191dfc-…" } }Сповіщення та вебхуки
Про отриманий рахунок ми можемо повідомити компанію електронною поштою або вебхуком (POST на Вашу URL-адресу). Доставка надійна (durable): сповіщення зберігається у вихідній черзі та доставляється асинхронно (тайм-аут 15 с); у разі збою ми повторюємо до 8 разів з експоненційною затримкою (30 с → макс. 1 год), потім dead-letter. Отже, збій Вашого сервера не втрачає сповіщення; ми доставимо його при наступній спробі. Захист від SSRF блокує loopback/локальні адреси; URL вебхука має бути публічною.
/companies/{id}/notificationssession / tokenНалаштування сповіщень: { webhookUrl, notificationEmail, hasSecret }.
/companies/{id}/notificationsowner / adminВстановлює обидва канали (порожній рядок вимикає відповідний канал).
| Поле | Тип | Обовʼязкове | Опис |
|---|---|---|---|
webhookUrl | string | ні | порожньо або http(s) URL, макс. 512 |
notificationEmail | string | ні | дійсна електронна адреса, макс. 256 |
/companies/{id}/webhooksession / tokenКонфігурація вебхука: { url, hasSecret } (без секрету).
/companies/{id}/webhookowner / adminВстановлює URL вебхука (автоматично генерує секрет для підпису, якщо його ще немає).
| Поле | Тип | Обовʼязкове | Опис |
|---|---|---|---|
url | string | так | http(s) URL, макс. 512 |
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 }/companies/{id}/webhookowner / adminВидаляє як URL вебхука, так і секрет. Повертає 204.
/companies/{id}/webhook/secretowner / adminГенерує новий секрет для підпису та повертає його ОДИН РАЗ; збережіть його для перевірки X-Verteco-Signature.
// 200 OK
{ "secret": "vpt_8f2a…" }/companies/{id}/webhook/testowner / adminСинхронно надсилає тестове сповіщення (подія webhook.test, підписана, із захистом від SSRF) на збережену URL і повертає, ЩО було надіслано і ЩО повернулося. Те саме запускає кнопка „Otestovať webhook“ (Тестувати вебхук) у деталях компанії.
// 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 storedPayload вебхука
Як для отриманого (invoice.received), так і для відправленого (invoice.sent) рахунка ми надсилаємо POST із таким тілом; поле event розрізняє тип.
Ще дві події повідомляють про вердикт мережі щодо відправленого Вами рахунка: invoice.delivered (Access Point отримувача підтвердив доставку підтвердженням доставки (MLS)) і invoice.rejected (відхилено, або мережею, або під час валідації перед відправленням). Вони містять ідентифікацію документа та компанії (documentId, invoiceNumber, receiverId, peppolMessageId, companyDic, peppolParticipantId), а також status, statusDetail із причиною відхилення та statusDateTime. Завдяки їм Вам не потрібно опитувати стан відправлених рахунків.
Подія company.activated надходить, коли клієнт завершує вибір постачальника на порталі (VPDS) Фінансової адміністрації Словаччини (Finančná správa, FS); тіло: event, companyId, companyDic, peppolParticipantId, status, verifiedAt. company.deactivated натомість надходить, коли компанію знімають з реєстрації в мережі (те саме тіло без verifiedAt); докладніше в посібнику /saas:
{
"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"
}Поля companyDic і peppolParticipantId ідентифікують компанію, якої стосується подія (важливо для партнерів, які використовують одну URL вебхука для всіх своїх клієнтів).
Вердикт мережі щодо відправленого рахунка:
{
"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"
}Активація компанії після вибору постачальника на порталі FS (VPDS):
{
"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"
}Назва події також передається в заголовку X-Verteco-Event. Повний список подій: invoice.received, invoice.sent, invoice.delivered, invoice.rejected, company.activated, company.deactivated і тестова подія webhook.test. Рекомендуємо відкладати невідомий тип події та логувати його; про новий тип ми завжди повідомляємо заздалегідь.
Перевірка підпису
Якщо компанія має секрет, ми надсилаємо заголовок X-Verteco-Signature у формі sha256=HMAC-SHA256(secret, raw body) (hex у нижньому регістрі). Завжди обчислюйте HMAC над точними байтами тіла:
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));
}POST /companies/{id}/webhook/secret; він повертається один раз (ротація генерує новий). Без секрету ми не надсилаємо заголовок X-Verteco-Signature.Масове налаштування: один токен, кілька компаній
Один API-токен (прив'язаний до Вашого облікового запису / електронної адреси) керує усіма компаніями, якими він володіє: хто створює компанію через POST /companies, стає її owner і може налаштувати її вебхук. Вебхук є окремим для кожної компанії (власна URL і секрет), тож одним і тим самим токеном Ви можете підключити будь-яку кількість компаній:
# 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": "…" }- Токен має бути
owner/adminвідповідної компанії; для компанії, де він лише member/viewer, повертається403 forbidden(жодного доступу між клієнтами (cross-tenant)). - Кожній компанії можна задати іншу URL або одну й ту саму для всіх; у payload Ви розрізняєте їх за
companyId(іreceiverId). - За сотень компаній дотримуйтеся ліміту запитів на токен (поточне значення повертається в заголовку
RateLimit-Limit); групуйте запити з затримкою (backoff) при429(заголовокRetry-After). - Вебхук фактично спрацьовує лише тоді, коли компанія активна в Peppol (після вибору Verteco як постачальника у Фінансовій адміністрації) і, отже, фактично отримує документи.
Моделі даних
Поля об'єктів, які повертає API.
Company
| Поле | Тип | Обовʼязкове | Опис |
|---|---|---|---|
id | UUID | – | ідентифікатор компанії |
ico | string | – | реєстраційний номер компанії (IČO, 8 цифр) |
dic | string|null | – | номер платника ПДВ (IČ DPH) |
legalName | string | – | юридична назва |
registeredAddress | string|null | – | адреса зареєстрованого офісу |
peppolParticipantId | string|null | – | учасник Peppol (після реєстрації) |
status | string | – | pending_verification | active |
role | string | – | owner | admin | member | viewer (Ваша роль) |
createdAt | Instant | – | час створення |
Document
| Поле | Тип | Обовʼязкове | Опис |
|---|---|---|---|
id | UUID | – | ідентифікатор документа |
direction | string | – | sent | received |
peppolMessageId | string|null | – | ID повідомлення Peppol |
docTypeId | string|null | – | тип документа (Peppol) |
senderId | string|null | – | відправник (scheme:id) |
receiverId | string|null | – | отримувач (scheme:id) |
invoiceNumber | string|null | – | номер рахунка |
issueDate | date|null | – | дата виставлення |
currency | string|null | – | валюта (напр. EUR) |
totalAmount | number|null | – | загальна сума |
status | string | – | стан обробки |
createdAt | Instant | – | час запису |
User · Token · Webhook
| Поле | Тип | Обовʼязкове | Опис |
|---|---|---|---|
User | object | – | { id: UUID, email: string } |
Token | object | – | { id, name, prefix, lastUsedAt|null, createdAt } |
Webhook | object | – | { url: string|null, hasSecret: boolean } |
Словацькі конвенції з практики розробників
Поза межами Peppol BIS Billing 3.0 словацькі постачальники ERP і програм для виставлення рахунків поступово сходяться на спільній інтерпретації опціональних полів (обговорення відбувається в Slack-каналі, який веде Фінансова адміністрація Словаччини, Finančná správa, FS). Нижче наведено конвенції, яких наш портал дотримується вже сьогодні: усі вони є валідними конструкціями BIS, проходять через наше API без змін, а отримані документи відображають їх також у зрозумілому для людини попередньому перегляді та PDF.
- Вирахування оподаткованого авансу в рядку: від'ємний рядок із
cac:DocumentReference, деcbc:IDмістить номер податкового документа на отриманий платіж, аcbc:DocumentTypeCodeдорівнює130(BIS: invoice line object identifier, макс. 1 на рядок). Отриманий рахунок із таким рядком відображається в нашому попередньому перегляді з приміткою „odpočet zálohy – daňový doklad č. …" (вирахування авансу, податковий документ №…). - Податковий документ на отриманий платіж: згідно з FAQ Фінансової адміністрації використовується код
InvoiceTypeCode 388(Tax invoice). Він проходить як наше API, так і валідацію; вирахування неоплаченого (неоподаткованого) авансу виражається черезcbc:PrepaidAmount. - Анулювання рахунка: кредит-нота
381(CreditNote) зcac:BillingReferenceна початковий рахунок, а не від'ємний рахунок 380. Примітка: мережа відхиляє код 384 для словацьких сторін (правило PEPPOL-EN16931-P0112 дозволяє його лише між німецькими суб'єктами); для коригування в бік збільшення використовуйте дебет-ноту 383. - BT-83 PaymentID: словацька практика сходиться на форматі референсу платника
/VS…/SS…/KS…; лише змінний символ (variabilný symbol) також поширений. Наша обробка передає значення без змін і відображає його разом із платіжними реквізитами. - Додаткові дані позицій (партії, серійні номери, терміни придатності) через
cac:AdditionalItemPropertyз усталеними назвами, такими якBatchNumber,SerialNumber,ExpirationDate.
Вкладення документів (BT-125)
Вкладення (PDF, зображення) можна додати до е-рахунка у форматі base64 в елементі cac:AdditionalDocumentReference (BT-125). Наш ліміт: 25 МБ на вкладення. Peppol не визначає єдиного ліміту для всієї мережі; окремі постачальники встановлюють власні (FS FAQ 9/DPH/2025/IM, приклад № 67), тому для дуже великих вкладень також перевірте ліміт постачальника іншої сторони.
Публічні інструменти (валідація, перевірка отримувача)
Два допоміжні endpoint-и без автентифікації: те саме ядро валідації і той самий SML/SMP lookup, які використовує наш Access Point. Вони підходять для CI та перевірок перед відправленням; на них діє суворіший публічний ліміт запитів.
/public/peppol-validateпублічнийВалідація е-рахунка за EN 16931 + Peppol BIS Billing 3.0 (включно зі словацькими правилами), те саме, що й UI-валідатор на /validator. Тіло запиту = безпосередньо UBL 2.1 XML (Invoice / CreditNote або весь Peppol SBD), Content-Type application/xml, ліміт 3 МБ.
curl -X POST https://peppol.verteco.digital/api/v1/public/peppol-validate \
-H "Content-Type: application/xml" \
--data-binary @faktura.xml// 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)/public/peppol-check?id=0245:2121358349публічнийПеревірка отримувача в робочій мережі Peppol (SML/SMP lookup): чи він зареєстрований і які типи документів може отримувати? Параметр id приймає Peppol ID (0245:…), номер платника ПДВ (IČ DPH, SK…) або сам DIČ (словацький податковий ідентифікаційний номер). Автентифікований еквівалент для ERP-конвеєрів: GET /sapi/discovery.
// 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"
}Стан (ping)
Публічний endpoint перевірки стану (health-check), придатний для моніторингу.
/pingпублічнийСтан backend.
// 200 OK
{ "service": "peppol-portal-backend", "status": "ok", "timestamp": "2026-06-17T…Z" }Актуальний огляд усіх компонентів доступний на сторінці стану системи.
Незабаром
- POST
/companies/{id}/peppol/register· Ручна реєстрація в Peppol SMP через API. Сьогодні це відбувається автоматично при виборі постачальника на порталі FS (VPDS) Фінансової адміністрації Словаччини (Finančná správa, FS).
POST /companies/{id}/documents/send уже доступний (beta: форма відповіді ще може змінитися); для стабільного програмного відправлення рекомендуємо SAPI-SK POST /sapi/document/send із Idempotency-Key.Хочете отримати ранній доступ до інтеграції, sandbox або маєте запитання? Зв'яжіться з нами безпосередньо:
