Verify and store a new passkey (session only).
const url = 'https://api.opdns.io/v1/auth/passkeys/register/finish';const options = { method: 'POST', headers: { cookie: 'opdns_session=<opdns_session>', 'Content-Type': 'application/json' }, body: '{"ceremony_id":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0","name":"example","credential":{}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.opdns.io/v1/auth/passkeys/register/finish \ --header 'Content-Type: application/json' \ --cookie opdns_session=<opdns_session> \ --data '{ "ceremony_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "name": "example", "credential": {} }'credential is the PublicKeyCredential from navigator.credentials.create()
serialised as WebAuthn JSON (PublicKeyCredential.toJSON()). 400
ceremony_invalid for an unknown, used or expired ceremony, passkey_invalid
when verification fails. The account’s first second factor also returns ten
recovery codes, shown once; restricted sessions are lifted.
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”object
Label; default “Passkey
object
Examplegenerated
{ "ceremony_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "name": "example", "credential": {}}Responses
Section titled “Responses”Registered.
object
object
The authenticator reported a discoverable (resident) credential.
The sign counter went backwards at some sign-in (possible clone; synced passkeys never set it).
Ten single-use codes (xxxx-xxxx-xxxx-xxxx), shown only in this response; null when the account already had codes.
Examplegenerated
{ "passkey": { "id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "name": "example", "discoverable": true, "clone_warning": true, "created_at": "2026-04-15T12:00:00Z", "last_used_at": "2026-04-15T12:00:00Z" }, "recovery_codes": [ "example" ]}Malformed request.
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/bad_request", "title": "Bad Request", "status": 400, "code": "bad_request", "detail": "invalid JSON body", "request_id": "5f2c9a0e7b1d4c38"}Not authenticated.
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/unauthenticated", "title": "Unauthorized", "status": 401, "code": "unauthenticated", "detail": "authentication required", "request_id": "5f2c9a0e7b1d4c38"}Authenticated but not allowed: insufficient_scope, session_required, csrf_rejected, mfa_enrolment_required (restricted session), mfa_required (an operator action, or an admin-scoped token, from a session signed in with the password alone; not in dev), reauth_required (sign in again within five minutes), account_pending_deletion (the account is in its deletion cooling-off).
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/insufficient_scope", "title": "Forbidden", "status": 403, "code": "insufficient_scope", "detail": "the token lacks the profiles:write scope", "request_id": "5f2c9a0e7b1d4c38"}Conflict. On POSTs with an Idempotency-Key: idempotency_key_reused (the key was used with a different request) or idempotency_in_progress (the first request with it is still running; retry after Retry-After).
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/idempotency_key_reused", "title": "Conflict", "status": 409, "code": "idempotency_key_reused", "detail": "the Idempotency-Key was used with a different request", "request_id": "5f2c9a0e7b1d4c38"}Headers
Section titled “Headers”Field validation failed (validation_failed, unknown_list).
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/validation_failed", "title": "Unprocessable Content", "status": 422, "code": "validation_failed", "detail": "the request has invalid fields", "errors": [ { "field": "settings.block_mode", "message": "one of nxdomain, refused, null, block-page" } ], "request_id": "5f2c9a0e7b1d4c38"}Passkeys are not configured on this server (passkeys_unavailable).
object
Stable machine code.
object
Seconds, repeating the Retry-After header (rate limits, offline nodes).
Example
{ "type": "https://opdns.io/problems/passkeys_unavailable", "title": "Service Unavailable", "status": 503, "code": "passkeys_unavailable", "detail": "passkeys are not configured on this server", "request_id": "5f2c9a0e7b1d4c38"}