Azur Facturación Electronica API de firmas electrónicas Referencia completa ⬇ OpenAPI 🔑 Mis credenciales

Venda firmas electrónicas desde su propio sistema

Con la API para distribuidores usted emite firmas en archivo (.p12) sin entrar al panel: su portal de ventas, su CRM o su app las crean, las pagan con su saldo y reciben un aviso en cada cambio de estado hasta que la firma queda emitida.

Persona naturalPersona jurídicaMiembro de empresaBorrador o pago con saldoWebhooks firmadosAmbiente de pruebas

Inicio rápido

1. Credencial de pruebasEn su panel: Saldo para firmas → API de firmas, cree una credencial de pruebas (sf_test_…).
2. Primera llamadaConsulte su cuenta y el catálogo (vigencias con su precio, documentos por tipo, provincias).
3. Cree y simuleCree firmas de prueba y simule estados para ver llegar los webhooks.
4. ProducciónCree una credencial sf_live_…: cada firma pagada se descuenta de su saldo.
curl https://azur.com.ec/plataforma/api/firmas/v1/cuenta -H "Authorization: Bearer sf_test_SU_CREDENCIAL"

curl https://azur.com.ec/plataforma/api/firmas/v1/catalogo -H "Authorization: Bearer sf_test_SU_CREDENCIAL"

URL base: https://azur.com.ec/plataforma/api/firmas/v1. Todas las respuestas tienen la forma {"ok": true, "datos": …} o {"ok": false, "error": {"codigo", "mensaje", "detalle", "reintentable"}}.

Autenticación

Envíe su credencial en la cabecera Authorization: Bearer sf_live_… (o X-Api-Key). Nunca en la URL ni en el cuerpo. Desde su panel puede:

  • tener varias credenciales con nombre (una por sistema) y revocar cualquiera al instante;
  • restringir cada una a sus IP (o rangos CIDR) y ponerle fecha de vencimiento.

Solo vemos un resumen (hash) de la credencial: si la pierde, revóquela y cree otra.

Pruebas y producción

CredencialQué pasa
sf_test_…Valida exactamente igual que producción (datos, documentos, vigencias), pero no crea firmas reales, no descuenta saldo y nada llega a la entidad certificadora. Puede simular estados con POST /firmas/{id}/simular.
sf_live_…Firmas reales. Con accion: "pagar" se descuenta de su saldo prepago (IVA incluido) y la solicitud entra a revisión de documentos.

Flujo de una firma

borrador→ pagar →ingresada→verificada→en_tramite→aprobada→emitida

En cualquier punto de la revisión puede pasar a requiere_correccion (nuestro equipo o la entidad certificadora piden corregir un dato o un documento): usted corrige por la API o en su panel y vuelve a ingresada. Cuando queda emitida, el titular recibe su archivo .p12 y su clave en su correo.

Tipos de firma y documentos requeridos

tipoPara quiénDocumentos obligatorios
persona_naturalUna persona, con o sin RUCcedula_frontal, cedula_posterior, selfie; si envía titular.ruc, además copia_ruc. Opcional: adicional.
persona_juridicaEl representante legal de una empresaLos de cédula y selfie + copia_ruc, constitucion, nombramiento. Opcional: adicional.
miembro_empresaUn empleado autorizado por el representante legalLos de cédula y selfie + copia_ruc, nombramiento (del representante), cedula_representante, autorizacion_representante. Opcional: constitucion.
DocumentoQué es
cedula_frontalCédula del titular: parte frontal (foto o PDF legible).
cedula_posteriorCédula del titular: parte posterior.
selfieFoto selfie del titular (rostro visible, sin lentes oscuros ni gorra).
copia_rucCopia del RUC (PDF del SRI).
constitucionEscritura de constitución de la empresa.
nombramientoNombramiento del representante legal vigente.
cedula_representanteCédula del representante legal.
autorizacion_representanteAutorización firmada por el representante legal para emitir la firma al miembro.
adicionalDocumento adicional (opcional).

Formatos: JPG, PNG o PDF, hasta 8 MB cada uno. Revisamos el contenido real del archivo, no su extensión. Las vigencias disponibles y su precio para usted (según su nivel del mes) están en GET /catalogo.

Crear una firma

POST /firmas con la cabecera Idempotency-Key. Elija la acción:

  • "accion": "pagar" — se descuenta de su saldo y entra a revisión de inmediato. Si el saldo no alcanza responde 402 saldo_insuficiente y no crea nada.
  • "accion": "borrador" — se guarda sin cobrar (útil si su cliente aún no paga). No la revisamos hasta que la pague; vence a los 7 días.
