Registrar una clave de acceso

POST /fapi/v1/me/passkeys · llamado desde el host de inicio de sesión del entorno

Finaliza un registro iniciado con POST /fapi/v1/me/passkeys/registration-options: verifica la respuesta del navegador, almacena la clave de acceso o la clave de seguridad y la devuelve. El usuario recibe un correo de seguridad sobre el nuevo método de inicio de sesión; este correo no puede desactivarse. Requiere la cookie __Host-idp_session del usuario autenticado; si la cookie falta, ha caducado o ha sido revocada, devuelve 401 unauthenticated. Una aplicación de primera parte en otro origen puede enviar en su lugar su token de acceso a la API frontal (Authorization: DPoP <token> con una prueba DPoP; consulta Token de acceso a la API frontal).

Las reglas de sesión son las de la llamada de inicio: verificada en los últimos 10 minutos y abierta con un segundo factor si el usuario tiene uno.

Solicitud

Encabezados:

Encabezado Obligatorio Descripción
Idp-Client sí Identificador del SDK.
Origin sí Debe ser exactamente https://<host de inicio de sesión>.
Content-Type sí application/json.

Cuerpo:

Campo Tipo Obligatorio Descripción
ceremony_id string sí El ceremony_id de la llamada de inicio.
credential object sí El resultado de navigator.credentials.create como JSON (PublicKeyCredential.toJSON()), como máximo 16 KiB.

Respuesta

201 Created, el nuevo autenticador:

{
  "id": "cred_01j9zzzzzzzzzzzzzzzzzzzzzz",
  "type": "passkey",
  "label": "iCloud Keychain",
  "status": "active",
  "synced": true,
  "created_at": "2026-10-12T09:00:00Z",
  "last_used_at": null
}

Errores

Un registro rechazado no cuenta como intento fallido; vuelve a empezar con un nuevo registro.

Estado Código Cuándo
400 malformed_request El cuerpo no es JSON válido.
400 unknown_field El cuerpo tiene un campo distinto de ceremony_id y credential.
401 unauthenticated No hay una cookie de sesión válida.
401 step_up_required La sesión es demasiado antigua o se requiere un segundo factor; vuelve a verificarte con los valores del encabezado WWW-Authenticate.
403 origin_not_allowed Origin falta o es incorrecto.
409 credential_already_registered Este autenticador ya está registrado en el entorno.
409 credential_limit_reached El usuario ya tiene el número máximo de claves de acceso y claves de seguridad.
413 payload_too_large El cuerpo es demasiado grande.
415 unsupported_media_type Content-Type no es application/json.
422 validation_failed /ceremony_id: el registro es desconocido, ha caducado, ya se usó o pertenece a otra sesión. /credential: la respuesta falta o no se verifica.
422 device_bound_passkey_required El entorno solo acepta claves de acceso que permanecen en un único dispositivo.
422 aaguid_not_allowed El entorno no permite este modelo de autenticador.
422 attestation_untrusted El entorno requiere una atestación de confianza y esta no lo es.

Ejemplo

curl -X POST https://example.keenauth.app/fapi/v1/me/passkeys \
  -H "Idp-Client: my-app/1.0.0 (node/22.0.0)" \
  -H "Origin: https://example.keenauth.app" \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{"ceremony_id": "CQAAAAAAAAAAAAAAAAAAAA", "credential": {"id": "…", "rawId": "…", "type": "public-key", "response": {"clientDataJSON": "…", "attestationObject": "…"}}}'

Datos personales

Este endpoint contiene datos personales: credenciales. Datos personales en las API de KeenAuth describe qué se almacena, durante cuánto tiempo se conserva y cómo se elimina. No envíes categorías especiales de datos personales (salud, datos biométricos, religión, opiniones políticas, orientación sexual) en ningún campo.