Skip to content
SimploSimplo Docs

Quickstart

Create your sandbox API key at app.simplo.cl and emit your first DTE (Chilean electronic invoice or receipt) in minutes, no certificate or CAF required — against the same REST API as production, with curl, C#, Java, Python or the TypeScript SDK.

Emit your first DTE (Documento Tributario Electronico — a Chilean electronic tax document, such as an invoice or receipt) in your own company’s sandbox: the same model as Stripe, where the test environment isn’t another account but a mode of yours, selected by the API key (sk_simplo_sandbox_… vs sk_simplo_…). A synthetic certificate and folios (CAF) are provisioned for you — no digital certificate to buy, no folios to file with the SII, no talking to sales. Simplo is a REST API: any language that speaks HTTP + JSON works. Here’s the same flow in curl, C#, Java, Python and the TypeScript SDK.

The sandbox’s amounts and tax math (VAT) are not fake — it’s the same engine that produces real invoices. The only thing simulated is the SII: the document never really reaches the SII and has no tax validity. When you’re ready to emit real documents, see Go to production.

With your Simplo account created (and your company carrying its real RUT and razón social), go to app.simplo.cl → Desarrolladores and create a sandbox API key. That’s the whole procedure: any plan with Facturación includes the sandbox, self-serve.

The key is shown exactly once — save it now:

Ventana de terminal
export SIMPLO_API_KEY="sk_simplo_sandbox_3f9a...e1"

Prefer the API? The same mint exists as an endpoint (with your session JWT, owner or admin role — see Authentication):

Ventana de terminal
curl -sS -X POST https://api.simplo.cl/api/v1/api-keys \
-H "Authorization: Bearer $SIMPLO_JWT" \
-H "Content-Type: application/json" \
-d '{"name": "mi integración", "environment": "sandbox", "scopes": ["billing:dte"]}'
// 201 Created
{
"id": "a1b2c3d4-...",
"name": "mi integración",
"prefix": "sk_simpl",
"is_sandbox": true,
"key": "sk_simplo_sandbox_3f9a...e1"
}

If your company doesn’t have its RUT or razón social yet, the mint responds 422 (COMPANY_RUT_REQUIRED_FOR_SANDBOX / COMPANY_RAZON_SOCIAL_REQUIRED_FOR_SANDBOX) — complete your company’s identity in the app and retry. There’s no certificate step and no CAF step: when the key is created, your company’s sandbox is provisioned with a synthetic certificate and folios, ready to emit.

The exact same endpoint as production — POST /api/v1/billing/dte, with an Idempotency-Key header (UUID) so a retry can never duplicate the invoice. Not a single line of the example changes between sandbox and production; the only thing that changes is which API key you use.

Ventana de terminal
curl -X POST https://api.simplo.cl/api/v1/billing/dte \
-H "X-Api-Key: $SIMPLO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"tipo_dte": 33,
"receptor": {
"rut": "76543210-3",
"razon_social": "Cliente Ejemplo SpA",
"giro": "Servicios de software",
"direccion": "Av. Providencia 1234",
"comuna": "Providencia"
},
"detalle": [
{ "nombre": "Servicios de consultoría", "cantidad": 10, "precio": 50000 }
]
}'
// 201 Created
{
"id": "4f9c9c2e-8a49-4f2e-9d5f-0d8f3a1b2c3d",
"folio": 1042,
"tipo_dte": 33,
"estado": "firmado",
"monto_total": 595000,
"created_at": "2026-08-01T14:30:00Z"
}

The 201 response returns as soon as the document is signed (estado: "firmado"): folio assigned from the active CAF, XML generated, electronic stamp (TED) and digital signature ready. Submission to the SII (or, in sandbox, to the SII simulator) happens asynchronously.

Amounts are integer Chilean pesos (CLP). VAT (19%) is computed by the API — you send net prices.

By polling GET /api/v1/billing/dte/{id}. In sandbox, the full cycle plays out in front of you in seconds — firmado → enviando → procesando → aceptado — so you actually see that the SII (real or simulated) is asynchronous, not just another synchronous call:

Ventana de terminal
curl https://api.simplo.cl/api/v1/billing/dte/4f9c9c2e-8a49-4f2e-9d5f-0d8f3a1b2c3d \
-H "X-Api-Key: $SIMPLO_API_KEY"
// 200 OK (excerpt)
{
"estado": "aceptado",
"tracking": { "track_id": "1234567890", "estado_envio": "aceptado" }
}

The full status lifecycle is documented in States. In sandbox you can force a verdict (rechazado, con_reparos, exhausted folios) with magic receptor RUTs instead of waiting for the happy path — see step 5.

Webhook delivery is not live yet — you follow the verdict by polling GET /api/v1/billing/dte/{id}, as above. See Webhooks.

A receipt (boleta) to an end consumer is the same endpoint with tipo_dte: 39 and one extra required field: ind_servicio (use 3 — boleta for sales and services). Omitting it is the most common 400 when integrating boletas:

Ventana de terminal
curl -X POST https://api.simplo.cl/api/v1/billing/dte \
-H "X-Api-Key: $SIMPLO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"tipo_dte": 39,
"ind_servicio": 3,
"receptor": { "rut": "66666666-6", "razon_social": "Cliente Boleta" },
"detalle": [
{ "nombre": "Producto", "cantidad": 1, "precio": 10000 }
]
}'

One difference from the invoice: on boletas precio is gross (VAT included, shelf-price style) — monto_total stays at 10000 and the engine breaks the VAT out internally (monto_neto: 8403). On invoices, precio is net and the API adds the VAT. The response is a 201 with estado: "firmado", just like the invoice.

A DTE aceptado on the first try is the easy case. To test your error handling — SII rejection, exhausted folios, a DTE stuck in procesando — without waiting for it to happen by chance, the sandbox ships magic receptor RUTs that force each outcome deterministically. See Try the unhappy paths.

Ventana de terminal
# PDF with PDF417 electronic stamp (add ?cedible=true for factoring)
curl -o factura.pdf \
"https://api.simplo.cl/api/v1/billing/dte/$DTE_ID/pdf" \
-H "X-Api-Key: $SIMPLO_API_KEY"
# Signed XML (ISO-8859-1)
curl -o factura.xml \
"https://api.simplo.cl/api/v1/billing/dte/$DTE_ID/xml" \
-H "X-Api-Key: $SIMPLO_API_KEY"

With the SDK (once it ships): simplo.dtes.pdf(dte.id, { cedible: true }) and simplo.dtes.xml(dte.id).

A billing:dte key (sandbox or live) reaches exactly six routes — the ones you just used, plus the boleta envelope. Everything else in the billing API is managed with your session at app.simplo.cl, never with the key:

Operation Via API key?
POST /api/v1/billing/dte — emit (requires Idempotency-Key) ✅
GET /api/v1/billing/dte — list ✅
GET /api/v1/billing/dte/{id} — detail and status ✅
GET /api/v1/billing/dte/{id}/pdf · …/xml — downloads ✅
POST /api/v1/billing/dte/send-boletas — send a set of boletas in one envelope (requires Idempotency-Key) ✅
CAF/folios, company, certificate, libros, webhooks, clients, products ❌ 403 BILLING_API_KEY_ROUTE_NOT_ALLOWED — session only
POST /api/v1/mcp (MCP for agents) ❌ 401 — the MCP takes agent:read keys or OAuth, not billing:dte

No “preflight” needed: in the sandbox the certificate and folios are already provisioned — just emit. If one of your calls returns 403 BILLING_API_KEY_ROUTE_NOT_ALLOWED, it’s not a problem with your account: that route simply isn’t part of the key surface.