Quickstart
Crea tu API key de sandbox en app.simplo.cl y emite tu primer DTE (factura o boleta electrónica chilena) en minutos, sin certificado ni CAF — contra la misma API REST que producción, con curl, C#, Java, Python o el SDK TypeScript.
Emite tu primer DTE (Documento Tributario Electrónico — una factura o boleta
electrónica chilena) en el sandbox de tu propia empresa: el mismo modelo
de Stripe, donde el ambiente de prueba no es otra cuenta sino un modo de
la tuya, seleccionado por la API key (sk_simplo_sandbox_… vs
sk_simplo_…). Certificado y folios (CAF) sintéticos se aprovisionan solos —
sin comprar un certificado digital, sin tramitar folios en el SII, sin
hablar con ventas. Simplo es una API REST: cualquier lenguaje que hable
HTTP + JSON sirve. Aquí el mismo flujo en curl, C#, Java, Python y el SDK
TypeScript.
Los montos y el cálculo tributario (IVA) del sandbox no son ficticios — es el mismo motor que produce facturas reales. Lo único simulado es el SII: el documento nunca llega al SII de verdad ni tiene validez tributaria. Cuando estés listo para emitir documentos reales, ver Pasar a producción.
1. Crea tu key de sandbox
Sección titulada «1. Crea tu key de sandbox»Con tu cuenta de Simplo creada (y tu empresa con su RUT y razón social reales), entra a app.simplo.cl → Desarrolladores y crea una API key de sandbox. Eso es todo el trámite: cualquier plan con Facturación incluye el sandbox, self-serve.
La key se muestra una sola vez — guárdala ahora:
export SIMPLO_API_KEY="sk_simplo_sandbox_3f9a...e1"¿Prefieres API? El mismo mint existe como endpoint (con tu sesión JWT, rol dueño o administrador — ver Autenticación):
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"}Si tu empresa aún no tiene RUT o razón social, el mint responde 422
(COMPANY_RUT_REQUIRED_FOR_SANDBOX /
COMPANY_RAZON_SOCIAL_REQUIRED_FOR_SANDBOX) — completa la identidad de tu
empresa en la app y reintenta. No hay paso de certificado ni de CAF: al
crear la key, el sandbox de tu empresa queda aprovisionado con certificado y
folios sintéticos, listos para emitir.
2. Emite una factura
Sección titulada «2. Emite una factura»Exactamente el mismo endpoint que producción — POST /api/v1/billing/dte,
con header Idempotency-Key (UUID) para que un reintento nunca duplique la
factura. Ni una línea del ejemplo cambia entre sandbox y producción; lo
único distinto es qué API key usas.
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"}using System.Net.Http.Json;using System.Text.Json;
var http = new HttpClient { BaseAddress = new Uri("https://api.simplo.cl") };http.DefaultRequestHeaders.Add("X-Api-Key", Environment.GetEnvironmentVariable("SIMPLO_API_KEY"));
var request = new HttpRequestMessage(HttpMethod.Post, "/api/v1/billing/dte"){ Content = JsonContent.Create(new { tipo_dte = 33, // Factura Electrónica receptor = new { rut = "76543210-3", razon_social = "Cliente Ejemplo SpA", giro = "Servicios de software", direccion = "Av. Providencia 1234", comuna = "Providencia", }, detalle = new[] { new { nombre = "Servicios de consultoría", cantidad = 10, precio = 50000 }, }, })};request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await http.SendAsync(request);response.EnsureSuccessStatusCode(); // 201
var dte = await response.Content.ReadFromJsonAsync<JsonElement>();Console.WriteLine($"folio {dte.GetProperty("folio")} — {dte.GetProperty("estado")}");// folio 1042 — firmadoimport java.net.URI;import java.net.http.*;import java.util.UUID;
var body = """ { "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 } ] }""";
HttpClient http = HttpClient.newHttpClient();HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://api.simplo.cl/api/v1/billing/dte")) .header("X-Api-Key", System.getenv("SIMPLO_API_KEY")) .header("Content-Type", "application/json") .header("Idempotency-Key", UUID.randomUUID().toString()) .POST(HttpRequest.BodyPublishers.ofString(body)) .build();
HttpResponse<String> response = http.send(request, HttpResponse.BodyHandlers.ofString());System.out.println(response.statusCode()); // 201System.out.println(response.body());// {"id":"4f9c…","folio":1042,"estado":"firmado",…}import http.client, json, os, uuid
conn = http.client.HTTPSConnection("api.simplo.cl")conn.request( "POST", "/api/v1/billing/dte", body=json.dumps({ "tipo_dte": 33, # Factura Electrónica "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} ], }), headers={ "X-Api-Key": os.environ["SIMPLO_API_KEY"], "Content-Type": "application/json", "Idempotency-Key": str(uuid.uuid4()), },)
dte = json.loads(conn.getresponse().read())print(dte["folio"], dte["estado"]) # 1042 firmadoVista previa de cómo se verá una vez publicado:
import Simplo from '@simplohq/sdk';
const simplo = new Simplo(); // lee SIMPLO_API_KEY
const dte = await simplo.dtes.emit({ tipo_dte: 33, // Factura Electrónica 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 }],});
console.log(dte.folio, dte.estado); // 1042 "firmado"El SDK generará la Idempotency-Key y reintentará con backoff por ti — ver
SDK TypeScript.
La respuesta 201 retorna en cuanto el documento queda firmado
(estado: "firmado"): folio asignado desde el CAF activo, XML generado,
timbre electrónico (TED) y firma digital listos. El envío al SII (o, en
sandbox, al simulador del SII) ocurre de forma asíncrona.
Los montos son pesos chilenos (CLP) enteros. El IVA (19%) lo calcula la API — tú envías precios netos.
3. Mira los estados
Sección titulada «3. Mira los estados»Por polling sobre GET /api/v1/billing/dte/{id}. En sandbox, el ciclo
completo ocurre delante de ti en cuestión de segundos —
firmado → enviando → procesando → aceptado — para que veas de verdad que
el SII (real o simulado) es asíncrono, no una llamada síncrona más:
curl https://api.simplo.cl/api/v1/billing/dte/4f9c9c2e-8a49-4f2e-9d5f-0d8f3a1b2c3d \ -H "X-Api-Key: $SIMPLO_API_KEY"// 200 OK (extracto){ "estado": "aceptado", "tracking": { "track_id": "1234567890", "estado_envio": "aceptado" }}var current = await http.GetFromJsonAsync<JsonElement>( $"/api/v1/billing/dte/{dte.GetProperty("id")}");Console.WriteLine(current.GetProperty("estado"));// "enviando" | "procesando" | "aceptado" | "rechazado" | "con_reparos"HttpRequest poll = HttpRequest.newBuilder() .uri(URI.create("https://api.simplo.cl/api/v1/billing/dte/" + dteId)) .header("X-Api-Key", System.getenv("SIMPLO_API_KEY")) .GET() .build();System.out.println(http.send(poll, HttpResponse.BodyHandlers.ofString()).body());// "estado": "enviando" | "procesando" | "aceptado" | "rechazado" | "con_reparos"conn.request( "GET", f"/api/v1/billing/dte/{dte['id']}", headers={"X-Api-Key": os.environ["SIMPLO_API_KEY"]},)current = json.loads(conn.getresponse().read())print(current["estado"])# "enviando" | "procesando" | "aceptado" | "rechazado" | "con_reparos"Vista previa — el SDK aún no está publicado, ver la pestaña curl:
const current = await simplo.dtes.retrieve(dte.id);console.log(current.estado); // "enviando" | "procesando" | "aceptado" | …console.log(current.tracking?.track_id); // track ID del SII una vez enviadoEl ciclo completo de estados está documentado en
Estados. En sandbox puedes forzar un veredicto
(rechazado, con_reparos, folios agotados) con RUTs mágicos de receptor
en vez de esperar el camino feliz — ver el paso 5.
La entrega de webhooks aún no está activa — el veredicto se sigue por polling de
GET /api/v1/billing/dte/{id}, como arriba. Ver Webhooks.
4. Emite una boleta (tipo 39)
Sección titulada «4. Emite una boleta (tipo 39)»Una boleta a consumidor final es el mismo endpoint con tipo_dte: 39 y un
campo extra obligatorio: ind_servicio (usa 3 — boleta de venta y
servicios). Omitirlo es el 400 más común al integrar boletas:
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 } ] }'Una diferencia con la factura: en boletas precio es bruto (IVA
incluido, como en la vitrina) — monto_total queda en 10000 y el motor
desglosa el IVA por dentro (monto_neto: 8403). En facturas, precio es
neto y la API agrega el IVA. La respuesta es 201 con estado: "firmado",
igual que la factura.
5. Prueba los casos infelices
Sección titulada «5. Prueba los casos infelices»Un DTE aceptado en el primer intento es el caso fácil. Para probar tu
manejo de errores —rechazo del SII, folios agotados, un DTE que se queda
pegado en procesando— sin esperar a que ocurra por azar, el sandbox trae
RUTs mágicos de receptor que fuerzan cada resultado de forma
determinística. Ver
Prueba los casos infelices.
6. Descarga el PDF y el XML
Sección titulada «6. Descarga el PDF y el XML»# PDF con timbre electrónico PDF417 (agrega ?cedible=true para factoring)curl -o factura.pdf \ "https://api.simplo.cl/api/v1/billing/dte/$DTE_ID/pdf" \ -H "X-Api-Key: $SIMPLO_API_KEY"
# XML firmado (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"Con el SDK (cuando se publique): simplo.dtes.pdf(dte.id, { cedible: true }) y
simplo.dtes.xml(dte.id).
Qué puede hacer tu API key
Sección titulada «Qué puede hacer tu API key»Una key billing:dte (sandbox o live) alcanza exactamente seis rutas —
las que acabas de usar, más el envelope de boletas. Todo lo demás de la API de
facturación se gestiona con tu sesión en app.simplo.cl, nunca con la key:
| Operación | ¿Por API key? |
|---|---|
POST /api/v1/billing/dte — emitir (exige Idempotency-Key) |
✅ |
GET /api/v1/billing/dte — listar |
✅ |
GET /api/v1/billing/dte/{id} — detalle y estado |
✅ |
GET /api/v1/billing/dte/{id}/pdf · …/xml — descargas |
✅ |
POST /api/v1/billing/dte/send-boletas — enviar un conjunto de boletas en un envelope (exige Idempotency-Key) |
✅ |
| CAF/folios, empresa, certificado, libros, webhooks, clientes, productos | ❌ 403 BILLING_API_KEY_ROUTE_NOT_ALLOWED — solo sesión |
POST /api/v1/mcp (MCP para agentes) |
❌ 401 — el MCP usa keys agent:read u OAuth, no billing:dte |
No necesitas “preflight”: en sandbox el certificado y los folios ya están
aprovisionados — emite directamente. Si una llamada tuya devuelve
403 BILLING_API_KEY_ROUTE_NOT_ALLOWED, no es un problema de tu cuenta: esa
ruta simplemente no es parte de la superficie por key.
Siguientes pasos
Sección titulada «Siguientes pasos»- Prueba los casos infelices — RUTs mágicos y el catálogo de errores estructurados
- Pasar a producción — la checklist honesta de go-live: certificado real, certificación SII, CAF real
- El contrato OpenAPI — descarga la spec y genera un cliente C#, Java o TypeScript
- Referencia por endpoint — los 27 endpoints, con ejemplos en curl, C#, Java y JavaScript
- Autenticación — API keys y auth avanzada
- Tipos de DTE — los 12 tipos de documento
- Errores — manejo de errores y reintentos
- Paginación — listados con cursor
- Webhooks — el contrato de entregas (aún no activo; usa polling)
- Multi-empresa — operar más de una empresa
- Agentes — punteros para coding agents