# El sandbox (/docs/empezar/sandbox)

## Qué es, y qué no es [#qué-es-y-qué-no-es]

|                            | **Modo test** (`sk_test_`) | **Certificación SII** (`sk_live_`, empresa `ambiente: certificacion`)          | **Producción** (`sk_live_`, empresa `ambiente: produccion`) |
| -------------------------- | -------------------------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------- |
| Tráfico al SII             | ninguno                    | maullin / apicert (servidores de prueba del SII)                               | palena / api.sii.cl                                         |
| Certificado requerido      | no                         | sí (el .pfx real de la empresa)                                                | sí                                                          |
| CAF real requerido         | no (folios virtuales)      | sí (CAF de maullin)                                                            | sí                                                          |
| Latencia a estado terminal | \~1 s, determinista        | minutos a horas                                                                | minutos a horas                                             |
| Resultado                  | forzable                   | lo que diga el SII                                                             | lo que diga el SII                                          |
| Efecto legal               | ninguno                    | ninguno                                                                        | completo                                                    |
| Precio                     | **gratis para siempre**    | el plan único: $19.990 CLP + IVA al mes **por empresa**, documentos ilimitados | el mismo plan, el mismo precio                              |

El modo test es una simulación completa en proceso. Nunca abre un socket al SII, así que es
instantáneo, determinista e inmune a las ventanas de mantención del SII. La certificación SII es el
SII real en sus servidores de prueba, usada durante la puesta en marcha para certificar una empresa
específica — rara vez la manejarás directamente.

## Garantías de determinismo [#garantías-de-determinismo]

En modo test:

* Los folios parten en **1** por cada `(empresa, tipo_dte)` e incrementan de a uno. No se necesita
  CAF; `GET /v1/folios` reporta un rango virtual de 1 a 1.000.000.
* El `track_id` es un entero sintético creciente de 10 dígitos que empieza en `9000000001`.
* Los documentos se asientan `queued → sent → accepted` en aproximadamente un segundo, disparando
  cada webhook que dispararía un documento real.
* El XML es válido contra el esquema, firmado con el certificado de sandbox de Facturia, y lleva un
  TED construido desde un CAF de sandbox. **No va a validar contra el SII** — ese es el punto.
* Los PDF traen el layout real con una marca de agua `SIN VALOR TRIBUTARIO`.
* Todo objeto lleva estampado `"mode": "test"`.

Los límites de tasa del modo test son los mismos que los de live, así que una prueba de carga es
representativa.

## Forzar resultados [#forzar-resultados]

Agrega un objeto `test` a cualquier emisión.

```bash
curl -sS https://api.facturia.cl/v1/documents \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA" \
  -H "Content-Type: application/json" \
  -d '{
    "tipo_dte": 33,
    "receptor": {
      "rut": "76543212-K",
      "giro": "Venta al por mayor de alimentos",
      "address": { "street": "Los Militares 5001, of. 302", "comuna": "Las Condes", "city": "Santiago" }
    },
    "items": [{ "description": "Consultoría", "quantity": 1, "unit_price": 1200000 }],
    "test": { "outcome": "rejected", "reason_code": "TED-2-510", "settle_after_ms": 3000 }
  }'
```

| `test.outcome`           | Resultado                                                                  |
| ------------------------ | -------------------------------------------------------------------------- |
| `accepted` (por defecto) | `status: accepted`, estado SII `DOK`                                       |
| `reparo`                 | `status: reparo`, estado SII `DNK`, un `rejection_reason`                  |
| `rejected`               | `status: rejected`, estado de sobre `RCT`, `reason_code` devuelto tal cual |
| `failed`                 | `status: failed` antes de transmitir (simula una falla al armar o firmar)  |
| `stuck`                  | se queda en `sent` para siempre (para probar tus timeouts de polling)      |

> **Trampa — El campo test es una alarma, no una opción**
>
> Enviar el objeto `test` con una llave live se rechaza con `400 test_field_in_live_mode`. Es un cable
> trampa deliberado: el código de simulación no puede correr en silencio contra el SII.

