Emisión de Certificados
Emisión de certificados con el proveedor que corresponda al tipo de emisión de la solicitud (issuance_flow: BIOMETRIC → viafirma, DOCUMENTARY → mail): disparar la emisión (POST /certificate-request/{id}/issue), consultar su estado (GET /certificate-request/{id}/issuance), obtener URL + PIN o el archivo en Base64 (GET /certificate-request/{uuid}/issuance/download y /download/base64) y generar la orden de renovación (POST /certificate-request/{id}/issuance/renew). El proveedor lo determina el issuance_flow guardado en la solicitud, no el issuance_provider actual de la empresa (viafirma, mail o dual, nunca null), que solo limita qué tipos puede crear.
Disparar la emisión del certificado (proveedor mail o viafirma)
Inicia la emisión del certificado de la solicitud con el proveedor de su tipo de emisión. **Resolución del proveedor:** lo decide el flujo de la solicitud (`issuance_flow`, fijado al crearla): BIOMETRIC → `viafirma`, DOCUMENTARY → `mail`, sea cual sea hoy el `issuance_provider` de la empresa (`viafirma`, `mail` o `dual`). Si ese proveedor no puede atender la solicitud se responde 422, sin probar otro. El campo `provider` del cuerpo no elige el proveedor: si contradice el flujo responde 422 `ISSUANCE_PROVIDER_MISMATCH` (recomendación: no enviarlo). **Cuerpo manual de la emisión documental** (`request_status` o `user_of_change`, que envían «Procesar / enviar correo» y «Reenviar solicitud»): solo se admite sobre solicitudes DOCUMENTARY; sobre una BIOMETRIC responde 409 `ISSUANCE_FLOW_ACTION_NOT_ALLOWED` sin abrir ningún trámite. **Condiciones de `viafirma`:** módulo Viafirma habilitado, `email_certificate` informado y sin otro trámite Viafirma vigente para la solicitud. Si la solicitud tiene varios trámites se evalúa el vigente (prioridad: con certificado emitido > con verificación de identidad completada > en curso > fallido > cancelado > sin estado; a igual prioridad, el más reciente): si está en FAILED, FAILED_RECOVERABLE o EXPIRED se permite reintentar; en cualquier otro estado (en curso, CANCELLED, REVOKED, COMPLETED) no. Solo puede haber una emisión Viafirma a la vez por solicitud: si otra emisión (p. ej. la automática) todavía está enviando a Viafirma y aún no registró su trámite, esta llamada responde 409 de inmediato, sin esperar; si la otra ya registró su trámite, este cuenta como trámite vigente en curso y la llamada no da 409: responde 422 ('El proveedor 'viafirma' del tipo de emisión de la solicitud no soporta esta solicitud.'). Responde 201 con el trámite en SUBMITTED; desde ahí avanza solo (polling cada 60 s) y se consulta con GET /certificate-request/{id}/issuance. **Condiciones de `mail`:** la solicitud debe tener al menos un archivo adjunto de tipo ATTACHED; se pasa a PROCESSING y se envía por correo a la autoridad certificadora. Responde 200. **Límite de peticiones:** 5 por minuto por usuario en este endpoint, además del límite general de 60 por minuto.
Consultar el estado de emisión de la solicitud
Devuelve el estado normalizado de la emisión. El proveedor NO se toma de la configuración actual de la empresa sino de cómo se tramitó la solicitud: si existe un trámite en viafirma_certificate_requests responde el proveedor `viafirma`; si no, `mail`. **Viafirma:** si la solicitud tiene varios trámites (p. ej. un reintento o un duplicado), se informa el trámite vigente, elegido por prioridad: con certificado emitido (COMPLETED o REVOKED, P7B descargado o certificado generado en Viafirma) > con verificación de identidad (KYC) completada > en curso > fallido (FAILED, FAILED_RECOVERABLE, EXPIRED) > cancelado > sin estado; a igual prioridad, el más reciente. dataRecords.resource_id y dataRecords.external_id son los de ese trámite. dataRecords.data es IssuanceViafirmaData (internal_state, remote_status, KYC, notas públicas, can_reject, revocation_code, etc.); dataRecords.status = submitted (SUBMITTED), processing (trámite sin estado interno, DRAFT, CSR_GENERATED, POLLING, DOWNLOADED, FAILED_RECOVERABLE), ready (READY_TO_DOWNLOAD, ASSEMBLED, COMPLETED) o failed (REVOKED, FAILED, EXPIRED, CANCELLED). **Mail:** dataRecords.data = {'request_status': '...'}; dataRecords.status = ready (PROCESSED), failed (REJECTED) o processing (cualquier otro estado). Siempre responde 200 cuando la solicitud existe.
Obtener URL de descarga y PIN del certificado emitido
Devuelve una URL firmada (vigencia 24 h) para descargar el archivo del certificado y el PIN para abrir el .p12. Es independiente del proveedor: responde para cualquier solicitud que tenga registrado un archivo de tipo CERTIFICATE en file_managers (en Viafirma se registra al completar el ensamblado, estado COMPLETED). **Vigencia:** al cliente solo se le entrega si la solicitud está en PROCESSED; en cualquier otro estado (revocada, vencida, cancelada, rechazada o aún en trámite) responde 409 con el estado actual en `status`, y esta comprobación se hace antes de buscar el archivo. El administrador (users.is_admin) puede descargarlo siempre, en cualquier estado. El archivo es normalmente un **.zip que contiene el .p12** (p. ej. `empresa-sas_636.zip` → `empresa-sas_636.p12`); en Viafirma siempre es así, pero un certificado cargado manualmente con POST /certificate-request/{id}/files y document_type=CERTIFICATE puede tener otro formato (PDF, imagen o ZIP). Si la solicitud tiene varios archivos de tipo CERTIFICATE se devuelve uno de ellos, sin garantía de que sea el más reciente. El PIN se lee de certificate_requests.pin y se devuelve en cada llamada; si la solicitud no tiene PIN registrado se devuelve el literal `NO_PIN`. El parámetro es el UUID público de la solicitud (`certificate_requests.uuid`), no su ID numérico.
Descargar el certificado emitido en Base64 (con PIN)
Devuelve el contenido del archivo del certificado codificado en Base64 junto con el PIN, pensado para integraciones desatendidas (ERP, scripts). Mismas reglas que GET /certificate-request/{uuid}/issuance/download: independiente del proveedor, requiere un archivo de tipo CERTIFICATE registrado y al cliente solo se le entrega si la solicitud está en PROCESSED; en cualquier otro estado (revocada, vencida, cancelada, rechazada o aún en trámite) responde 409 con el estado actual en `status`, antes de buscar el archivo. El administrador (users.is_admin) puede descargarlo siempre. **Importante:** `p12_base64` es el Base64 del archivo almacenado, que normalmente es un **.zip que contiene el .p12** (no el .p12 directamente): decodifique, descomprima y abra el .p12 con `p12_pin`. En Viafirma siempre es así, pero un certificado cargado manualmente con POST /certificate-request/{id}/files y document_type=CERTIFICATE puede tener otro formato (PDF, imagen o ZIP); revise `p12_filename` antes de procesarlo. Si la solicitud tiene varios archivos de tipo CERTIFICATE se devuelve uno de ellos, sin garantía de que sea el más reciente. Si la solicitud no tiene PIN registrado, `p12_pin` vale `NO_PIN`. El parámetro es el UUID público de la solicitud (`certificate_requests.uuid`), no su ID numérico.
Consultar si un certificado se puede renovar y cuánto cuesta
Indica si el certificado de la solicitud se puede renovar hoy (1 año más, sin reemitirlo), por qué no, sus fechas de vencimiento comercial y de revocación, el precio y la orden de renovación pendiente. Solo son renovables los certificados Viafirma emitidos, en PROCESSED, de 1 año (`life` menor a 2) y hasta `revocation_date` (vencimiento comercial + viafirma.revocation.grace_days, 15 días por defecto); se puede renovar desde la emisión, sin esperar al vencimiento. Si no es renovable, `reason` trae el código estable (ver CertificateRenewalEligibility) y `quote` y `pending_order` son null. **Precio (`quote`):** tarifa actual de 1 año (IVA incluido) para el tipo de usuario de quien consulta (users.type_id); si consulta un administrador (type_id 1), la del primer usuario no administrador de la empresa dueña de la solicitud (business_users) y, si la empresa no tiene ninguno, la del propio administrador (tipo 1). Para la mayoría de tipos se usa el tramo de 1 certificado; para los tipos 3 (Arrendamiento en Servidor) y 4 (Partner) el tramo se elige por volumen: solicitudes de la empresa en PROCESSED o PROCESSING (también las que siguen en emisión) creadas en el año actual o el anterior y aún vigentes (las de 1 año, sin fecha de vencimiento o con vencimiento futuro; las de 2 años, sin fecha de vencimiento o con más de un año de vigencia restante), más 1. El propio certificado consultado suele contar mientras no haya vencido (en el periodo de gracia ya no cuenta), por lo que el precio puede ser el de un tramo de mayor volumen. **Orden pendiente (`pending_order`):** la orden CERTIFICATE_RENEWAL en PENDING más reciente de la solicitud; si existe, se paga esa (con los endpoints de Órdenes) en lugar de crear otra. Este endpoint solo consulta: no crea ni modifica órdenes.
Generar la orden de pago para renovar un certificado
Crea una orden de pago (order_type=CERTIFICATE_RENEWAL, status=PENDING, quantity=1, vigencia=1) para extender 1 año la vigencia de un certificado Viafirma de 1 año, sin reemitirlo (Viafirma ya lo emitió por 2 años). Sin cuerpo. **Elegibilidad:** la misma de GET /certificate-request/{id}/issuance/renewal (certificado Viafirma emitido, solicitud en PROCESSED, `life` menor a 2 y hasta el fin del periodo de gracia: vencimiento comercial + viafirma.revocation.grace_days); si no se cumple responde 422 con `reason` y las fechas en `data`, sin crear orden. **Una sola orden pendiente:** si ya existe una orden de renovación PENDING para la solicitud, devuelve esa misma (con su precio original) en lugar de crear otra y actualiza su updated_at; también responde 200. Una orden de renovación PENDING creada o actualizada (o con un pago iniciado) en las últimas 48 h cuenta como pago en curso y frena la revocación automática, pero solo hasta vencimiento comercial + días de gracia + 3 días; pasado ese tope el certificado se revoca aunque haya un pago en curso. **Orden nueva:** el precio es la tarifa de 1 año (IVA incluido) del tipo de usuario de quien llama (users.type_id); si llama un administrador (type_id 1) se usa la del primer usuario no administrador de la empresa dueña de la solicitud (business_users) y, si la empresa no tiene ninguno, la del propio administrador (tipo 1). Para los tipos 3 (Arrendamiento en Servidor) y 4 (Partner) el tramo se elige por volumen (el mismo cálculo de GET .../issuance/renewal: solicitudes de la empresa en PROCESSED o PROCESSING creadas en el año actual o el anterior y aún vigentes, más 1; suele incluir el propio certificado mientras no haya vencido), así que puede no ser la tarifa de 1 certificado; para los demás tipos es la de 1 certificado. La orden queda a nombre de quien llama (user_id) y de la empresa de la solicitud (company_id), con el proveedor de pago WOMPI (payment_provider=`WOMPI`, payment_method=null en una orden nueva; una orden PENDING reutilizada puede traer el medio de pago de un intento anterior que quedó pendiente, anulado o con error) y una referencia con el formato {prefijo}-RNW-{AAAAMMDDhhmmss}-{6 caracteres}. Esta llamada NO cobra: el pago se ejecuta después con los endpoints de Órdenes; al aprobarse, se extienden `life` y `expiration_date` del mismo certificado.