MRZ 0.2.0 XAdES-BES 1.3.2 Certificación SRI

Documentación y Guía de Integración

Guía práctica con ejemplos listos para copiar y probar. Esta API se encarga de la generación del XML v2.1.0, gestión Multitenant nativa con certificados PKCS#12 cifrados en reposo (AES-256-GCM), firma digital, transmisión SOAP al SRI, reintentos con respaldo SQLite y generación automática de la representación gráfica RIDE (PDF).

⚡ Inicio Rápido

Para levantar el servidor localmente en PowerShell con la clave de sesión generada:

# 1. Crear entorno y activar dependencias
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt

# 2. Generar clave segura y asignarla al portapapeles y entorno
$env:SRI_API_KEY = .\.venv\Scripts\python.exe -c "import secrets; print(secrets.token_urlsafe(32))"
$env:SRI_API_KEY | Set-Clipboard

# 3. Arrancar la API
.\.venv\Scripts\python.exe -m uvicorn app.main:app --host 127.0.0.1 --port 8000
💡 ¿Cómo aprovechar Swagger UI (/docs)?
Una vez levantado Uvicorn, haz clic en el botón "Abrir Swagger UI (/docs)" en la barra lateral. Haz clic en el botón verde Authorize 🔓 en la esquina superior derecha y pega tu SRI_API_KEY. Todos los endpoints quedarán listos para probar interactivamente con "Try it out".

🔐 Autenticación

Todas las llamadas requieren autenticación mediante encabezado HTTP con la clave definida en SRI_API_KEY. Puedes usar cualquiera de las dos formas:

Encabezado Ejemplo de Formato Descripción
X-API-Key X-API-Key: eB2u9f_zX4-k7qR... Encabezado estándar recomendado para clientes REST y scripts.
Authorization Authorization: Bearer eB2u9f_zX4-k7qR... Formato Bearer Token (ideal para librerías HTTP estándar).

🔄 Flujo de Emisión: 2 Formas de Usar la API

La API ofrece dos modalidades según tus necesidades de integración:

A

Ruta /api (Recomendada)

Tú envías los datos de la venta con un Idempotency-Key. La API guarda el emisor, genera el XML, firma, envía al SRI, gestiona los reintentos en segundo plano y produce el RIDE en PDF automáticamente.

B

Ruta Directa (Paso a Paso)

Para ERPs que desean controlar manualmente cada etapa: POST /invoices (generar) ➔ POST /documents/{access_key}/send (firmar y enviar) ➔ POST /documents/{access_key}/check (consultar estado).

🩺 Estado del Sistema & Monitoreo

Endpoint público para sondas de disponibilidad, monitoreo de la base de datos y métricas de emisores activos:

GET /health
Público (Sin API Key)
curl -X GET "http://127.0.0.1:8000/health"
{
  "status": "ok",
  "database": "conectada",
  "ambiente": "PRUEBAS",
  "multitenant": true,
  "total_tenants": 3,
  "tenants_activos": 3,
  "certificado_configurado": true,
  "emisor_ruc_configurado": true
}

🏢 Gestión Multitenant de Certificados Digitales (.p12)

Permite a una sola instancia de la API firmar comprobantes para múltiples empresas o RUCs de forma aislada. Los certificados .p12 y sus contraseñas se almacenan cifrados en reposo mediante AES-256-GCM.

