# Documents (/en/docs/referencia/documentos)

Base: `https://api.facturia.cl/v1`. Every endpoint in this chapter authenticates with `Authorization: Bearer` unless stated otherwise, and the error envelope is the one in [Errors](/en/docs/errores).

| Method   | Path                                                                                  | What it does                                                              |
| -------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `GET`    | [`/documents`](#get-documents)                                                        | List emitted documents                                                    |
| `POST`   | [`/documents`](#post-documents)                                                       | Emit a DTE                                                                |
| `POST`   | [`/documents/previews`](#post-documents-previews)                                     | Price and validate a document without emitting it                         |
| `GET`    | [`/documents/previews/{preview_id}`](#get-documents-previews-preview-id)              | Retrieve a stored preview                                                 |
| `GET`    | [`/documents/{document_id}`](#get-documents-document-id)                              | Retrieve a document                                                       |
| `GET`    | [`/documents/{document_id}/pdf`](#get-documents-document-id-pdf)                      | Download the PDF                                                          |
| `GET`    | [`/documents/{document_id}/xml`](#get-documents-document-id-xml)                      | Download the signed XML exactly as sent to the SII                        |
| `GET`    | [`/documents/{document_id}/events`](#get-documents-document-id-events)                | Lifecycle events for one document                                         |
| `POST`   | [`/documents/{document_id}/retry`](#post-documents-document-id-retry)                 | Retry a document in `failed`                                              |
| `POST`   | [`/documents/{document_id}/send`](#post-documents-document-id-send)                   | Email the document to the receptor                                        |
| `POST`   | [`/documents/{document_id}/cesion`](#post-documents-document-id-cesion)               | Ask the SII whether this factura is cedible                               |
| `POST`   | [`/documents/{document_id}/cede`](#post-documents-document-id-cede)                   | Cede this factura to a factoring company, registering it in the SII's RTC |
| `POST`   | [`/documents/{document_id}/credit_note`](#post-documents-document-id-credit-note)     | Emit a nota de crédito against this document                              |
| `POST`   | [`/documents/{document_id}/public_links`](#post-documents-document-id-public-links)   | Create or rotate public links for this document's artifacts               |
| `DELETE` | [`/documents/{document_id}/public_links`](#delete-documents-document-id-public-links) | Revoke every public link for this document                                |

## `GET /documents` [#get-documents]

**List emitted documents**

List documents for the empresa, newest first, filterable by `tipo_dte`, `status` and date range.

```bash
curl -sS https://api.facturia.cl/v1/documents \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA"
```

**Parameters**

| Parameter          | In     | Required | Type                                                                           | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Facturia-Empresa` | header | —        | string                                                                         | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |
| `limit`            | query  | —        | integer                                                                        |                                                                                                                                                                                                                                                                                                                                                             |
| `cursor`           | query  | —        | string                                                                         | Opaque cursor from a previous response's `next_cursor`.                                                                                                                                                                                                                                                                                                     |
| `expand`           | query  | —        | string                                                                         | Comma-separated, applied per returned page. On a LIST the vocabulary is narrower than on `GET /documents/\{document_id\}`: `events`, `references` and `received_document` only. `xml` and `pdf_base64` inline a whole artifact per row and are `400 invalid_field` here — fetch them from the single document, or from `/pdf` and `/xml` (§5.4).            |
| `status`           | query  | —        | `queued` · `sent` · `accepted` · `reparo` · `rejected` · `failed` · `annulled` |                                                                                                                                                                                                                                                                                                                                                             |
| `tipo_dte`         | query  | —        | `33` · `34` · `39` · `41` · `46` · `52` · `56` · `61`                          |                                                                                                                                                                                                                                                                                                                                                             |
| `folio`            | query  | —        | integer                                                                        |                                                                                                                                                                                                                                                                                                                                                             |
| `receptor_rut`     | query  | —        | Rut                                                                            |                                                                                                                                                                                                                                                                                                                                                             |
| `external_id`      | query  | —        | string                                                                         |                                                                                                                                                                                                                                                                                                                                                             |
| `issue_date[gte]`  | query  | —        | string                                                                         |                                                                                                                                                                                                                                                                                                                                                             |
| `issue_date[lte]`  | query  | —        | string                                                                         |                                                                                                                                                                                                                                                                                                                                                             |
| `created_at[gte]`  | query  | —        | string                                                                         |                                                                                                                                                                                                                                                                                                                                                             |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body              |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
| `200`     | A list of documents.                                                                                                                                                                                                                                                                                    | lista de Document |
| `400`     | Malformed or missing input.                                                                                                                                                                                                                                                                             | ErrorResponse     |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse     |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse     |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse     |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse     |

## `POST /documents` [#post-documents]

**Emit a DTE**

Returns `201` with `status: queued&#x60; and &#x2A;*`folio: null`**. The folio arrives when the
document reaches `sent`: it is allocated by the engine after the row exists, so no `201`
can carry one. `null` there is a WAIT, not a failure and not a placeholder — observe it
with `document.sent`, or by re-reading the document on the cadence
`Facturia-Poll-After` gives you.

The SII round-trip after that is a state machine you watch the same way. Everything not
supplied is defaulted from the empresa profile (emisor block, giro, dirección), the
receptor registry, and the tipo's tax rules.

```bash
curl -sS -X POST https://api.facturia.cl/v1/documents \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"tipo_dte":33,"items":[{"description":"Consultoría","quantity":1,"unit_price":1200000}]}'
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |
| `Idempotency-Key`  | header | —        | string | Client-generated key, unique per logical operation, retained 24h and scoped to (account, empresa, endpoint). Replays return the original response with `Facturia-Idempotent-Replay: true`. Same key + different body → `409`.                                                                                                                               |

**Body**

| Field                | Type                                                  | Required | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| -------------------- | ----------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `preview_id`         | string                                                | —        | Emit a previously computed preview (`POST /documents/previews`). The stored request is replayed through the ordinary create path, so nothing about the emission differs from a direct one. Only `external_id` and `metadata` may be supplied alongside it — nothing that could change an amount, a receptor or a date. Emitting the same preview twice returns the original document with `200` rather than a second `201`.  E.g.: `"prev_01K2R9M3D8V5QW7N"`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `tipo_dte`           | `33` · `34` · `39` · `41` · `46` · `52` · `56` · `61` | yes      | 33 factura afecta · 34 factura exenta · 39 boleta afecta · 41 boleta exenta · 46 factura de compra · 52 guía de despacho · 56 nota de débito · 61 nota de crédito. Boletas (39/41) travel a different SII transport; that is invisible through this API.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `external_id`        | string                                                | —        | Your own identifier. Unique per empresa; a duplicate returns `409 external_id_exists`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `issue_date`         | string                                                | —        | Defaults to today in America/Santiago.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `prices_include_tax` | boolean                                               | —        | Defaults to true for 39/41 and false for every other tipo.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `receptor`           | Party                                                 | —        | Who the document is issued to. `giro` here is the SII's `GiroRecep`, capped at **40 characters** — tighter than the emisor's own `GiroEmis` (80), so the same name of trade can be legal on one side of a document and illegal on the other. `legal_name` is 100 and `address` is 70/20/20. Over-long values are refused with `400 field_too_long` before a folio is allocated, and never truncated: shortening a razón social or a name of trade would change what the document says about the parties. `address` must be an object; a bare string is `400 invalid_field`, because there is no way to split one into the three components the SII asks for and dropping it silently would emit a document with no address at all. AND THE ADDRESS IS NOT OPTIONAL on 33, 34, 46, 52, 56 and 61: the SII accepts the ENVELOPE and then REJECTS the document whose `&lt;Receptor&gt;` carries no `GiroRecep`/`DirRecep`/`CmnaRecep`, with the folio already spent. So `giro`, `address.street` and `address.comuna` are resolved from this empresa's own earlier documents to the same RUT and, failing that, refused with `400 receptor_incomplete` before a folio is allocated. Three exceptions: a tipo 52 needs no `giro` (its receptor is often the emisor itself, whose own giro frequently exceeds 40); `emission_channel=sfg` also needs `address.city`, which the SII portal's own form demands; and 39/41 and a foreign 46 (`foreign: true`, or `55555555-5`) need none of them. |
| `items`              | DocumentItem\[]                                       | yes      |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `global_discounts`   | object\[]                                             | —        | The engine emits a single global discount line — the SII's `&lt;DscRcgGlobal&gt;` is one hard-coded `NroLinDR&gt;1` — so a second entry is refused with `400 invalid_field` before a folio is allocated, rather than dropped. MERCADO CHANNEL ONLY: on `emission_channel=sfg` it is refused with `422 global_discount_not_available_for_channel`, because the SII portal's emission form has no discount field at all — its `EFXP_PCT_DESC`/`EFXP_MNT_DESC` inputs are commented out in the captured form, and `items[].discount_percent` is refused there for the same reason. Fold the discount into `items[].unit_price` on that channel.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `references`         | DocumentReference\[]                                  | —        |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `dispatch`           | object                                                | —        | Required for tipo 52, and its `transfer_type` / `dispatch_type` are refused on any other tipo. Both emission channels emit a guía; they differ in which fields they can express. `destination` and `dispatch_type` are accepted on `emission_channel=mercado` (the engine writes them into the DTE's `IdDoc/TipoDespacho` and Transporte block) and refused on `emission_channel=sfg` with `422 dispatch_not_available_for_channel`, because the SII portal's guía form has nowhere to put them: it carries a single address — the receptor's, so put a differing one in `receptor.address` — and its only traslado select is the kind of movement, with no TipoDespacho input at all. The two channels also differ on amounts: `sfg` refuses a guía with any line priced at or below 0, or a zero total, with `422 sfg_guia_zero_amount` — the portal validates the guía with its factura validations, whatever the traslado kind — while `mercado` accepts one.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `withholding`        | object                                                | —        | Tipo 46 — you are the withholding agent.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `payment`            | object                                                | —        |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `totals`             | Totals + any                                          | —        |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `pdf`                | object                                                | —        |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `xml`                | object                                                | —        | The XML artifact shares the PDF's public-link mechanism on identical terms — it is the artifact the receptor's accounting system actually ingests, so gating it behind a key would force integrators to proxy a file we have already generated.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `notes`              | string                                                | —        |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `metadata`           | object                                                | —        | Up to 20 keys, ≤500 chars each. Stored and returned untouched; never sent to the SII.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `test`               | object                                                | —        | Test mode only. Sending this with a live key fails with `400 test_field_in_live_mode`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| **Responses**        |                                                       |          |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |

| Code      | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | Body            |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
| `200`     | The preview named by `preview_id` was ALREADY emitted, by this call's own earlier attempt or by a concurrent one. The original document, unchanged — nothing was created by this call and no second folio was spent (§10.2). Only reachable on a `\{"preview_id": "prev_…"\}` body.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | EmittedDocument |
| `201`     | Document created and queued for transmission. Carries `Facturia-Poll-After` when the document is not terminal — which the `201` always is on the live lane, since it answers `status: "queued"`. It was attached only by `GET /v1/documents/\{document_id\}` until 2026-09-04, so an agent following «poll per `Facturia-Poll-After`» had to issue a first read purely to discover the number it was told to poll with (#522). Same value, same function, both doors.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | EmittedDocument |
| `400`     | Malformed or missing input.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | ErrorResponse   |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | ErrorResponse   |
| `402`     | `subscription_required` - this live act needs an active subscription for the EMPRESA the request names, and that empresa has none (enforced). The subscription is per empresa: another empresa on the same account is unaffected, and `error.details` carries `empresa`, `empresa_rut`, `empresa_name`, `account_plan`, `subscription_status`, `grace_until`, `blocked_by`, a `next` handoff and a `checkout_url` pointing at that empresa. Or `plan_limit_reached` - a plan quota is exhausted (declared, not yet enforced). Test mode is never gated on either. **ELIGIBILITY IS EVALUATED FIRST** (2026-09-04, #475). This refusal now arrives ONLY when the empresa is otherwise able to emit: while its checklist is unfinished, its `puesta en vivo` pending or the empresa suspended, the act is refused by `422 empresa_not_emitting` with the checklist handoff instead. So this `402` and `Empresa.capabilities.blocked_by` can no longer name two different next actions for one state — which they did, the object saying «sign the mandato» while the door said «pay».                                                                                                                                                                                                                                                                                                           | ErrorResponse   |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | ErrorResponse   |
| `409`     | State conflict — idempotency reuse, duplicate external\_id, artifact not ready.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | ErrorResponse   |
| `422`     | Well-formed, and refused by a domain rule. The codes this operation answers, in the order the door checks them: - `empresa_not_emitting` — **live only**: this endpoint requires   `onboarding.status = emitting`, and the empresa has not got there yet. In SANDBOX it   is not checked at all: a test-mode empresa emits from the first minute, which is what   makes the whole surface exercisable before the SII has issued anything.   `error.details` is an `EmissionRefusalDetails` and carries the `pending_action` —   who must act, where, and in what words — so the refusal itself is the handoff. - `empresa_not_active` — the empresa is `suspended` or `archived`. - `tipo_not_available_for_channel` — this `tipo_dte` is not emitted on this empresa's   `emission_channel` (§6.2). - plus the payload rules: `totals_mismatch`, `receptor_incomplete`,   `reference_required` and their siblings — see `GET /error_codes`. This list named folios\_exhausted until 2026-09-04. There is no such code and there never was: running out of folios is not refused at this door at all — the range is drawn from AFTER the request is accepted, so it arrives as a `rejected` document or, on `POST /documents/previews`, as the non-blocking warning `no_folios_available` (#496 found it by cross-checking every code these sentences name against the published dictionary). | ErrorResponse   |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | ErrorResponse   |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | ErrorResponse   |

## `POST /documents/previews` [#post-documents-previews]

**Price and validate a document without emitting it**

Runs the ENTIRE emission validator — the same refusals, in the same words — and then
performs none of the emission. `folio` is `null` because none was taken; `folio_preview` is
the folio that WOULD be used, read from the counter and not reserved.

Stored for an hour and readable with `GET /documents/previews/\{preview_id\}`, which returns
what was computed rather than re-pricing: totals that moved between being shown and being
approved is the failure this flow exists to prevent.

Emit it by sending `\{"preview_id": "prev_…"\}` to `POST /documents`. Emitting the same
preview twice returns the ORIGINAL document with `200` and spends no second folio — a
property enforced in the database, because an agent retrying a tool call is the ordinary
case here and agents rarely send an `Idempotency-Key`.

```bash
curl -sS -X POST https://api.facturia.cl/v1/documents/previews \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA" \
  -H "Content-Type: application/json" \
  -d '{"tipo_dte":33,"items":[{"description":"Consultoría","quantity":1,"unit_price":1200000}]}'
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |

**Body**

| Field                | Type                                                  | Required | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| -------------------- | ----------------------------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `preview_id`         | string                                                | —        | Emit a previously computed preview (`POST /documents/previews`). The stored request is replayed through the ordinary create path, so nothing about the emission differs from a direct one. Only `external_id` and `metadata` may be supplied alongside it — nothing that could change an amount, a receptor or a date. Emitting the same preview twice returns the original document with `200` rather than a second `201`.  E.g.: `"prev_01K2R9M3D8V5QW7N"`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `tipo_dte`           | `33` · `34` · `39` · `41` · `46` · `52` · `56` · `61` | yes      | 33 factura afecta · 34 factura exenta · 39 boleta afecta · 41 boleta exenta · 46 factura de compra · 52 guía de despacho · 56 nota de débito · 61 nota de crédito. Boletas (39/41) travel a different SII transport; that is invisible through this API.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `external_id`        | string                                                | —        | Your own identifier. Unique per empresa; a duplicate returns `409 external_id_exists`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `issue_date`         | string                                                | —        | Defaults to today in America/Santiago.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `prices_include_tax` | boolean                                               | —        | Defaults to true for 39/41 and false for every other tipo.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `receptor`           | Party                                                 | —        | Who the document is issued to. `giro` here is the SII's `GiroRecep`, capped at **40 characters** — tighter than the emisor's own `GiroEmis` (80), so the same name of trade can be legal on one side of a document and illegal on the other. `legal_name` is 100 and `address` is 70/20/20. Over-long values are refused with `400 field_too_long` before a folio is allocated, and never truncated: shortening a razón social or a name of trade would change what the document says about the parties. `address` must be an object; a bare string is `400 invalid_field`, because there is no way to split one into the three components the SII asks for and dropping it silently would emit a document with no address at all. AND THE ADDRESS IS NOT OPTIONAL on 33, 34, 46, 52, 56 and 61: the SII accepts the ENVELOPE and then REJECTS the document whose `&lt;Receptor&gt;` carries no `GiroRecep`/`DirRecep`/`CmnaRecep`, with the folio already spent. So `giro`, `address.street` and `address.comuna` are resolved from this empresa's own earlier documents to the same RUT and, failing that, refused with `400 receptor_incomplete` before a folio is allocated. Three exceptions: a tipo 52 needs no `giro` (its receptor is often the emisor itself, whose own giro frequently exceeds 40); `emission_channel=sfg` also needs `address.city`, which the SII portal's own form demands; and 39/41 and a foreign 46 (`foreign: true`, or `55555555-5`) need none of them. |
| `items`              | DocumentItem\[]                                       | yes      |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `global_discounts`   | object\[]                                             | —        | The engine emits a single global discount line — the SII's `&lt;DscRcgGlobal&gt;` is one hard-coded `NroLinDR&gt;1` — so a second entry is refused with `400 invalid_field` before a folio is allocated, rather than dropped. MERCADO CHANNEL ONLY: on `emission_channel=sfg` it is refused with `422 global_discount_not_available_for_channel`, because the SII portal's emission form has no discount field at all — its `EFXP_PCT_DESC`/`EFXP_MNT_DESC` inputs are commented out in the captured form, and `items[].discount_percent` is refused there for the same reason. Fold the discount into `items[].unit_price` on that channel.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `references`         | DocumentReference\[]                                  | —        |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `dispatch`           | object                                                | —        | Required for tipo 52, and its `transfer_type` / `dispatch_type` are refused on any other tipo. Both emission channels emit a guía; they differ in which fields they can express. `destination` and `dispatch_type` are accepted on `emission_channel=mercado` (the engine writes them into the DTE's `IdDoc/TipoDespacho` and Transporte block) and refused on `emission_channel=sfg` with `422 dispatch_not_available_for_channel`, because the SII portal's guía form has nowhere to put them: it carries a single address — the receptor's, so put a differing one in `receptor.address` — and its only traslado select is the kind of movement, with no TipoDespacho input at all. The two channels also differ on amounts: `sfg` refuses a guía with any line priced at or below 0, or a zero total, with `422 sfg_guia_zero_amount` — the portal validates the guía with its factura validations, whatever the traslado kind — while `mercado` accepts one.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `withholding`        | object                                                | —        | Tipo 46 — you are the withholding agent.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `payment`            | object                                                | —        |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `totals`             | Totals + any                                          | —        |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `pdf`                | object                                                | —        |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `xml`                | object                                                | —        | The XML artifact shares the PDF's public-link mechanism on identical terms — it is the artifact the receptor's accounting system actually ingests, so gating it behind a key would force integrators to proxy a file we have already generated.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `notes`              | string                                                | —        |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `metadata`           | object                                                | —        | Up to 20 keys, ≤500 chars each. Stored and returned untouched; never sent to the SII.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `test`               | object                                                | —        | Test mode only. Sending this with a live key fails with `400 test_field_in_live_mode`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| **Responses**        |                                                       |          |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body            |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
| `201`     | The computed preview. Nothing was emitted and no folio was reserved.                                                                                                                                                                                                                                    | DocumentPreview |
| `400`     | Malformed or missing input.                                                                                                                                                                                                                                                                             | ErrorResponse   |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse   |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse   |
| `422`     | Well-formed but violates a domain rule — folios exhausted, acuse window closed.                                                                                                                                                                                                                         | ErrorResponse   |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse   |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse   |

## `GET /documents/previews/{preview_id}` [#get-documents-previews-preview-id]

**Retrieve a stored preview**

Returns what was computed, never a re-computation. A preview that has been emitted stays
readable with `emitted: true` and a `consumed_at`; an unconsumed one is gone an hour after
it was created and answers `404`.

```bash
curl -sS https://api.facturia.cl/v1/documents/previews/prev_01K2R9M3D8V5QW7N \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA"
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `preview_id`       | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body            |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
| `200`     | The preview.                                                                                                                                                                                                                                                                                            | DocumentPreview |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse   |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse   |
| `404`     | No such object under this key.                                                                                                                                                                                                                                                                          | ErrorResponse   |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse   |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse   |

## `GET /documents/{document_id}` [#get-documents-document-id]

**Retrieve a document**

One document: its lifecycle `status`, totals, `public_links` if any are live, and `rejection_reasons` if the SII refused it.

```bash
curl -sS https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA"
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document_id`      | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                                                                       |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`.                                           |
| `expand`           | query  | —        | string | Comma-separated. One or more of `xml`, `pdf_base64`, `events`, `references`, `received_document`. An unrecognised value is `400 invalid_field`. `received_document` is populated when this document was emitted in response to a supplier's — matched at emission by reference (tipo\_dte, folio) plus emisor RUT = receptor RUT, within the same empresa, and only when that match is unique (§5.4). |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `200`     | The document.                                                                                                                                                                                                                                                                                           | Document      |
| `400`     | Malformed or missing input.                                                                                                                                                                                                                                                                             | ErrorResponse |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse |
| `404`     | No such object under this key.                                                                                                                                                                                                                                                                          | ErrorResponse |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse |

## `GET /documents/{document_id}/pdf` [#get-documents-document-id-pdf]

**Download the PDF**

The document's rendered PDF (`?copy=original` or `cedible` where Ley 19.983 gives one). `409 artifact_not_ready` if the SII has not accepted the document yet — the representación impresa is rendered on acceptance, not before.

```bash
curl -sS https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N/pdf \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA"
```

**Parameters**

| Parameter          | In     | Required | Type                   | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| ------------------ | ------ | -------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document_id`      | path   | yes      | string                 |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `Facturia-Empresa` | header | —        | string                 | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `copy`             | query  | —        | `original` · `cedible` | Which printed copy to serve. `cedible` is available for facturas — tipo\_dte 33 and 34 (Ley 19.983 art. 1; Res. Ex. SII N°14/2005 §1°; Manual de Muestras Impresas §1.4). Any other type returns `422 cedible_not_available`. `cedible` does not exist AT ALL on an `emission_channel=sfg` empresa, on any tipo: the SII signs and proxies its own PDF for that channel, and its bytes carry no acuse-de-recibo box or CEDIBLE legend to serve as one. `copy=cedible` there returns `422 cedible_not_available_for_channel`; `copy=original` is unaffected. The two copies are two separate files: the original carries no acuse-de-recibo box and no CEDIBLE legend, the cedible copy carries both. `both` was withdrawn in wave 9 — the muestras manual allows exactly one page per file (p.12) — and now returns `400 invalid_field`, as does any other unrecognised value. `format` (`carta` \| `80mm`) was also withdrawn: no thermal layout exists and none was ever served. Supplying it returns `400 invalid_field`. **Omitting it** does not always mean `original`. The default is resolved in order: this document's own `pdf.cedible` (set at emission, §9.3) if it named one; else the empresa's `branding.cedible_by_default` (§7.6); else `original` — and never `cedible` on the SFG channel, regardless of either default. Send `?copy=` explicitly to override either default for one read. |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body            |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
| `200`     | The rendered PDF.                                                                                                                                                                                                                                                                                       | application/pdf |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse   |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse   |
| `404`     | No such object under this key.                                                                                                                                                                                                                                                                          | ErrorResponse   |
| `409`     | State conflict — idempotency reuse, duplicate external\_id, artifact not ready.                                                                                                                                                                                                                         | ErrorResponse   |
| `422`     | Well-formed but violates a domain rule — folios exhausted, acuse window closed.                                                                                                                                                                                                                         | ErrorResponse   |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse   |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse   |

## `GET /documents/{document_id}/xml` [#get-documents-document-id-xml]

**Download the signed XML exactly as sent to the SII**

The exact XML Facturia sent to the SII (or will send), for a caller that wants the wire bytes rather than the parsed object.

```bash
curl -sS https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N/xml \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA"
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document_id`      | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body            |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
| `200`     | The signed EnvioDTE / EnvioBOLETA XML (ISO-8859-1).                                                                                                                                                                                                                                                     | application/xml |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse   |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse   |
| `404`     | No such object under this key.                                                                                                                                                                                                                                                                          | ErrorResponse   |
| `409`     | State conflict — idempotency reuse, duplicate external\_id, artifact not ready.                                                                                                                                                                                                                         | ErrorResponse   |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse   |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse   |

## `GET /documents/{document_id}/events` [#get-documents-document-id-events]

**Lifecycle events for one document**

The document's own event history — every `document.*` webhook Facturia published for it, in order, independent of whether delivery succeeded.

```bash
curl -sS https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N/events \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA"
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document_id`      | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body                   |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
| `200`     | Events, oldest first.                                                                                                                                                                                                                                                                                   | lista de DocumentEvent |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse          |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse          |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse          |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse          |

## `POST /documents/{document_id}/retry` [#post-documents-document-id-retry]

**Retry a document in `failed`**

Reuses the already-assigned folio. Never creates a second document.

```bash
curl -sS -X POST https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N/retry \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA"
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document_id`      | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `200`     | The document, back in `queued`.                                                                                                                                                                                                                                                                         | Document      |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse |
| `409`     | State conflict — idempotency reuse, duplicate external\_id, artifact not ready.                                                                                                                                                                                                                         | ErrorResponse |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse |

## `POST /documents/{document_id}/send` [#post-documents-document-id-send]

**Email the document to the receptor**

`202` when THIS call created the send; `200` with the SAME job when an identical one
(same document, same addresses, same attachments) already exists — one email, one job id,
mirroring §10.2's "emitting the same preview twice returns the original document". Both
statuses carry the same body, so a client that only handles one of them is handling half
the endpoint.

```bash
curl -sS -X POST https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N/send \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"to":["pagos@andina.cl"],"attach":["pdf","xml"]}'
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document_id`      | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |
| `Idempotency-Key`  | header | —        | string | Client-generated key, unique per logical operation, retained 24h and scoped to (account, empresa, endpoint). Replays return the original response with `Facturia-Idempotent-Replay: true`. Same key + different body → `409`.                                                                                                                               |

**Body**

| Field         | Type             | Required | Notes                                                                                                                                                                                                                                                   |
| ------------- | ---------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `to`          | string\[]        | —        |                                                                                                                                                                                                                                                         |
| `attach`      | `pdf` · `xml`\[] | —        | Always the ORIGINAL copy of the PDF — never cedible, whatever this document's or the empresa's default says. §9.6: the cedible copy is an instrument for assigning the debt, not the invoice you send a customer to be paid.  Default: `["pdf","xml"]`. |
| **Responses** |                  |          |                                                                                                                                                                                                                                                         |

| Code      | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | Body          |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `200`     | An identical send already exists. The ORIGINAL job — no second email.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | SendJob       |
| `202`     | Queued for delivery.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | SendJob       |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | ErrorResponse |
| `402`     | `subscription_required` - this live act needs an active subscription for the EMPRESA the request names, and that empresa has none (enforced). The subscription is per empresa: another empresa on the same account is unaffected, and `error.details` carries `empresa`, `empresa_rut`, `empresa_name`, `account_plan`, `subscription_status`, `grace_until`, `blocked_by`, a `next` handoff and a `checkout_url` pointing at that empresa. Or `plan_limit_reached` - a plan quota is exhausted (declared, not yet enforced). Test mode is never gated on either. **ELIGIBILITY IS EVALUATED FIRST** (2026-09-04, #475). This refusal now arrives ONLY when the empresa is otherwise able to emit: while its checklist is unfinished, its `puesta en vivo` pending or the empresa suspended, the act is refused by `422 empresa_not_emitting` with the checklist handoff instead. So this `402` and `Empresa.capabilities.blocked_by` can no longer name two different next actions for one state — which they did, the object saying «sign the mandato» while the door said «pay». | ErrorResponse |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | ErrorResponse |
| `409`     | State conflict — idempotency reuse, duplicate external\_id, artifact not ready.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | ErrorResponse |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | ErrorResponse |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | ErrorResponse |

## `POST /documents/{document_id}/cesion` [#post-documents-document-id-cesion]

**Ask the SII whether this factura is cedible**

READ-ONLY (ticket #47). Queues a query against the SII's own registro
(`WSREGISTRORECLAMODTE.consultarDocDteCedible`) and caches the answer on the document's
`cesion` object. Nothing here cedes the invoice, builds an AEC, or writes to the Registro
de Cesión de Créditos — that operation takes no action code and cannot change SII state.

Under Ley 19.983 a factura becomes assignable when the receptor gives acuse de recibo, or
when eight días corridos pass without a reclamo; one declared as paid al contado never
does (Circular N°35 de 23.06.2017). Only the SII knows which of those applies, so this is
a report, never a computation.

`202` when this call queued the question, `200` when an identical one is already in
flight. Poll `GET /documents/\{document_id\}` for the answer; there is no webhook.

Accepts a `documents:read` key: the caller this exists for is a factoring integration,
which should not need one that can issue invoices.

In test mode the answer is simulated in-process against the empresa's simulated clock and
no SII socket is opened — `24` until eight days after acceptance, `25` after.

```bash
curl -sS -X POST https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N/cesion \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA" \
  -H "Idempotency-Key: $(uuidgen)"
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document_id`      | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |
| `Idempotency-Key`  | header | —        | string | Client-generated key, unique per logical operation, retained 24h and scoped to (account, empresa, endpoint). Replays return the original response with `Facturia-Idempotent-Replay: true`. Same key + different body → `409`.                                                                                                                               |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `200`     | A check against this same answer is already queued (or, in test mode, the simulated answer, already applied). The document, with its current `cesion`.                                                                                                                                                  | Document      |
| `202`     | Queued. The document, with `cesion` still showing the previously known answer — null throughout if this was the first check.                                                                                                                                                                            | Document      |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse |
| `409`     | State conflict — idempotency reuse, duplicate external\_id, artifact not ready.                                                                                                                                                                                                                         | ErrorResponse |
| `422`     | Well-formed but violates a domain rule — folios exhausted, acuse window closed.                                                                                                                                                                                                                         | ErrorResponse |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse |

## `POST /documents/{document_id}/cede` [#post-documents-document-id-cede]

**Cede this factura to a factoring company, registering it in the SII's RTC**

THE WRITE (ticket #60), unlike `POST …/cesion` above (a read). Assembles an Archivo
Electrónico de Cesión — the emisor's original signed DTE plus the terms of the transfer,
signed by the cedente — and uploads it to the SII's Registro Electrónico de Transferencia
de Crédito. A real, irreversible act.

Works the same regardless of channel (ticket #60, ruled 2026-09-06): the AEC carries the
emisor's original signed envelope verbatim, so it does not care whether the DTE was emitted
through `emission_channel=sfg` or `emission_channel=mercado`. `cesion_channel_unsupported`,
the code the old channel guard raised, is RETIRED from the catalogue.

`202` with a `job` when this call queued a NEW attempt; `200` with the SAME job when one
is already `queued`/`submitted`/`aec_generated` for this document (one attempt in flight
at a time). `GET /documents/\{document_id\}` carries the newest attempt's outcome under
`cesion.status`.

A RECEIPT IS NOT A REGISTRATION (ticket #69). The furthest the upload itself can take an
attempt is `submitted` — the SII answered «Envío recibido OK» and issued a TrackID. Its
validation happens afterwards, and a rejection is notified by e-mail to the cedente hours
later, so this API claims `confirmed` only when the registry's own
`wsRPETCConsulta.getEstEnvio` answers `EOK` («Envío Aceptado») for that TrackID. Webhooks
follow that exactly: `document.cesion_submitted` means «AEC recibido, anotación
pendiente», `document.cesion_confirmed` is the one to settle money on, and
`document.cesion_failed` covers a refusal, a fence, an answer nobody recognises, and a
registration that could never be confirmed.

`409 cesion_attempt_may_have_registered` when the newest attempt for this document had
already put the signed AEC on the wire when it stopped (ticket #76). Whether it registered
cannot be decided from here, so a second cesión is refused rather than risking the same
credit being assigned twice. `error.details` carries this system's own last known registry
answer for that attempt (`rtc_estado`, `rtc_track_id`) when one was ever recorded — reading
it costs a column, not a new SII call; when neither was ever recorded the details say so.

In test mode this settles in the same request (§4.1) — no socket opened, the attempt
lands `simulated`, and BOTH `document.cesion_submitted` and `document.cesion_confirmed`
fire, in that order, so the event a factoring integration acts on is exercisable in test.

Live submission is owner-gated, and since the 2026-09-06 ruling (R6) also gated per
empresa: the AEC assembly and the registry upload are built and checked against the SII's
own schema — the first live upload (2026-09-03) was accepted by the registry with a real
TrackID and then rejected at validation for a signature defect, since fixed. Opening it
needs BOTH `ALLOW_LIVE_CESION_SUBMITS` (an operator's own shell, never a deploy) AND the
ceding empresa's own connection reaching `onboarding_status=emitting`, `active`,
`ambiente=palena` and not a sandbox connection. A live attempt missing either one is
accepted and queued like any other and settles `failed` non-retryably, naming whichever
condition is missing.

```bash
curl -sS -X POST https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N/cede \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"cesionario":{},"ultimo_vencimiento":"…"}'
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document_id`      | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |
| `Idempotency-Key`  | header | —        | string | Client-generated key, unique per logical operation, retained 24h and scoped to (account, empresa, endpoint). Replays return the original response with `Facturia-Idempotent-Replay: true`. Same key + different body → `409`.                                                                                                                               |

**Body**

| Field                | Type    | Required | Notes                                                   |
| -------------------- | ------- | -------- | ------------------------------------------------------- |
| `cesionario`         | object  | yes      |                                                         |
| `monto`              | integer | —        | CLP, in `[1, total]`. Defaults to the document's total. |
| `ultimo_vencimiento` | string  | yes      |                                                         |
| `otras_condiciones`  | string  | —        |                                                         |
| `email_deudor`       | string  | —        |                                                         |
| `contacto`           | object  | —        |                                                         |
| **Responses**        |         |          |                                                         |

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `200`     | A cesión attempt was already in flight for this document. The same job.                                                                                                                                                                                                                                 | CesionJob     |
| `202`     | Queued.                                                                                                                                                                                                                                                                                                 | CesionJob     |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse |
| `409`     | State conflict — idempotency reuse, duplicate external\_id, artifact not ready.                                                                                                                                                                                                                         | ErrorResponse |
| `422`     | Well-formed but violates a domain rule — folios exhausted, acuse window closed.                                                                                                                                                                                                                         | ErrorResponse |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse |

## `POST /documents/{document_id}/credit_note` [#post-documents-document-id-credit-note]

**Emit a nota de crédito against this document**

There is no "delete an invoice" in Chile. `code: 1` annuls the referenced document,
`2` corrects text, `3` corrects amounts (supply `items` for the corrected values).

```bash
curl -sS -X POST https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N/credit_note \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"code":1,"reason":"content"}'
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document_id`      | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |
| `Idempotency-Key`  | header | —        | string | Client-generated key, unique per logical operation, retained 24h and scoped to (account, empresa, endpoint). Replays return the original response with `Facturia-Idempotent-Replay: true`. Same key + different body → `409`.                                                                                                                               |

**Body**

| Field         | Type            | Required | Notes |
| ------------- | --------------- | -------- | ----- |
| `code`        | `1` · `2` · `3` | yes      |       |
| `reason`      | string          | yes      |       |
| `items`       | DocumentItem\[] | —        |       |
| **Responses** |                 |          |       |

| Code      | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | Body          |
| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `201`     | The nota de crédito (tipo 61).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | Document      |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | ErrorResponse |
| `402`     | `subscription_required` - this live act needs an active subscription for the EMPRESA the request names, and that empresa has none (enforced). The subscription is per empresa: another empresa on the same account is unaffected, and `error.details` carries `empresa`, `empresa_rut`, `empresa_name`, `account_plan`, `subscription_status`, `grace_until`, `blocked_by`, a `next` handoff and a `checkout_url` pointing at that empresa. Or `plan_limit_reached` - a plan quota is exhausted (declared, not yet enforced). Test mode is never gated on either. **ELIGIBILITY IS EVALUATED FIRST** (2026-09-04, #475). This refusal now arrives ONLY when the empresa is otherwise able to emit: while its checklist is unfinished, its `puesta en vivo` pending or the empresa suspended, the act is refused by `422 empresa_not_emitting` with the checklist handoff instead. So this `402` and `Empresa.capabilities.blocked_by` can no longer name two different next actions for one state — which they did, the object saying «sign the mandato» while the door said «pay». | ErrorResponse |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | ErrorResponse |
| `422`     | Well-formed but violates a domain rule — folios exhausted, acuse window closed.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | ErrorResponse |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | ErrorResponse |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | ErrorResponse |

## `POST /documents/{document_id}/public_links` [#post-documents-document-id-public-links]

**Create or rotate public links for this document's artifacts**

Turns a public link on after the fact, or rotates an existing one (which invalidates the
previous URL). A link exposes exactly one artifact of one document — never the empresa's
other documents, never account data — and cannot be escalated into an API credential.

`cedible` (ticket #18 wave 10) is NOT in the default set: unlike `pdf`/`xml` it does not
exist for every document, so a caller who did not ask for it does not get one minted
silently — mirroring `?copy=` on `GET …/pdf`, which defaults to `original` rather than
guessing. Requesting it for a tipo outside 33/34 is `422 cedible_not_available`; requesting
it on an `emission_channel=sfg` empresa, on any tipo, is `422 cedible_not_available_for_channel`
(#48) — the SII proxies its own PDF for that channel and no cedible copy of it ever exists,
so this refuses the mint rather than handing back a `.cedible` link that could only ever
resolve to the non-cedible file.

```bash
curl -sS -X POST https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N/public_links \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"artifacts":["pdf","xml"]}'
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document_id`      | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |
| `Idempotency-Key`  | header | —        | string | Client-generated key, unique per logical operation, retained 24h and scoped to (account, empresa, endpoint). Replays return the original response with `Facturia-Idempotent-Replay: true`. Same key + different body → `409`.                                                                                                                               |

**Body**

| Field                | Type                         | Required | Notes                                                                                                                                                                                                                       |
| -------------------- | ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `artifacts`          | `pdf` · `xml` · `cedible`\[] | yes      | Default: `["pdf","xml"]`.                                                                                                                                                                                                   |
| `expires_in_days`    | integer,null                 | —        | Null means the link does not expire. Default: `90`.                                                                                                                                                                         |
| `expires_in_seconds` | integer,null                 | —        | The same lifetime in seconds, clamped to 30s–365d. WINS when both units are sent: days cannot express the ten-minute link an agent needs, and the shorter, more specific unit is the safer reading of an ambiguous request. |
| **Responses**        |                              |          |                                                                                                                                                                                                                             |

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `200`     | The minted links. NOT the document: the secret half of each URL is stored hashed, so this response is the only place a working URL ever exists. Capture it.                                                                                                                                             | PublicLinks   |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse |
| `409`     | State conflict — idempotency reuse, duplicate external\_id, artifact not ready.                                                                                                                                                                                                                         | ErrorResponse |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse |

## `DELETE /documents/{document_id}/public_links` [#delete-documents-document-id-public-links]

**Revoke every public link for this document**

Revoke every live public link minted for the document. Already-cached copies of the URL keep working until they expire; this only stops new fetches.

```bash
curl -sS -X DELETE https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N/public_links \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA"
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `document_id`      | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `204`     | Revoked. Existing URLs stop resolving immediately.                                                                                                                                                                                                                                                      | —             |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse |
