Crear solicitud de certificado
POST/certificate-request
Crea una solicitud de certificado digital para la empresa del usuario autenticado y consume un cupo del tipo de emisión y la vigencia pedidos (life). Tipo de emisión (issuance_flow, opcional): BIOMETRIC o DOCUMENTARY. Si no se envía se usa el de la empresa: issuance_provider = viafirma → BIOMETRIC; mail → DOCUMENTARY; dual (la empresa puede elegir en cada solicitud) → DOCUMENTARY. Se valida contra los tipos que la empresa tiene habilitados (viafirma solo BIOMETRIC, mail solo DOCUMENTARY, dual ambos). El tipo queda guardado en la solicitud y no cambia después; decide el proveedor, las acciones disponibles y el saldo que se consume (un cupo de un tipo nunca se consume en el otro). BIOMETRIC: exige legal_rep_email, legal_rep_first_name y legal_rep_last_name; los adjuntos son opcionales (si llegan se guardan sin validar cantidad ni tamaño); la solicitud nace en PROCESSING y la emisión automática se encola (llega el enlace de verificación por correo y WhatsApp). Si la emisión biométrica está apagada en la plataforma responde 400 ISSUANCE_FLOW_UNAVAILABLE. DOCUMENTARY: attachments es obligatorio, con 2 a 3 archivos, máximo 7 MB por archivo y 10 MB en total (valores por defecto, configurables en el servidor); formatos esperados: PDF, JPG o PNG; el servidor genera y adjunta además un Excel con los datos de la solicitud; la solicitud nace en DRAFT. En todos los casos: no puede existir otra solicitud de la misma empresa con el mismo NIT y DV en DRAFT, SENT, PENDING, ACCEPTED o PROCESSING; terms_version_id debe ser la versión vigente de los Términos y Condiciones; los archivos viajan en Base64 dentro del JSON (no multipart). Las etiquetas HTML (<...>) se eliminan sin error de document_number, address, legal_representative, legal_rep_first_name, legal_rep_last_name, company_name, info, phone y mobile antes de guardar (un < sin cerrar seguido de un carácter distinto de espacio, p. ej. en Calle 5 <3 piso 2, elimina todo el texto que le sigue); legal_rep_email se guarda sin cambios. Nota sobre el cupo: el cupo se consume en la misma transacción que crea la solicitud; si la creación falla, no se consume. Límite: 10 solicitudes por minuto por usuario.
Request
Responses
- 200
- 400
- 401
- 402
- 403
- 422
- 429
- 500
Solicitud creada. dataRecords trae la solicitud con sus files y su issuance_flow (y también city e identity cuando el tipo de emisión es DOCUMENTARY). Solo incluye los datos asignados al crear: no incluye uuid (lo asigna la base de datos al insertar): obténgalo con GET /certificate-request/{id} usando el id devuelto; el uuid es el identificador que piden los endpoints de descarga y revocación. Tampoco incluye pin, expiration_date, issued_at ni cert_valid_to (la clave no aparece, ni siquiera como null); entity_document_type_id solo aparece si se envió (si se omite se guarda 1); info llega como cadena vacía si no se envió; dv llega como número. Use GET /certificate-request/{id} para el registro completo.
Datos inválidos o regla de negocio incumplida, con dos formatos. CertificateFormRequestError (validación de campos): tipo de emisión (errors.issuance_flow, con error_code en el primer nivel: INVALID_ISSUANCE_FLOW, ISSUANCE_FLOW_NOT_ALLOWED o ISSUANCE_FLOW_UNAVAILABLE, y message con el texto del error de tipo de emisión, p. ej. Su empresa no tiene habilitado este tipo de emisión.; los demás 400 no traen error_code y su message es Los datos de la solicitud son inválidos.), obligatorios ausentes, catálogos inexistentes, reglas del tipo de emisión (BIOMETRIC: legal_rep_email, legal_rep_first_name y legal_rep_last_name; DOCUMENTARY: adjuntos), versión de T&C no vigente, cantidad o tamaño de adjuntos, Base64 inválido. Claves de errors para adjuntos (N = posición del adjunto, desde 0): attachments cuando faltan los adjuntos y son obligatorios (Los adjuntos son requeridos para la emisión documental; si la empresa es dual y no envió issuance_flow, el texto añade La empresa admite ambos flujos; envíe issuance_flow=BIOMETRIC para emisión biométrica.) y attachments.N.base64, attachments.N.name, attachments.N.type o attachments.N.size por valor inválido (tipo de dato o longitud); la cantidad (Debe enviar al menos 2 archivos. / El número de archivos supera los 3 soportados.) y el tamaño total (El tamaño total de los archivos supera los 10 MB permitidos. ...) se informan en files, el tamaño de un archivo en files.N (El archivo supera el tamaño máximo de 7 MB ...) y el Base64 inválido en files.N.base64 (El contenido en base64 no es válido); un adjunto sin base64 devuelve error tanto en attachments.N.base64 (El contenido en base64 es requerido para cada adjunto) como en files.N.base64 (El contenido en base64 es requerido). ApiErrorResponse (regla de negocio): ya existe una solicitud en curso con el mismo NIT y DV (Ya existe una solicitud de certificado, en proceso, con el mismo NIT y DV. ...) o un adjunto con Base64 inválido.
No autenticado
Sin cupo en el tipo de emisión y la vigencia pedidos (error_code = QUOTA_EXHAUSTED). available_in_other_flows lista los otros tipos que la empresa puede usar y que tienen cupo para esa vigencia (puede venir vacío).
La empresa del usuario está inactiva. Cuerpo: {"message": "La empresa se encuentra inactiva."}, sin success (o una página HTML si la petición no envía Accept: application/json).
Defensa del servidor ante un tipo de emisión que no pasó por la validación (mismo error_code que el 400: INVALID_ISSUANCE_FLOW, ISSUANCE_FLOW_NOT_ALLOWED o ISSUANCE_FLOW_UNAVAILABLE, con errors.issuance_flow). También solo si la petición se envía como multipart con archivos (este endpoint no lee archivos multipart: los adjuntos van en Base64 dentro de attachments): un archivo cuyo tipo real no está permitido responde El archivo '<nombre>' tiene un tipo de contenido no permitido (<tipo>). antes de validar los datos. Envíe siempre JSON con los adjuntos en Base64.
Más de 10 solicitudes por minuto. Mensaje: Demasiadas solicitudes de certificado. Intente nuevamente en un minuto. (ApiErrorResponse, sin cabecera Retry-After). También puede responder 429 el límite general de 60 peticiones por minuto; en ese caso el cuerpo es ThrottleErrorResponse (Too Many Attempts., sin success) e incluye la cabecera Retry-After.
Error interno. Normalmente ApiErrorResponse. Un dni no numérico o con más de 15 dígitos también responde 500, con cualquiera de los dos formatos. Nota: si el usuario no tiene empresa asociada, si phone, mobile o info no llegan como texto, o si, cuando los adjuntos son obligatorios (tipo de emisión DOCUMENTARY), attachments no es un arreglo (p. ej. un texto o un número) o algún attachments[].base64 llega como arreglo u objeto JSON (un número o booleano responde 400 con errors.attachments.N.base64), el cuerpo es el genérico {"message": "Server Error"}, sin success (o una página HTML si la petición no envía Accept: application/json). Nota: un error no garantiza que la solicitud no se haya creado. Si falla el aviso por correo que se envía después de guardarla, la solicitud ya existe pero la respuesta es un error ApiErrorResponse, normalmente 500 con Error interno del servidor. ... (si el servidor de correo rechaza el envío, el código HTTP puede ser otro 4xx o 5xx y el mensaje no lleva ese prefijo) y, en el tipo de emisión BIOMETRIC, la emisión automática no se inicia. Antes de reintentar, búsquela con GET /certificate-request?query={dni}: un reintento con el mismo NIT y DV responde 400 por duplicado.