Partner API
A partner account manages many client companies. Its API key acts for any
of them, under /api/v1/partner/. This guide is the map for an integrator
building on that surface: which paths the key can call, how a document moves
through create, validate and send, which fields track the two things that
happen after a send, and how to get the original files back.
The key and its paths
A partner API key is created in the partner console (Connect → API keys) and
sent as X-API-Key: efk_... or Authorization: Bearer efk_.... It works on
/api/v1/partner/* only. Any other path, including
/api/v1/companies/{id}, answers 403 partner_api_key_not_allowed: the
per-company routes are for the company's own users and keys.
Scopes on the key:
| Scope | Allows |
|---|---|
invoices:read | Clients, invoices, detail, downloads, exports, events, webhook listing |
invoices:write | Creating invoices and customers, registering webhooks |
invoices:send | Sending |
validate:only | Validation without any other write |
apps:manage | Installing a client's SAPI-SK connector |
A call without the needed scope answers 403 insufficient_scope with the
scope it wanted.
Clients
GET /api/v1/partner/clients
GET /api/v1/partner/clients/{company_id}
A company joins your portfolio when it is activated under your partner
account (the activation code from the Finančná správa portal, entered in the
console, or POST /companies/dev-enroll on the sandbox). The company_id in
every path below is that client's id from the list.
Create, validate, send
POST /api/v1/partner/clients/{company_id}/invoices
POST /api/v1/partner/clients/{company_id}/invoices/{invoice_id}/validate
POST /api/v1/partner/clients/{company_id}/invoices/{invoice_id}/send
The body of the create call is the same InvoiceCreate the company API uses
(see Sending invoices). Send your own
invoice_number: a retry with the same number answers
409 invoice_number_conflict instead of creating a second draft, and
GET /api/v1/partner/documents?client={company_id}&q={invoice_number} finds
the one that exists.
Validate and send carry the invoice's revision in If-Match, taken from the
version field of the create or detail response, for example If-Match: "3".
Validate answers the new version and status; use that version on the
send. A missing header is 428 precondition_required, a stale one
412. Send accepts an invoice in draft, validated or approved; any
other status is 409 invalid_status, so a repeated send never transmits
twice. Send answers 202 and the work continues in the background;
402 means the client workspace's monthly quota is used up.
Two things happen after a send
The buyer's access point confirms delivery over AS4 and answers with a
Peppol MLS. Separately, eFakturuj reports the invoice to the Finančná správa
(the SK TaxData Document, TDD) and the tax authority answers with its own
MLS. GET /api/v1/partner/invoices/{invoice_id} tracks them apart.
Peppol delivery (AS4 and MLS)
statusis the document's overall state (sent_peppol,delivered,rejected,failed, ...);peppol_message_idandpeppol_errorare the transmission's id and last error.eventsentries withcategory: "peppol"are the transport timeline. An outbound invoice ispeppol.outbound.invoice.<state>(a credit notepeppol.outbound.credit_note.<state>):transmittedwhen AS4 accepted it,acknowledgedwhen the buyer's MLS arrived. The receipt itself ispeppol.inbound.mls.<state>withdetail.mls_response_code(AP,ABorRE) anddetail.anchor_kind:invoicefor the buyer's receipt,tddfor the tax authority's answer to our report.
FS reporting (TDD)
c5is the report's own state:state(pending,transmitted,acknowledged,rejected,failed), the tax authority'smls_response_codeandmls_reasons,tdd_uuid,transmission_idand the timestamps. It isnullwhile nothing has been filed.
Webhooks follow the same split: invoice.delivered and invoice.rejected
(a negative MLS from the buyer) for delivery, invoice.fs_acknowledged and
invoice.fs_rejected for the report, invoice.received for documents that
arrive for the client. See Webhooks below.
The files
The detail's files list names every downloadable file of the invoice with a
partner API path and whether a download will answer:
[
{"kind": "ubl", "label": "invoice.ubl.xml", "href": "/api/v1/partner/invoices/{id}/ubl", "available": true},
{"kind": "pdf", "label": "invoice.pdf", "href": "/api/v1/partner/invoices/{id}/pdf", "available": true},
{"kind": "peppol_message", "label": "mls-receipt.xml", "href": "/api/v1/partner/invoices/{id}/peppol-messages/{message_id}/payload", "available": true},
{"kind": "peppol_message", "label": "tax-data-document.xml", "href": "/api/v1/partner/invoices/{id}/peppol-messages/{message_id}/payload", "available": true}
]
GET /api/v1/partner/invoices/{invoice_id}/ubl returns the document as it
exists: for an invoice that went out over Peppol the file that was sent, for a
received invoice the supplier's document as it arrived, for a draft XML
generated from the invoice. The X-UBL-Source header says which
(original or generated). /json and /pdf sit beside it.
GET /api/v1/partner/invoices/{invoice_id}/peppol-messages/{message_id}/payload
returns a stored Peppol message: a received envelope (received-invoice.xml,
received-credit-note.xml), the buyer's receipt (mls-receipt.xml), the tax
authority's receipt (fs-mls-receipt.xml) or the TaxData Document as filed
(tax-data-document.xml). Envelopes received before copies were kept show
available: false and answer 404; outbound envelopes other than the TDD are
not kept.
For a month at a time, the export bundles the originals:
POST /api/v1/partner/clients/{company_id}/exports {"period_from": "2026-09-01", "period_to": "2026-09-30"}
GET /api/v1/partner/clients/{company_id}/exports/{export_id}
The poll answers parts with signed download_urls valid for 7 days; each
ZIP holds the sent files under ubl/ next to a CSV and JSON summary.
Received documents
GET /api/v1/partner/clients/{company_id}/invoices?direction=received
lists what arrived for a client, and the detail and /ubl work the same way
for those. A client that consumes documents through SAPI-SK instead gets its
own credentials from POST /api/v1/partner/clients/{company_id}/apps/sapi-sk/install
(scope apps:manage); the invoice.received webhook carries
provider_document_id, the handle GET /sapi/document/receive/{documentId}
takes. See SAPI-SK.
Webhooks
POST /api/v1/partner/clients/{company_id}/webhooks {"url": "https://...", "events": "invoice.delivered,invoice.rejected,invoice.fs_acknowledged,invoice.fs_rejected,invoice.received"}
GET /api/v1/partner/clients/{company_id}/webhooks
GET /api/v1/partner/clients/{company_id}/webhooks/{webhook_id}/deliveries
POST /api/v1/partner/clients/{company_id}/webhooks/{webhook_id}/test
The default events list does not include invoice.received; add it when the
client receives documents. Signing, retries and payloads are the same as for a
company's own webhooks (Webhooks).
Retries and idempotency
The partner API does not read an Idempotency-Key header; only the SAPI-SK
send does. What makes retries safe here is the invoice number on create and
If-Match plus the status rule on send, described above. The
Idempotency guide has the client-side pattern, and
Rate limits the per-minute budget and the
Retry-After header on 429.
See also
- Sending invoices for the invoice body, VAT and credit notes
- Receiving invoices for the inbound path
- Partner onboarding for activation and mass enrolment