---
title: "Complete a login that was challenged for MFA"
method: POST
path: "/auth/login/mfa"
tags: ["Auth"]
---

# Complete a login that was challenged for MFA

`POST /auth/login/mfa`

## Request

- Base URL: `http://localhost:38200`
- URL: `http://localhost:38200/auth/login/mfa`
- Auth: none required

T731: the second step of login for an account with confirmed TOTP MFA. Redeems the `challenge` from POST /auth/login's AuthMfaChallengeResponse together with either a live 6-digit TOTP code or a single-use backup code, and only then sets the session cookies. Rate-limited to 10 requests/5min per IP.

## Request body

- object: Exactly one of `code` or `backupCode` must be present.
  - `challenge` string, required
  - `code` string: 6-digit TOTP code.
  - `backupCode` string: A single-use backup code issued at MFA confirm time.

## Response `200`

Authenticated. JWT + refresh cookies set on the response.

- AuthSessionResponse
  - `user` object
    - `id` integer
    - `email` string, email
    - `role` 'owner' | 'admin' | 'member'
    - `isSuperAdmin` boolean
    - `emailVerified` boolean
    - `createdAt` string, date-time
  - `tenant` object
    - `id` integer
    - `name` string
    - `slug` string
    - `plan` string
    - `createdAt` string, date-time

## Other responses

- `400`: Request body/query failed Zod validation.
- `401`: Invalid/expired challenge, or an invalid/expired code or backup code -- both collapse to the same generic body (`invalid_mfa_challenge`) so this route is never an oracle for which half of the pair was wrong.
- `429`: Rate limit exceeded for this endpoint.

---

[API](https://skmtc.dev/contextq/apis/contextq-api.md) · [All operations](https://skmtc.dev/contextq/apis/contextq-api/llms.txt) · [OpenAPI document](https://skmtc.dev/contextq/apis/contextq-api/revisions/7afc44056a22?raw)
