# Create documents (/en/docs/emision)

## The minimal issue call [#the-minimal-issue-call]

The point of storing the emisor profile on the empresa is that a factura — Chile's electronic
invoice — is three fields.

The receptor carries its `giro` and `address` because the SII will not file a factura without them: it accepts the ENVELOPE and then refuses the DOCUMENT, and the folio is spent either way. Once you have invoiced a RUT once, `receptor: {"rut": "…"}` on its own is enough — we fill the rest from your own earlier document to that RUT. When there is no earlier one, you get `400 receptor_incomplete` naming the exact fields, before any folio is allocated. Boletas (39/41) and a foreign factura de compra (46) never need them.

#### curl

```bash
curl -sS 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,
    "receptor": {
      "rut": "76543212-K",
      "giro": "Venta al por mayor de alimentos",
      "address": { "street": "Los Militares 5001, of. 302", "comuna": "Las Condes", "city": "Santiago" }
    },
    "items": [
      { "description": "Desarrollo a medida — agosto", "quantity": 1, "unit_price": 2400000 }
    ]
  }'
```

#### JavaScript

```js
const res = await fetch('https://api.facturia.cl/v1/documents', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.FACTURIA_KEY}`,
    'Facturia-Empresa': process.env.EMPRESA,
    'Idempotency-Key': crypto.randomUUID(),
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    tipo_dte: 33,
    receptor: {
      rut: '76543212-K',
      giro: 'Venta al por mayor de alimentos',
      address: { street: 'Los Militares 5001, of. 302', comuna: 'Las Condes', city: 'Santiago' },
    },
    items: [{ description: 'Desarrollo a medida — agosto', quantity: 1, unit_price: 2400000 }],
  }),
});

if (!res.ok) {
  const { error } = await res.json();
  throw new Error(`${error.code}: ${error.message} (${error.request_id})`);
}

const documento = await res.json();
```

### What we fill in for you [#what-we-fill-in-for-you]

| Field                                                                                                   | Where it comes from                                                                                                                                                                               |
| ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Emisor block — RUT (the tax id every Chilean business has), razón social, giro, address, comuna, acteco | the empresa profile                                                                                                                                                                               |
| `folio`                                                                                                 | the next folio from the CAF active for this type — a folio is the pre-authorised sequential number a document must carry, and a CAF is the block of them signed by the SII, Chile's tax authority |
| `issue_date`                                                                                            | today in America/Santiago                                                                                                                                                                         |
| Razón social, giro, address and comuna of the receptor                                                  | the empresa's address book, otherwise the SII's taxpayer registry, resolved by RUT                                                                                                                |
| `totals`                                                                                                | calculated from `items` under the tax rules of the type                                                                                                                                           |
| `payment_terms`, `currency`, `indicators`                                                               | sensible defaults (`contado`, CLP)                                                                                                                                                                |

If the receptor cannot be resolved and the type requires those fields, you get `400 receptor_incomplete`
naming exactly which ones to send — never a silent SII rejection three minutes later.

## The full issue call [#the-full-issue-call]

Everything the SII lets you say, said explicitly.

```bash
curl -sS 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,
    "external_id": "order-8842",
    "issue_date": "2026-08-14",
    "prices_include_tax": false,
    "receptor": {
      "rut": "76543212-K",
      "legal_name": "Comercial Andina Ltda.",
      "giro": "Venta al por mayor de alimentos",
      "address": { "street": "Los Militares 5001, of. 302", "comuna": "Las Condes", "city": "Santiago" },
      "contact": "pagos@andina.cl",
      "email_document_to": ["pagos@andina.cl", "gerencia@andina.cl"]
    },
    "items": [
      {
        "description": "Licencia plataforma — plan Enterprise",
        "detail": "Periodo 2026-08-01 a 2026-08-31",
        "quantity": 12, "unit": "UN", "unit_price": 180000,
        "discount_percent": 5,
        "item_code": { "type": "INT1", "value": "PLAT-ENT" }
      },
      { "description": "Servicio exento de capacitación", "quantity": 1, "unit_price": 300000, "exempt": true }
    ],
    "global_discounts": [ { "type": "percent", "value": 2, "applies_to": "afecto", "reason": "Acuerdo comercial" } ],
    "references": [
      { "tipo_dte": 801, "folio": "OC-99213", "date": "2026-08-01", "code": null, "reason": "Orden de compra" }
    ],
    "payment": { "terms": "credito", "due_date": "2026-09-13", "method": "transferencia" },
    "totals": { "net": 2352000, "iva": 446880, "exempt": 300000, "total": 3098880 },
    "pdf": { "format": "carta", "cedible": true, "public": true },
    "xml": { "public": true },
    "notes": "Gracias por su compra.",
    "metadata": { "crm_deal": "D-1182", "cost_center": "LATAM" }
  }'
