Register a passkey
Registration is session-only and, in practice, a dashboard flow (Settings → Security → Add passkey) since it needs a browser’s WebAuthn API:1
Get registration options
POST /me/passkeys/options returns WebAuthn creation options; the
challenge rides in a signed, account-bound cookie.2
Create the credential
The browser calls
navigator.credentials.create() with those options and
the authenticator does its ceremony.3
Register it
POST /me/passkeys/register with the WebAuthn credential (and an
optional name like “MacBook Touch ID”) verifies the attestation against
the challenge cookie and stores the credential. Re-registering the same
authenticator returns 409 passkey_exists.Sign in with a passkey
email omitted, discoverable credentials let the authenticator pick the
account: true one-tap, usernameless sign-in.
Challenge handling is strict: options and verification must come from the same
client (the challenge cookie is signed), challenges expire quickly
(400 challenge_expired), and each is single-use (400 invalid_challenge).
An assertion from an authenticator the account doesn’t know fails with
401 unknown_passkey.
Manage devices
id, deviceName, transports, createdAt, and
lastUsedAt, enough to audit which devices can access the account and prune
stale ones.