Tax
RCV, characterisation, the F29 proposal and filing it, expenses and tipo-46 suggestions.
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.
| Method | Path | What it does |
|---|---|---|
GET | /tax/purchases | RCV — registro de compras |
GET | /tax/sales | RCV — registro de ventas |
GET | /tax/summary | Aggregated RCV totals for a period (the F29 inputs) |
POST | /tax/sync | Force an RCV resync (async) |
POST | /tax/purchases/characterize | Caracterizar up to 500 purchase entries in one call |
POST | /tax/purchases/{entry_id}/characterize | Caracterizar one purchase entry (writes to the SII registry) |
POST | /tax/purchases/{entry_id}/characterize/revert | Undo the last settled caracterización on a purchase |
POST | /tax/purchases/{entry_id}/estado_contable | Move an entry between REGISTRO / PENDIENTE / NO_INCLUIR |
GET | /tax/f29/proposals | List the periods that have a computed propuesta |
GET | /tax/f29/proposals/{period} | Computed F29 propuesta for a period |
GET | /tax/f29/proposals/{period}/upload_file | Download the SII-format upload .txt for this proposal |
POST | /tax/f29/proposals/{period}/public_links | Mint a no-auth link to the propuesta's upload .txt |
DELETE | /tax/f29/proposals/{period}/public_links | Revoke every public link for this propuesta |
POST | /tax/f29/proposals/{period}/recompute | Recompute the proposal, optionally overriding codes |
GET | /tax/f29/filings | List F29 filings |
POST | /tax/f29/filings | File the F29 for a period (async job) |
GET | /tax/f29/filings/{filing_id} | Retrieve a filing |
GET | /tax/expenses | List ingested foreign-currency charges |
POST | /tax/expenses | Ingest a charge that may require a tipo-46 factura de compra |
GET | /tax/suggestions | List tax suggestions |
GET | /tax/suggestions/{suggestion_id} | Retrieve a suggestion |
POST | /tax/suggestions/{suggestion_id}/confirm | Act on a suggestion (for emit_46, emits the document) |
POST | /tax/suggestions/{suggestion_id}/dismiss | Dismiss a suggestion |
GET /tax/purchases
RCV — registro de compras
The purchases ledger (Registro de Compras) synced from the SII, filterable by period, with each entry's estado_contable and any characterize outcome.
curl -sS https://api.facturia.cl/v1/tax/purchases \
-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. |
period | query | — | Period | Tax period, YYYY-MM, America/Santiago. |
estado_contable | query | — | REGISTRO · PENDIENTE · NO_INCLUIR · RECLAMADO | |
tipo_dte | query | — | 33 · 34 · 39 · 41 · 46 · 52 · 56 · 61 | |
counterparty_rut | query | — | Rut |
Responses
| Code | Meaning | Body |
|---|---|---|
200 | RCV purchase entries, with sync freshness metadata. | RcvEntryList |
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 |
GET /tax/sales
RCV — registro de ventas
The sales ledger (Registro de Ventas) synced from the SII, filterable by period.
curl -sS https://api.facturia.cl/v1/tax/sales \
-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. |
period | query | — | Period | Tax period, YYYY-MM, America/Santiago. |
tipo_dte | query | — | 33 · 34 · 39 · 41 · 46 · 52 · 56 · 61 | |
counterparty_rut | query | — | Rut |
Responses
| Code | Meaning | Body |
|---|---|---|
200 | RCV sales entries. | RcvEntryList |
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 |
GET /tax/summary
Aggregated RCV totals for a period (the F29 inputs)
Period totals across purchases and sales — the numbers an F29 proposal is built from, before any characterization is applied.
curl -sS https://api.facturia.cl/v1/tax/summary \
-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. |
period | query | yes | Period |
Responses
| Code | Meaning | Body |
|---|---|---|
200 | Aggregation by direction and doc type. | TaxSummary |
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 /tax/sync
Force an RCV resync (async)
Trigger a fresh pull of the purchases and sales ledgers from the SII for the empresa, for ONE
period. Returns a job (type: rcv_sync) to poll on GET /jobs/\{job_id\}; the ledger updates
only once it succeeds, and result then carries what was read.
period defaults to the previous month (America/Santiago), and the job always reports the
period it read in result.period. The daily sync reads the last three months, and the first
sweep after an empresa's first successful sync backfills the twelve months before that; anything
older has NEVER been read unless somebody asked for it here — a sync.last_synced_at of null
on GET /tax/sales?period=… is how you can tell. To reach further back, call this once per
period; the bucket is 10 requests per minute per empresa.
Force means force. A call while a sync for the same period is still queued or running attaches to that job rather than queueing a second one; a call after it has finished queues a fresh read, whatever the daily sync did this morning.
curl -sS -X POST https://api.facturia.cl/v1/tax/sync \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"period":"2026-07"}'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 |
|---|---|---|---|
period | Period | — | Tax period YYYY-MM (America/Santiago). E.g.: "2026-07". |
| Responses |
| Code | Meaning | Body |
|---|---|---|
202 | Sync job accepted. | Job |
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 /tax/purchases/characterize
Caracterizar up to 500 purchase entries in one call
Characterize purchase-ledger entries in bulk (entry_ids[] plus the shared estado_contable/tax treatment), for the common case of clearing a whole period at once.
curl -sS -X POST https://api.facturia.cl/v1/tax/purchases/characterize \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"entries":[{"id":"rcv_01K2RB7Q2M4X","tipo_compra":"del_giro"}]}'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 |
|---|---|---|---|
entries | object + Characterization[] | yes | |
| Responses |
| Code | Meaning | Body |
|---|---|---|
200 | Per-entry results. | object |
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 /tax/purchases/{entry_id}/characterize
Caracterizar one purchase entry (writes to the SII registry)
Characterize one purchase-ledger entry — its estado_contable and whether its IVA is recoverable — overriding the SII's own proposal where the empresa's own accounting disagrees.
curl -sS -X POST https://api.facturia.cl/v1/tax/purchases/rcv_01K2RB7Q2M4X/characterize \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"tipo_compra":"del_giro","iva_uso_comun":true}'Parameters
| Parameter | In | Required | Type | Notes |
|---|---|---|---|---|
entry_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 |
|---|---|---|---|
tipo_compra | del_giro · supermercado · activo_fijo · iva_uso_comun · no_recuperable | — | |
iva_uso_comun | boolean | — | |
iva_no_recuperable_code | integer,null | — | SII reason code, required when tipo_compra is no_recuperable. |
| Responses |
| Code | Meaning | Body |
|---|---|---|
200 | The updated entry. | RcvEntry |
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 |
POST /tax/purchases/{entry_id}/characterize/revert
Undo the last settled caracterización on a purchase
Queues a NEW caracterización restoring the previous_tipo_compra recorded on the last
settled action for this purchase, linked to it by reverts. It does not edit or delete the
original: a write to a tax register that happened, happened, and its row is the evidence.
An undo of a write to the SII is itself a write to the SII, so it passes the identical
opt-in gate and the identical confirmation two-step. 409 characterization_nothing_to_revert
when no settled action exists, or when the last one recorded no previous value.
Reverting to no_recuperable needs an iva_no_recuperable_code: the SII does not accept one
without a reason, and the reason the earlier characterization used is only recoverable when a
prior action on the same document recorded it.
curl -sS -X POST https://api.facturia.cl/v1/tax/purchases/rcv_01K2RB7Q2M4X/characterize/revert \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"iva_no_recuperable_code":1,"confirmation_id":"…"}'Parameters
| Parameter | In | Required | Type | Notes |
|---|---|---|---|---|
entry_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 |
|---|---|---|---|
iva_no_recuperable_code | 1 · 2 · 3 · 4 · 9 | — | Required only when the value being restored is no_recuperable. |
confirmation_id | string | — | |
| Responses |
| Code | Meaning | Body |
|---|---|---|
202 | The queued revert action. | CharacterizationAction |
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 /tax/purchases/{entry_id}/estado_contable
Move an entry between REGISTRO / PENDIENTE / NO_INCLUIR
Records a LOCAL bookkeeping estado for the purchase. It is written to
estado_contable_override and never over estado_contable, which belongs to the SII's own
register and is refreshed by every sync.
The F29 propuesta ignores the override unless the empresa's
honor_estado_contable_override automation setting is on; the response's
estado_contable_effective says which value the propuesta will use. Every write is recorded
with the key that made it and the SII value it did not replace.
Changing an entry's caracterización at the SII is a different act, with a different
endpoint (POST /tax/purchases/\{entry_id\}/characterize).
curl -sS -X POST https://api.facturia.cl/v1/tax/purchases/rcv_01K2RB7Q2M4X/estado_contable \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"estado_contable":"REGISTRO"}'Parameters
| Parameter | In | Required | Type | Notes |
|---|---|---|---|---|
entry_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 |
|---|---|---|---|
estado_contable | REGISTRO · PENDIENTE · NO_INCLUIR · RECLAMADO | yes | |
| Responses |
| Code | Meaning | Body |
|---|---|---|
200 | The updated entry. | RcvEntry |
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 |
GET /tax/f29/proposals
List the periods that have a computed propuesta
A SPEC ADDITION over §12.3, which documents only the per-period read. Without it a caller
reconciling a year, or a dashboard drawing twelve months, has to guess which periods exist
and probe each one — twelve requests, eleven of them 404.
The rows omit validation and filing_id: both are one query per proposal, and a caller
scanning a year is asking "which months are computed", which status already answers. Read
the single propuesta for those.
curl -sS https://api.facturia.cl/v1/tax/f29/proposals \
-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. |
Responses
| Code | Meaning | Body |
|---|---|---|
200 | A list of F29 propuestas, newest period first. | lista de F29Proposal |
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 |
GET /tax/f29/proposals/{period}
Computed F29 propuesta for a period
Computed by Facturia from the synced RCV plus the empresa's PPM and remanente parameters. The SII pre-fills its own F29 for its own portal but publishes no API for it.
curl -sS https://api.facturia.cl/v1/tax/f29/proposals/2026-07 \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA"Parameters
| Parameter | In | Required | Type | Notes |
|---|---|---|---|---|
period | path | yes | Period | |
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 proposal. | F29Proposal |
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 /tax/f29/proposals/{period}/upload_file
Download the SII-format upload .txt for this proposal
The SII's own upload-ready .txt for this F29 period, generated from the same proposal GET /tax/f29/proposals/\{period\} returns.
curl -sS https://api.facturia.cl/v1/tax/f29/proposals/2026-07/upload_file \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA"Parameters
| Parameter | In | Required | Type | Notes |
|---|---|---|---|---|
period | path | yes | Period | |
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 | Fixed-format upload file, ready to submit manually if you prefer. | text/plain |
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 /tax/f29/proposals/{period}/public_links
Mint a no-auth link to the propuesta's upload .txt
upload_file_url needs a bearer key, which makes it useless as an MCP resource_link —
most MCP hosts cannot attach the caller's OAuth token when dereferencing one. This mints the
same kind of signed, unguessable, expiring link a document's artifacts get (§9.6), serving
the identical ISO-8859-1 bytes.
tax:read, not tax:write: minting a link publishes nothing and changes no tax position.
curl -sS -X POST https://api.facturia.cl/v1/tax/f29/proposals/2026-07/public_links \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA" \
-H "Content-Type: application/json" \
-d '{"artifacts":["upload_file"],"expires_in_days":90}'Parameters
| Parameter | In | Required | Type | Notes |
|---|---|---|---|---|
period | path | yes | Period | |
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 |
|---|---|---|---|
artifacts | upload_file[] | — | Default: ["upload_file"]. |
expires_in_days | integer,null | — | Default: 90. |
expires_in_seconds | integer,null | — | Clamped to 30s–365d. Wins when both units are sent. |
| Responses |
| Code | Meaning | Body |
|---|---|---|
200 | The minted link. Capture it — the secret half is stored hashed. | PublicLinks |
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 |
DELETE /tax/f29/proposals/{period}/public_links
Revoke every public link for this propuesta
Revoke every live public link minted for this F29 proposal's upload file.
curl -sS -X DELETE https://api.facturia.cl/v1/tax/f29/proposals/2026-07/public_links \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA"Parameters
| Parameter | In | Required | Type | Notes |
|---|---|---|---|---|
period | path | yes | Period | |
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 |
POST /tax/f29/proposals/{period}/recompute
Recompute the proposal, optionally overriding codes
Rebuild the F29 proposal from the ledgers and any characterizations recorded since it was last computed. Does not file anything with the SII.
curl -sS -X POST https://api.facturia.cl/v1/tax/f29/proposals/2026-07/recompute \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA" \
-H "Content-Type: application/json" \
-d '{"overrides":[]}'Parameters
| Parameter | In | Required | Type | Notes |
|---|---|---|---|---|
period | path | yes | Period | |
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 |
|---|---|---|---|
overrides | object[] | — | |
| Responses |
| Code | Meaning | Body |
|---|---|---|
200 | The recomputed proposal. | F29Proposal |
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 |
GET /tax/f29/filings
List F29 filings
F29 filings recorded for the empresa, newest first, each naming the period and the proposal it was filed from.
curl -sS https://api.facturia.cl/v1/tax/f29/filings \
-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. |
period[gte] | query | — | string |
Responses
| Code | Meaning | Body |
|---|---|---|
200 | A list of filings. | lista de F29Filing |
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 /tax/f29/filings
File the F29 for a period (async job)
There is no SII webservice for filing an F29. Facturia automates the SII "Upload" flow —
a certificate-authenticated session submitting a fixed-format .txt — and models it as a job.
confirm_total_payable must equal the proposal's figure.
curl -sS -X POST https://api.facturia.cl/v1/tax/f29/filings \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"period":"2026-07","confirm_total_payable":1373000}'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 |
|---|---|---|---|
period | Period | yes | Tax period YYYY-MM (America/Santiago). E.g.: "2026-07". |
proposal_id | string | — | |
confirm_total_payable | integer | yes | Guard against filing the wrong number. Must match the proposal. |
| Responses |
| Code | Meaning | Body |
|---|---|---|
202 | Filing accepted and queued. | F29Filing |
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 /tax/f29/filings/{filing_id}
Retrieve a filing
One F29 filing: the period, the filed totals, and the SII's own acknowledgment if one was captured.
curl -sS https://api.facturia.cl/v1/tax/f29/filings/f29fil_01K2RD9K3M8T \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA"Parameters
| Parameter | In | Required | Type | Notes |
|---|---|---|---|---|
filing_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 filing. | F29Filing |
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 /tax/expenses
List ingested foreign-currency charges
Expense-ledger entries imported from a connected bank or accounting feed, filterable by period.
curl -sS https://api.facturia.cl/v1/tax/expenses \
-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. |
period | query | — | Period | Tax period, YYYY-MM, America/Santiago. |
Responses
| Code | Meaning | Body |
|---|---|---|
200 | A list of expenses. | lista de ExpenseCreateRequest + object |
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 /tax/expenses
Ingest a charge that may require a tipo-46 factura de compra
Import expense-ledger entries directly (outside a connections sync), for a source the empresa does not have an automatic feed for yet.
curl -sS -X POST https://api.facturia.cl/v1/tax/expenses \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"provider":"fintoc","amount_original":1050,"currency":"USD","date":"2026-07-31"}'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 |
|---|---|---|---|
provider | object | yes | |
description | string | — | |
amount_original | number | yes | |
currency | string | yes | E.g.: "USD". |
date | string | yes | |
fx_rate | number | — | REQUIRED whenever currency is not CLP; omitting it returns 400 fx_rate_required. Facturia never invents a rate — it sets the peso base of a tax document. |
fx_source | card_rate · sii_observado · custom | — | card_rate (the settlement rate the issuer actually applied) is the documented recommendation. CAVEAT: which rate is definitively correct for tipo 46 on foreign digital services is under review with an accountant and is not settled by a citable ruling; the value you send is stored verbatim and shown on the document. |
external_id | string | — | |
| Responses |
| Code | Meaning | Body |
|---|---|---|
201 | The stored expense; a suggestion may follow asynchronously. | Expense |
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 |
GET /tax/suggestions
List tax suggestions
Categorization suggestions Facturia derived from imported statements and expenses, awaiting a confirm or dismiss.
curl -sS https://api.facturia.cl/v1/tax/suggestions \
-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. |
type | query | — | emit_46 · missing_characterization · folios_low · unclaimed_credit | |
status | query | — | open · confirmed · auto_confirmed · dismissed · expired | |
period | query | — | Period | Tax period, YYYY-MM, America/Santiago. |
Responses
| Code | Meaning | Body |
|---|---|---|
200 | A list of suggestions. | lista de Suggestion |
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 |
GET /tax/suggestions/{suggestion_id}
Retrieve a suggestion
One suggestion: what it proposes, and the evidence (matching entries, prior confirmations) it was derived from.
curl -sS https://api.facturia.cl/v1/tax/suggestions/sug_01K2RE2X7Q9V \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA"Parameters
| Parameter | In | Required | Type | Notes |
|---|---|---|---|---|
suggestion_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 suggestion. | Suggestion |
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 /tax/suggestions/{suggestion_id}/confirm
Act on a suggestion (for emit_46, emits the document)
Accept a suggestion, applying its proposed categorization to the entries it names.
curl -sS -X POST https://api.facturia.cl/v1/tax/suggestions/sug_01K2RE2X7Q9V/confirm \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA" \
-H "Idempotency-Key: $(uuidgen)"Parameters
| Parameter | In | Required | Type | Notes |
|---|---|---|---|---|
suggestion_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 |
|---|---|---|
201 | The suggestion, with the resulting document when one was emitted. | object |
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 |
POST /tax/suggestions/{suggestion_id}/dismiss
Dismiss a suggestion
Reject a suggestion without applying it. Facturia does not re-suggest the identical categorization for the same entries.
curl -sS -X POST https://api.facturia.cl/v1/tax/suggestions/sug_01K2RE2X7Q9V/dismiss \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Facturia-Empresa: $EMPRESA" \
-H "Content-Type: application/json" \
-d '{"reason":"not_digital_service","note":"…"}'Parameters
| Parameter | In | Required | Type | Notes |
|---|---|---|---|---|
suggestion_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. |
Body
| Field | Type | Required | Notes |
|---|---|---|---|
reason | not_digital_service · already_declared · not_applicable · other | — | |
note | string | — | |
| Responses |
| Code | Meaning | Body |
|---|---|---|
200 | The dismissed suggestion. | Suggestion |
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 |