Authentication
Simplo API keys (sk_simplo_ and sk_simplo_sandbox_), scopes, the X-Api-Key header, creation, revocation and credential hygiene.
API keys (recommended)
Section titled “API keys (recommended)”Simplo authenticates with API keys per company. A key is shown only once when created — store it in a secrets manager (Simplo only keeps its SHA-256 hash and an 8-character prefix for display).
Besides the company, each key fixes two things:
- The environment — the Stripe model:
sk_simplo_sandbox_...operates your company’s sandbox (self-serve, included in any plan with Facturación);sk_simplo_...(without_sandbox_) operates production (enabled per company — see Go to production). Same endpoint, same contract: the key decides the environment. - The scope — which surface it reaches:
| Scope | What it allows |
|---|---|
billing:dte |
Emit and query DTEs via the billing REST API — exactly the five routes in the quickstart’s table (POST/GET /billing/dte, detail, PDF, XML). The rest of /api/v1/billing/* is session-only and responds 403 BILLING_API_KEY_ROUTE_NOT_ALLOWED. |
agent:read |
Read data via the MCP and the agent tools. It’s the default scope of a new key. It does not emit. |
A billing:dte key is not read-only — it emits tax documents. And it’s
not interchangeable with agent:read: the MCP responds 401 to a
billing:dte key, and the billing facade doesn’t accept agent:read.
The key travels in the X-Api-Key header. With the SDK (not yet published on npm):
import Simplo from '@simplohq/sdk';
const simplo = new Simplo({ apiKey: process.env.SIMPLO_API_KEY });If you omit apiKey, the client reads the SIMPLO_API_KEY environment
variable and throws immediately (not on the first request) if none exists.
The credential is the company. An API key is bound to exactly one company: every call is scoped to it, and no parameter can widen that scope. To operate several companies, see Multi-company.
Create, list and revoke keys
Section titled “Create, list and revoke keys”You can manage your keys from Desarrolladores in your Simplo account
(company owner or admin only), or via the API by authenticating with your
session JWT. environment picks the environment ("sandbox" or "live";
it defaults to "live" if omitted) and scopes the surface:
curl -sS -X POST https://api.simplo.cl/api/v1/api-keys \ -H "Authorization: Bearer $SIMPLO_JWT" \ -H "Content-Type: application/json" \ -d '{"name": "Backend de facturación", "environment": "sandbox", "scopes": ["billing:dte"]}'The 201 Created response includes the key field this one time — it
can’t be retrieved afterward:
{ "id": "a1b2c3d4-...", "name": "Backend de facturación", "prefix": "sk_simpl", "is_sandbox": true, "revoked": false, "created_at": "2026-06-13T12:00:00Z", "key": "sk_simplo_sandbox_3f9a...e1"}When creating a sandbox key, your company needs its full identity: without
a real RUT the mint responds 422 COMPANY_RUT_REQUIRED_FOR_SANDBOX (and
without a razón social, 422 COMPANY_RAZON_SOCIAL_REQUIRED_FOR_SANDBOX) —
complete it in the app and retry.
To list or revoke:
curl -sS https://api.simplo.cl/api/v1/api-keys \ -H "Authorization: Bearer $SIMPLO_JWT"
curl -sS -X DELETE https://api.simplo.cl/api/v1/api-keys/$KEY_ID \ -H "Authorization: Bearer $SIMPLO_JWT"The list endpoint never returns the full key value, only its metadata
(prefix, scopes, last_used_at, revoked). Revocation is idempotent and
takes effect immediately.
Key hygiene
Section titled “Key hygiene”- Never send an API key to a browser or mobile app. Call Simplo from your backend.
- Never commit it. Use environment variables or a secrets manager.
- Rotate by creating a new key, deploying it, then revoking the old one. Revocation is immediate.
Bearer tokens (advanced)
Section titled “Bearer tokens (advanced)”If you already have a JWT issued by Simplo (for example inside an
integration that authenticates users against Simplo), you can pass it
instead of an API key. It’s sent as Authorization: Bearer <token>:
const simplo = new Simplo({ token: sessionJwt });Prefer API keys for server-to-server integrations: they don’t expire on a session’s schedule and are individually revocable.
Failure modes
Section titled “Failure modes”| Status | Error class | Meaning |
|---|---|---|
| 401 | AuthenticationError |
Missing, malformed, revoked, expired or unknown credential — or a billing:dte key against the MCP. |
| 403 | PermissionError |
Valid credential, but not permitted for this action. With an API key on /billing/*, the code BILLING_API_KEY_ROUTE_NOT_ALLOWED means the route is session-only — it’s not a problem with your account. |
The API intentionally doesn’t distinguish why a 401 happened
(anti-enumeration). Check the header name (X-Api-Key), the key prefix
(sk_simplo_) and that it hasn’t been revoked.
See Errors for full error handling.