Facturas
Crear y gestionar comprobantes electrónicos. El endpoint principal
(POST /api/v1/facturas) es asíncrono: responde con la
factura en PENDIENTE y la autoriza en background.
Crear un comprobante
POST /api/v1/facturas — Crea un comprobante (async)
Body
| Parámetro | Tipo | Descripción |
|---|---|---|
tipo_identificacion required | string | Tipo de identificación del comprador (tabla SRI): '04' RUC, '05' cédula, '06' pasaporte, '07' consumidor final, '08' id. del exterior. |
identificacion required | string | RUC (13 dígitos), cédula (10) o documento según el tipo. |
razon_social required | string | Nombre o razón social del comprador. Máx 300 caracteres. |
direccion optional | string | Dirección del comprador (se imprime en el RIDE). |
email optional | string | Email del comprador; se usa al enviar el RIDE por correo. |
detalles required | array | Líneas del comprobante. Mínimo 1. |
sucursal_id optional | integer | Sucursal emisora (estab/punto de emisión). Si se omite, se infiere del usuario o de la matriz. |
es_borrador optional | boolean | Si true, se guarda como BORRADOR y no se envía al SRI. Default: false. |
idempotency_key optional | string | Idempotencia (también vía header Idempotency-Key): reintentar con la misma key devuelve la MISMA factura (200) en vez de crear otra. |
pagos optional | array | Formas de pago (split). Si se omite, se registra un único pago '01' (efectivo) por el total. Cada elemento tiene 'forma_pago' (código Tabla 24 SRI), 'total', y opcionalmente 'plazo'+'unidadTiempo' ('dias') para crédito. |
condicion_pago optional | string | 'contado' (default) o 'credito'. Si 'credito', se exige 'fecha_vencimiento'. |
fecha_vencimiento optional | date | Solo si 'condicion_pago'='credito' (YYYY-MM-DD). |
propina optional | number | Propina / 10% de servicio en USD (≥ 0). Solo para empresas marcadas como restaurante, bar u hotel. Suma al total y no grava IVA. Default: 0. Ver propina. |
Forma de pagos[] (Tabla 24 SRI)
| Parámetro | Tipo | Descripción |
|---|---|---|
forma_pago required | string | Código de la Tabla 24 SRI: '01' efectivo, '15' compensación, '16' T. débito, '17' dinero electrónico, '18' T. prepago, '19' T. crédito, '20' otros, '21' endoso. |
total required | number | Monto del pago en USD. La Σ de todos los pagos debe cuadrar (tolerancia ±0.01) con el total de la factura (incluida la propina, si la hay). |
plazo optional | integer | Plazo del pago a crédito (entero ≥ 1). Solo si aplica. |
unidad_tiempo optional | string | Unidad del plazo. Únicamente 'dias' está soportado por el SRI. |
Forma de detalles[]
| Parámetro | Tipo | Descripción |
|---|---|---|
codigo_principal required | string | Código del producto/servicio (codigoPrincipal del SRI). Máx 25 caracteres. |
descripcion required | string | Texto que aparece en el RIDE. Máx 300 caracteres. |
cantidad required | number | Cantidad, mayor a 0. Hasta 6 decimales. |
precio_unitario required | number | Precio sin impuestos, en USD. Hasta 6 decimales. |
descuento optional | number | Descuento por línea en valor absoluto (no porcentaje). Default: 0. |
tarifa_iva optional | integer | Tarifa de IVA (%): 0, 5 ó 15. Default: 15. |
iva_codigo optional | string | codigoPorcentaje del SRI si necesitas distinguir 0% ('0') de exento ('7') o no objeto ('6'). Si se omite, se deriva de tarifa_iva. |
Respuesta (201 Created)
{
"id": 177,
"numero_comprobante": "001-001-000000177",
"fecha_emision": "2026-07-03T10:12:34",
"tipo_identificacion": "04",
"identificacion": "0991234567001",
"razon_social": "ACME S.A.",
"direccion": null,
"email": "facturacion@acme.example",
"subtotal_0": 0.0,
"subtotal_15": 75.0,
"iva": 11.25,
"total": 86.25,
"propina": 0.0,
"estado": "PENDIENTE",
"clave_acceso": null,
"numero_autorizacion": null,
"fecha_autorizacion": null,
"estado_sri": null,
"detalles": [ { "...": "..." } ],
"pagos": [ { "forma_pago": "01", "total": 86.25 } ]
}import { Emitoo } from "emitoo";
const client = new Emitoo(); // lee la API key de EMITOO_API_KEY
const factura = await client.facturas.crear(
{
tipo_identificacion: "04",
identificacion: "0991234567001",
razon_social: "ACME S.A.",
email: "facturacion@acme.example",
detalles: [
{ codigo_principal: "LIC-1", descripcion: "Licencia mensual",
cantidad: 1, precio_unitario: 75.0, tarifa_iva: 15 },
],
},
{ idempotencyKey: "order-90210" },
);from emitoo import EmitooClient
client = EmitooClient() # lee la API key de EMITOO_API_KEY
factura = client.facturas.crear(
{
"tipo_identificacion": "04",
"identificacion": "0991234567001",
"razon_social": "ACME S.A.",
"email": "facturacion@acme.example",
"detalles": [
{"codigo_principal": "LIC-1", "descripcion": "Licencia mensual",
"cantidad": 1, "precio_unitario": 75.0, "tarifa_iva": 15},
],
},
idempotency_key="order-90210",
)client, err := emitoo.New("") // lee la API key de EMITOO_API_KEY
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
factura, err := client.Facturas.Crear(ctx, emitoo.M{
"tipo_identificacion": "04",
"identificacion": "0991234567001",
"razon_social": "ACME S.A.",
"email": "facturacion@acme.example",
"detalles": []emitoo.M{
{"codigo_principal": "LIC-1", "descripcion": "Licencia mensual",
"cantidad": 1, "precio_unitario": 75.0, "tarifa_iva": 15},
},
}, emitoo.WithIdempotencyKey("order-90210"))
if err != nil {
log.Fatal(err)
}curl -X POST https://api.emitoo.io/api/v1/facturas \
-H "X-API-Key: $EMITOO_API_KEY" \
-H "Idempotency-Key: order-90210" \
-H "Content-Type: application/json" \
-d '{
"tipo_identificacion": "04",
"identificacion": "0991234567001",
"razon_social": "ACME S.A.",
"email": "facturacion@acme.example",
"detalles": [
{ "codigo_principal": "LIC-1", "descripcion": "Licencia mensual",
"cantidad": 1, "precio_unitario": 75.00, "tarifa_iva": 15 }
]
}'¿Cuándo se considera autorizada?
PENDIENTE. La firma,
envío y respuesta del SRI ocurren en segundo plano. Te avisamos por
webhook
(factura.autorizada) cuando el comprobante queda firme, o
puedes hacer polling a /status.
Propina (10% de servicio)
Restaurantes, bares y hoteles pueden cobrar la propina en la misma factura
con el campo propina. Va en el elemento
<propina> del XML, se suma a
importeTotal (y al total de la factura, que es lo
que el cliente debe), no grava IVA y se imprime en el RIDE. Las
pagos[] deben cuadrar con el total ya incluida la propina.
- Solo la aceptan las empresas marcadas como Restaurante, bar u hotel en Configuración; si no,
400. - Una factura dividida en partes (
POST /api/v1/facturas/lote) no puede llevar propina (400). - No se acredita con nota de crédito: el tope de una NC sobre esa factura es su total sin la propina.
{
"tipo_identificacion": "07",
"identificacion": "9999999999999",
"razon_social": "CONSUMIDOR FINAL",
"detalles": [
{ "codigo_principal": "MENU-1", "descripcion": "Almuerzo ejecutivo",
"cantidad": 2, "precio_unitario": 10.00, "tarifa_iva": 15 }
],
"propina": 2.00,
"pagos": [ { "forma_pago": "01", "total": 25.00 } ]
}Subtotal 20,00 + IVA 3,00 + propina 2,00 = total 25,00.
RUC Proveedor en el XML
Desde el 26 de septiembre de 2026 el SRI exige que todo comprobante
electrónico identifique al proveedor del sistema de facturación. Emitoo
agrega en infoAdicional de los seis tipos de comprobante
(factura, nota de crédito, nota de débito, guía de remisión, retención y
liquidación de compra) el campo
<campoAdicional nombre="RUC Proveedor">0993411199001</campoAdicional>.
Va como primer campo adicional, antes del email y la descripción del
comprobante. No tienes que enviarlo ni configurarlo.
Obtener un comprobante
GET /api/v1/facturas/{id} — Detalle completo, con líneas
Consultar el estado
GET /api/v1/facturas/{id}/status — Solo el estado actual (más liviano)
{
"id": 177,
"estado": "AUTORIZADO",
"clave_acceso": "0307202601099336782800110010010000001771234567813",
"numero_autorizacion": "0307202601099336782800110010010000001771234567813",
"fecha_autorizacion": "2026-07-03T10:12:48",
"estado_sri": "[AUTORIZADO]"
}
Estados posibles: BORRADOR, PENDIENTE,
PROCESANDO, EN_PROCESO (recibida por el SRI,
esperando autorización), AUTORIZADO, RECHAZADO y
DEVUELTA (la recepción del SRI no la aceptó). Más detalle en
estados de un comprobante.
Reenviar un comprobante
POST /api/v1/facturas/{id}/reenviar — Re-encola la factura para el worker (sin body)
Si la factura fue DEVUELTA o RECHAZADO, se
re-emite con clave de acceso nueva (corrige primero la causa, p.ej. la
configuración del emisor). Si está colgada (PENDIENTE /
EN_PROCESO), conserva la clave y solo se re-consulta la
autorización, sin duplicar. Con una factura ya AUTORIZADO
responde 409. El motivo del rechazo viene en
estado_sri (en GET /facturas/{id} o
/status).
Descargar el RIDE en PDF
GET /api/v1/facturas/{id}/ride — Devuelve el PDF binario
Devuelve el PDF del RIDE con Content-Type: application/pdf,
generado con el logo y colores configurados en tu empresa.
Enviar el comprobante por email
POST /api/v1/facturas/{id}/email — Envía el RIDE al cliente final (sin body)
Query params
| Parámetro | Tipo | Descripción |
|---|---|---|
to optional | string | Dirección de destino. Si se omite, usa el email del comprador en la factura (400 si no hay ninguno). |
Listar comprobantes
GET /api/v1/facturas?desde=&hasta=&estado=&q=&cliente_id=&con_saldo=&limit=&offset= — Listado compacto (id, número, fecha, cliente, total, estado, ambiente)
| Parámetro | Tipo | Descripción |
|---|---|---|
desde / hasta optional | date | Fecha de emisión (inclusive). |
estado optional | string | Estado exacto: PENDIENTE, EN_PROCESO, AUTORIZADO, RECHAZADO, DEVUELTA, ANULADO… |
q optional | string | Busca en razón social del cliente, identificación y número de comprobante. |
cliente_id optional | integer | Solo las del cliente del catálogo con ese id. |
con_saldo optional | boolean | true = solo las AUTORIZADO con saldo por cobrar. |
limit / offset optional | integer | Paginación. Sin parámetros devuelve las últimas 100. |
format optional | string | 'csv' = el mismo listado como archivo CSV (UTF-8 con BOM, para que Excel muestre bien las tildes). Sin limit no se trunca a 100 (tope 50 000). |
Resumen de ventas
GET /api/v1/facturas/resumen — Tablero: ventas de hoy, la semana y el mes, serie de 30 días, pendientes ante el SRI, cartera y top de clientes
Devuelve hoy, semana, mes,
mes_anterior, serie (últimos 30 días),
pendientes_sri, por_cobrar,
top_clientes del mes, ambiente_sri,
tiene_certificado y cert_expira (vencimiento de la
firma electrónica). Respeta el mismo alcance que el listado.