Contenido de esta página

¿Integras tu propio sistema? Emite los seis comprobantes del SRI desde tu código con la API de Contadeo: idempotencia, webhooks firmados y ambiente de Pruebas que no gasta cupo.

Empezar gratis →

Tu primera factura al SRI por API: el recorrido completo, de la cuenta al RIDE

Tienes un checkout que ya cobra y quieres que, al confirmarse el pago, salga la factura electrónica autorizada por el SRI sin que nadie abra un panel. Desde el 1 de enero de 2026, con la Resolución NAC-DGERCGC25-00000017, esa factura viaja al SRI en el momento de emitirla: ya no hay lote nocturno donde esconder un error de integración.

Este artículo es el recorrido entero, en el orden real en que hay que hacerlo: crear la cuenta, generar la API key, registrar el emisor con su establecimiento y su punto de emisión, subir el certificado .p12, emitir la factura, esperar la autorización y descargar el RIDE. Todo contra el ambiente de Pruebas del SRI, que no consume el cupo de tu plan.

Ojo: para emitir en Pruebas necesitas un RUC real y un certificado .p12 real. No hay un certificado de pruebas compartido: el ambiente de Pruebas es el del propio SRI y firma con tu certificado, igual que Producción. Lo único que cambia es que los comprobantes no tienen validez tributaria.

Pruebas y Producción son el mismo código con un campo distinto

Cada cuenta emite contra un ambiente y se cambia con un PATCH. Lo que certificas en Pruebas es exactamente lo que emitirás en Producción.

Pruebas (ambienteActivo: 1) Producción (ambienteActivo: 2)
Validez tributaria No
Cupo de tu plan No lo consume (tope propio de 500/mes) Lo consume
Firma Tu .p12 Tu .p12

Con el plan gratuito emites 10 comprobantes de Producción al mes, sin tarjeta. Los 500 de Pruebas van aparte, así que puedes integrar sin gastar nada.

Paso 1: la cuenta se crea con un POST público

POST /tenants/register es de los pocos endpoints que no piden token. Crea la cuenta y su usuario owner en plan free, y devuelve el par de tokens JWT.

API=https://contadeo.com/api

curl -X POST $API/tenants/register -H 'content-type: application/json' \
  -d '{"nombre":"Mi Empresa","email":"yo@empresa.ec","password":"secreta123",
       "ruc":"0912345675001","declaraTitularidadRuc":true,
       "aceptaPrivacidad":true,"aceptaTerminos":true}'

Los cuatro campos que la gente olvida: ruc (con dígito verificador válido) y declaraTitularidadRuc, más aceptaPrivacidad y aceptaTerminos, que son el consentimiento LOPDP del aviso de privacidad. Sin cualquiera de ellos la respuesta es 400. El slug no se envía: lo genera el sistema. El registro está limitado a 5 altas por IP cada 10 minutos; al pasarte recibes 429.

Paso 2: la API key se genera en el panel, no por API

Aquí es donde muchas integraciones se atascan buscando un endpoint que no existe: no hay una ruta pública para crear API keys. Se generan en el panel, en Configuración → API, con rol owner o admin, y la key se muestra una sola vez.

Lo que sí conviene saber antes de crearla:

  • Se envía como Authorization: Bearer cdo_... y no expira ni necesita refresh: es la credencial de tu servidor.
  • Sus permisos son acotados por diseño. Puede llevar los roles emisor, contador, lector y webhooks (por defecto, emisor), pero nunca owner ni admin: una key filtrada no puede tocar usuarios, otras keys ni la configuración de la cuenta.
  • Hasta 5 keys activas por cuenta, y la revocación desde el panel es inmediata (quien la use recibe 401 al instante).

Para el resto del recorrido, TOKEN es esa key.

Paso 3: emisor, establecimiento y punto de emisión

El emisor es el RUC que factura. Debajo cuelgan el establecimiento y el punto de emisión, que son los dos primeros bloques del número de comprobante (001-001-000000001).

curl -X POST $API/emisores -H "authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' \
  -d '{"ruc":"0912345675001","razonSocial":"MI EMPRESA S.A.",
       "dirMatriz":"Av. Principal 123, Guayaquil",
       "obligadoContabilidad":false,"regimen":"GENERAL"}'
# regimen: GENERAL | RIMPE_EMPRENDEDOR | RIMPE_NEGOCIO_POPULAR
# El dígito verificador del RUC se valida aquí → 400 si es inválido.

curl -X POST $API/emisores/$EMISOR_ID/establecimientos \
  -H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
  -d '{"codigo":"001","direccion":"Matriz centro","nombre":"Matriz"}'

El codigo es de exactamente 3 dígitos, igual para el punto de emisión (POST /establecimientos/:estabId/puntos-emision).

Consejo: si ese RUC ya facturaba con otro sistema, sincroniza el secuencial antes de emitir con PATCH /emisores/:emisorId/secuenciales (ultimoNumero = el último número ya usado). Si no lo haces, Contadeo se autorecupera reemitiendo, pero verás el error 45 del SRI («secuencial registrado») hasta alcanzar el número bueno.

Paso 4: el .p12 sube como JSON en base64

El certificado de firma no va como multipart: va como un campo más del JSON, en base64, junto con su contraseña.

