:::endpoint POST /v1/auth/token/two-factor/setup/confirm

The second half of setting up two-factor during a sign-in. Send the setup
`challenge` and the code the authenticator shows for the
[secret you were given](/docs/api/apps/two-factor-setup). When it is right, the
account has two-factor from now on and the answer is a token, with the recovery
codes beside it.

## Request

```bash
curl -X POST https://api.proppertrading.com/v1/auth/token/two-factor/setup/confirm \
  -H "Content-Type: application/json" \
  -d '{"challenge": "c3a91f0e5b7d2c4e6a8f1b3d5c7e9a0b2d4f6a8c1e3b5d7f9a0c2e4b6d8f1a3c", "code": "492039"}'
```

## Response

The same as [a sign-in](/docs/api/apps/sign-in#response-signed-in), status
`201`, with `recovery_codes` added:

```json
{
    "data": {
        "object": "access_token",
        "status": "signed_in",
        "token": "ptat_9f2c1a44_3b8e7d2f5c9a1b4e6d8f0a2c4e6b8d1f",
        "session": { "id": "9f2c1a44", "object": "session", "name": "Jamie iPhone", "app": "admin", "platform": "ios", "two_factor": true },
        "workspace": { "object": "workspace", "id": "acmefunded", "name": "Acme Funded", "platform": false, "url": "https://acmefunded.com", "branding": null, "maintenance": false },
        "recovery_codes": [
            "jY8q3Lw2Pk-Rt5vN1xMa",
            "Hq2Zc7Ws4B-Ny6dF3kLp"
        ]
    },
    "meta": { "request_id": "req_01kz4bkr1aj1gv63d8fv3133ey" }
}
```

The `session` is shortened above. `recovery_codes` holds eight codes, each good
for one sign-in without the authenticator. This is the only time an app sees
them: show them, and ask the person to keep them somewhere other than this
phone.

## Errors

| Status | Code                           | Meaning                                                                   |
| ------ | ------------------------------ | ------------------------------------------------------------------------- |
| 401    | `invalid_two_factor_code`      | Wrong code, or no secret asked for yet. The challenge is still good       |
| 401    | `expired_two_factor_challenge` | Expired, already used, burned by five wrong codes, or not a setup challenge. Start again from the password |
| 401    | `account_deactivated`          | The account was switched off in the meantime                              |
| 403    | `admin_access_required`        | The account no longer helps run the environment                           |
| 403    | `block_anonymizer`             | The firm blocks VPN, proxy and Tor connections                            |
| 403    | `block_country`                | The firm blocks connections from this country                             |
| 422    | `validation_failed`            | The challenge or the code is missing                                      |
| 429    | `rate_limit_exceeded`          | Shares the limit of the two-factor step                                   |