Ir al contenido

Claves de API acotadas y webhooks firmados

Las nuevas integraciones deben usar claves de API con nombre y permisos acotados. Cada clave se puede revocar sin interrumpir otras integraciones y recibe únicamente los permisos que necesita. Las claves secretas de API heredadas de la organización siguen siendo compatibles durante la migración.

Crea una clave de API acotada

Un Administrador crea las claves desde la configuración de desarrollador de la organización. El token completo se muestra una sola vez. Los tokens de producción comienzan con exm_live.; los tokens del entorno de pruebas para desarrolladores comienzan con exm_test.. Guarda cada token en un gestor de secretos en el servidor.

Permiso Permite
examinees:read Leer registros de candidatos a través de los endpoints existentes
examinees:write Crear, actualizar y registrar candidatos de forma masiva
exams:read Leer definiciones de exámenes
exams:write Cargar, configurar, etiquetar y eliminar exámenes
groups:read Leer grupos y sus miembros
groups:write Crear grupos y cambiar sus miembros
assignments:read Leer asignaciones de exámenes
assignments:write Crear, cambiar y eliminar asignaciones no iniciadas
results:read Leer resultados completados y resúmenes en papel
sessions:write Crear URL de inicio de examen de un solo uso
webhooks:read Listar endpoints e historial de envíos
webhooks:write Crear endpoints, desactivar endpoints y reintentar envíos

Autentícate mediante el esquema Bearer:

curl --request GET \
  --header "Authorization: Bearer $EXAMINA_API_KEY" \
  --header "Accept: application/json" \
  "https://www.examina.io/api/v1/results?page=1&pageSize=25"

No coloques claves de API en código de navegador, aplicaciones móviles, capturas de pantalla, control de versiones o registros de soporte.

Las claves de API están vinculadas al entorno. Una clave exm_live. funciona solo en la API de producción. Una clave exm_test. funciona solo en https://sandbox.examina.io/api/v1. La autenticación básica heredada solo se acepta en la API de producción.

Haz que las mutaciones sean idempotentes

Los endpoints de creación y actualización requieren el encabezado Idempotency-Key. Genera un valor único para la operación lógica y reutilízalo solo cuando reintentes esa misma solicitud:

curl --request POST \
  --header "Authorization: Bearer $EXAMINA_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: candidate-import-2026-08-23-0001" \
  --data '{"code":"CANDIDATE-42","passcode":"temporary-secret","firstName":"Ada","lastName":"Okafor"}' \
  "https://www.examina.io/api/v1/examinees"

La clave se conserva durante al menos 24 horas. Repetirla con un cuerpo idéntico devuelve el recurso original. Reutilizarla con datos diferentes devuelve un error HTTP 409.

Configura un webhook firmado

Crea un endpoint suscrito a result.completed:

curl --request POST \
  --header "Authorization: Bearer $EXAMINA_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: webhook-results-v1" \
  --data '{"url":"https://integrator.example/webhooks/examina","events":["result.completed"]}' \
  "https://www.examina.io/api/v1/webhook-endpoints"

La respuesta incluye un signingSecret que comienza con whsec_. Se muestra una sola vez. Las URL de los webhooks deben usar HTTPS público y no deben resolverse en una dirección privada, de bucle de retorno (loopback), de enlace local (link-local) o de multidifusión (multicast).

Cada envío contiene un evento JSON. La solicitud también incluye:

La envoltura del evento incluye livemode y environment. Los envíos del entorno de pruebas usan "livemode": false y "environment": "test"; los envíos de producción usan true y "live". Rechaza cualquier entorno no esperado antes de procesar los datos.

Encabezado Significado
X-Examina-Event-Id Identificador de evento estable para desduplicación
X-Examina-Timestamp Marca de tiempo de Unix utilizada en la firma
X-Examina-Signature v1= seguido de la firma hexadecimal HMAC-SHA256

Concatena la marca de tiempo, un punto y el cuerpo exacto sin procesar de la solicitud. Calcula HMAC-SHA256 con el secreto de firma y compáralo con la firma v1 mediante una comparación de tiempo constante:

signed_content = timestamp + "." + raw_request_body
expected = hex(HMAC_SHA256(signing_secret, signed_content))

Devuelve una respuesta 2xx rápidamente y pon en cola los procesamientos más largos. Usa el ID del evento para desduplicar el procesamiento y luego recupera el resultado definitivo desde GET /results/{assignmentId}.

Inspecciona y reintenta envíos

curl --header "Authorization: Bearer $EXAMINA_API_KEY" \
  "https://www.examina.io/api/v1/webhook-endpoints/deliveries?page=1&pageSize=25"

curl --request POST \
  --header "Authorization: Bearer $EXAMINA_API_KEY" \
  "https://www.examina.io/api/v1/webhook-endpoints/deliveries/DELIVERY_ID/retry"

La devolución de llamada de formulario previa a nivel de organización sigue estando disponible para las integraciones existentes, pero está en desuso. Las nuevas integraciones deben usar recursos de endpoint firmados porque proporcionan ID de eventos, firmas, estado del envío y reintento.

Rota o revoca credenciales

Crea una clave de reemplazo, despliégala en cada consumidor, verifica que las llamadas sean exitosas y luego revoca la clave anterior. Dado que las claves son independientes, la rotación no requiere un cambio simultáneo. Revoca una clave de inmediato si existe la posibilidad de que haya quedado expuesta.