Si tu cliente no puede agregar campos, los RUT de receptor mágicos hacen lo mismo:

| RUT del receptor | Fuerza                                                          |
| ---------------- | --------------------------------------------------------------- |
| `44444440-1`     | `accepted`                                                      |
| `44444441-K`     | `reparo`                                                        |
| `44444442-8`     | `rejected`                                                      |
| `44444443-6`     | `failed`                                                        |
| `44444444-4`     | `stuck`                                                         |
| `66666666-6`     | consumidor final anónimo (válido también en live, solo boletas) |

## Test helpers [#test-helpers]

Los endpoints bajo `/v1/test_helpers` existen solo para llaves de test (`403 test_mode_only` en otro
caso). Te dejan manejar las mitades del sistema que normalmente maneja el mundo exterior.

```bash
# Inyectar un DTE de proveedor como si hubiera llegado a la casilla de la empresa
# (una empresa de sandbox no tiene casilla real: `reception_email` va en null)
curl -sS https://api.facturia.cl/v1/test_helpers/received_documents \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA" \
  -H "Content-Type: application/json" \
  -d '{
    "tipo_dte": 33,
    "folio": 8812,
    "emisor": { "rut": "96790240-3", "legal_name": "Proveedor Austral SpA" },
    "issue_date": "2026-08-12",
    "totals": { "net": 450000, "iva": 85500, "total": 535500 }
  }'
```

```bash
# Sembrar filas de RCV en un período para que la propuesta de F29 tenga sobre qué calcular
curl -sS https://api.facturia.cl/v1/test_helpers/rcv/seed \
  -H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
  -H "Content-Type: application/json" \
  -d '{"period":"2026-07","purchases":12,"sales":40}'

# Adelantar el reloj simulado de esta empresa
# (prueba la ventana de acuse de 8 días, el vencimiento de folios, los plazos del F29)
curl -sS https://api.facturia.cl/v1/test_helpers/clock \
  -H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
  -H "Content-Type: application/json" \
  -d '{"advance_days":9}'

# Llevar una máquina de estados de puesta en marcha a cualquier estado sin esperar al SII
curl -sS https://api.facturia.cl/v1/test_helpers/empresas/emp_01K2R.../onboarding \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"action_required","step":"sii_postulacion"}'

# Forzar UN paso: lo que el estado completo no alcanza a expresar
# (una prueba de certificación que falla para el 61 mientras el 33 pasa)
curl -sS https://api.facturia.cl/v1/test_helpers/empresas/emp_01K2R.../onboarding/steps \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Content-Type: application/json" \
  -d '{"step":"set_de_pruebas","tipo_dte":61,"status":"failed"}'
```

> **El helper del reloj es cómo se prueba la ventana de 8 días**
>
> Inyecta un documento recibido, avanza el reloj nueve días y observa cómo la respuesta comercial deja
> de aceptar acciones con `422 commercial_response_window_closed`. Es la única forma de ejercitar ese
> plazo sin esperar más de una semana. La ventana está explicada en
> [La ventana de 8 días](/docs/recepcion/ventana-8-dias).

## Realidades de arriba que igual conviene diseñar [#realidades-de-arriba-que-igual-conviene-diseñar]

Por encima de nuestros límites hay dos realidades del SII que existen aunque el sandbox no las
simule: el SII limita tasa sin publicar sus cifras, y tiene ventanas de mantención programadas. La
emisión está encolada de nuestro lado, así que una ráfaga sobre 10 req/s es un `429` del lado del
cliente, nunca un documento perdido — pero un documento que ya aceptamos va a quedarse en `queued`
más tiempo durante una caída del SII. Construye sobre webhooks, no sobre polling apretado.

## Siguiente paso [#siguiente-paso]

- [De sandbox a producción](/docs/empezar/produccion): Lo que el sandbox se salta: los dos carriles, el mandato, los pasos humanos y la puesta en vivo.
