DavyCorp APIs

Comprobantes emitidos

Consulta facturas, liquidaciones, notas y retenciones emitidas por el contribuyente en SRI en Línea. Cada consulta es un trabajo asíncrono.

BASE URL https://apis.davycorp.ec/v2
Demo. Solo verifyApiUser. apiwhatsapp. El dueño del trabajo es el id del API user. Un trabajo de Demo no puede leerse ni descargarse desde Comercial ni desde otro usuario.
Portal real. Demo consulta el SRI de verdad si envías un RUC y una clave reales. No es un simulador.
POST /docs-emitidos/demo DEMO

Autenticación

AuthorizationBearer TU_API_KEYrequerido
Cuerpo JSON
CampoTipoDescripción
rucstringrequeridoRUC con el que se inicia sesión en el portal del SRI. No se persiste en base.
clavestringrequeridoClave del portal del SRI. Solo vive en memoria. No confundir con claveAcceso.
fechaEmisionstringrequeridoFecha de emisión en YYYY-MM-DD o DD/MM/YYYY. Debe ser anterior a la fecha actual de Ecuador (America/Guayaquil). Hoy o futuro responde 400.
estadoAutorizacionstringopcionalPor defecto autorizados. También noAutorizados y porProcesar.
tipostringopcionalPor defecto factura. Valores: factura, liquidacion, credito, debito, guia, retencion. Varios separados por coma.
establecimientostringopcionalTres dígitos, por ejemplo 001. Solo se envía si el formulario muestra el campo.
puntoEmisionstringopcionalTres dígitos. Solo se envía si el formulario muestra el campo.
claveAccesostringopcionalFiltro de 49 dígitos (clave de acceso / número de autorización). No es la clave de login.
identificacionstringopcionalRUC, cédula o pasaporte del filtro de consulta, 10–13 dígitos.
httpHandoffbooleanopcionalPor defecto true. La descarga HTTP de TXT y XML se resuelve contra la URL absoluta del formulario JSF (recuperarComprobantes.jsf) con javax.faces.ViewState. Con false solo baja la primera página por clic. La API no descarga RIDE/PDF: rideDisponible indica si el portal expuso el enlace.
soloReportebooleanopcionalPor defecto false. En true baja únicamente el TXT y no vuelve a pedir los XML.
esperarbooleanopcionalPor defecto true: el POST espera el trabajo real hasta SRI_ESPERA_HTTP_MS (máx. 120 s). Con false responde 202 de inmediato y hay que consultar el GET de estado. Si se agota el tiempo, responde 202 con esperaAgotada: true y el mismo jobId.

fechaEmision es obligatoria. anio y mes no forman parte del cuerpo de emitidos (si se envían, se ignoran).

Ejemplos de consumo
cURL
fetch
Python
curl -X POST "https://apis.davycorp.ec/v2/docs-emitidos/demo" \
  -H "Authorization: Bearer TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "ruc": "1790000000001",
    "clave": "TU_CLAVE_SRI",
    "fechaEmision": "2026-09-14",
    "estadoAutorizacion": "autorizados",
    "tipo": "factura"
  }'
await fetch("https://apis.davycorp.ec/v2/docs-emitidos/demo", {
  method: "POST",
  headers: {
    Authorization: "Bearer TU_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    ruc: "1790000000001",
    clave: "TU_CLAVE_SRI",
    fechaEmision: "2026-09-14",
    estadoAutorizacion: "autorizados",
    tipo: "factura"
  })
});
import requests
requests.post(
    "https://apis.davycorp.ec/v2/docs-emitidos/demo",
    headers={"Authorization": "Bearer TU_API_KEY"},
    json={
        "ruc": "1790000000001",
        "clave": "TU_CLAVE_SRI",
        "fechaEmision": "2026-09-14",
        "estadoAutorizacion": "autorizados",
        "tipo": "factura",
    },
)
Respuestas
202 · Creación
200 · Estado
Errores
{
  "job_id": "8c1d0c2e-4b1a-4f0e-9c2a-6e5b1a0d4f11",
  "estado": "pendiente",
  "mensaje": "Descarga iniciada. Consulta el estado con el mismo prefijo de modalidad."
}
{
  "id": "JOB_ID",
  "estado": "completado",
  "modalidad": "demo",
  "zip_url": "/v2/docs-emitidos/demo/JOB_ID/archivo",
  "archivoUrl": "/v2/docs-emitidos/demo/JOB_ID/archivo",
  "comprobantesUrl": "/v2/docs-emitidos/demo/JOB_ID/comprobantes",
  "resultadoUrl": "/v2/docs-emitidos/demo/JOB_ID",
  "error": null,
  "creado": "2026-10-26T18:00:00.000Z",
  "terminado": "2026-10-26T18:04:12.000Z"
}
// 400 — cuerpo incompleto
{ "error": "ruc y clave son obligatorios" }

