Certificados de firma
El SRI solo acepta comprobantes firmados (XAdES-BES) con la firma electrónica del emisor: un archivo .p12 (PKCS#12) emitido por una entidad de certificación acreditada en Ecuador. Flashpi lo guarda cifrado, lo verifica con su entidad de certificación y firma con él cada comprobante del emisor.
El emisor demo compartido firma con el certificado de prueba de Flashpi, así que solo necesitas el tuyo para emitir con tu propio RUC.
Hay dos formas de subir un certificado:
- El alta desde el certificado (
POST /v1/issuer-onboardings): crea el emisor desde su.p12, o renueva el certificado del emisor que ya tiene ese RUC. El certificado sirve para pruebas y producción (allModes: true). Es lo que hace la consola. Consulta Crear un emisor desde su certificado y Renovar un certificado. - La carga a un emisor (
POST /v1/issuers/{issuerId}/certificates, abajo): el certificado sirve para el ambiente de la llave que lo sube.
Subir el certificado
Sección titulada «Subir el certificado»Sube el archivo y su contraseña como multipart/form-data. Requiere una llave read_write con alcance account.
curl https://api.flashpi.com.ec/v1/issuers/01a0fd6a-d098-76ca-b492-1bcb6505a7bd/certificates \ -H "Authorization: Bearer $FLASHPI_API_KEY" \ -F "file=@signature.p12" \ -F "password=$P12_PASSWORD"file: el archivo.p12, de máximo 1 MiB (1.048.576 bytes;413payload_too_largesi lo supera).password: su contraseña, de máximo 1024 bytes.- Importa el ambiente de la llave. Un certificado subido aquí con una llave de prueba solo firma comprobantes de prueba; uno subido con una llave de producción solo firma comprobantes de producción. Para un solo certificado que sirva a ambos ambientes, usa el alta desde el certificado.
La respuesta es 202 Accepted con el certificado en estado processing:
{ "id": "01a0fd6e-f718-7c9c-b50c-fafb236eb1a6", "issuerId": "01a0fd6a-d098-76ca-b492-1bcb6505a7bd", "environment": "test", "allModes": false, "status": "processing", "usable": false, "subject": null, "issuedBy": null, "serialNumber": null, "validFrom": null, "validUntil": null, "sha256Fingerprint": null, "ruc": null, "revocation": null, "rejection": null, "createdAt": "2026-10-02T16:25:03.000Z", "updatedAt": "2026-10-02T16:25:03.000Z"}Flashpi cifra el archivo y la contraseña apenas llegan. La contraseña nunca se guarda en claro ni se devuelve. GET /v1/issuers/{issuerId}/certificates lista los certificados de un emisor (del más nuevo al más antiguo) y GET /v1/issuers/{issuerId}/certificates/{certificateId} lee uno.
allModes dice si el certificado sirve para pruebas y producción (subido con el alta desde el certificado). Una llave lee los certificados de su ambiente y los de ambos ambientes, y en un certificado de ambos ambientes environment es el ambiente de la llave que lo lee.
Renovar un certificado
Sección titulada «Renovar un certificado»Para renovar la firma de un emisor con un solo certificado para ambos ambientes, inicia un alta desde el certificado con el .p12 nuevo. Como tu cuenta ya tiene un emisor con ese RUC, el alta lista trae existingIssuer, y la completas con un cuerpo vacío:
curl https://api.flashpi.com.ec/v1/issuer-onboardings/01a0fd70-2b4c-7d1e-9f3a-5c6b7d8e9f01/complete \ -H "Authorization: Bearer $FLASHPI_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{}'El certificado nuevo se agrega al emisor (allModes: true, en processing) sin cambiar su perfil. En la consola, Subir certificado en un emisor hace lo mismo: no eliges ambiente y confirmas con el código de tu app de autenticación o con tu contraseña. Si el .p12 es de otro RUC, la consola te lleva a Nuevo emisor con el mismo archivo. Los miembros que escriben los certificados de algunos emisores sin administrar emisores suben, en cambio, un certificado por ambiente.
Verificación
Sección titulada «Verificación»Un servicio aislado abre el archivo y verifica la contraseña, que contenga exactamente una clave de firma con su certificado, sus fechas de validez, su cadena hasta una entidad de certificación acreditada en Ecuador y su estado de revocación con esa entidad. Normalmente tarda unos segundos. Vuelve a leer el certificado hasta que su status deje de ser processing:
accepted: puede firmar. El certificado muestra ahora susubject,issuedBy,serialNumber,validFrom,validUntil,sha256Fingerprint, elrucque trae (cuando su entidad lo escribe) y su estado derevocation. Flashpi generacertificate.verified, ocertificate.pendingcuando todavía no se pudo verificar el estado de revocación.rejected:rejection.codeyrejection.messagedicen por qué. Hoy un certificado rechazado no genera un evento de webhook.
rejection.code |
Significado |
|---|---|
invalid_password |
La contraseña no abre el archivo. |
invalid_pkcs12 |
El archivo no es un .p12 válido. |
pkcs12_mac_missing |
El archivo no tiene verificación de integridad con contraseña. Expórtalo de nuevo con una contraseña. |
no_signing_certificate |
El archivo no tiene una clave privada con un certificado de firma. |
ambiguous_signing_certificate |
El archivo tiene varios certificados de firma. Sube un archivo con uno solo. |
certificate_not_yet_valid, certificate_expired |
Está fuera de sus fechas de validez. |
untrusted_certificate_chain |
No lo emitió una entidad de certificación acreditada en Ecuador. |
certificate_revoked |
Su entidad de certificación lo revocó. |
revocation_status_unknown |
No se pudo determinar su estado de revocación. |
certificate_unsupported |
Tiene un formato que Flashpi no puede usar. |
upload_unreadable, upload_too_large |
No se pudo leer el archivo subido, o es demasiado grande. |
Revisiones de revocación
Sección titulada «Revisiones de revocación»Una entidad puede revocar un certificado en cualquier momento, por ejemplo cuando su titular reporta que lo perdió. Flashpi vuelve a revisar cada certificado aceptado: cada día mientras su estado es bueno y cada hora mientras está pendiente o bloqueado. El objeto revocation muestra el resultado:
revocation.status |
¿Firma? | Qué significa |
|---|---|---|
good |
Sí | Verificado como no revocado. checkedAt y nextCheckAt dicen cuándo se revisó y cuándo se revisará. |
pending |
Sí, hasta blockAt |
El servicio de revocación de la entidad no respondió, así que no se pudo verificar el estado. Flashpi sigue intentando cada hora. |
blocked |
No | Sigue sin verificarse en blockAt (blockedReason: "revocation_status_unverified"), o su cadena ya no es confiable (blockedReason: "untrusted_certificate_chain"). |
revoked |
Nunca más | Su entidad de certificación lo revocó. |
Cómo pasa un certificado de un estado a otro:
- Cuando no se puede verificar el estado, el certificado pasa a
pendingcon unblockAt7 días después (certificate.pending). Mientras tanto sigue firmando. - Se generan recordatorios los días 3 y 6, de nuevo como
certificate.pending. - Verificado como bueno antes de
blockAt: vuelve agood(certificate.verified). - Sin verificar todavía en
blockAt:blocked(certificate.blocked). Deja de firmar enblockAtaunque una revisión llegue tarde. Cuando una revisión lo verifica como bueno, se reactiva y vuelve a firmar (certificate.reactivated). - Un certificado bueno que no se puede verificar en una revisión posterior vuelve a
pending, con una nueva ventana de 7 días. - Si su cadena deja de ser confiable (cambió la entidad o un certificado intermedio), pasa a
blockedde inmediato. Sube un certificado nuevo. - Si la entidad lo reporta revocado, pasa a
revoked(certificate.revoked) y nunca vuelve a firmar. Un certificado revocado también se rechaza al subirlo.
Lo que ves como cliente
Sección titulada «Lo que ves como cliente»- El propio certificado:
usabledice si firma en este momento (aceptado, dentro de sus fechas de validez y ni bloqueado ni revocado; un certificado pendiente se puede usar hasta sublockAt). - La consola muestra un aviso en los certificados del emisor cuando uno está pendiente (con la fecha en que deja de firmar), bloqueado, revocado, vencido o por vencer.
- Webhooks: suscríbete a
certificate.pending,certificate.blocked,certificate.revoked,certificate.reactivatedycertificate.verifiedpara alertar a tu equipo. Sudataes el certificado. Los eventos de un certificado de ambos ambientes se generan una vez por ambiente, así que los reciben los endpoints de pruebas y los de producción. Consulta Webhooks. - Comprobantes: un comprobante emitido mientras el emisor no tiene un certificado utilizable para su ambiente se acepta y luego termina
failedconfailure.codecertificate_required,certificate_blocked,certificate_revoked,certificate_expiredocertificate_not_yet_valid. Usa su secuencial, así que emítelo de nuevo cuando un certificado firme.
Qué certificado firma
Sección titulada «Qué certificado firma»Los comprobantes se firman con el certificado utilizable más nuevo que sirve a su ambiente: uno subido para ese ambiente, o uno de ambos ambientes (allModes). Para renovar una firma, sube el nuevo .p12 antes de que venza el anterior (Renovar un certificado): cuando se acepta, toma el relevo, y el anterior solo firma si el más nuevo deja de ser utilizable.
Cómo se protege el certificado
Sección titulada «Cómo se protege el certificado»- El archivo y la contraseña se cifran al llegar con una llave administrada por AWS KMS, en un área de almacenamiento dedicada. El archivo de una carga a un emisor se elimina tras revisarlo. El de un alta desde el certificado espera a que completes el alta, que lo elimina; el de un alta que no se completa (también una rechazada o vencida) se elimina automáticamente unos 7 días después de subirlo.
- Solo el servicio de firma aislado puede descifrar el certificado, en memoria, para firmar tus comprobantes. La API que recibe tus solicitudes no puede leerlo.
- Consulta Seguridad.