> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pacifica.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# Begin WebAuthn Registration

> This endpoint allows users to start registering a passkey or security key.

```http theme={null}
POST /api/v1/account/2fa/webauthn/register/begin
```

Starts registering a passkey or a security key as a [two-factor](https://docs.pacifica.fi/api-documentation/api/rest-api/two-factor) factor. The response has WebAuthn options for the browser. Pass them to `navigator.credentials.create()`, then call [Finish WebAuthn registration](https://docs.pacifica.fi/api-documentation/api/rest-api/two-factor/finish-webauthn-registration.md) within 10 minutes.

Pacifica accepts passkeys only from the Pacifica app. A script or bot cannot register one. API clients should use an [authenticator app](https://docs.pacifica.fi/api-documentation/api/rest-api/two-factor/begin-totp-enrollment.md). See [Passkeys and security keys](https://docs.pacifica.fi/api-documentation/api/rest-api/two-factor#passkeys-and-security-keys).

#### Operation Type (for Signing)

| Header Field | Type | Content |
| - | - | - |
| `"type"` | string | `"begin_webauthn_registration"` |

#### Request Body

<table><thead><tr><th width="176">Field</th><th width="98">Type</th><th width="95">Need</th><th>Description</th><th>Example</th></tr></thead><tbody><tr><td>`"account"`</td><td>string</td><td>required</td><td>User's wallet address</td><td>`42trU9A5...`</td></tr><tr><td>`"signature"`</td><td>string</td><td>required</td><td>Cryptographic signature</td><td>`5j1Vy9Uq...`</td></tr><tr><td>`"timestamp"`</td><td>integer</td><td>required</td><td>Current timestamp in milliseconds</td><td>`1716200000000`</td></tr><tr><td>`"kind"`</td><td>string</td><td>required</td><td>Factor kind:\
`"passkey"`\
`"security_key"`</td><td>`security_key`</td></tr><tr><td>`"label"`</td><td>string</td><td>required</td><td>Your name for the factor. 1 to 64 characters, with no control characters and no leading or trailing spaces</td><td>`YubiKey 5C`</td></tr><tr><td>`"expiry_window"`</td><td>integer</td><td>optional</td><td>Signature expiry in milliseconds</td><td>`30000`</td></tr><tr><td>`"two_factor"`</td><td>object</td><td>conditional</td><td>Proof. Required while 2FA is on. Not part of the signed payload. See [Proofs](https://docs.pacifica.fi/api-documentation/api/rest-api/two-factor#proofs)</td><td>`{"type": "totp", "code": "123456"}`</td></tr></tbody></table>

```json theme={null}
{
  "account": "42trU9A5...",
  "signature": "5j1Vy9Uq...",
  "timestamp": 1716200000000,
  "kind": "security_key",
  "label": "YubiKey 5C",
  "expiry_window": 30000,
  "two_factor": {
    "type": "totp",
    "code": "123456"
  }
}
```

Sign this request with the account's own key. Agent wallets cannot sign it. The account must be a main account.

If 2FA is already on, send a proof in `two_factor`. Any proof type works, including a recovery key. After the proof passes, you can send the same request with the same `kind` and `label` again for 5 minutes without a new proof. This helps when the user cancels the browser prompt.

A `"passkey"` must verify the user with a PIN or biometric. A `"security_key"` asks the browser for a separate device, such as a USB or NFC key. The device names the new credential with a short form of your wallet address and your `label`.

#### Signing

Sign `kind` and `label` as the `data` object. Do not sign `two_factor`. For the request above, the message to sign is:

```json theme={null}
{"data":{"kind":"security_key","label":"YubiKey 5C"},"expiry_window":30000,"timestamp":1716200000000,"type":"begin_webauthn_registration"}
```

#### Response

* Status 200: Registration started

```json theme={null}
{
  "success": true,
  "data": {
    "challenge_id": "45c48cce-2e2d-4fbd-8f3b-7a1c9e0d5b62",
    "options": {
      "publicKey": {
        "challenge": "x8Jf2KqLm0pR..."
      }
    }
  },
  "error": null,
  "code": null
}
```

The `options` above are shortened.

| Field | Type | Description |
| - | - | - |
| `'challenge_id'` | string | Challenge ID (UUID). Send it to [Finish WebAuthn registration](https://docs.pacifica.fi/api-documentation/api/rest-api/two-factor/finish-webauthn-registration.md) within 10 minutes. It works once |
| `'options'` | object | WebAuthn creation options for `navigator.credentials.create()`. Binary values are base64url strings |

* Status 400: Invalid request parameters, label, or signature
* Status 401: The proof is wrong, expired, or already used
* Status 403: The account is a subaccount, or it does not exist
* Status 422: The account has no room for another factor (`a user can have at most 8 factors`)
* Status 428: 2FA is on, and the request has no `two_factor`
* Status 429: Too many proof attempts, or more than 20 enrollments started in 10 minutes
* Status 500: Internal server error
* Status 503: The two-factor service is unavailable. Retry later

#### Code Example (Python)

```python theme={null}
import requests

payload = {
    "account": "42trU9A5...",
    "signature": "5j1Vy9Uq...",
    "timestamp": 1716200000000,
    "kind": "security_key",
    "label": "YubiKey 5C",
    "two_factor": {"type": "totp", "code": "123456"}
}

response = requests.post(
    "/api/v1/account/2fa/webauthn/register/begin",
    json=payload,
    headers={"Content-Type": "application/json"}
)

data = response.json()
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.