// 400 — fecha hoy o futura
{ "error": "La fecha ingresada debe ser menor a la fecha actual" }

// 401 — sin header Authorization
{ "error": "API Key requerida" }

// 403 — API key inválida
{ "success": false, "error": "Api user inválido" }

// 404 — job inexistente o de otro dueño
{ "error": "Job no encontrado" }

// 409 — consultar comprobantes/archivo mientras se ejecuta
{ "error": "El trabajo sigue en ejecución" }

// 429 — cupo del API user
{ "error": "Límite de consultas alcanzado", "status": false }

// 500 — fallo interno
{ "error": "Error interno del servidor", "status": false }
Endpoints secundarios (Demo)
MétodoEndpoint relativoFunción
GET/v2/docs-emitidos/demo/:jobIdConsultar estado del trabajo.
GET/v2/docs-emitidos/demo/:jobId/comprobantesObtener listado JSON de comprobantes.
GET/v2/docs-emitidos/demo/:jobId/archivoDescargar ZIP (cuando completado o parcial).
POST/v2/docs-emitidos/demo/:jobId/cancelarCancelar trabajo si el estado lo permite.

Los GET de esta API no incrementan el cupo. El POST que crea el trabajo sí pasa por el conteo existente.

Comercial. Solo verifyApiUser. No pasa por verifyLicense. El dueño del trabajo es el id del API user, no el código de licencia. Aislamiento estricto respecto a Demo.
POST /docs-emitidos/comercial COMERCIAL

Autenticación

AuthorizationBearer TU_API_KEYrequerido
Cuerpo JSON
CampoTipoDescripción
rucstringrequeridoRUC con el que se inicia sesión en el portal del SRI.
clavestringrequeridoClave del portal del SRI. Distinta de claveAcceso.
fechaEmisionstringrequeridoFecha de emisión en YYYY-MM-DD o DD/MM/YYYY. Debe ser anterior a hoy en America/Guayaquil.
estadoAutorizacionstringopcionalPor defecto autorizados. También noAutorizados y porProcesar.
tipostringopcionalPor defecto factura. Valores: factura, liquidacion, credito, debito, guia, retencion. Varios separados por coma.
establecimientostringopcionalTres dígitos, por ejemplo 001, si el formulario lo muestra.
puntoEmisionstringopcionalTres dígitos, si el formulario lo muestra.
claveAccesostringopcionalFiltro de 49 dígitos (clave de acceso / nro. autorización).
identificacionstringopcionalRUC, cédula o pasaporte del filtro de consulta, 10–13 dígitos.
httpHandoffbooleanopcionalPor defecto true. Igual comportamiento que en Demo: descarga HTTP contra el formulario JSF con javax.faces.ViewState.
soloReportebooleanopcionalPor defecto false. En true baja solo el TXT y no pide XML.
esperarbooleanopcionalPor defecto true. Con false responde 202 de inmediato. Si se agota SRI_ESPERA_HTTP_MS, 202 + esperaAgotada: true.

Restricciones de fecha: fechaEmision es obligatoria, admite YYYY-MM-DD o DD/MM/YYYY y debe ser anterior al día actual en America/Guayaquil. El SRI rechaza la fecha de hoy y no se sustituye por otra.

Diferencias con Demo: el contrato JSON es idéntico. Lo único que cambia es el prefijo de ruta (/comercial) y que los jobs de una modalidad no pueden leerse desde la otra.

Ejemplos de consumo
cURL
fetch
Python
curl -X POST "https://apis.davycorp.ec/v2/docs-emitidos/comercial" \
  -H "Authorization: Bearer TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "ruc": "1790000000001",
    "clave": "TU_CLAVE_SRI",
    "fechaEmision": "2026-09-14",
    "tipo": "factura,retencion"
  }'
