Skip to content

Archive

Fiscal archive restitution: the exact transmitted bytes of your e-invoicing documents, their SHA-256 manifest, their audit trail, and the export that packages all three.

Show the state of this organization's fiscal archive

GET /api/v1/archive

Requires authentication (Bearer token) and the X-Organization-Id header.

What the fiscal archive does for this organization. state is vault (the paid ArchiveVault: every transmitted byte written to a locked, retention-governed bucket), france_capture (the French transmission capture, which does not depend on the vault) or none; entitled says whether the current plan includes the vault, and plans_with_vault names the plans that do, for an organization that does not have it yet. vault_status (provisioning, active, retained, error) reports a vault that is being set up or wound down.

The rest is what an auditor asks for: region — where the bytes physically live; retention_days — the object-lock retention the storage bucket itself enforces, which is why an archived object cannot be altered or deleted before it lapses; locked; object_count; and last_proven_at / integrity_state (never, running, passed, failed, inconclusive, or not_applicable for an organization that archives nothing) from the platform's own periodic re-verification of every stored hash.

quota_bytes and used_bytes are METERED, never enforced: exceeding the quota drops nothing. (#980)

Responses

Status Description
200 For non-paginated data, return as before
422
403

Example request

curl -X GET "https://kworia.com/api/v1/archive" \
  -H "Authorization: Bearer {{access_token}}" \
  -H "X-Organization-Id: {{organization_id}}" \
  -H "Accept: application/json"

List the archived objects (the manifest index)

GET /api/v1/archive/documents

Requires authentication (Bearer token) and the X-Organization-Id header.

The paginated index over the archive's manifest, most recently archived first.

Each row is one archived OBJECT, not one document. A single invoice normally contributes several — the request body sent to the e-invoicing provider, the response it returned, the UBL XML, the PDF, each attachment, the webhook events and the delivery evidence — and each carries its own id, its own object_kind and its own sha256. That sha256 is the fingerprint of the exact bytes GET /api/v1/archive/documents/{id}/download returns, so a recipient can recompute it and prove the archive did not alter what was transmitted.

Filters: number and counterparty (partial, case-insensitive), issued_from / issued_until (the document's issue date), amount_min / amount_max, direction (outbound, inbound), kind (request_body, response_body, ubl_xml, pdf, attachment, webhook_event, received_document_json, status_snapshot, evidence), plus per_page (1–200, default 25) and page.

Amounts are strings, never floats — an index that rounded a total is an index an auditor can disprove. The storage address (bucket, storage account, object key) is deliberately absent here; the export's manifest.csv carries it for an auditor who needs it. (#980)

Parameters

Name In Type Required Description
number query string no
counterparty query string no
issued_from query string no
issued_until query string no
amount_min query number no
amount_max query number no
direction query string no
kind query string no
per_page query integer no
page query integer no

Responses

Status Description
200 For non-paginated data, return as before
422
403

Example request

curl -X GET "https://kworia.com/api/v1/archive/documents" \
  -H "Authorization: Bearer {{access_token}}" \
  -H "X-Organization-Id: {{organization_id}}" \
  -H "Accept: application/json"

Download one archived object, byte for byte

GET /api/v1/archive/documents/{id}/download

Requires authentication (Bearer token) and the X-Organization-Id header.

The archived bytes of one object, streamed back exactly as they were stored — nothing is re-generated, re-encoded or re-signed. Content-Type is the manifest row's content_type and Content-Length its size_bytes, so the response can be hashed and compared with the row's sha256. {id} is the id of a row from GET /api/v1/archive/documents.

404 for an identifier that is not in your organization's archive — the same answer as for one that does not exist at all, so an identifier cannot be tested for existence. 503, never 404, when the archive cannot produce bytes the manifest names: that is an integrity incident rather than a missing page, the platform's integrity check is alerted, and reporting it as "not found" would hide it.

Every successful download is appended to this organization's audit chain, naming the user and the surface. (#980)

Parameters

Name In Type Required Description
id path string yes

Responses

Status Description
503 The archive could not produce the bytes this manifest row names. The platform's integrity check has been alerted.
404 No archived object with that identifier — including one that belongs to another organization.
200 The archived bytes, with the manifest row's own content type and length.
422
403

Example request

curl -X GET "https://kworia.com/api/v1/archive/documents/{id}/download" \
  -H "Authorization: Bearer {{access_token}}" \
  -H "X-Organization-Id: {{organization_id}}" \
  -H "Accept: application/json"

Order an export of the archive (ZIP)

POST /api/v1/archive/exports

Requires authentication (Bearer token) and the X-Organization-Id header.

Orders one ZIP containing the archived objects, their manifest, the audit trail and the network exchanges. 202, not 201: the build runs asynchronously on the archive queue, so what exists when this returns is the work order (status: pending) and not yet the artifact — poll GET /api/v1/archive/exports/{id} and collect it when download_url is no longer null.

An empty body means the whole archive. Otherwise the same eight clauses as GET /api/v1/archive/documents narrow it (number, counterparty, issued_from, issued_until, amount_min, amount_max, direction, kind); there is no paging, because an export walks the whole matching set. The set is fixed at the instant the export is ordered, so documents archived while it builds are not silently added to it.

Only one export builds at a time per organization. A second request while one is pending or building is refused with 409, as is a request whose filters match nothing. One ZIP also packages a bounded number of objects — 72 000 by default, derived from what a single build can hold in memory and finish inside its time budget — and a request covering more is refused with the same 409 rather than accepted and failed an hour later; narrow it with issued_from/issued_until, one financial year per export. The finished artifact expires — seven days by default — and is then deleted from the operational disk, because a copy of a decade of counterparties and amounts must not sit outside the locked vault indefinitely.

Requires the archive.export permission (and an API token carrying the archive.export scope). Unlike every other write on this API, this endpoint stays available to an ARCHIVED organization: it mutates no business record, and an archived organization is precisely the one that most needs its fiscal records handed back. (#980)

Request body

Field Type Required Description
number string no
counterparty string no
issued_from string no
issued_until string no
amount_min number no
amount_max number no
direction string no
kind string no

Responses

Status Description
202 The work order was accepted. The ZIP does not exist yet.
403
409 An export is already being assembled for this organization, the filters match nothing to export, or the request covers more objects than one export may package. None of the three is an authorization failure.
422

Example request

curl -X POST "https://kworia.com/api/v1/archive/exports" \
  -H "Authorization: Bearer {{access_token}}" \
  -H "X-Organization-Id: {{organization_id}}" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "string",
    "counterparty": "string",
    "issued_from": "string",
    "issued_until": "string",
    "amount_min": 1,
    "amount_max": 1,
    "direction": "string",
    "kind": "string"
}'

Show one export and where to collect it

GET /api/v1/archive/exports/{id}

Requires authentication (Bearer token) and the X-Organization-Id header.

The state of one work order: status (pending, building, completed, failed, expired), object_count — what the build actually packaged — and, separately, missing_object_count, because folding a shortfall into the count would make a partial restitution read exactly like a complete one. Also file_size_bytes, manifest_sha256, the filters the export was ordered with, and expires_at.

Once there is something to collect, download_url addresses GET /api/v1/archive/exports/{id}/download — authenticated by the same bearer token as every other operation here. It is not the signed browser link the notification email carries: that one sits behind the session guard and a bearer token presented to it is a redirect to the login page. While there is nothing to collect, download_url is null.

The ZIP contains, per spec §3.8: objects/<object key> — the archived bytes themselves; manifest.json and manifest.csv — one record per object with its SHA-256, bucket, storage account, region, size and present_in_export; audit-trail.json and audit-trail.csv — this organization's append-only hash chain, exported WHOLE even for a filtered export, because a chain can only be verified end to end; transmissions.json and transmissions.csv — every exchange with the e-invoicing network or the tax authority, joined to the trail on the document identifier and including the French e-reporting submissions that belong to no single document; and a bilingual FR/EN README telling the recipient how to recompute the hashes themselves.

404 for an identifier outside your organization. (#980)

Parameters

Name In Type Required Description
id path integer yes

Responses

Status Description
200 For non-paginated data, return as before
404 No export with that identifier — including one that belongs to another organization.
422
403

Example request

curl -X GET "https://kworia.com/api/v1/archive/exports/{id}" \
  -H "Authorization: Bearer {{access_token}}" \
  -H "X-Organization-Id: {{organization_id}}" \
  -H "Accept: application/json"

Download a finished export (ZIP)

GET /api/v1/archive/exports/{id}/download

Requires authentication (Bearer token) and the X-Organization-Id header.

The ZIP itself — the address download_url points at — authenticated by the same bearer token as every other operation here, which is why it carries no signature.

404 for an identifier outside your organization and for an export that is not ready (one answer for "not yours", "no such export" and "not finished"). 410 once expires_at has passed: the artifact was deliberately deleted from the operational disk, and the next step is to order another one — which "not found" would not tell you. 503 if the row is complete but the artifact is not on the disk; the platform's integrity check is alerted.

Each successful download is appended to this organization's audit chain, naming the acting user and recording which door was used — the handover is itself part of the evidence a tax inspector may be shown. (#980)

Parameters

Name In Type Required Description
id path integer yes

Responses

Status Description
503 The export is recorded as complete but its artifact could not be read. The platform's integrity check has been alerted.
410 The export's deadline has passed and the artifact was deleted. Order another one.
404 No export with that identifier — including one that belongs to another organization, and one that is not ready.
200 The export archive.
422
403

Example request

curl -X GET "https://kworia.com/api/v1/archive/exports/{id}/download" \
  -H "Authorization: Bearer {{access_token}}" \
  -H "X-Organization-Id: {{organization_id}}" \
  -H "Accept: application/json"

We use cookies and privacy-respecting analytics

We use essential cookies for authentication and privacy-respecting analytics (self-hosted, respects Do Not Track). No advertising or third-party tracking. Learn more in our Privacy Policy