Endpoint Método Descripción
/tenants POST Registra un emisor enviando el certificado .p12 codificado en Base64.
/tenants/upload POST Carga directa del archivo .p12 o .pfx mediante multipart/form-data.
/tenants GET Lista todos los emisores registrados, estado de vigencia y días restantes de la firma.
/tenants/{ruc} GET Consulta el detalle, emisor de la firma y metadatos de un RUC específico.
/tenants/{ruc}/health GET Comprobación de salud de la firma (alerta si faltan menos de 30 días para su vencimiento).
/tenants/{ruc}/toggle?active=true|false PATCH Activa o inhabilita temporalmente la emisión para ese RUC.
/tenants/{ruc} DELETE Elimina el emisor y destruye su certificado digital del almacén seguro.
POST /tenants/upload
Subir archivo .p12 directamente
$form = @{
  file = Get-Item "C:\claves\firma_empresa.p12"
  ruc = "1790000000001"
  business_name = "Mi Empresa Multitenant S.A."
  password = "ClaveDelCertificado123"
}
Invoke-RestMethod "http://127.0.0.1:8000/tenants/upload" `
  -Method Post `
  -Headers @{ 'X-API-Key' = $env:SRI_API_KEY } `
  -Form $form
curl -X POST "http://127.0.0.1:8000/tenants/upload" \
  -H "X-API-Key: TU_CLAVE_API" \
  -F "file=@/ruta/a/firma.p12" \
  -F "ruc=1790000000001" \
  -F "business_name=Mi Empresa Multitenant S.A." \
  -F "password=ClaveDelCertificado123"
curl -X POST "http://127.0.0.1:8000/tenants" \
  -H "X-API-Key: TU_CLAVE_API" \
  -H "Content-Type: application/json" \
  -d '{
    "ruc": "1790000000001",
    "business_name": "Mi Empresa Multitenant S.A.",
    "p12_base64": "MIIKYgIBAzCCCl4GCSqGSIb3DQEHAaCCCK8EggirMII...==",
    "password": "ClaveDelCertificado123"
  }'

🔢 Control y Configuración de Secuenciales

Los secuenciales del SRI se incrementan de forma automática, atómica y aislada por serie: {ambiente}-{ruc}-{tipo_doc}-{establecimiento}-{punto_emision}.

Si tu empresa ya venía emitiendo en otro sistema o sucursal y necesitas fijar el siguiente secuencial de arranque, utiliza POST /api/sequential:

POST /api/sequential
Establecer secuencial inicial de una serie
# Configurar para que la serie empiece en el secuencial 500
curl -X POST "http://127.0.0.1:8000/api/sequential" \
  -H "X-API-Key: TU_CLAVE_API" \
  -H "Content-Type: application/json" \
  -d '{
    "series": "1-1790000000001-01-001-001",
    "next_sequential": 500
  }'
$config = @{
  series = "1-1790000000001-01-001-001"
  next_sequential = 500
}
Invoke-RestMethod "http://127.0.0.1:8000/api/sequential" `
  -Method Post `
  -Headers @{ 'X-API-Key' = $env:SRI_API_KEY } `
  -ContentType "application/json" `
  -Body ($config | ConvertTo-Json)
# Consultar el secuencial actual emitido para la serie
curl -X GET "http://127.0.0.1:8000/api/sequential/1-1790000000001-01-001-001" \
  -H "X-API-Key: TU_CLAVE_API"

🏢 1. Configurar Perfil del Emisor

Configura una sola vez los datos de tu empresa para el ambiente actual (Certificación o Producción).

PUT /api/issuer
Establece el titular emisor

Guarda el RUC, razón social, serie (establecimiento + punto de emisión) y dirección matriz.

curl -X PUT "http://127.0.0.1:8000/api/issuer" \
  -H "X-API-Key: TU_CLAVE_API" \
  -H "Content-Type: application/json" \
  -d '{
    "ruc": "1790000000001",
    "razon_social": "ACME SOLUCIONES S.A.S.",
    "dir_matriz": "Av. Amazonas y Naciones Unidas, Quito",
    "dir_establecimiento": "Av. Amazonas y Naciones Unidas, Quito",
    "establecimiento": "001",
    "punto_emision": "001",
    "obligado_contabilidad": "NO"
  }'
$headers = @{ 'X-API-Key' = $env:SRI_API_KEY; 'Content-Type' = 'application/json' }
$emisor = @{
    ruc = "1790000000001"
    razon_social = "ACME SOLUCIONES S.A.S."
    dir_matriz = "Av. Amazonas y Naciones Unidas, Quito"
    dir_establecimiento = "Av. Amazonas y Naciones Unidas, Quito"
    establecimiento = "001"
    punto_emision = "001"
    obligado_contabilidad = "NO"
}
Invoke-RestMethod "http://127.0.0.1:8000/api/issuer" -Method Put -Headers $headers -Body ($emisor | ConvertTo-Json)
import requests

headers = {"X-API-Key": "TU_CLAVE_API"}
data = {
    "ruc": "1790000000001",
    "razon_social": "ACME SOLUCIONES S.A.S.",
    "dir_matriz": "Av. Amazonas y Naciones Unidas, Quito",
    "dir_establecimiento": "Av. Amazonas y Naciones Unidas, Quito",
    "establecimiento": "001",
    "punto_emision": "001",
    "obligado_contabilidad": "NO"
}
res = requests.put("http://127.0.0.1:8000/api/issuer", json=data, headers=headers)
print(res.json())
{
  "ruc": "1790000000001",
  "razon_social": "ACME SOLUCIONES S.A.S.",
  "dir_matriz": "Av. Amazonas y Naciones Unidas, Quito",
  "dir_establecimiento": "Av. Amazonas y Naciones Unidas, Quito",
  "establecimiento": "001",
  "punto_emision": "001",
  "obligado_contabilidad": "NO"
}

🧾 2. Emitir Factura Electrónica (Asíncrona)

Envía la venta usando el encabezado Idempotency-Key. Si la red falla o reintentas, el servidor devuelve el mismo documento sin duplicar la numeración tributaria.

POST /api/documents/invoice
Retorna 202 Accepted + Clave de Acceso
curl -X POST "http://127.0.0.1:8000/api/documents/invoice" \
  -H "X-API-Key: TU_CLAVE_API" \
  -H "Idempotency-Key: factura-orden-1002" \
  -H "Content-Type: application/json" \
  -d '{
    "fecha": "2026-10-30",
    "comprador": {
      "tipo": "05",
      "identificacion": "1710034065",
      "razon_social": "JUAN PEREZ GONZALEZ",
      "direccion": "Quito, Ecuador"
    },
    "forma_pago": "20",
    "lineas": [
      {
        "codigo": "SERV-001",
        "descripcion": "Consultoría Técnica en Facturación",
        "cantidad": "1",
        "precio_unitario": "50.00",
        "descuento": "0.00",
        "codigo_iva": "4"
      },
      {
        "codigo": "LIB-002",
        "descripcion": "Manual Impreso de Normativas",
        "cantidad": "2",
        "precio_unitario": "15.00",
        "descuento": "5.00",
        "codigo_iva": "0"
      }
    ]
  }'
$headers = @{
    'X-API-Key' = $env:SRI_API_KEY
    'Idempotency-Key' = "orden-$((Get-Date).Ticks)"
    'Content-Type' = 'application/json'
}

$payload = @{
    fecha = (Get-Date -Format yyyy-MM-dd)
    comprador = @{
        tipo = "05"
        identificacion = "1710034065"
        razon_social = "JUAN PEREZ GONZALEZ"
        direccion = "Quito"
    }
    forma_pago = "20"
    lineas = @(
        @{ codigo = "SERV-001"; descripcion = "Servicio Profesional"; cantidad = "1"; precio_unitario = "50.00"; descuento = "0.00"; codigo_iva = "4" }
    )
}

$res = Invoke-RestMethod "http://127.0.0.1:8000/api/documents/invoice" -Method Post -Headers $headers -Body ($payload | ConvertTo-Json -Depth 6)
Write-Host "Clave generada:" $res.clave
Write-Host "Estado inicial:" $res.estado
import datetime, requests

headers = {
    "X-API-Key": "TU_CLAVE_API",
    "Idempotency-Key": f"venta-{datetime.datetime.now().timestamp()}"
}

payload = {
    "fecha": datetime.date.today().isoformat(),
    "comprador": {
        "tipo": "05",
        "identificacion": "1710034065",
        "razon_social": "JUAN PEREZ",
        "direccion": "Quito"
    },
    "forma_pago": "20",
    "lineas": [
        {"codigo": "ITM-1", "descripcion": "Servicio de Integración", "cantidad": "1", "precio_unitario": "100.00", "codigo_iva": "4"}
    ]
}

res = requests.post("http://127.0.0.1:8000/api/documents/invoice", json=payload, headers=headers)
print("Respuesta:", res.status_code, res.json())
{
  "fecha": "2026-10-30",
  "comprador": {
    "tipo": "05",
    "identificacion": "1710034065",
    "razon_social": "JUAN PEREZ",
    "direccion": "Quito"
  },
  "forma_pago": "20",
  "lineas": [
    {
      "codigo": "SERV-001",
      "descripcion": "Servicio de desarrollo",
      "cantidad": "1",
      "precio_unitario": "100.00",
      "descuento": "0.00",
      "codigo_iva": "4"
    }
  ]
}

↩️ 3. Emitir Nota de Crédito

Acredita una o varias líneas específicas de una factura previamente autorizada. La API previene devoluciones duplicadas de la misma línea.

POST /api/documents/credit-note
Devolución sobre factura autorizada
curl -X POST "http://127.0.0.1:8000/api/documents/credit-note" \
  -H "X-API-Key: TU_CLAVE_API" \
  -H "Idempotency-Key: devolucion-nota-001" \
  -H "Content-Type: application/json" \
  -d '{
    "fecha": "2026-10-30",
    "factura": "3010202601179000000000110010010000000011234567813",
    "motivo": "Devolución de ítem por inconformidad de servicio",
    "lineas": [1]
  }'

📑 4. Consultar Estado, Descargar RIDE (PDF) y XML

Una vez que el documento alcanza el estado AUTORIZADO, puedes obtener el PDF oficial y el XML firmado:

Endpoint Método Retorno Descripción
/api/documents GET JSON (Lista) Historial ordenado de comprobantes emitidos por el RUC.
/api/documents/{access_key} GET JSON (Detalle) Estado tributario actual (RECIBIDA, AUTORIZADO, etc.) y reintentos.
/api/documents/{access_key}/ride GET application/pdf RIDE Oficial en PDF con código de barras, desglose y logotipo.
/api/documents/{access_key}/xml GET application/xml XML con firma digital XAdES-BES y sobre de autorización del SRI.
# Descargar el PDF RIDE con PowerShell
$clave = "3010202601179000000000110010010000000011234567813"
Invoke-WebRequest "http://127.0.0.1:8000/api/documents/$clave/ride" `
  -Headers @{ 'X-API-Key' = $env:SRI_API_KEY } `
  -OutFile "factura-$clave.pdf"

⚙️ API Directa: Generación, Firma y Transmisión Paso a Paso

Diseñada para integraciones con ERPs o sistemas comerciales que gestionan individualmente cada fase del comprobante:

Paso Endpoint Método Descripción
1. Crear /invoices o /credit-notes POST Genera la clave de acceso de 49 dígitos, asigna el secuencial por serie y construye el XML 2.1.0 inicial.
2. Firmar y Enviar /documents/{access_key}/send POST Firma en formato XAdES-BES 1.3.2 usando el certificado del emisor y transmite al servicio SOAP de recepción del SRI.
3. Consultar SRI /documents/{access_key}/check POST Consulta el resultado de la autorización con el SRI y actualiza el estado a AUTORIZADO o DEVUELTA.
4. Descargar XML /documents/{access_key}/xml?version=autorizado GET Descarga el XML final con el sobre oficial de autorización del SRI (o ?version=firmado para el XML enviado).
POST /invoices
Ejemplo de emisión directa completa con pagos y sucursal
$headers = @{ 'X-API-Key' = $env:SRI_API_KEY }
$base = "http://127.0.0.1:8000"

# 1. Crear la factura y obtener la clave de acceso
$factura = Invoke-RestMethod "$base/invoices" -Method Post -Headers $headers `
  -ContentType 'application/json' -InFile ".\ejemplos\factura.json"