await fetch("https://apis.davycorp.ec/v2/docs-emitidos/comercial", {
  method: "POST",
  headers: {
    Authorization: "Bearer TU_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    ruc: "1790000000001",
    clave: "TU_CLAVE_SRI",
    fechaEmision: "2026-09-14",
    tipo: "factura,retencion"
  })
});
import requests
requests.post(
    "https://apis.davycorp.ec/v2/docs-emitidos/comercial",
    headers={"Authorization": "Bearer TU_API_KEY"},
    json={
        "ruc": "1790000000001",
        "clave": "TU_CLAVE_SRI",
        "fechaEmision": "2026-09-14",
        "tipo": "factura,retencion",
    },
)
Respuestas
202 · Creación
200 · Estado
Errores
{
  "job_id": "8c1d0c2e-4b1a-4f0e-9c2a-6e5b1a0d4f11",
  "estado": "pendiente",
  "mensaje": "Descarga iniciada. Consulta el estado con el mismo prefijo de modalidad."
}
{
  "id": "JOB_ID",
  "estado": "completado",
  "modalidad": "comercial",
  "zip_url": "/v2/docs-emitidos/comercial/JOB_ID/archivo",
  "archivoUrl": "/v2/docs-emitidos/comercial/JOB_ID/archivo",
  "comprobantesUrl": "/v2/docs-emitidos/comercial/JOB_ID/comprobantes",
  "resultadoUrl": "/v2/docs-emitidos/comercial/JOB_ID",
  "error": null,
  "creado": "2026-10-26T18:00:00.000Z",
  "terminado": "2026-10-26T18:04:12.000Z"
}
// 400 — cuerpo incompleto
{ "error": "ruc y clave son obligatorios" }

// 400 — fecha inválida
{ "error": "La fecha ingresada debe ser menor a la fecha actual" }

// 401 — sin header Authorization
{ "error": "API Key requerida" }

// 403 — API key inválida
{ "success": false, "error": "Api user inválido" }

// 404 — job inexistente o de otro dueño/modalidad
{ "error": "Job no encontrado" }

// 409 — consultar comprobantes/archivo en ejecución
{ "error": "El trabajo sigue en ejecución" }

// 429 — cupo del API user
{ "error": "Límite de consultas alcanzado", "status": false }

// 500 — fallo interno
{ "error": "Error interno del servidor", "status": false }
Endpoints secundarios (Comercial)
MétodoEndpoint relativoFunción
GET/v2/docs-emitidos/comercial/:jobIdConsultar estado del trabajo.
GET/v2/docs-emitidos/comercial/:jobId/comprobantesObtener listado JSON.
GET/v2/docs-emitidos/comercial/:jobId/archivoDescargar ZIP.
POST/v2/docs-emitidos/comercial/:jobId/cancelarCancelar trabajo.

Estado, archivo y cancelación repiten la cadena de verifyApiUser y la comprobación de dueño. Cruzar modalidad o dueño responde 404 con {"error":"Job no encontrado"} o {"error":"Archivo no disponible"}.

Flujo completo de un trabajo
  1. Enviar el POST a la modalidad elegida (/demo o /comercial).
  2. Leer el identificador devuelto en job_id.
  3. Consultar el estado con el prefijo de la misma modalidad: GET /v2/docs-emitidos/{modalidad}/:jobId.
  4. Consultar los comprobantes cuando el estado lo permita: GET .../:jobId/comprobantes.
  5. Descargar el ZIP cuando archivoUrl esté disponible: GET .../:jobId/archivo.
  6. Cancelar si todavía se puede: POST .../:jobId/cancelar.
No mezclar modalidades. Un jobId creado con /demo solo se consulta con /demo; lo mismo para /comercial. Cruzar modalidad o dueño responde 404.
Ejemplo con cURL
# 1) Crear trabajo
curl -X POST "https://apis.davycorp.ec/v2/docs-emitidos/demo" \
  -H "Authorization: Bearer TU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ruc":"1790000000001","clave":"TU_CLAVE_SRI","fechaEmision":"2026-09-14","tipo":"factura"}'

# 2) Consultar estado (usa el job_id devuelto)
curl "https://apis.davycorp.ec/v2/docs-emitidos/demo/JOB_ID" \
  -H "Authorization: Bearer TU_API_KEY"

# 3) Listado JSON de comprobantes
curl "https://apis.davycorp.ec/v2/docs-emitidos/demo/JOB_ID/comprobantes" \
  -H "Authorization: Bearer TU_API_KEY"

