Getting started
This is the start-here guide for integrating your system with eFakturuj. In five steps you'll push a Peppol BIS Billing 3.0 invoice through the Slovak 5-corner model — the invoice to the buyer's Access Point and the Slovak Tax Data Document (SK TDD) to the tax authority — and know it arrived.
Everything below is one base URL and one header:
- Base URL:
https://api.efakturuj.sk/api/v1 - Auth:
X-Api-Key: efk_…— a single key type (see Authentication)
The flow at a glance
POST /invoices → create a draft (returns {id})
POST /invoices/{id}/validate → check BIS 3.0.20 (no delivery — safe to loop)
POST /invoices/{id}/send → 5-corner: invoice → buyer (C3) + SK TDD → tax authority (C5)
GET /invoices/{id} → track DRAFT → SENT_PEPPOL → DELIVERED
0. Get an API key
Create one in the dashboard (Settings → API keys) or via the API. Keys are a
single type, prefixed efk_ — there is no per-key test/live toggle; the
behaviour is decided by the deployment you call.
curl -X POST https://api.efakturuj.sk/api/v1/api-keys \
-H 'Authorization: Bearer <your-dashboard-jwt>' \
-H 'Content-Type: application/json' \
-d '{"name": "my-integration", "scopes": ["invoices:read","invoices:write","invoices:send"]}'
# → { "api_key": "efk_…", "key_prefix": "efk_…", "id": "…" }
Store api_key securely — it's shown once. Send it as X-Api-Key on every call.
1. Create an invoice
POST /invoices takes the whole document in one call. The supplier and buyer
each carry a Peppol participant id in scheme:identifier form (e.g.
0245:2122813913); discover a buyer's id with GET /lookup/... if you don't
have it.
curl -X POST https://api.efakturuj.sk/api/v1/invoices \
-H 'X-Api-Key: efk_…' -H 'Content-Type: application/json' \
-d '{
"invoice_number": "2026-0001",
"issue_date": "2026-06-25", "due_date": "2026-07-25",
"currency_code": "EUR",
"supplier": { "name": "Moja firma s.r.o.", "vat_id": "SK2122813913", "ico": "53510160",
"street": "Mlynské nivy 5", "city": "Bratislava", "postal_code": "82109",
"country_code": "SK", "peppol_id": "0245:2122813913" },
"buyer": { "name": "Odberateľ s.r.o.", "vat_id": "SK2020999999", "ico": "20209999",
"street": "Hlavná 1", "city": "Košice", "postal_code": "04001",
"country_code": "SK", "peppol_id": "0245:2020999999" },
"supplier_iban": "SK3112000000001987426375",
"lines": [ { "line_number": 1, "item_name": "Konzultácie", "quantity": "1",
"unit_code": "HUR", "unit_price": "100.00",
"vat_rate": "23.00", "vat_category_code": "S" } ]
}'
# → { "id": "…", "status": "draft", … }
| Field | Notes |
|---|---|
peppol_id | scheme:identifier. eFakturuj splits it into the UBL EndpointID (schemeID + value) for you — never send the scheme inline. |
vat_rate / vat_category_code | SK rates: 0, 5, 19, 23; category S (standard), Z (zero), AE (reverse charge). |
supplier_iban | Required for the payment means block. |
| amounts | Always strings (decimal-safe). |
2. Validate before you send
POST /invoices/{id}/validate runs XSD + Peppol BIS 3.0.20 + Slovak
Schematron and returns the issues — without sending anything. This is your
safe development loop: iterate here until valid: true with zero errors,
then send.
curl -X POST https://api.efakturuj.sk/api/v1/invoices/<id>/validate -H 'X-Api-Key: efk_…'
# → { "valid": true, "xml_validation": { "xsd_valid": true, "peppol_valid": true, "errors": [] } }
Each error carries the Schematron rule id (e.g. BR-CO-10) and a message —
map them straight back to the field you sent. GET /invoices/{id}/ubl returns
the generated UBL if you want to inspect it.
3. Send — the 5-corner flow
POST /invoices/{id}/send queues the real delivery and returns immediately.
A single send performs the full 5-corner exchange:
- the invoice → the buyer's Access Point (C3), and
- a referencing SK Tax Data Document → the Slovak tax authority (C5),
each correlated by a deterministic BDID-01 UUID. You never build the TDD — it's derived from the invoice.
curl -X POST https://api.efakturuj.sk/api/v1/invoices/<id>/send -H 'X-Api-Key: efk_…'
# → { "invoice_id": "…", "status": "queued", "message": "Invoice queued for delivery" }
4. Track delivery
The send is asynchronous. Poll GET /invoices/{id} or (recommended) subscribe to
webhooks. The status walks:
DRAFT → SENT_PEPPOL → DELIVERED (DELIVERED = the buyer's AP returned a positive MLS)
The matching SK TDD is filed in the same step; its acknowledgement (the MLS from the tax authority) is tracked alongside.
5. Credit notes
A credit note is the same call with invoice_type: "381" and a reference to the
invoice it credits:
-d '{ "invoice_type": "381", "source_invoice_id": "<original-invoice-id>", … }'
Send it the same way — POST /invoices/{id}/send files the credit note + its TDD.
Testing safely
- Validate-only (step 2) never delivers and never bills — use it freely to prove your data produces a compliant invoice.
- A dedicated self-serve sandbox with an internal Peppol loop-back (full send → MLS → TDD lifecycle, no real delivery, isolated from production) is on the roadmap. Until it lands, validate before you send, and coordinate a controlled first live send with us.
Next steps
- Authentication — key scopes, JWT vs API key
- Sending invoices — the field-by-field reference
- Receiving invoices — inbound + the MLS you send back
- Webhooks · Errors · Idempotency