curl -X POST https://azur.com.ec/plataforma/api/firmas/v1/firmas \
  -H "Authorization: Bearer sf_live_SU_CREDENCIAL" \
  -H "Idempotency-Key: 6f1c2b7e-1d1a-4c9e-9a51-2f0d8b4c1a10" \
  -H "Content-Type: application/json" \
  -d '{
    "tipo": "persona_natural",
    "accion": "pagar",
    "vigencia": "1 año",
    "referencia_externa": "PEDIDO-1001",
    "titular": {
      "tipo_identificacion": "CEDULA", "identificacion": "0912345678", "codigo_dactilar": "V4443V4444",
      "nombres": "MARIA JOSE", "primer_apellido": "PEREZ", "segundo_apellido": "LOPEZ",
      "fecha_nacimiento": "1990-05-20", "nacionalidad": "ECUATORIANA", "sexo": "MUJER",
      "celular": "0991234567", "email": "maria.perez@ejemplo.com"
    },
    "domicilio": { "provincia": 9, "ciudad": 1, "direccion": "AV. 9 DE OCTUBRE 100 Y MALECON" },
    "documentos": {
      "cedula_frontal": "data:image/jpeg;base64,/9j/4AAQ...",
      "cedula_posterior": "data:image/jpeg;base64,/9j/4AAQ...",
      "selfie": "data:image/jpeg;base64,/9j/4AAQ..."
    }
  }'

Respuesta 201 con la firma (id, estado, total descontado, documentos recibidos…). Guarde el id: con él consulta, paga, corrige y lo recibe en los webhooks. Para persona_juridica y miembro_empresa agregue el bloque empresa (ruc, razon_social, cargo y, para miembro, area) y, para miembro, representante_legal. Ejemplos completos en la referencia.

Si hay errores le devolvemos todos juntos en error.detalle con el nombre del campo (titular.celular, documentos.selfie…), para que los corrija de una vez.

Enviar los documentos

Opción 1: JSON con base64

Como en el ejemplo anterior: cada documento como data URI (data:image/jpeg;base64,…) o el base64 solo.

Opción 2: multipart (archivos)

curl -X POST https://azur.com.ec/plataforma/api/firmas/v1/firmas \
  -H "Authorization: Bearer sf_live_SU_CREDENCIAL" \
  -H "Idempotency-Key: 0b8e5f62-2b0e-4d8f-8c3e-1a2b3c4d5e6f" \
  -F 'datos={"tipo":"persona_natural","accion":"borrador","vigencia":"1 año","titular":{...},"domicilio":{...}}' \
  -F "documentos[cedula_frontal]=@frontal.jpg" \
  -F "documentos[cedula_posterior]=@posterior.jpg" \
  -F "documentos[selfie]=@selfie.jpg"

Pagar un borrador

curl -X POST https://azur.com.ec/plataforma/api/firmas/v1/firmas/123456/pagar \
  -H "Authorization: Bearer sf_live_SU_CREDENCIAL" \
  -H "Idempotency-Key: 9a7c...-pago-123456"

Se cobra al precio con el que se guardó. Para eliminar un borrador que ya no va: DELETE /firmas/{id} (solo borradores sin pagar).

Consultar y listar

GET https://azur.com.ec/plataforma/api/firmas/v1/firmas/123456
GET https://azur.com.ec/plataforma/api/firmas/v1/firmas?estado=requiere_correccion&desde=2026-10-01&pagina=1
GET https://azur.com.ec/plataforma/api/firmas/v1/firmas?referencia=PEDIDO-1001

El listado incluye también las firmas que creó en su panel web. 50 por página.

Correcciones: por la API o en su panel, usted decide

Cuando una firma pasa a requiere_correccion, en correccion le decimos el motivo y qué campos corregir:

"correccion": { "motivo": "La selfie no muestra el rostro completo.", "campos": ["documentos.selfie"] }

Corríjala con POST /firmas/{id}/correccion enviando solo lo que cambia (los documentos que ya tiene no hace falta reenviarlos), o ábrala en su panel web como siempre. También puede corregir una firma ingresada antes de que la revisemos.

curl -X POST https://azur.com.ec/plataforma/api/firmas/v1/firmas/123456/correccion \
  -H "Authorization: Bearer sf_live_SU_CREDENCIAL" \
  -H "Idempotency-Key: 3c2d...-correccion-1" \
  -H "Content-Type: application/json" \
  -d '{ "documentos": { "selfie": "data:image/jpeg;base64,/9j/4AAQ..." } }'

El tipo, el formato y la vigencia no se cambian por aquí.

Estados