```

### The four fields worth understanding [#the-four-fields-worth-understanding]

> **Trap — prices_include_tax is where the 19% bug comes from**
>
> The default depends on the type: `true` for boletas (39/41, the receipt a consumer gets), `false` for
> everything else. Set it explicitly and we normalise in either direction.
>
> It is the number-one source of 19% errors in Chilean invoicing. That it is a named field instead of an
> implicit convention is deliberate: if your system stores gross prices and you issue a factura, say so.
>
> Normalisation is not symmetric. On a factura (33/34/56/61/46) the SII's `<PrcItem>`/`<MontoItem>` is
> always NET (`DTE_v10.xsd`: net unless `MntBruto` is present, which we never send), so
> `prices_include_tax: true` there normalises DOWNWARD at the door — the `items` we return, the PDF and
> the `<PrcItem>` all end up net (`11990` → `10075.6303`), and the total can land one peso away from the
> gross you quoted. On a boleta (39/41), whose `MontoItem` is gross by schema, the price stays gross
> whatever `prices_include_tax` says.

* **`totals` is optional, and when it is present it is an assertion.** If our calculation differs by
  even one peso, you get `422 totals_mismatch` with both figures and nothing is issued. A financial
  system should always send it.
* **`totals.other_taxes`** is 0 except on a tipo 46 with `withholding`, where it carries the retención
  as a NEGATIVE number (for example `-1891` when the IVA — Chile's VAT — withheld is `1891`) — the only
  way for `total = net + exempt + iva + other_taxes` to stay true whether or not tax is withheld.
* **`global_discounts` takes at most one entry.** The SII's `<DscRcgGlobal>` is a single `NroLinDR>1`,
  so a second entry is refused with `400 invalid_field` before any folio is reserved — merge them into
  one, or push the rest into `items[].discount_percent`.
* **Discounts belong to the `mercado` channel.** On an empresa with `emission_channel=sfg` both are
  refused at the door: `global_discounts` with `422 global_discount_not_available_for_channel`, and any
  `items[].discount_percent` greater than 0 with `422 line_discount_not_available_for_channel`, naming
  the line. The SII portal's emission form has no discount field we have ever captured — in the captured
  form both the per-line "% Desc" column and its `EFXP_PCT_DESC`/`EFXP_MNT_DESC` entries are commented
  out — so a discount accepted there would be a discount the portal never sees: we would quote you
  `neto 80.000 / total 95.200` and the SII would sign `neto 100.000 / total 119.000`. It is refused
  rather than silently dropped, because you would be charging your customer the difference on a document
  that only a nota de crédito can undo. Fold the discount into `unit_price`, or issue through
  `emission_channel=mercado`. A `discount_percent` of `0` is accepted on both channels: it is exactly
  what the portal would issue.
* **`references` with `code: 1|2|3`** are the SII's reference codes (1 = voids the referenced document,
  2 = corrects text, 3 = corrects amounts). References to documents that are not DTEs (*documentos
  tributarios electrónicos*, Chile's electronic tax documents) — a purchase order, a contract — use the
  SII's `tipo_dte` codes in the 800 range and omit `code`. `references[].date` takes the document's
  `issue_date` when omitted; `references[].folio` accepts a number or a string, and a number is
  converted to its decimal string (`<FolioRef>` is `xs:string` in the SII schema).
* **`metadata`** is an arbitrary string map (≤ 20 keys, ≤ 500 characters each) that we store and hand
  back untouched. It never reaches the SII.
* **`email_document_to`** sends the PDF and the XML to the receptor when the document reaches
  `accepted`.

## The document object [#the-document-object]

```json
{
  "id": "doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N",
  "object": "document",
  "mode": "live",
  "empresa": { "id": "emp_01K2R6ZC4P8QW1VN7T3MHDY9EK", "rut": "77928532-4" },
  "external_id": "order-8842",
  "tipo_dte": 33,
  "folio": 412,
  "issue_date": "2026-08-14",
  "status": "accepted",
  "receptor": { "rut": "76543212-K", "legal_name": "Comercial Andina Ltda." },
  "items": [ { "description": "Licencia plataforma — plan Enterprise", "quantity": 12, "unit_price": 180000, "amount": 2052000 } ],
  "totals": { "net": 2352000, "iva": 446880, "exempt": 300000, "other_taxes": 0, "total": 3098880 },
  "references": [],
  "pdf_url": "https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N/pdf",
  "xml_url": "https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N/xml",
  "sii": {
    "environment": "produccion",
    "track_id": "0252083112",
    "estado": "DOK",
    "glosa": "Documento Recibido por el SII, datos coinciden",
    "err_code": "0",
    "num_atencion": "8812394",
    "received_at": "2026-08-14T13:06:55Z",
    "last_checked_at": "2026-08-14T13:07:02Z"
  },
  "rejection_reasons": [],
  "metadata": { "crm_deal": "D-1182" },
  "created_at": "2026-08-14T13:04:11Z",
  "accepted_at": "2026-08-14T13:06:55Z"
}
```

## Reading documents [#reading-documents]

```bash
# Listar, del más nuevo al más antiguo, con filtros
curl -G https://api.facturia.cl/v1/documents \
  -H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
  -d status=accepted -d tipo_dte=33 \
  -d "issue_date[gte]=2026-08-01" -d "issue_date[lte]=2026-08-31" \
  -d limit=50

