not authorized
Release notes — 2026-06-22

Read-only API documentation at a new URL

A published, read-only API reference is now served at /reference. It includes a browsable error-code catalogue, and every application/problem+json error now carries a type URI that deep-links straight to the section for that code, explaining what the condition means and how to resolve it. The interactive "Try it out" console here on /docs is unchanged.

Changes to POST /document/send

Cheap structural checks now run synchronously, before the 202. A payload that is not well-formed XML, declares a DTD, is not a recognised Peppol document, or does not match the declared metadata.documentTypeId is rejected immediately with a 400 instead of being accepted and failing later. All such rejections happen before any side-effect, so the same Idempotency-Key may be retried with a corrected payload. The expensive BIS3 / Schematron validation stays asynchronous, surfaced via document status and webhooks as before.

Behaviour change — receiver reachability is now resolved asynchronously. Sending to a receiver that is absent from the SMP (or does not advertise the requested document type / process) is no longer a synchronous 422. The document is accepted with 202 and resolves asynchronously to sendingStatus = SENDING_FAILED (no AS4 attempt is made). Observe the outcome on GET /document/send/{id} or the document.sendingFailed webhook — not on the POST response. The synchronous 422 now covers only UNSUPPORTED_DOCUMENT_TYPE / UNSUPPORTED_PROCESS (types this Access Point does not handle at all). This keeps an undeliverable document in the system for C5 fiscal reporting.

Acceptance is now atomic. A 202 is returned only once the payload is durably stored and the document is persisted — acceptance is all-or-nothing. Replaying an accepted submission (same Idempotency-Key + body) returns the original 202 verbatim — it is an acceptance acknowledgement, not a live status, so use GET /document/send/{id} or webhooks for current state.

New error codes to handle

This release introduces error codes you may now receive. If you branch on the stable code field, add handling for:

  • MALFORMED_XML, XML_DTD_FORBIDDEN, DOCTYPE_DETECTION_FAILED, DOCTYPE_MISMATCH — synchronous 400 on /document/send from the new structural pre-validation. Permanent; fix the payload and retry with the same Idempotency-Key.
  • RECEIVER_NOT_FOUND, RECEIVER_DOES_NOT_SUPPORT_DOCUMENT_TYPE, RECEIVER_DOES_NOT_SUPPORT_PROCESS — asynchronous errorCode on a SENDING_FAILED document (and on the document.sendingFailed webhook), replacing the former synchronous 422. The receiver is unroutable; fix the address or document type rather than blindly resubmitting.
  • PAYLOAD_STORE_UNAVAILABLE — transient 503 on /document/send when the payload store is briefly unavailable. Nothing is persisted (no document, your Idempotency-Key is not consumed, no webhook), so retry with the same key — a transient infra outage is never recorded as a terminal document failure.
  • PAYLOAD_UNAVAILABLE404 on payload-read endpoints (GET /document/send/{id}/payload, GET /document/receive/{id}/payload): the document exists but its stored payload can no longer be retrieved. Permanent and distinct from DOCUMENT_NOT_FOUND and from the transient PAYLOAD_STORE_UNAVAILABLE.

Make sure every code above is covered in your integration. The full, authoritative set a client can receive — with the meaning and recommended action for each — is in the error-code catalogue at /reference. Branch on the stable code field, and treat any code you do not recognise as a non-retryable failure to surface for investigation.

Inbound creationDateTime surfaced on receive

Received documents now expose the document creation timestamp from the inbound SBDH as metadata.creationDateTime. Inbound wrappers from the Peppol network do not always carry it, so the field is nullable — clients MUST handle null.

Webhook delivery retries extended to ~72 hours

Failed webhook deliveries are now retried for roughly 72 hours (up to 26 attempts, each backoff gap capped at 6 hours) so a weekend-long outage on your endpoint can recover before delivery is abandoned. The X-Everifin-Attempt counter now ranges up to 26.

Release notes — 2026-06-09

POST /document/validatevalid now means structural acceptance only

To make the result more intuitive, valid no longer folds in whether the receiver is reachable. It now equals structuralValid — it answers a single question: will /send accept this document? A new required deliverable: boolean carries the routing check (the logical AND of receiverReachable, receiverSupportsDocType, and processIdAdvertised), and those three fields are now advisory / warning only.

Previously valid was the AND of all four layers, which misleadingly signalled "do not send" whenever the receiver's Access Point was unreachable — even though such a document should still be sent (and, where applicable, reported to Finančná správa). Gate sending on valid only; treat deliverable and the reachability fields as advisory. A document with valid: true, deliverable: false is correct to submit.

Release notes — 2026-06-03

Webhooks are live

Lifecycle events are now delivered as HMAC-signed webhooks — the preferred way to observe document progress without polling. Each delivery carries an X-Everifin-Delivery-Id and a signature over the body; failed deliveries are retried with exponential backoff. The event payload includes participantId, so a single endpoint can be reused across tenants and routed internally.

