---
title: "Authenticate a user and obtain an authorization code"
method: POST
path: "/api/auth"
tags: ["Authentication"]
---

# Authenticate a user and obtain an authorization code

`POST /api/auth`

## Request

- Base URL: `https://mail.example.com`
- URL: `https://mail.example.com/api/auth`
- Auth: none required
- TypeScript: <https://skmtc.dev/stalwartlabs/apis/stalwart-management-api/docs/api/auth/post.ts> (a function with typed inputs; its response is checked against the schema)

Anonymous endpoint used by the web UI and device-flow clients to exchange
user credentials (plus optional MFA token and PKCE challenge) for an
OAuth authorization `client_code` that can then be exchanged for an
access token via `POST /auth/token`. Rate-limited as an anonymous request.

## Request body

- union: Tagged union discriminated by `type`. Use `authCode` for the standard OAuth authorization-code flow (optionally with PKCE) and `authDevice` to complete an OAuth device-authorization flow.
  - object
    - `type` 'authCode', required
    - `accountName` string, required
    - `accountSecret` string, password, required
    - `mfaToken` string, nullable: MFA token returned by a previous `mfaRequired` response
    - `clientId` string, required: OAuth client identifier
    - `redirectUri` string, uri, nullable: Must use `https://` unless the server is in recovery or dev mode
    - `nonce` string, nullable
    - `scope` string, nullable
    - `codeChallenge` string, nullable: PKCE code challenge (RFC 7636)
    - `codeChallengeMethod` 'plain' | 'S256', nullable: Defaults to `plain` when a `codeChallenge` is present
    - `state` string, nullable
  - object
    - `type` 'authDevice', required
    - `accountName` string, required
    - `accountSecret` string, password, required
    - `mfaToken` string, nullable
    - `code` string, required: User-facing device code issued by `POST /auth/device`

## Response `200`

Result of the authentication attempt

- union: Tagged union discriminated by `type`.
  - object
    - `type` 'authenticated', required
    - `clientCode` string, required: Authorization code to exchange at `POST /auth/token`
  - object
    - `type` 'verified', required
  - object
    - `type` 'mfaRequired', required
  - object
    - `type` 'failure', required

## Other responses

- `400`: Request payload is malformed or fails validation
- `429`: Anonymous-request rate limit exceeded

## Changes

- **2026-07-17** (v1) `a38a1bbfe8b2`: 1 info
  - endpoint added
- **2025-01-05** (v1) `fbbe298bfa82`: 1 breaking
  - api path removed without deprecation

[Operation history](https://skmtc.dev/stalwartlabs/apis/stalwart-management-api/changes/api/auth/post.md)

---

[API](https://skmtc.dev/stalwartlabs/apis/stalwart-management-api.md) - [All operations](https://skmtc.dev/stalwartlabs/apis/stalwart-management-api/llms.txt) - [OpenAPI document](https://skmtc.dev/stalwartlabs/apis/stalwart-management-api/revisions/a38a1bbfe8b2?raw)
