---
title: "Login Complete With Mfa"
method: POST
path: "/api/auth/token/mfa"
tags: ["Authentication"]
---

# Login Complete With Mfa

`POST /api/auth/token/mfa`

## Request

- Base URL: `https://app.getdot.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://app.getdot.ai/api/auth/token/mfa`
- Auth: none declared

Second step of the password login flow: exchange a pending MFA token + a
valid TOTP code (or recovery code) for a real session JWT.

Race protection is at the SQLite layer: `claim_totp_counter` and
`consume_recovery_code` are conditional UPDATEs that succeed only if the
underlying value is still the one we verified against. Two concurrent
requests with the same captured code race to the UPDATE; one wins, the
other's WHERE clause fails to match and the request is rejected.

## Request body

- BodyLoginCompleteWithMfaApiAuthTokenMfaPost
  - `mfa_token` string, required
  - `code` string, nullable
  - `recovery_code` string, nullable

## Response `200`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/getdot/apis/dot-api-2.md) · [All operations](https://skmtc.dev/getdot/apis/dot-api-2/llms.txt) · [OpenAPI document](https://skmtc.dev/getdot/apis/dot-api-2/revisions/d26fe7163a7f?raw)
