Prepare passkey updates
Prepare a user-scoped passkey update. The prepare endpoint updates the stored Passlock vault username for the user’s passkeys and returns a short-lived token for browser-side WebAuthn signalling.
POST https://api.passlock.dev/v2/{tenancyId}/passkeys/update HTTP/1.1Authorization: Bearer {apiKey}Accept: application/jsonContent-Type: application/json
{ "userId": "tenant-user-id", "username": "jdoe@example.com", "displayName": "Jane Doe"}HTTP/1.1 202 AcceptedContent-Type: application/json
{ "_tag": "PreparedPasskeyUpdate", "updatePasskeysToken": "opaque-random-token", "expiresAt": 1770123593000, "warnings": []}Send only updatePasskeysToken to your frontend, then call @passlock/browser’s updatePasskeys helper. The browser helper exchanges the token with:
POST https://api.passlock.dev/v2/{tenancyId}/passkeys/update/exchange HTTP/1.1Accept: application/jsonContent-Type: application/json
{ "updatePasskeysToken": "opaque-random-token"}HTTP/1.1 200 OKContent-Type: application/json
{ "_tag": "PasskeyUpdateInstructions", "instructions": [ { "rpId": "example.com", "userId": "MTVkMTFmdHM1Yzg0bDN0anpieG9w", "username": "jdoe@example.com", "displayName": "Jane Doe" } ], "warnings": []}Warnings are non-fatal. For example, updating a user with no passkeys succeeds with a token and a NO_PASSKEYS_FOUND warning.
Server helper
Section titled “Server helper”Prefer @passlock/server where possible:
import { Passlock } from "@passlock/server";
const passlock = new Passlock({ tenancyId, apiKey });
const result = await passlock.updatePasskeys({ userId: user.id, username: "jdoe@example.com", displayName: "Jane Doe",});