{"openapi":"3.1.0","info":{"title":"API de Firmas Electrónicas para distribuidores","version":"1.0.0","description":"Emita firmas electrónicas en **archivo (.p12)** desde su propio sistema o portal de ventas: persona natural, persona jurídica y miembro de empresa.\n\n**Dos formas de crear:** `accion: \"borrador\"` (se guarda sin cobrar; la paga después) o `accion: \"pagar\"` (se descuenta de su saldo prepago y entra a revisión de inmediato).\n\n**Credenciales:** se crean en su panel (Saldo para firmas → API de firmas). `sf_test_…` = ambiente de **pruebas** (valida todo igual, pero no crea firmas reales, no descuenta saldo y nunca llega a la entidad certificadora); `sf_live_…` = producción. Envíela en `Authorization: Bearer …`.\n\n**Idempotencia:** toda operación que crea o cobra exige la cabecera `Idempotency-Key` (un UUID por operación). Si reintenta con la misma llave recibe la misma respuesta y no se cobra dos veces.\n\n**Documentos:** en JSON como base64 (`data:image/jpeg;base64,…`) o en multipart (`documentos[cedula_frontal]`, con el resto de datos en el campo `datos`). JPG, PNG o PDF, máximo 8 MB cada uno.\n\n**Webhooks:** regístrelos con `POST /webhooks`; cada aviso va firmado con `X-Webhook-Firma = HMAC-SHA256(secreto, \"{X-Webhook-Momento}.{cuerpo}\")`. Si su servidor no responde 2xx se reintenta (1, 5, 15, 60 min, 3, 6 y 12 h)."},"servers":[{"url":"https://azur.com.ec/plataforma/api/firmas/v1"}],"security":[{"bearer":[]}],"tags":[{"name":"Cuenta y catálogo"},{"name":"Firmas"},{"name":"Webhooks"},{"name":"Pruebas"}],"paths":{"/cuenta":{"get":{"tags":["Cuenta y catálogo"],"summary":"Su cuenta, ambiente y saldo","operationId":"cuenta","responses":{"200":{"description":"Datos de la cuenta.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"type":"object","properties":{"reseller":{"type":"object"},"ambiente":{"type":"string","enum":["pruebas","produccion"]},"saldo":{"type":"number","description":"Saldo prepago disponible (USD, IVA incluido)."},"nivel":{"type":"object"},"borradores_abiertos":{"type":"integer"}}},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/catalogo":{"get":{"tags":["Cuenta y catálogo"],"summary":"Tipos, vigencias con SU precio, documentos por tipo, provincias, nacionalidades, estados y eventos","operationId":"catalogo","responses":{"200":{"description":"Catálogo.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"type":"object"},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/catalogo/ciudades":{"get":{"tags":["Cuenta y catálogo"],"summary":"Ciudades de una provincia","operationId":"ciudades","parameters":[{"name":"provincia","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Ciudades.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"nombre":{"type":"string"}}}},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"422":{"description":"Provincia no válida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/firmas":{"post":{"tags":["Firmas"],"summary":"Crear una solicitud (borrador o pagada con saldo)","operationId":"crearFirma","description":"Valida datos y documentos según el tipo (los mismos que exige el formulario web). Con `accion: \"pagar\"` descuenta el saldo y la firma entra a revisión; si no alcanza responde 402 `saldo_insuficiente` y no crea nada. Con `accion: \"borrador\"` se guarda sin cobrar (vence a los 7 días).","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NuevaFirma"},"examples":{"persona_natural":{"summary":"Persona natural, pagada con saldo","value":{"tipo":"persona_natural","accion":"pagar","vigencia":"1 año","referencia_externa":"PED-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@ejemplo.com"},"domicilio":{"provincia":9,"ciudad":1,"direccion":"AV. 9 DE OCTUBRE 100 Y MALECON, EDIFICIO CENTRO"},"documentos":{"cedula_frontal":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ…","cedula_posterior":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ…","selfie":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ…"}}},"persona_juridica":{"summary":"Persona jurídica, como borrador","value":{"tipo":"persona_juridica","accion":"borrador","vigencia":"2 años","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@ejemplo.com"},"domicilio":{"provincia":9,"ciudad":1,"direccion":"AV. 9 DE OCTUBRE 100 Y MALECON, EDIFICIO CENTRO"},"empresa":{"ruc":"0991234567001","razon_social":"COMERCIAL EJEMPLO S.A.","cargo":"GERENTE GENERAL"},"documentos":{"cedula_frontal":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ…","cedula_posterior":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ…","selfie":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ…","copia_ruc":"data:application/pdf;base64,JVBERi0…","constitucion":"data:application/pdf;base64,JVBERi0…","nombramiento":"data:application/pdf;base64,JVBERi0…"}}},"miembro_empresa":{"summary":"Miembro de empresa","value":{"tipo":"miembro_empresa","accion":"pagar","vigencia":"1 año","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@ejemplo.com"},"domicilio":{"provincia":9,"ciudad":1,"direccion":"AV. 9 DE OCTUBRE 100 Y MALECON, EDIFICIO CENTRO"},"empresa":{"ruc":"0991234567001","razon_social":"COMERCIAL EJEMPLO S.A.","cargo":"CONTADORA","area":"CONTABILIDAD"},"representante_legal":{"tipo_identificacion":"CEDULA","identificacion":"0911111111","nombres":"JUAN CARLOS","primer_apellido":"GOMEZ","segundo_apellido":"RUIZ"},"documentos":{"cedula_frontal":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ…","cedula_posterior":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ…","selfie":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ…","copia_ruc":"data:application/pdf;base64,JVBERi0…","nombramiento":"data:application/pdf;base64,JVBERi0…","cedula_representante":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ…","autorizacion_representante":"data:application/pdf;base64,JVBERi0…"}}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"datos":{"type":"string","description":"El mismo JSON de NuevaFirma, sin `documentos`."},"documentos[cedula_frontal]":{"type":"string","format":"binary"},"documentos[cedula_posterior]":{"type":"string","format":"binary"},"documentos[selfie]":{"type":"string","format":"binary"}}}}}},"responses":{"201":{"description":"Firma creada.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"$ref":"#/components/schemas/Firma"},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"402":{"description":"Saldo insuficiente (use accion borrador o recargue).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Duplicada: ya hay una en trámite para esa identificación, el celular ya tiene 3 firmas vigentes o la referencia_externa ya existe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Datos o documentos inválidos: `detalle` lista cada campo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"428":{"description":"Falta Idempotency-Key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["Firmas"],"summary":"Listar sus firmas","operationId":"listarFirmas","description":"Incluye también las que creó en el panel web. 50 por página, la más reciente primero.","parameters":[{"name":"estado","in":"query","schema":{"type":"string","enum":["borrador","ingresada","verificada","en_tramite","aprobada","emitida","requiere_correccion","eliminada","suspendida","revocada","en_revocacion","cancelada"]}},{"name":"referencia","in":"query","schema":{"type":"string"}},{"name":"identificacion","in":"query","schema":{"type":"string"}},{"name":"desde","in":"query","schema":{"type":"string","format":"date"}},{"name":"hasta","in":"query","schema":{"type":"string","format":"date"}},{"name":"pagina","in":"query","schema":{"type":"integer","minimum":1}}],"responses":{"200":{"description":"Página de firmas.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"type":"object","properties":{"total":{"type":"integer"},"pagina":{"type":"integer"},"por_pagina":{"type":"integer"},"firmas":{"type":"array","items":{"$ref":"#/components/schemas/Firma"}}}},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/firmas/{id}":{"get":{"tags":["Firmas"],"summary":"Ver una firma (estado, corrección pedida, vencimiento)","operationId":"verFirma","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"La firma.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"$ref":"#/components/schemas/Firma"},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"404":{"description":"No existe en su cuenta.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Firmas"],"summary":"Eliminar un borrador","operationId":"eliminarBorrador","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"description":"Solo borradores sin pagar. Una firma pagada no se elimina por la API.","responses":{"200":{"description":"Borrador eliminado.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"$ref":"#/components/schemas/Firma"},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"409":{"description":"No es un borrador.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/firmas/{id}/pagar":{"post":{"tags":["Firmas"],"summary":"Pagar un borrador con su saldo","operationId":"pagarBorrador","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Pagada: entra a revisión.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"$ref":"#/components/schemas/Firma"},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"402":{"description":"Saldo insuficiente.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Ya no es borrador, venció o hay otra en trámite.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Le faltan documentos obligatorios.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/firmas/{id}/correccion":{"post":{"tags":["Firmas"],"summary":"Corregir datos o documentos","operationId":"corregirFirma","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"description":"Para una firma `ingresada` (antes de la revisión) o que `requiere_correccion`. Envíe SOLO lo que cambia (mismos bloques que al crear); los documentos que ya tiene no hace falta reenviarlos. Formato, vigencia y tipo no se cambian por aquí. La firma vuelve a la cola de revisión. También puede corregirla en su panel web: usted elige.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Correccion"},"example":{"titular":{"codigo_dactilar":"V4443V4444"},"documentos":{"selfie":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ…"}}}}},"responses":{"200":{"description":"Corrección recibida.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"$ref":"#/components/schemas/Firma"},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"409":{"description":"El estado no permite corregir.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Datos inválidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/firmas/{id}/simular":{"post":{"tags":["Pruebas"],"summary":"Simular un cambio de estado (SOLO credencial sf_test_)","operationId":"simularEstado","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"description":"Para ver llegar los webhooks sin esperar a la entidad certificadora.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["estado"],"properties":{"estado":{"type":"string","enum":["ingresada","verificada","en_tramite","aprobada","emitida","requiere_correccion","cancelada"]},"motivo":{"type":"string"},"campos":{"type":"array","items":{"type":"string"}}}},"example":{"estado":"requiere_correccion","motivo":"La selfie está borrosa.","campos":["documentos.selfie"]}}}},"responses":{"200":{"description":"Estado cambiado.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"$ref":"#/components/schemas/Firma"},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"403":{"description":"Solo en pruebas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks":{"get":{"tags":["Webhooks"],"summary":"Listar sus webhooks","operationId":"listarWebhooks","responses":{"200":{"description":"Webhooks del ambiente de la credencial.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Webhooks"],"summary":"Registrar un webhook (devuelve el secreto UNA vez)","operationId":"crearWebhook","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"https público."},"eventos":{"type":"array","items":{"type":"string","enum":["firma.borrador","firma.ingresada","firma.verificada","firma.en_tramite","firma.aprobada","firma.emitida","firma.requiere_correccion","firma.eliminada","firma.cancelada","firma.suspendida","firma.revocada","firma.en_revocacion","webhook.prueba"]},"description":"Vacío = todos."},"descripcion":{"type":"string"}}},"example":{"url":"https://mi-portal.com/webhooks/firmas","eventos":["firma.emitida","firma.requiere_correccion"]}}}},"responses":{"201":{"description":"Webhook creado; `secreto` solo aparece aquí.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"$ref":"#/components/schemas/Webhook"},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"422":{"description":"URL o eventos inválidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/{id}":{"delete":{"tags":["Webhooks"],"summary":"Borrar un webhook","operationId":"borrarWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Borrado.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"type":"object"},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/{id}/probar":{"post":{"tags":["Webhooks"],"summary":"Enviar un aviso de prueba","operationId":"probarWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"202":{"description":"Encolado.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"type":"object"},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/{id}/envios":{"get":{"tags":["Webhooks"],"summary":"Últimos 50 envíos y su resultado","operationId":"enviosWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Envíos.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","const":true},"datos":{"type":"array","items":{"type":"object"}},"avisos":{"type":"array","items":{"type":"string"}}}}}}},"401":{"description":"Credencial inválida, revocada o vencida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"IP no permitida o cuenta sin venta de firmas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Más de 120 llamadas por minuto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{"firma":{"post":{"summary":"Aviso de cambio de una firma","description":"Eventos: firma.borrador, firma.ingresada, firma.verificada, firma.en_tramite, firma.aprobada, firma.emitida, firma.requiere_correccion, firma.eliminada, firma.cancelada, firma.suspendida, firma.revocada, firma.en_revocacion, webhook.prueba. Responda 2xx en menos de 10 s.","parameters":[{"name":"X-Webhook-Evento","in":"header","schema":{"type":"string"}},{"name":"X-Webhook-Momento","in":"header","schema":{"type":"string"}},{"name":"X-Webhook-Firma","in":"header","schema":{"type":"string"},"description":"HMAC-SHA256(secreto, \"{X-Webhook-Momento}.{cuerpo}\") en hexadecimal."},{"name":"X-Webhook-Id","in":"header","schema":{"type":"string"},"description":"Id único del evento: úselo para no procesar dos veces el mismo aviso."}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id_evento":{"type":"string"},"evento":{"type":"string"},"momento":{"type":"string","format":"date-time"},"ambiente":{"type":"string"},"datos":{"$ref":"#/components/schemas/Firma"}}}}}},"responses":{"200":{"description":"Recibido."}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"sf_live_… (producción) o sf_test_… (pruebas). Se crea en el panel: Saldo para firmas → API de firmas."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"Un UUID por operación. Reintente con la MISMA llave y recibirá la misma respuesta (no se cobra dos veces)."}},"schemas":{"NuevaFirma":{"type":"object","required":["tipo","accion","vigencia","titular","domicilio","documentos"],"properties":{"tipo":{"type":"string","enum":["persona_natural","persona_juridica","miembro_empresa"]},"accion":{"type":"string","enum":["borrador","pagar"],"description":"borrador = guardar sin cobrar; pagar = descontar del saldo y enviar a revisión."},"vigencia":{"type":"string","description":"Una de las vigencias de /catalogo para ese tipo (ej. \"1 año\")."},"referencia_externa":{"type":"string","maxLength":100,"description":"Su id de pedido; no se puede repetir."},"titular":{"type":"object","required":["identificacion","codigo_dactilar","nombres","primer_apellido","fecha_nacimiento","nacionalidad","sexo","celular","email"],"properties":{"tipo_identificacion":{"type":"string","enum":["CEDULA","PASAPORTE"],"default":"CEDULA"},"identificacion":{"type":"string","description":"Cédula de 10 dígitos (o pasaporte)."},"codigo_dactilar":{"type":"string","description":"Reverso de la cédula, ej. V4443V4444."},"nombres":{"type":"string"},"primer_apellido":{"type":"string"},"segundo_apellido":{"type":"string"},"fecha_nacimiento":{"type":"string","format":"date","description":"AAAA-MM-DD; mayor de edad."},"nacionalidad":{"type":"string","description":"Ej. ECUATORIANA (lista en /catalogo)."},"sexo":{"type":"string","enum":["HOMBRE","MUJER"]},"celular":{"type":"string","description":"10 dígitos."},"email":{"type":"string","format":"email","description":"Aquí recibe el titular su firma."},"ruc":{"type":"string","description":"Solo persona natural CON RUC (13 dígitos). Exige el documento copia_ruc."}}},"domicilio":{"type":"object","required":["provincia","ciudad","direccion"],"properties":{"provincia":{"type":"integer"},"ciudad":{"type":"integer"},"direccion":{"type":"string","minLength":10}}},"empresa":{"type":"object","description":"persona_juridica y miembro_empresa.","properties":{"ruc":{"type":"string"},"razon_social":{"type":"string"},"cargo":{"type":"string"},"area":{"type":"string","description":"Solo miembro_empresa."},"motivo":{"type":"string","description":"Solo miembro_empresa (opcional)."}}},"representante_legal":{"type":"object","description":"Solo miembro_empresa.","properties":{"tipo_identificacion":{"type":"string","enum":["CEDULA","PASAPORTE"]},"identificacion":{"type":"string"},"nombres":{"type":"string"},"primer_apellido":{"type":"string"},"segundo_apellido":{"type":"string"}}},"documentos":{"type":"object","properties":{"cedula_frontal":{"type":"string","description":"Cédula del titular: parte frontal (foto o PDF legible). Base64 o data URI."},"cedula_posterior":{"type":"string","description":"Cédula del titular: parte posterior. Base64 o data URI."},"selfie":{"type":"string","description":"Foto selfie del titular (rostro visible, sin lentes oscuros ni gorra). Base64 o data URI."},"copia_ruc":{"type":"string","description":"Copia del RUC (PDF del SRI). Base64 o data URI."},"constitucion":{"type":"string","description":"Escritura de constitución de la empresa. Base64 o data URI."},"nombramiento":{"type":"string","description":"Nombramiento del representante legal vigente. Base64 o data URI."},"cedula_representante":{"type":"string","description":"Cédula del representante legal. Base64 o data URI."},"autorizacion_representante":{"type":"string","description":"Autorización firmada por el representante legal para emitir la firma al miembro. Base64 o data URI."},"adicional":{"type":"string","description":"Documento adicional (opcional). Base64 o data URI."}},"description":"Requeridos: persona_natural = cedula_frontal, cedula_posterior, selfie (+ copia_ruc si lleva RUC); persona_juridica = + copia_ruc, constitucion, nombramiento; miembro_empresa = + copia_ruc, nombramiento, cedula_representante, autorizacion_representante."},"observacion":{"type":"string","maxLength":500}}},"Correccion":{"type":"object","properties":{"titular":{"type":"object"},"domicilio":{"type":"object"},"empresa":{"type":"object"},"representante_legal":{"type":"object"},"documentos":{"type":"object","properties":{"cedula_frontal":{"type":"string","description":"Cédula del titular: parte frontal (foto o PDF legible). Base64 o data URI."},"cedula_posterior":{"type":"string","description":"Cédula del titular: parte posterior. Base64 o data URI."},"selfie":{"type":"string","description":"Foto selfie del titular (rostro visible, sin lentes oscuros ni gorra). Base64 o data URI."},"copia_ruc":{"type":"string","description":"Copia del RUC (PDF del SRI). Base64 o data URI."},"constitucion":{"type":"string","description":"Escritura de constitución de la empresa. Base64 o data URI."},"nombramiento":{"type":"string","description":"Nombramiento del representante legal vigente. Base64 o data URI."},"cedula_representante":{"type":"string","description":"Cédula del representante legal. Base64 o data URI."},"autorizacion_representante":{"type":"string","description":"Autorización firmada por el representante legal para emitir la firma al miembro. Base64 o data URI."},"adicional":{"type":"string","description":"Documento adicional (opcional). Base64 o data URI."}}}}},"Firma":{"type":"object","properties":{"id":{"type":"integer"},"ambiente":{"type":"string","enum":["pruebas","produccion"]},"referencia_externa":{"type":["string","null"]},"tipo":{"type":"string"},"estado":{"type":"string","enum":["borrador","ingresada","verificada","en_tramite","aprobada","emitida","requiere_correccion","eliminada","suspendida","revocada","en_revocacion","cancelada"]},"estado_descripcion":{"type":"string"},"vigencia":{"type":"string"},"valor":{"type":"number","description":"Sin IVA."},"total":{"type":"number","description":"Lo que se descuenta del saldo (IVA incluido)."},"pagada":{"type":"boolean"},"titular":{"type":"object"},"ruc":{"type":["string","null"]},"empresa":{"type":["object","null"]},"documentos":{"type":"object","description":"Qué documentos tiene guardados (true/false)."},"correccion":{"type":["object","null"],"description":"Si requiere corrección: motivo y campos.","properties":{"motivo":{"type":["string","null"]},"campos":{"type":"array","items":{"type":"string"}}}},"creada":{"type":"string"},"actualizada":{"type":"string"},"aprobada_en":{"type":["string","null"]},"emitida_en":{"type":["string","null"]},"vence_en":{"type":["string","null"]},"borrador_vence_en":{"type":"string"}}},"Webhook":{"type":"object","properties":{"id":{"type":"integer"},"url":{"type":"string"},"eventos":{"type":"array","items":{"type":"string"}},"estado":{"type":"string"},"secreto":{"type":"string","description":"Solo al crearlo."}}},"Error":{"type":"object","properties":{"ok":{"type":"boolean","const":false},"error":{"type":"object","properties":{"codigo":{"type":"string","enum":["credencial_invalida","sin_permiso","no_encontrado","datos_invalidos","documentos_faltantes","saldo_insuficiente","estado_no_permite","duplicada","idempotencia_en_proceso","idempotencia_distinta","falta_idempotencia","demasiadas_peticiones","error_interno"]},"mensaje":{"type":"string"},"reintentable":{"type":"boolean"},"detalle":{"type":"object","description":"campo => motivo"}}}}}}}}