# Un documento
curl https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N \
  -H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA"

# Por folio (los folios son únicos por empresa+tipo, así que es una búsqueda legítima)
curl -G https://api.facturia.cl/v1/documents \
  -H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
  -d tipo_dte=33 -d folio=412
```

Filters: `status`, `tipo_dte`, `folio`, `receptor_rut`, `external_id`, `issue_date[gte|lte]`,
`created_at[gte|lte]`. The `mode` is implicit in the key.

An unrecognised `status` returns `400 invalid_field` naming the seven valid values — an empty page would
read as "you have none of those", which is a different answer and a far more confusing one.

**Every filter, `status` included, is applied in the query.** A filtered page is a complete page, and
`has_more` / `next_cursor` mean what they say: page until `has_more` is false and you have the whole
set.

## Expansion [#expansion]

Documents return `pdf_url` and `xml_url` by default. To avoid a second round trip:

```bash
curl "https://api.facturia.cl/v1/documents/doc_01K2R7Q4XW9M3B8ZC5YHTVJD6N?expand=xml,pdf_base64,events" \
  -H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA"
```

`expand` takes a comma-separated list: `xml` (an inline string), `pdf_base64`, `events`, `references`,
`received_document` (on documents issued in response to a received one). An unrecognised value is
`400 invalid_field` with the list this resource does accept — not a silent 200 in which you cannot tell
a typo from an empty result.

**On a listing the vocabulary is narrower.** `GET /v1/documents?expand=…` accepts `events`,
`references` and `received_document`; `xml` and `pdf_base64` are a `400` there and exist only on
`GET /v1/documents/{document_id}`. Each of the excluded ones embeds a whole artifact per row, so a page
of a hundred documents would mean a hundred file reads in a single response.

`received_document` is resolved **at issue time**: the issued document must reference the `tipo_dte` and
`folio` of the received one, and the emisor RUT of the received document must be the receptor RUT of the
issued one, within the same empresa. If two match, the link is left `null` — the wrong antecedent is an
assertion, and an absence is not.

**The document object carries no public links.** Not on a read, not on a listing, not in a webhook: the
URL with its `?k=` secret appears exactly once, inside the `public_links` object of the response that
mints it — the issue call that asked for `pdf: { "public": true }` / `xml: { "public": true }`, or
`POST /v1/documents/{document_id}/public_links`. We store the secret hashed, the same as an API key, so
no read can reconstruct it. See
[Artifacts and public links](/en/docs/emision/artefactos#enlaces-publicos).

- [Document types](/en/docs/emision/tipos): The eight types, their type-specific blocks and references.

- [Previews](/en/docs/emision/previews): Full pricing and validation without spending a folio.

- [Statuses](/en/docs/emision/estados): The map of DOK, DNK, RCT and the seven public statuses.