# 4) Descargar ZIP
curl -L "https://apis.davycorp.ec/v2/docs-emitidos/demo/JOB_ID/archivo" \
  -H "Authorization: Bearer TU_API_KEY" \
  -o comprobantes.zip

# 5) Cancelar (si sigue pendiente/procesando)
curl -X POST "https://apis.davycorp.ec/v2/docs-emitidos/demo/JOB_ID/cancelar" \
  -H "Authorization: Bearer TU_API_KEY"
Estados del trabajo
EstadoSignificado
pendienteEn cola. La clave está solo en memoria de este proceso.
procesandoLogin y descarga en curso. Hay un solo trabajo a la vez.
completadoLa consulta al SRI terminó. Puede ser período vacío (total 0) o ZIP completo. archivoUrl / zip_url apuntan a GET /{jobId}/archivo si el temporal sigue.
parcialHay listado pero el portal no entregó todos los XML (o ninguno), o quedó paginación sin recorrer. El ZIP, si existe, no se presenta como completo.
fallidoError o reinicio del servidor. No se vuelve a intentar el login solo.
canceladoEl cliente pidió parar.

Reintentos. INTENTOS vale 6. No se reintenta un rechazo explícito de credenciales ni un Chromium que no arranca. Dentro de una página, SRI_XML_WORKERS vale 2. SRI_JOB_TIMEOUT_MS en 0 no corta el trabajo.

Archivos. XML, TXT y ZIP viven en un directorio temporal por trabajo (os.tmpdir()), no en el repo. El listado JSON se guarda en PostgreSQL (metadatos, no el XML). El ZIP incluye xml/, comprobantes.json y resultado.json. Se borra al terminar la transmisión o al vencer SRI_TMP_TTL_MS (30 min por defecto). El nombre del ZIP es comprobantes_<TIPO>_<anio>_<mes>.zip.

Modo esperar. Si se omite esperar vale true y el POST espera el trabajo real. Con esperar=false responde 202 de inmediato. Si el tiempo HTTP se agota, 202 con esperaAgotada: true y el mismo jobId. Hay que seguir consultando el GET de estado.

Reinicio. Al arrancar, lo que quedó pendiente o procesando pasa a fallido. La clave no está en PostgreSQL, así que el proceso no puede volver a entrar al SRI por su cuenta.

Modalidades disponibles
ModalidadCrear trabajoMiddlewaresDueño
DemoPOST /v2/docs-emitidos/demoverifyApiUserid del API user
ComercialPOST /v2/docs-emitidos/comercialverifyApiUserid del API user

Estado, archivo y cancelación repiten la misma cadena. Cruzar modalidad o dueño responde 404 con {"error":"Job no encontrado"} o {"error":"Archivo no disponible"}.

No es documentos recibidos. Esta API entra por pages/consultas/menu.jsf y consulta los documentos que el contribuyente emitió. Los recibidos siguen en /v2/docs-recibidos.
Códigos que devuelve el servidor
HTTPCuándoCuerpo
200Consulta de estado, comprobantes, o cancelación de un pendienteJSON del trabajo, o estado: cancelado
202Trabajo creado (asíncrono), espera HTTP agotada, o cancelación diferidajob_id, estado, mensaje, opcionalmente esperaAgotada
400Faltan ruc y clave, tipo desconocido, fecha inválida o filtros incompatibleserror
401Sin header Authorization{"error":"API Key requerida"}
403API key inválidasuccess: false, error
404Trabajo de otro dueño o modalidad, o ZIP que ya no estáJob no encontrado o Archivo no disponible
409Cancelar un trabajo ya terminado, o consultar comprobantes/ZIP mientras sigue en ejecuciónEl trabajo ya terminó o El trabajo sigue en ejecución
429El API user llegó a usage_limit{"error":"Límite de consultas alcanzado","status":false}
500Fallo interno al crear, consultar o guardarerror y status: false

No todos los endpoints devuelven todos los códigos. Los GET de estado, comprobantes y archivo no atraviesan verifyLicense; aplican 401, 403, 404, 409 y 500. El POST de creación añade 400 y 429 según el cuerpo y el cupo del API user.

Un fallo del portal queda en error del trabajo y no detiene el proceso de las otras APIs. La descarga masiva contra el SRI no forma parte de esta integración: un trabajo, un período.