Quickstart

A complete end-to-end flow through the Agent API: create a test key, set up a client organization (including address), enroll it in the Peppol sandbox, issue an invoice, send it over Peppol, track its status, and receive a webhook. All in the sandbox, no credits, a real Peppol TEST network.

Prerequisites

ItemValue
Base URLhttps://api.efaktura.sk/v1
AuthenticationThe X-API-Key header, plus X-Organization-Id for operations on an organization
Test keyefk_pk_test_…
Both the sandbox and production use the same base URL. The environment is determined solely by the key prefix: efk_pk_test_… = sandbox (Peppol TEST network, no credits), efk_pk_live_… = production.

Integration flow

Fast path: if you already have UBL/CII XML ready, you can merge steps 4–5 into a single call via the Connector (POST /v1/agent/peppol/connector/send): it validates, reserves credit, and sends in one go, with idempotency and opt-in auto-fix. For bulk sending from a spreadsheet, use CSV ingest. The step-by-step flow below is the universal foundation.
1
Create a test key

In the partner portal, under API keys, create a sandbox key. It's shown only once, so store it in a secret store. A partner key (efk_pk_*) can create client organizations; it's tied to your partner account.

2
Set up a client organization (with an address!)

A partner key creates a white-label child organization. In this call you don't send X-Organization-Id: the organization doesn't exist yet. The org:provision scope is required.

Fill in the address (street, city, postalCode) and dic + ic_dph right away. Without a complete seller address, Peppol sending fails on SK validation rules (BT-35/37/38). More in the Invoices section.
curl -X POST https://api.efaktura.sk/v1/agent/organizations \
  -H "X-API-Key: efk_pk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Tatra Servis s.r.o.",
    "ico": "12345678",
    "dic": "2020202020",
    "ic_dph": "SK2020202020",
    "address": {
      "street": "Hlavná 1",
      "city": "Bratislava",
      "postalCode": "81101",
      "country": "SK"
    }
  }'

Response (201 Created, or 200 if an existing organization was reused):

{
  "data": {
    "org_id": "0a2c1f3e-…",
    "partner_id": "7b8d…",
    "slug": "tatra-servis-sro",
    "reused": false,
    "status": "caka_na_token"
  }
}

org_id is the value you send in X-Organization-Id from now on. You can get the organization's detail (including participant_id and peppol_status) via GET /v1/agent/organizations/{org_id}.

3
Enroll the organization in Peppol (sandbox enroll)

Enroll registers the organization's DIČ as a Peppol participant in the TEST SMP (9915:<DIČ>). The invoice:send scope and the X-Organization-Id header are required. In the sandbox, the verification token is optional; for production (live) enroll it is required (a Financial Administration verification code, more in Going live).

curl -X POST https://api.efaktura.sk/v1/agent/peppol/enroll \
  -H "X-API-Key: efk_pk_test_..." \
  -H "X-Organization-Id: 0a2c1f3e-…" \
  -H "Content-Type: application/json" \
  -d '{}'
{
  "data": {
    "status": "active",
    "registration_id": "…",
    "participant_id": "9915:2020202020"
  }
}

The organization's DIČ must have 10 digits, otherwise enroll returns VALIDATION_ERROR.

4
Issue an invoice

You issue an invoice via POST /v1/agent/invoices (scope invoice:create). The seller is derived from the organization, the buyer from customer (or an existing customer_id). For the invoice to be sendable over Peppol, the buyer must have a complete address and (for a company) ico/dic/ic_dph.

curl -X POST https://api.efaktura.sk/v1/agent/invoices \
  -H "X-API-Key: efk_pk_test_..." \
  -H "X-Organization-Id: 0a2c1f3e-…" \
  -H "Content-Type: application/json" \
  -d '{
    "customer": {
      "name": "Customer s.r.o.",
      "ico": "87654321",
      "dic": "2010101010",
      "ic_dph": "SK2010101010",
      "address": {
        "street": "Obchodná 5",
        "city": "Košice",
        "postalCode": "04001",
        "country": "SK"
      },
      "email": "fakturacia@odberatel.sk"
    },
    "items": [
      {
        "description": "Service work",
        "quantity": 2,
        "unit": "hod",
        "unit_price": 50,
        "vat_rate": 23
      }
    ],
    "payment_method": "bank_transfer",
    "due_days": 14
  }'

Response (201 Created), then save the id:

{
  "id": "b1f0d7a2-…",
  "invoice_number": "2026001",
  "status": "issued",
  "customer": { "id": "…", "name": "Customer s.r.o." },
  "items": [ … ],
  "subtotal": "100.00",
  "vat_total": "23.00",
  "total": "123.00",
  "currency": "EUR",
  "issue_date": "2026-06-22",
  "due_date": "2026-07-06",
  "pdf_url": "https://…",
  "created_at": "2026-06-22T10:00:00.000Z"
}
5
Send the invoice over Peppol

Sending queues the invoice (scope invoice:send). A test key routes the send through the sandbox AP on the real Peppol TEST network, no credits.

curl -X POST https://api.efaktura.sk/v1/agent/peppol/send/b1f0d7a2-… \
  -H "X-API-Key: efk_pk_test_..." \
  -H "X-Organization-Id: 0a2c1f3e-…"

Response (202 Accepted):

{
  "data": {
    "invoice_id": "b1f0d7a2-…",
    "job_id": "peppol-send:b1f0d7a2-…",
    "status": "queued"
  }
}
Send several invoices at once via POST /v1/agent/peppol/send/batch with the body { "invoiceIds": ["…", "…"] } (1–200 IDs).
6
Track the status (polling)

You check transmission status via GET /v1/agent/peppol/status/{invoiceId} (scope invoice:read). The endpoint's actual states are: QUEUED, SENDING, SENT, DEFERRED, ERROR; if nothing has been sent yet, a synthetic not_sent value is returned. (DELIVERED is a webhook event state, not a polling-endpoint state.) Details in Receiving and statuses.

curl https://api.efaktura.sk/v1/agent/peppol/status/b1f0d7a2-… \
  -H "X-API-Key: efk_pk_test_..." \
  -H "X-Organization-Id: 0a2c1f3e-…"
{
  "data": {
    "invoice_id": "b1f0d7a2-…",
    "state": "SENT",
    "error_message": null,
    "receiver_identifier": "9915:2010101010",
    "document_id": "…",
    "updated_at": "2026-06-22T10:00:05.000Z"
  }
}
7
Receive the webhook

Instead of polling, we recommend webhooks. Register an HTTPS endpoint in the portal and react to peppol.document.sent / peppol.document.delivered / peppol.document.failed, or to an inbound document via peppol.document.received. Every delivery is HMAC-signed: verify the signature and deduplicate by X-Webhook-Id. The full picture is in Webhooks.

{
  "event": "peppol.document.delivered",
  "timestamp": "2026-06-22T10:00:08.000Z",
  "data": {
    "invoiceId": "b1f0d7a2-…",
    "invoiceNumber": "2026001",
    "documentType": "invoice",
    "mode": "test",
    "state": "DELIVERED",
    "messageId": "…",
    "transactionId": "…",
    "orgId": "0a2c1f3e-…"
  }
}

Next steps

Before sending, you can pre-validate your UBL XML (Validation). Once the flow is verified in the sandbox, move on to Going live: production enroll requires a Financial Administration verification token and partner activation.