curl -X POST $API/certificados -H "authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' \
  -d "{\"emisorId\":\"$EMISOR_ID\",
       \"p12Base64\":\"$(base64 -w0 certificado.p12)\",
       \"passphrase\":\"<contraseña del .p12>\",\"alias\":\"firma 2026\",
       \"declaraTitularidadFirma\":true}"
# → { "id": "<certificadoId>", "subject": "...", "notAfter": "2029-..." }

El archivo y su contraseña se cifran con envelope AES-256-GCM y solo se descifran en memoria en el momento de firmar. El GET /certificados nunca devuelve material secreto.

Paso 5: la factura responde 202, no 200

La emisión es asíncrona. El POST valida el cuadre, reserva el secuencial de forma atómica, genera la clave de acceso de 49 dígitos y encola la firma y la transmisión. Por eso responde 202 con el comprobante en BORRADOR.

Manda siempre Idempotency-Key con un identificador tuyo —el id del pedido, por ejemplo—: si el request se corta y reintentas, recibes el mismo comprobante en vez de duplicarlo y quemar otro secuencial.

curl -s -X POST $API/comprobantes/factura \
  -H "authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: pedido-8841" \
  -H 'content-type: application/json' -d '{
  "emisorId":"'$EMISOR_ID'","certificadoId":"'$CERT_ID'",
  "establecimiento":"001","puntoEmision":"001",
  "infoFactura":{
    "tipoIdentificacionComprador":"05",
    "razonSocialComprador":"JUAN PEREZ","identificacionComprador":"1745678902",
    "obligadoContabilidad":"NO",
    "totalSinImpuestos":10,"totalDescuento":0,
    "totalConImpuestos":[{"codigo":"2","codigoPorcentaje":"4",
      "baseImponible":10,"tarifa":15,"valor":1.5}],
    "importeTotal":11.5,"pagos":[{"formaPago":"01","total":11.5}]},
  "detalles":[{"descripcion":"Producto","cantidad":1,"precioUnitario":10,
    "descuento":0,"precioTotalSinImpuesto":10,
    "impuestos":[{"codigo":"2","codigoPorcentaje":"4","tarifa":15,
      "baseImponible":10,"valor":1.5}]}]
}'
# → { "comprobanteId": "uuid", "claveAcceso": "49 dígitos", "estado": "BORRADOR" }

Ese cuerpo son $10.00 + 15 % de IVA = $11.50. El IVA general del 15 % es codigo: "2" con codigoPorcentaje: "4". La fechaEmision no se envía: la fija el servidor en hora de Ecuador.

Si los totales no cuadran, la respuesta es 400 con la lista de problemas[] antes de tocar al SRI. Es la diferencia entre enterarte en el mismo request y enterarte tres minutos después por un rechazo.

Paso 6: consulta hasta AUTORIZADO y descarga el RIDE

El comprobante recorre BORRADOR → FIRMADO → ENVIADO → AUTORIZADO. Haz polling de GET /comprobantes/:id cada ~3 segundos hasta un estado terminal (AUTORIZADO, RECHAZADO o DEVUELTA); el SRI suele resolver en 5 a 30 segundos.

curl -s $API/comprobantes/$ID -H "authorization: Bearer $TOKEN"
# → { "estado": "AUTORIZADO", "claveAcceso": "...", "numeroAutorizacion": "..." }

curl -s $API/comprobantes/$ID/ride -H "authorization: Bearer $TOKEN"  # {"url": ...}
curl -s $API/comprobantes/$ID/xml  -H "authorization: Bearer $TOKEN"  # {"url": ...}

El RIDE (PDF) y el XML autorizado vuelven como URLs prefirmadas que expiran en 1 hora. Si el comprobante termina en DEVUELTA o RECHAZADO, la respuesta incluye mensajesSri con los mensajes literales del SRI, para mostrar la razón sin adivinar.

Cuando la integración pase de prototipo a producto, cambia el polling por webhooks firmados: un POST a tu servidor cuando el comprobante llega a estado final.

Preguntas frecuentes

¿Necesito RUC y firma electrónica para probar la API? Sí, los dos, incluso en Pruebas. El ambiente de Pruebas es el del SRI y firma con tu certificado .p12; no hay uno compartido para desarrolladores. Lo que no necesitas es tarjeta: el plan gratuito y los 500 comprobantes de Pruebas al mes cubren la integración.

¿Puedo crear la API key por API? No. Se genera en el panel, en Configuración → API, con rol owner o admin, y se muestra una sola vez. Es deliberado: la credencial de máquina no se emite desde la máquina.

¿Qué pasa si reintento el mismo POST de factura? Con la misma Idempotency-Key recibes el mismo comprobante marcado reutilizado: true, sin duplicar ni quemar secuencial. La clave no caduca, y si llega con un cuerpo distinto la respuesta es 422 en vez de un comprobante que no corresponde.

¿Cómo paso a Producción? PATCH /tenants/current con {"ambienteActivo": 2}, o un clic en el panel, cuando tu RUC ya certificó en Pruebas los tipos de comprobante que vas a emitir. Desde ese momento son documentos tributarios reales.

Cómo empezar

Crea tu cuenta gratis —10 comprobantes al mes, sin tarjeta— y haz el recorrido completo en el ambiente de Pruebas. La documentación para integradores trae los seis tipos de comprobante con sus cuerpos, y la referencia OpenAPI tiene cada endpoint con sus esquemas y errores. Si prefieres generar el cliente, el spec descargable y el SDK oficial para TypeScript te ahorran el trabajo.


Contadeo — Facturación electrónica del SRI (Ecuador) por API, panel o IA. Documentación de la API · Matriz de capacidades · Crea tu cuenta