estadoSignificado
borradorGuardada sin pagar. No la revisamos hasta que se pague; vence a los 7 días de creada.
ingresadaPagada con su saldo y en cola de revisión de documentos.
verificadaDocumentos revisados; lista para enviarse a la entidad certificadora.
en_tramiteEn validación por la entidad certificadora.
aprobadaAprobada por la entidad certificadora; falta que el titular la descargue/emita.
emitidaFirma emitida. El titular recibe el archivo .p12 y su clave en su correo.
requiere_correccionHay que corregir datos o documentos (ver «correccion»). Corríjala por la API o en el panel.
eliminadaDada de baja (borrador vencido o eliminado).
suspendidaCertificado suspendido.
revocadaCertificado revocado.
en_revocacionRevocación en curso.
canceladaSolicitud cancelada.

Webhooks

Regístrelos en su panel o con POST /webhooks (url https pública y, si quiere, la lista de eventos). Le enviamos un POST JSON cada vez que una firma cambia:

EventoCuándo
firma.borradorSe creó como borrador (sin pagar).
firma.ingresadaSe pagó con su saldo y entró a revisión (al crearla o al pagar el borrador).
firma.verificadaNuestro equipo revisó los documentos.
firma.en_tramiteSe envió a la entidad certificadora.
firma.aprobadaLa entidad certificadora la aprobó.
firma.emitidaFirma emitida: el titular recibió su archivo .p12.
firma.requiere_correccionHay que corregir datos o documentos (vea «correccion»).
firma.eliminadaDada de baja (p. ej. borrador vencido a los 7 días).
firma.canceladaSolicitud cancelada.
firma.suspendidaCertificado suspendido.
firma.revocadaCertificado revocado.
firma.en_revocacionRevocación en curso.
webhook.pruebaEnvío de prueba pedido desde la API o el panel.
{
  "id_evento": "b3f2c1e0-…",
  "evento": "firma.emitida",
  "momento": "2026-10-17T15:42:10-05:00",
  "ambiente": "produccion",
  "datos": { "id": 123456, "referencia_externa": "PEDIDO-1001", "estado": "emitida", … }
}

Verifique la firma de cada aviso

Cabeceras: X-Webhook-Evento, X-Webhook-Id (único: úselo para no procesar dos veces), X-Webhook-Momento y X-Webhook-Firma = HMAC-SHA256 en hexadecimal de "{momento}.{cuerpo}" con el secreto que le dimos al crear el webhook.

// PHP
$cuerpo = file_get_contents('php://input');
$esperada = hash_hmac('sha256', $_SERVER['HTTP_X_WEBHOOK_MOMENTO'] . '.' . $cuerpo, $secreto);
if (!hash_equals($esperada, $_SERVER['HTTP_X_WEBHOOK_FIRMA'])) { http_response_code(401); exit; }
$evento = json_decode($cuerpo, true);   // responda 200 rápido y procese después

// Node.js (Express con express.raw())
const esperada = crypto.createHmac('sha256', secreto).update(req.get('X-Webhook-Momento') + '.' + req.body).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(esperada), Buffer.from(req.get('X-Webhook-Firma')))) return res.sendStatus(401);

Responda 2xx en menos de 10 segundos. Si no, reintentamos a los 1, 5, 15 y 60 minutos y a las 3, 6 y 12 horas. Puede ver cada envío en su panel o con GET /webhooks/{id}/envios, y mandar uno de prueba con POST /webhooks/{id}/probar.

Idempotencia: nunca se cobra dos veces

Crear, pagar, corregir y eliminar exigen la cabecera Idempotency-Key (un UUID nuevo por operación). Si se corta la red y reintenta con la misma llave, le devolvemos la misma respuesta sin volver a crear ni cobrar (cabecera Idempotent-Replayed: true). La misma llave con otros datos responde 422 idempotencia_distinta. Además, referencia_externa no se puede repetir: es una segunda red de seguridad con su propio número de pedido.

Errores

HTTPcodigoQué hacer
401credencial_invalidaRevise la credencial (revocada o vencida).
403sin_permisoIP no permitida para esa credencial, o acción solo de pruebas.
402saldo_insuficienteRecargue saldo o guárdela como borrador.
409duplicadaYa hay una firma en trámite para esa identificación, el celular ya tiene 3 firmas vigentes o la referencia ya existe.
409estado_no_permiteLa acción no aplica al estado actual (p. ej. pagar algo que no es borrador).
422datos_invalidos / documentos_faltantesCorrija los campos de error.detalle.
428falta_idempotenciaEnvíe Idempotency-Key.
429demasiadas_peticionesEspere y reintente.
500error_internoReintente con la misma Idempotency-Key.

Límites y buenas prácticas

  • 120 llamadas por minuto por credencial. 50 resultados por página.
  • Hasta 20 borradores abiertos a la vez; vencen a los 7 días de creados.
  • Solo firmas en archivo (.p12).
  • Use los webhooks en lugar de consultar cada pocos segundos.
  • Guarde la credencial en su servidor, nunca en el navegador ni en una app móvil.

¿Dudas? Escríbanos desde su panel. ¿Listo para empezar? Cree su credencial de pruebas.