$clave = $factura.clave
Write-Host "Comprobante creado con clave: $clave"

# 2. Firmar con el certificado del emisor y enviar al SRI
$envio = Invoke-RestMethod "$base/documents/$clave/send" -Method Post -Headers $headers
Write-Host "Estado de recepción SRI: $($envio.estado)"

# 3. Consultar autorización
Start-Sleep -Seconds 3
$auth = Invoke-RestMethod "$base/documents/$clave/check" -Method Post -Headers $headers
Write-Host "Estado final SRI: $($auth.estado)"

# 4. Descargar XML autorizado
Invoke-RestMethod "$base/documents/$clave/xml?version=autorizado" -Headers $headers -OutFile "$clave-autorizado.xml"
# 1. Crear documento
curl -X POST "http://127.0.0.1:8000/invoices" \
  -H "X-API-Key: TU_CLAVE_API" \
  -H "Content-Type: application/json" \
  -d @factura.json

# 2. Firmar y transmitir
curl -X POST "http://127.0.0.1:8000/documents/CLAVE_DE_ACCESO/send" \
  -H "X-API-Key: TU_CLAVE_API"

# 3. Consultar estado
curl -X POST "http://127.0.0.1:8000/documents/CLAVE_DE_ACCESO/check" \
  -H "X-API-Key: TU_CLAVE_API"

