Manejo de errores
Todos los errores de la API siguen el mismo formato: error es un mensaje legible para humanos y code es el código estable de máquina contra el que debes programar tu lógica.
{
"ok": false,
"error": "La empresa no tiene folios disponibles para el tipo 33.",
"code": "NO_FOLIOS"
}
Errores HTTP comunes
| Código | Descripción | Qué hacer |
|---|---|---|
400 | Request inválido (datos faltantes o mal formados) | Revisar el body del request |
401 | No autenticado | Renovar el JWT o verificar la API Key |
403 | Sin permisos o límite del plan alcanzado | Verificar el rol del usuario; si el code es PLAN_LIMIT, ver Límites del plan |
404 | Recurso no encontrado | Verificar el ID o folio en el path |
409 | Conflicto (ej: folio ya usado) | Verificar el estado actual del recurso |
410 | Archivo expirado (plan gratuito) | Si el code es XML_EXPIRADO, ver Expiración de archivos |
422 | Validación fallida | El SII rechazó los datos del DTE |
429 | Rate limit superado | Esperar el tiempo indicado en Retry-After |
503 | Servicio no disponible | Redis no disponible, reintentar en 30s |
Límites del plan
Aparte del rate limit HTTP (429), cada plan tiene cuotas mensuales: emisión de DTEs, boletas, consultas al SII, usuarios, empresas y API keys. Cuando alcanzas un tope, la API responde 403 con el código estable PLAN_LIMIT:
{
"ok": false,
"error": "Límite de consultas mensuales alcanzado. Actualice su plan.",
"code": "PLAN_LIMIT"
}
A diferencia del 429, esto no se resuelve esperando unos segundos: el contador de cada período se reinicia al inicio del próximo mes (hora de Chile), o subes de plan. Distingue PLAN_LIMIT (403, cupo del plan agotado) de 429 (ráfaga de requests, se recupera solo) por el code, no por el status.
La cuota de consultas al SII cubre las llamadas que Folyo hace por ti a servicios externos de pago por uso (consulta de contribuyente, situación tributaria, sincronización del RCV, estado de DTE, folios, RCOF, acuse, extracción con IA). Emitir DTEs no descuenta de esta cuota; tiene la suya. Cada respuesta sujeta a cuota trae los headers X-Quota-Limit, X-Quota-Remaining y X-Quota-Period. Revisa Rate limits y cuotas para el detalle de qué llamadas consumen cuota.
Expiración de archivos en el plan gratuito
En el plan gratuito, la descarga del XML firmado y del PDF de cada documento está disponible solo por un tiempo desde la emisión. En los planes de pago los archivos no expiran.
| Ambiente del documento | Descarga disponible por |
|---|---|
| Producción | 4 horas |
| Certificación | 30 minutos |
Pasada la ventana, GET /v1/dte/xml/:tipo/:folio y GET /v1/dte/pdf/:tipo/:folio responden 410 con el código estable XML_EXPIRADO (el PDF comparte el código porque se genera a partir del XML):
{
"ok": false,
"error": "El XML del DTE tipo 33 folio 1001 ya no está disponible: el plan gratuito lo conserva por 4 horas desde la emisión (30 minutos si es del ambiente de certificación). El documento sigue emitido y vigente ante el SII; no vuelva a emitirlo. Los planes de pago conservan los XML sin límite de tiempo.",
"code": "XML_EXPIRADO"
}
Dos cosas importantes:
- El documento no desaparece: solo expira la descarga. El DTE sigue emitido y vigente ante el SII, con su folio consumido, y lo sigues viendo en el listado de documentos con montos, receptor y estado. No vuelvas a emitirlo: duplicarías el documento ante el SII.
- Guarda los archivos al emitir. El resultado del job de emisión y el webhook
dte.emitidollegan dentro de la ventana: descarga el XML y el PDF apenas el job termina y almacénalos de tu lado. Si necesitas re-descargar más adelante, cualquier plan de pago conserva los archivos sin expiración.
Errores de emisión DTE
Cuando el job de emisión falla (estado: "failed"), el campo error del resultado contiene el detalle:
| Error | Descripción |
|---|---|
SII_REJECTED | El SII rechazó el DTE. Ver detail para el código SII. |
NO_FOLIOS | No hay folios disponibles para el tipo de DTE. |
CERT_ERROR | Error con el certificado digital (vencido o inválido). |
XML_SIGN_ERROR | Error al firmar el XML. Verificar el certificado. |
Reintentos
La API no reintenta automáticamente los requests fallidos del cliente. Sin embargo, Folyo reintenta el envío al SII de forma automática antes de marcar el job como failed.
Para los webhooks, Folyo reintenta la entrega hasta 5 veces con backoff exponencial.