# Archiles Peppol API — changelog and change policy This file records every change to the published contract ([`openapi.yaml`](openapi.yaml)) and to the [integration guide](integration-guide.md). It is append-only: entries are added at the top, never rewritten. --- ## Change policy ### Versions and surfaces Each surface carries its own version in its path, and the two change independently: - the **native surface**, `/einvoicing/v1/*`, is versioned by Archiles under the rules below; - the **SAPI profile**, `/v1/sapi/*`, is versioned by SAPI-SK (see *How the SAPI profile tracks SAPI-SK*). A new version of one never moves the other. ### What may change inside a version without a new one These are **additive** changes. A correctly written client keeps working across all of them, and they ship without notice as part of normal releases: - **New endpoints**, and new optional query parameters or request headers on existing ones. - **New optional fields** in a request body. - **New fields in a response body.** Ignore fields you do not recognise — do not fail on them. - **New values in an open-ended list.** `error.code` and the registry's `documentTypes` are explicitly open sets and will grow. - **New values in a native enum** — for example a new `format`, or a new `taxReporting.state`. Handle an unrecognised value by treating it as unknown rather than crashing. - For the send status (`SubmissionState`) "unknown" has a specific meaning: **treat an unrecognised status as non-final**, keep the submission under observation and surface it to a human. A new value is always introduced with its finality stated in the entry below that adds it, so you never have to guess whether polling should stop. - **New HTTP status codes** for conditions that previously produced a more general one, within the same `error.category`. - **Relaxed limits** — a higher payload or batch ceiling. Lowering one is a breaking change. - **Documentation and description changes** that do not alter behaviour. ### What will not change inside a version These are **breaking** and will not happen without a new major version: - Removing or renaming an endpoint, a field, an enum value or a status code. - Making an optional request field required, or a response field disappear. - Changing a field's type, or the meaning of an existing value. - Repurposing a published `error.code`. - Tightening a limit, or making a previously accepted request invalid. - Changing the meaning of an identifier, or which routes accept it. ### Notice for breaking changes A new major version of the native surface is published under a new path prefix (`/einvoicing/v2/...`), and the current version keeps running alongside it. We will give **at least 6 months' notice** before a version is withdrawn, and no version is withdrawn while an active integration is still using it without an agreed migration date. Notice is sent to the technical contact on record for each integrator. Keep that contact current — it is the only channel used for deprecation notices. ### Security exception A change required to close a security vulnerability may ship without the notice period above. If it is breaking, affected integrators are contacted directly. ### How the SAPI profile tracks SAPI-SK The `/v1/sapi/*` surface is frozen to **SAPI-SK v1.0.0** and is verified field-by-field against its published schema. Its three documented deviations are listed in the contract preamble and in §2 of the integration guide. - Archiles does **not** extend the SAPI surface, even where it has a gap. Native endpoints fill gaps instead; the profile stays conformant. - A **new SAPI-SK version** is published as a **new profile beside the current one**, at `/v2/sapi/*`, rather than by changing `/v1/sapi/*` in place. A client written against SAPI-SK v1.0.0 therefore never has to move because SAPI moved. - Clarifications to descriptions may be made in place. Paths, schemas and request/response status codes may not — with one narrow exception: **statuses the API already returns may be documented on SAPI operations** even though SAPI's schema omits them - `429` and `500` everywhere, `402` on the send and `400` on the receive listing. That is a documentation change, not a behavioural one; the contract preamble lists every such difference. --- ## Versions ### v1.0.0 — 2026-10-13 The first published contract. It is available on the test environment, `https://api.test.archiles.sk`; production, `https://api.archiles.sk`, is not yet available and will be announced to each integrator. The change policy above applies to every line of this entry. **Two surfaces** - `/einvoicing/v1/*` — the Archiles native surface: validation (`/validate`), sending and its status (`/submissions`), received documents (`/inbox`), and participants and the registry under `/peppol`. - `/v1/sapi/*` — a SAPI-SK v1.0.0 compatibility profile, with three documented deviations (20 MB payload ceiling; Archiles-assigned `documentId` on received documents; `creationDateTime` treated as a submission timestamp and excluded from the payload-mismatch check). - Each surface has its own token routes, `/einvoicing/v1/auth/*` and `/v1/sapi/auth/*`, which behave identically. - **Entitlement is per surface.** A client is entitled to the SAPI profile, to the native surface, or to both, and a token works on the surfaces its client is entitled to. A call to another surface is `403` with `error.code` `ARCH-AUTH-004`. **Authentication** - Client credentials in, an access token (15 minutes) and a refresh token out. Refresh tokens rotate: each renewal returns a new one and ends the one presented. - Revoking ends a refresh token. An access token issued before the revoke stays valid until it expires. - Repeated wrong secrets lock the client: `423` with `error.code` `ARCH-AUTH-423` and a `Retry-After`. While a client is locked the right secret is refused as well. **Native capabilities** - Participant provisioning and `registrationState` polling. A DIČ whose subject already has a Peppol registration with Archiles is a `409`. A participant the client is not entitled to is `403`, whether or not it exists. - Registry checks, single and bulk, returning every document type the participant publishes in the SMP as fully qualified Peppol identifiers — also types Archiles does not process, and wildcard patterns. - Pre-send validation, single and batch (≤ 20 items), with an XSD / Schematron / mapping breakdown per issue. - Send, single and batch (≤ 20 items, ≤ 100 MB), with `Idempotency-Key`. The receiver is looked up in the SMP for the exact document type before a submission is accepted: not registered is a `400`, a lookup that cannot be made a retryable `503`. - The payload is transmitted as submitted except for `cbc:IssueDate`, which Archiles sets to the date it accepts the submission when the two differ. XML signatures inside the payload are not supported. - Sent-status tracking with the public status set `Queued`, `Sent`, `Delivered`, `Rejected`, `Undeliverable`, `DeliveryUnconfirmed`, `Failed`, plus a `taxReporting` side-flow whose own values are `NotApplicable`, `Pending`, `Sent`, `Delivered`, `DeliveryUnconfirmed`, `Rejected`, `Unreachable` and `Disregarded`. A recorded `Delivered` or `Rejected` is never overturned by a later contradicting message. - Retry, single and bulk, allowed from `DeliveryUnconfirmed`, `Undeliverable` and `Failed`. - Cursor-paged inbox, content retrieval as JSON, optional PDF rendering, addressable attachments. A ZIP bundle is planned; until it ships `Accept: application/zip` gets `406`. - Custody acknowledgement, single and bulk, returning `acknowledgedAt`. **Scope of v1** - `peppol-bis` (Peppol BIS Billing 3.0 UBL) is the only document format, in both directions, and is the default when `format` is omitted. - Inbound delivery is pull-only. Webhooks are on the roadmap, not in v1. - `scope` on the token request is accepted for SAPI conformance. It enforces nothing and is **not** echoed back. - No documents are purged automatically; the only time-bounded record is `Idempotency-Key` state (24 hours), honoured on the two send operations, the two retry operations and the SAPI send. - `emailDelivery` and `email` (`to`, `cc`, `replyTo`, `subject`, all optional) are **reserved** on the send envelope: v1 accepts `emailDelivery: none` only and rejects anything else with `400`. They exist so that the delivery-channel axis is visible in the contract from the beginning, and so that adding an email channel later needs no new path family and no new major version. - The token routes (`/einvoicing/v1/auth/*`, `/v1/sapi/auth/*`) return neither `X-Correlation-Id` nor `X-RateLimit-*`; every other operation returns both. **Changed since publication** Production is not yet available, so these changes stay within `1.0.0`; the lines above remain as published. - **2026-10-19 — no retry from `DeliveryUnconfirmed`, which follows a configured waiting time.** `POST /einvoicing/v1/submissions/{submissionId}/retry` now answers a `DeliveryUnconfirmed` submission with `409` (was: `202`), and the bulk retry refuses it per item; retry stays allowed from `Undeliverable` and `Failed`. The receiving access point accepted the document and only its MLS is missing: a retry would resend an envelope it already has, and Archiles does not resend a document only because its MLS is missing (Peppol SPOG on MLS §6.2). If the recipient reports that the document did not arrive, contact Archiles support. A submission is reported `DeliveryUnconfirmed` once the configured waiting time after the hand-off has passed (24 hours by default; was: after 10 minutes). Until 31 March 2027 some receiving access points send no MLS at all, so a submission can stay `DeliveryUnconfirmed`; keep polling it, less often the longer it lasts. `taxReporting.state` `Disregarded` no longer follows a missing MLS; it follows only a rejected invoice or a transmission that was given up on. No path or field changes. - **2026-10-20 — sent documents are filed into a category and processed like an uploaded XML.** In Archiles, a document sent through the API is filed into the category the account's owner set for documents sent through the API (otherwise the first issued-invoice category) and goes through the same processing as an XML uploaded in Archiles; see the integration guide, section *What happens to your bytes*. Approval does not block or delay the send. Integration guide only; no path or field changes.