---
title: "WebAuthn creation options for enrolling a passkey. (Roles: user)"
method: POST
path: "/auth/2fa/webauthn/register-options"
tags: ["Authentication"]
---

# WebAuthn creation options for enrolling a passkey. (Roles: user)

`POST /auth/2fa/webauthn/register-options`

Requires NO step-up proof, even on an account that already has 2FA: this call mutates nothing, and the only thing it exposes that the session cannot already read is excludeCredentials, whose ids GET /auth/2fa/status returns to the same session. The single proof for adding a passkey accompanies POST /auth/2fa/webauthn/register. Asking at both would cost two distinct proofs per passkey, since every proof type is single-use.

## Request body

- TwoFactorStepUpPayload — A fresh second-factor proof for a change to the second factors themselves. Exactly one field; an empty body is answered with error_payload.code STEP_UP_REQUIRED.
  - `totp_code` string
  - `recovery_code` string
  - `webauthn_assertion` object

## Response `200`

Success

## Other responses

- `400` — Error
- `429` — Too many failed second-factor attempts

## Changes

- **2026-09-01** `37a21589e770` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/ludo/apis/ludo-ai-api/changes/auth/2fa/webauthn/register-options/post.md)

---

[API](https://skmtc.dev/ludo/apis/ludo-ai-api.md) · [All operations](https://skmtc.dev/ludo/apis/ludo-ai-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/ludo/ludo-ai-api/revisions/8c2e600e07d4/schema)