# 4. Descargar XML autorizado
curl -X GET "http://127.0.0.1:8000/documents/CLAVE_DE_ACCESO/xml?version=autorizado" \
  -H "X-API-Key: TU_CLAVE_API" -o factura.xml
{
  "id_operacion": "venta-sucursal-002-881",
  "fecha": "2026-11-01",
  "emisor": {
    "ruc": "1790000000001",
    "razon_social": "Mi Empresa S.A.",
    "dir_matriz": "Quito, Av. Amazonas N21-15",
    "dir_establecimiento": "Guayaquil, Av. 9 de Octubre 104",
    "establecimiento": "002",
    "punto_emision": "001",
    "obligado_contabilidad": "SI",
    "contribuyente_especial": "5368",
    "agente_retencion": "1",
    "regimen_rimpe": "CONTRIBUYENTE RÉGIMEN RIMPE"
  },
  "comprador": {
    "tipo": "07",
    "identificacion": "9999999999999",
    "razon_social": "CONSUMIDOR FINAL",
    "direccion": "Ecuador"
  },
  "pagos": [
    {
      "medio": "20",
      "total": "28.75",
      "plazo": 30,
      "unidad_tiempo": "dias"
    }
  ],
  "campos_adicionales": [
    {"nombre": "Email", "valor": "[email protected]"},
    {"nombre": "Observacion", "valor": "Entrega a domicilio sin costo"}
  ],
  "lineas": [
    {
      "codigo": "PROD-01",
      "descripcion": "Producto con IVA 15%",
      "cantidad": "1",
      "precio_unitario": "25.00",
      "descuento": "0.00",
      "codigo_iva": "4"
    }
  ]
}

