Documentación
Estados y respuestas
Qué significa cada respuesta, cómo consultar, listar, validar y reintentar.
Qué responde una emisión
- 201Qué pasó: AUTORIZADO por el SRI.Qué hacer: Guarda
xmlAutorizadoy entrega el comprobante. - 202Qué pasó: El SRI no respondió a tiempo (PENDIENTE, RECIBIDA o EN_PROCESO). El servicio lo termina solo.Qué hacer: Consulta luego o espera el webhook
comprobante.autorizado. No lo emitas otra vez. - 422Qué pasó: Datos inválidos (
COMPROBANTE_INVALIDO) o el SRI lo rechazó (COMPROBANTE_DEVUELTO,COMPROBANTE_NO_AUTORIZADO).Qué hacer: Corrige segúndetailsy reintenta (ver abajo). - 409Qué pasó: Conflicto de configuración (secuencial sin confirmar, clave de idempotencia con otro contenido…).Qué hacer: Lee
error.solucion. - 429 / 503Qué pasó: Demasiadas peticiones, serie ocupada o SRI no disponible. No se gastó número.Qué hacer: Reintenta tras
Retry-Aftercon la mismaIdempotency-Key.
| HTTP | Qué pasó | Qué hacer |
|---|---|---|
| 201 | AUTORIZADO por el SRI. | Guarda xmlAutorizado y entrega el comprobante. |
| 202 | El SRI no respondió a tiempo (PENDIENTE, RECIBIDA o EN_PROCESO). El servicio lo termina solo. | Consulta luego o espera el webhook comprobante.autorizado. No lo emitas otra vez. |
| 422 | Datos inválidos (COMPROBANTE_INVALIDO) o el SRI lo rechazó (COMPROBANTE_DEVUELTO, COMPROBANTE_NO_AUTORIZADO). | Corrige según details y reintenta (ver abajo). |
| 409 | Conflicto de configuración (secuencial sin confirmar, clave de idempotencia con otro contenido…). | Lee error.solucion. |
| 429 / 503 | Demasiadas peticiones, serie ocupada o SRI no disponible. No se gastó número. | Reintenta tras Retry-After con la misma Idempotency-Key. |
Por defecto la emisión espera hasta 12 segundos la autorización. Con ?esperar=0 responde 202 apenas crea el comprobante (útil en un punto de venta con mucha carga). Otros parámetros: ?ride=true incluye el PDF en base64 en ridePdfBase64 y ?correo=false no envía el correo al comprador.
Consultar un comprobante
Por id o por clave de acceso. Con ?eventos=true trae su recorrido (firmado, recibido, autorizado, correo enviado…), el mismo que ves en el panel.
curl "https://api.devfact.fonles.com/v1/comprobantes/e9adcca8-8817-4212-911f-9a9f511f8a02?eventos=true" \
-H "Authorization: Bearer $DEVFACT_API_KEY"Esperar un 202
Lo mejor es un webhook. Si no puedes recibirlos, consulta cada pocos segundos y espacia las consultas; el servicio sigue reintentando con el SRI aunque tú no consultes.
async function esperarAutorizacion(id, { maxMinutos = 10 } = {}) {
const fin = Date.now() + maxMinutos * 60_000;
let espera = 2_000;
while (Date.now() < fin) {
const res = await fetch(`https://api.devfact.fonles.com/v1/comprobantes/${id}`, {
headers: { Authorization: `Bearer ${process.env.DEVFACT_API_KEY}` },
});
const c = await res.json();
if (["AUTORIZADO", "NO_AUTORIZADO", "DEVUELTA", "ANULADO"].includes(c.estado)) return c;
await new Promise((r) => setTimeout(r, espera));
espera = Math.min(espera * 2, 60_000);
}
return null; // Sigue en proceso: el servicio lo terminará; revisa más tarde.
}Listar y buscar
Del más reciente al más antiguo, 50 por página (hasta 100 con limite). Filtros: emisor, tipo, estado (varios separados por coma), desde/hasta (fecha de emisión), ambiente, numero y claveAcceso. Para la página siguiente pasa siguienteCursor como cursor; null es la última.
curl "https://api.devfact.fonles.com/v1/comprobantes?estado=AUTORIZADO&tipo=factura&desde=2026-11-01&hasta=2026-11-30" \
-H "Authorization: Bearer $DEVFACT_API_KEY"Validar sin emitir
POST /v1/comprobantes/validar valida el cuerpo, calcula los totales y valida el XML contra el esquema del SRI, sin gastar número, firmar ni enviar nada. Útil para mostrar los totales antes de confirmar una venta. POST /v1/comprobantes/vista-previa devuelve el RIDE de muestra en PDF.
curl -X POST "https://api.devfact.fonles.com/v1/comprobantes/validar" \
-H "Authorization: Bearer $DEVFACT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tipo": "factura",
"comprador": {
"tipoIdentificacion": "cedula",
"identificacion": "1710034065",
"razonSocial": "Carlos Andrade"
},
"items": [
{
"codigo": "TV-55",
"descripcion": "Televisor 55 pulgadas",
"cantidad": 1,
"precioUnitario": "650.00",
"descuento": "50.00",
"iva": "15"
}
],
"pagos": [
{
"formaPago": "tarjetaDebito"
}
]
}'Cuando el SRI rechaza
Un rechazo trae los mensajes del SRI con su explicación y qué hacer. details.accion resume el camino:
- CORREGIR_DATOSCorrige y llama a
POST /v1/comprobantes/{id}/reintentarcon el comprobante corregido: conserva el mismo número y la misma clave de acceso. - CONFIGURAR_SECUENCIALError 45: el número ya lo usó otro sistema. Reintentar no sirve: configura el secuencial (en el panel, Emisores → Secuenciales) y emite uno nuevo.
| accion | Qué hacer |
|---|---|
| CORREGIR_DATOS | Corrige y llama a POST /v1/comprobantes/{id}/reintentar con el comprobante corregido: conserva el mismo número y la misma clave de acceso. |
| CONFIGURAR_SECUENCIAL | Error 45: el número ya lo usó otro sistema. Reintentar no sirve: configura el secuencial (en el panel, Emisores → Secuenciales) y emite uno nuevo. |
{
"error": {
"code": "COMPROBANTE_DEVUELTO",
"message": "El SRI devolvió el comprobante: 65 FECHA EMISIÓN EXTEMPORANEA",
"source": "sri",
"details": {
"estado": "DEVUELTA",
"mensajes": [{
"identificador": "65",
"mensaje": "FECHA EMISIÓN EXTEMPORANEA",
"titulo": "El comprobante se envió fuera de plazo",
"solucion": "Emita con la fecha de hoy…",
"reintentable": true
}],
"accion": "CORREGIR_DATOS",
"sugerencia": "Corrija lo que indica el SRI y llame a POST /v1/comprobantes/79a31dab-…/reintentar"
},
"requestId": "1e676c55-5ebf-4f1b-9811-9c6c86258ed4",
"docUrl": "https://api.devfact.fonles.com/v1/errores/COMPROBANTE_DEVUELTO",
"solucion": "Corrija lo que indica el SRI y llame a POST /v1/comprobantes/79a31dab-…/reintentar"
},
"comprobante": { "id": "79a31dab-8d18-49f0-b7ff-b3083c3ca888", "estado": "DEVUELTA", "numero": "001-001-000004522", "…": "…" }
}curl -X POST "https://api.devfact.fonles.com/v1/comprobantes/79a31dab-8d18-49f0-b7ff-b3083c3ca888/reintentar" \
-H "Authorization: Bearer $DEVFACT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"descripcion": "Café americano",
"cantidad": 2,
"precioUnitario": "2.50",
"iva": "15"
}
],
"pagos": [
{
"formaPago": "efectivo"
}
]
}'Un error de validación nunca llega al SRI ni gasta número: details.issues dice qué campo corregir.
{
"error": {
"code": "COMPROBANTE_INVALIDO",
"message": "Comprobante inválido: items.0.cantidad: Debe ser mayor que cero; pagos: Debe tener al menos 1 elemento(s)",
"source": "validacion",
"details": {
"issues": [
{ "path": "items.0.cantidad", "code": "MONTO_DEBE_SER_POSITIVO", "message": "Debe ser mayor que cero" },
{ "path": "pagos", "code": "LISTA_VACIA", "message": "Debe tener al menos 1 elemento(s)" }
]
},
"requestId": "2e1fa07e-1a67-4788-8860-092cdaf2fe85",
"docUrl": "https://api.devfact.fonles.com/v1/errores/COMPROBANTE_INVALIDO"
}
}