There is no self-service subscription API yet. To enable webhooks for your tenant, request a subscription by email at [email protected] — Everifin operations provisions the endpoint URL and signing secret for you. REST polling (GET /document/inbox, GET /document/send/{id}) remains available as a fallback when no webhook is configured or a delivery fails.

Per-document event journal

GET /document/send/{id}/events and GET /document/receive/{id}/events are now liveThey return the ordered lifecycle event journal for a single document — the same events that drive webhooks — so you can reconcile a document's full history on demand.

Release notes — 2026-05-22

Cross-network participant lookup is live

GET /participants/{participantId} now lets you check whether a business partner is already registered in the Peppol network — anywhere in it, not just on our Access Point. A 200 means the partner is reachable over Peppol; a 404 means they are not (yet) registered. The response additionally lists which document types they advertise and (when published) their Business Card.

POST /document/validate — new processIdAdvertised check

ValidateResponse gains a required processIdAdvertised: boolean. valid is now the logical AND of four layers (was three): structuralValid, receiverReachable, receiverSupportsDocType, and the new processIdAdvertised. The new field is true only when the receiver's SMP record advertises the requested processId under the requested documentTypeId — closes a previous gap where a mismatched processId would pass /validate and then fail on the actual send.

Structured violations on VALIDATION_FAILED

When sendingStatus = VALIDATION_FAILED, the response now includes a violations[] array (new required field on SentDocumentSummary, returned by GET /document/send and GET /document/send/{id}) with rule-level detail: rule code, XPath, and message. Empty array on the happy path, on non-validation terminal states, and when the verifier rejected without enumerable rule detail (e.g. XML parse failure, unknown document type).

Release notes — 2026-05-18

Send & receive endpoints available on stage

Stage is wired to the Peppol test network — documents really travel through AS4 to a real receiver AP, but only test participants live there. Two pre-provisioned test firms are available for end-to-end exercises (request for access if you didn't obtain test credentials).

  • POST /document/send — submit a UBL document for delivery.
  • GET /document/send — list sent documents (cursor pagination, filters, sort by submittedAt). New.
  • GET /document/send/{id} — sent-document status (three-axis snapshot: sending / C3 delivery / C5 reporting).
  • GET /document/send/{id}/payload — download the raw bytes of a sent document. New.
  • GET /document/receive — list received documents (cursor pagination, filters, sort by receivedAt).
  • GET /document/inbox — polling-friendly worklist of not-yet-acknowledged received documents, oldest first.
  • GET /document/receive/{id} — received-document detail (with payload, controlled by payloadFormat).
  • GET /document/receive/{id}/payload — download the raw bytes of a received document. New.
  • POST /document/receive/{id}/acknowledge — mark a received document as processed by the downstream system.

Major changes to API specifications

  • Idempotency-Key scope is now per-participant (was per-tenant).
  • payloadTransferEncoding default and enum changed. New values: raw (default) and base64 — replacing the previous base64 (default) / none. The default switched from base64 to raw XML; clients relying on the default will now send/receive raw XML inline in JSON. The receive side additionally accepts none (omit payload, fetch bytes via the new /payload endpoint).
  • SendDocumentResponse fields renamed. receivedAtsubmittedAt, the timestamp field has been removed, and a new required payloadSize (bytes, int64) was added.
  • List query parameters renamed. fromreceivedAtFrom, toreceivedAtTo, and the single sort parameter has been split into SortReceivedAt (receive endpoints) and SortSubmittedAt (send list). The upper-bound semantics also changed: the previous to was exclusive (< to), receivedAtTo is now inclusive (<= receivedAtTo).
  • New terminal TIMED_OUT value on both c3DeliveryStatus and c5DeliveryStatus. On C3, returned when the receiving Access Point did not acknowledge the message via MLS within the expected window — the message was received by the receiving AP, but the receiver participant might not be reachable or the receiving AP did not send the MLS response due to a technical error. On C5, mirrors the same shape on the reporting side — set when the fiscal authority does not return an acceptance or rejection within the expected window. Treat both as "sent successfully without read receipt": do not auto-resend or auto-resubmit.

Other additions

  • GET /document/receive/{id} accepts a new payloadFormat query parameter (raw | base64 | none) controlling how the payload is encoded in the JSON response (or whether it is included at all).
  • List responses now include an explicit required hasMore boolean alongside nextPageToken. Prefer checking hasMore over relying on the absence of nextPageToken.
  • payloadSize (bytes, int64) added to send and receive summary/detail schemas — the size of the stored payload after transfer-encoding has been decoded.
  • New schema ReceivedDocumentMetadata for inbound documents: creationDateTime is now optional and nullable, because inbound SBDH wrappers from the Peppol network do not always carry a creation timestamp.