📊 Catálogos Oficiales del SRI (Ficha 2.34)

Tabla 17: Códigos de Tarifa del IVA

codigo_iva Porcentaje Detalle
"4"15%Tarifa estándar vigente general (marzo 2024 en adelante)
"0"0%Bienes o servicios con tarifa 0%
"5"5%Materiales de construcción y proyectos calificados
"2"12%Tarifa histórica 12%
"6"0%No objeto de impuesto
"7"0%Exento de IVA

Tipos de Identificación de Comprador

Código Tipo Identificación requerida Validación
"04"RUC13 dígitos (ej: 1790000000001)Algoritmo Módulo 11 oficial
"05"Cédula de Identidad10 dígitos (ej: 1710034065)Algoritmo Módulo 10 oficial
"06"PasaporteAlfanumérico (hasta 13 caracteres)Sin caracteres especiales
"07"Consumidor Final9999999999999Hasta USD $50.00 según normativa
"08"Identificación del ExteriorAlfanumérico extranjeroCompradores sin residencia en Ecuador

Tabla 24: Formas de Pago

Código Descripción
"01"Sin utilización del sistema financiero (Efectivo)
"16"Tarjeta de débito
"19"Tarjeta de crédito
"20"Otros con utilización del sistema financiero (Transferencia bancaria / Cheque)
SRI Ecuador Facturación Electrónica · Ficha Técnica v2.34
Interactúa directamente en /docs