API reference
Every /v1 endpoint, generated from the OpenAPI 3.1 document we publish alongside the specification.
This reference is generated from public-api-openapi.yaml on every build, so it cannot drift from the contract. The prose specification governs wherever the two disagree.
https://api.facturia.cl/v1TLS 1.2+ only. No unversioned root, no unencrypted port. Every response carries Facturia-Request-Id; quote it in support.
The raw contract
This page is the human reading of it. The OpenAPI 3.1 document it comes from, version 1.0.0, is published verbatim to generate clients from:
| File | What it is |
|---|---|
/openapi.yaml | The /v1 contract, byte for byte the one we review. |
/openapi.json | The same document in JSON, generated from the YAML on every build. |
/openapi-bootstrap.yaml | The cold start: creating the account and minting the first key. |
/openapi-bootstrap.json | The same thing, in JSON. |
There are two documents because there are two surfaces: /v1 authenticates with an sk_ key, and a freshly created account has none yet. The cold start answers on a different base URL, with an account session instead of a key, so folding it into the same file would declare URLs and credentials that do not exist. Generate a client from the second one to get the key, and one from the first to use the product.
No path reaches the published file without having been probed against the real router: if the contract declared an endpoint the API does not mount, this site’s build fails before publishing it.
Generate a typed client
We publish no npm or pip package: the API is HTTP and nothing else, and an in-house SDK is a layer that lags behind the contract. What we do publish is the contract, and a typed client comes out of it in one line. There are two commands because there are two documents: the cold-start one gets you the key, the /v1 one uses the product.
TypeScript
npx openapi-typescript https://docs.facturia.cl/openapi-bootstrap.yaml -o bootstrap.d.ts
npx openapi-typescript https://docs.facturia.cl/openapi.yaml -o facturia.d.tsIt emits types only, no runtime. For calls, fetch with those types is enough; if you would rather have a client with methods, openapi-fetch consumes the same facturia.d.ts.
Python
pipx run openapi-python-client generate --url https://docs.facturia.cl/openapi-bootstrap.yaml
pipx run openapi-python-client generate --url https://docs.facturia.cl/openapi.yaml
# uvx openapi-python-client generate --url … # lo mismo, si usas uv / same thing, with uvBoth documents go through both Python generators whole: openapi-python-client emits all 11 cold-start operations and all 122 /v1 ones without dropping a single response or schema, and openapi-generator-cli -g python finishes on both without an exception. It was not so until 2026-09-07 — the envelope's nullable data clashed with each operation's typed data and all five /account/* responses came out untyped, the one that hands over data.api_key.secret included; and SendJob, StatementImportJob, RcvEntry, RcvEntryList and AutomationSettings vanished from the client. Those were shapes in the document, not limits of the generator, and they are fixed (#476) without changing one byte of what goes over the wire.
The one exception left: the four binary artifacts (GET /documents/{document_id}/pdf and /xml, and their two twins under /received_documents) answer application/pdf and application/xml, and openapi-python-client only types JSON bodies. The method is generated all the same and response.content carries the bytes; if you want the type, hand it a config.yml with content_type_overrides: {"application/pdf": "application/octet-stream", "application/xml": "text/plain"}. We do not fix this in the document because the declared Content-Type is the one the server really sends.
Both documents are OpenAPI 3.1. A generator that only understands 3.0 will trip over the nullable types (type: [integer, "null"]), which is the correct 3.1 shape — use a version that supports 3.1 rather than converting the document.
Versioning inside /v1 is additive (§5.8), so a regenerated client never loses a method: it only gains new fields and new enum values. A client that breaks on an unknown field has a bug, and that is the only compatibility rule we ask for.
Chapters
Account and keys (5)
Empresas (40)
Folios and CAF (5)
Documents (15)
Received documents (7)
Tax (23)
Connectors (7)
Webhooks (11)
Usage (2)
Test helpers (8)
Meta (3)
Schemas (5)
Every endpoint
| Method | Path | What it does |
|---|---|---|
GET | /account | Retrieve the account and the key in use |
GET | /api_keys | List API keys (metadata only; secrets are never returned) |
POST | /api_keys | Mint an API key (root key only) |
DELETE | /api_keys/{key_id} | Revoke an API key immediately (root key only) |
POST | /api_keys/{key_id}/roll | Issue a replacement secret for a key (root key only) |
GET | /empresas | List empresas visible to this key |
POST | /empresas | Create an empresa |
GET | /empresas/{empresa_id} | Retrieve an empresa |
PATCH | /empresas/{empresa_id} | Update an empresa |
DELETE | /empresas/{empresa_id} | Delete a SANDBOX empresa |
GET | /empresas/{empresa_id}/mandato | Whether the representante legal has signed, against which terms, and how |
POST | /empresas/{empresa_id}/mandato | Record the mandato authorizing Facturia to act before the SII |
DELETE | /empresas/{empresa_id}/mandato | Revoke the mandato |
GET | /empresas/{empresa_id}/certificate | Retrieve certificate metadata |
POST | /empresas/{empresa_id}/certificate | Upload (or reuse) the empresa's digital certificate |
DELETE | /empresas/{empresa_id}/certificate | Purge the certificate from the vault (revokes custody, suspends emission) |
GET | /empresas/{empresa_id}/sfg_credential | Retrieve the SFG centralizado clave's custody metadata |
POST | /empresas/{empresa_id}/sfg_credential | Store (or replace) the SFG centralizado clave |
DELETE | /empresas/{empresa_id}/sfg_credential | Destroy the SFG centralizado clave (ends custody) |
POST | /empresas/{empresa_id}/mandato/revocation_link | Mint the hosted page where the representante legal revokes |
POST | /empresas/{empresa_id}/resolucion/verify | Verify a declared resolución with one production timbraje (Facturia operators only) |
GET | /empresas/{empresa_id}/counterparties | Counterparties you have invoiced, with the address and contacts on file for each |
GET | /contribuyentes/{rut} | What the SII publishes about a company, by RUT, and a giro that fits a factura |
GET | /empresas/{empresa_id}/counterparties/{counterparty_rut} | What you know about one counterparty, and whether you stated it or we inferred it |
PATCH | /empresas/{empresa_id}/counterparties/{counterparty_rut} | Put a counterparty's razón social, giro and address on file |
GET | /empresas/{empresa_id}/counterparties/{counterparty_rut}/contacts | The contacts on file for one counterparty |
POST | /empresas/{empresa_id}/counterparties/{counterparty_rut}/contacts | Put a contacto responsable on file |
PATCH | /empresas/{empresa_id}/counterparties/{counterparty_rut}/contacts/{contact_id} | Edit a contact, promote it, or record an opt-out |
DELETE | /empresas/{empresa_id}/counterparties/{counterparty_rut}/contacts/{contact_id} | Remove a contact from the address book |
GET | /empresas/{empresa_id}/onboarding | Onboarding lifecycle, steps and blocking human actions |
POST | /empresas/{empresa_id}/onboarding/links | Mint a link to a hosted representante-legal page |
DELETE | /empresas/{empresa_id}/onboarding/links/{step} | Revoke a hosted representante-legal link |
POST | /empresas/{empresa_id}/onboarding/go_live | Ask the titular to approve the go-live, or state the decision on their behalf |
POST | /empresas/{empresa_id}/onboarding/steps/{step}/recheck | Tell us a human step was performed, and we go and look |
POST | /empresas/{empresa_id}/onboarding/steps/{step}/attest | Record that a human performed a step this build cannot probe (#395) |
POST | /empresas/{empresa_id}/onboarding/steps/{step}/approve | Record the titular's authorization for a step Facturia then performs (#452, #453) |
GET | /empresas/{empresa_id}/onboarding/certification | The set de pruebas - what was uploaded, what is missing, what the SII said |
POST | /empresas/{empresa_id}/onboarding/certification/set_file | Upload the set de pruebas the SII issued for this empresa |
POST | /empresas/{empresa_id}/onboarding/certification/inputs | Supply the facts the set de pruebas does not carry |
GET | /empresas/{empresa_id}/onboarding/evidence | The rendicion de cuentas - what we did on the empresa's behalf |
GET | /empresas/{empresa_id}/onboarding/evidence/export | The rendicion de cuentas as one CSV file |
GET | /empresas/{empresa_id}/automation_settings | Retrieve per-empresa automation settings |
PATCH | /empresas/{empresa_id}/automation_settings | Update per-empresa automation settings |
GET | /empresas/{empresa_id}/branding | Read logo, default print format and footer text |
PATCH | /empresas/{empresa_id}/branding | Update logo, default print format and footer text |
GET | /folios | Folio availability per doc type |
POST | /folios/requests | Request a new CAF from the SII (async) |
GET | /cafs | List CAFs held for this empresa |
POST | /cafs | Upload a CAF you already hold |
DELETE | /cafs/{caf_id} | Deactivate a CAF (history is preserved) |
GET | /documents | List emitted documents |
POST | /documents | Emit a DTE |
POST | /documents/previews | Price and validate a document without emitting it |
GET | /documents/previews/{preview_id} | Retrieve a stored preview |
GET | /documents/{document_id} | Retrieve a document |
GET | /documents/{document_id}/pdf | Download the PDF |
GET | /documents/{document_id}/xml | Download the signed XML exactly as sent to the SII |
GET | /documents/{document_id}/events | Lifecycle events for one document |
POST | /documents/{document_id}/retry | Retry a document in failed |
POST | /documents/{document_id}/send | Email the document to the receptor |
POST | /documents/{document_id}/cesion | Ask the SII whether this factura is cedible |
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 | Emit a nota de crédito against this document |
POST | /documents/{document_id}/public_links | Create or rotate public links for this document's artifacts |
DELETE | /documents/{document_id}/public_links | Revoke every public link for this document |
GET | /received_documents | List supplier DTEs received for this empresa |
GET | /received_documents/{received_document_id} | Retrieve a received document |
GET | /received_documents/{received_document_id}/xml | Download the original supplier XML |
GET | /received_documents/{received_document_id}/pdf | Render the received document as PDF |
POST | /received_documents/{received_document_id}/accept | Accept the content (SII acción ACD) |
POST | /received_documents/{received_document_id}/reject | Reclamar the document (RCD / RFP / RFT) |
POST | /received_documents/{received_document_id}/acknowledge_receipt | Otorgar recibo de mercaderías o servicios (SII acción ERM) |
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 | /connections | List connector connections for this empresa |
POST | /connections | Create a Fintoc bank/card connection |
GET | /connections/{connection_id} | Retrieve a connection |
DELETE | /connections/{connection_id} | Disconnect (revokes the link, stops ingestion) |
POST | /connections/{connection_id}/sync | Force a movement sync (async) |
GET | /tax/statements | List uploaded cartolas |
POST | /tax/statements | Upload a cartola (CSV/XLSX) to create expenses |
GET | /webhook_endpoints | List webhook endpoints |
POST | /webhook_endpoints | Register a webhook endpoint |
GET | /webhook_endpoints/{webhook_endpoint_id} | Retrieve a webhook endpoint |
PATCH | /webhook_endpoints/{webhook_endpoint_id} | Update a webhook endpoint |
DELETE | /webhook_endpoints/{webhook_endpoint_id} | Delete a webhook endpoint |
POST | /webhook_endpoints/{webhook_endpoint_id}/ping | Send a synthetic event to verify plumbing |
POST | /webhook_endpoints/{webhook_endpoint_id}/rotate_secret | Rotate the signing secret |
GET | /webhook_endpoints/{webhook_endpoint_id}/deliveries | Inspect delivery attempts |
POST | /webhook_endpoints/{webhook_endpoint_id}/deliveries/{delivery_id}/retry | Redeliver an event |
GET | /events | Query the event ledger (retained 12 months) |
GET | /events/{event_id} | Retrieve an event |
GET | /usage | Usage summary for a billing period |
GET | /usage/records | The immutable usage ledger |
POST | /test_helpers/received_documents | Inject a supplier DTE as if it had arrived at the reception address |
POST | /test_helpers/rcv/seed | Seed RCV rows for a period so F29 propuestas have data |
POST | /test_helpers/clock | Advance this empresa's simulated clock |
POST | /test_helpers/empresas/{empresa_id}/onboarding | Drive an empresa's onboarding to any state |
POST | /test_helpers/empresas/{empresa_id}/onboarding/steps | Force one onboarding step to a status |
POST | /test_helpers/documents/{document_id}/estado | Force the raw SII estado of an already-emitted sandbox document |
POST | /test_helpers/f29/proposals | Inject a computed F29 propuesta |
POST | /test_helpers/f29/validations | Force the cross-validation verdict for a period |
GET | /jobs/{job_id} | Retrieve an async job (folio request, send, cesión, RCV sync, import) |
GET | /mandato_terms | The current mandato text and version |
GET | /error_codes | The machine-readable error dictionary (unauthenticated) |
Webhooks
The OpenAPI also describes the outgoing deliveries. Their shape, their signature and their retry schedule are in Webhooks.
| Group | Events |
|---|---|
document.lifecycle | document.created | .sent | .accepted | .reparo | .rejected | .failed | .annulled |
document.delivery | document.emailed | .email_failed |
document.cesion | document.cesion_submitted | .cesion_confirmed | .cesion_failed |
received_document.lifecycle | received_document.created | .deadline_approaching | .accepted | .rejected | .receipt_acknowledged |
reception.operations | reception.acuse_sent | .acuse_failed | .quarantined |
empresa.lifecycle | empresa.* | certificate.* | folios.* | connection.* | api_key.* | webhook_endpoint.disabled |
tax.lifecycle | tax.rcv.synced | tax.f29.* | tax.suggestion.* | tax.statement.imported |
ping | ping |