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

# Verify two-factor authentication

> Complete login with an authenticator code or an unused backup code to obtain a JWT

Call this endpoint after [password login](/en/apis/rest/auth/post-api-auth-login) or [session resumption](/en/apis/rest/auth/post-api-auth-mfa-resume) returns `status: "mfa_required"`.

## Required cookie and method

Send the `vos_mfa_challenge` cookie returned by the preceding request. Preserve it with a cookie jar for command-line or server clients. Browser clients must send requests from the authentication host origin. The cookie is HttpOnly and must be treated as an opaque credential.

This endpoint does not require a Bearer JWT. The challenge response does not expose a session token or a challenge identifier to submit in the body.

| `method` | `code` | Condition |
| - | - | - |
| `totp` | Current authenticator code as a string containing exactly six digits. Preserve leading zeros. | `totp` is listed in the challenge `methods`. |
| `lookup_secret` | One unused saved backup code as a string. | `lookup_secret` is listed in the challenge `methods`. Successful verification consumes the code. |

Send only `method` and `code`. Additional body fields are rejected. See the [login procedure](/en/apis/rest/auth/post-api-auth-login#2-verify-the-second-factor-when-required) for a complete cURL example with cookie handling.

## Successful verification

HTTP `200` returns `status: "authenticated"`, `sessionToken`, `jwt`, `session`, `identity`, and `tokenizedSession`. Both session objects report `authenticator_assurance_level: "aal2"`. The response clears the pending challenge cookie. Send `jwt` as `Authorization: Bearer <jwt>` to protected REST API endpoints.

For [password recovery](/en/apis/rest/auth/post-api-auth-recovery-verify), preserve all updated cookies and continue to the password-reset request after successful verification.

## Error handling

| HTTP status | Error code | Next action |
| - | - | - |
| `400` | `invalid_code` | Send a valid method and code format. |
| `400` | `invalid_mfa_request` | Check the code and retry while the challenge remains valid. A consumed backup code cannot be reused. |
| `401` | `session_invalid` | Sign in again. |
| `403` | `origin_not_allowed` | Send the request from the authentication host origin or use a server client. |
| `403` | `session_invalid`, `session_refresh_required`, `session_aal2_required` | Restart authentication and complete its required steps. |
| `410` | `challenge_expired`, `flow_expired` | Restart login or session resumption to obtain a new challenge and cookie. |
| `429` | `rate_limited` | Wait before retrying. |
| `502` | `mfa_incomplete`, `mfa_service_unavailable` | No JWT was issued. Retry later. |


## OpenAPI

````yaml openapi.oms.en.json POST /api/auth/mfa/verify
openapi: 3.0.3
info:
  title: VOS OMS Public API
  version: 1.0.0
  description: >-
    Public REST API surface for Vero OMS. Authentication requests use
    platform.verolabs.co. REST API requests use api-oms.verolabs.co.
servers:
  - url: https://platform.verolabs.co
    description: Authentication host
  - url: https://api-oms.verolabs.co
    description: REST API host
security: []
tags:
  - name: Authentication
    description: >-
      Password login, two-factor authentication, session resumption, and
      password recovery.
  - name: Trading
    description: Order entry, quote, IOI, and trading activity APIs.
  - name: Portfolio & Risk
    description: Accounts, holdings, mappings, and risk-rule read APIs.
  - name: Administration
    description: Permissions, groups, workflow, reference data, and audit APIs.
  - name: System & Diagnostics
    description: Health and latency endpoints.
paths:
  /api/auth/mfa/verify:
    post:
      tags:
        - Authentication
      summary: Verify two-factor authentication
      description: >-
        Completes a pending challenge using a six-digit authenticator code or an
        unused backup code. Send the challenge cookie from login or session
        resumption. No Bearer JWT is required. On success, returns
        status=authenticated and an aal2 session with a JWT, then clears the
        challenge cookie. Browser requests must use the authentication host
        origin.
      operationId: post_api_auth_mfa_verify
      requestBody:
        required: true
        description: Second-factor method and code.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuthMfaVerifyRequest'
            examples:
              totp:
                summary: Authenticator code
                value:
                  method: totp
                  code: '012345'
              backup_code:
                summary: Unused saved backup code
                value:
                  method: lookup_secret
                  code: <unused-backup-code>
      responses:
        '200':
          description: Two-factor authentication complete; JWT issued.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthAuthenticatedResponse'
              examples:
                authenticated:
                  summary: Authentication complete
                  value:
                    status: authenticated
                    sessionToken: <session-token>
                    jwt: <jwt>
                    session:
                      active: true
                      authenticator_assurance_level: aal2
                      tokenized: <jwt>
                    identity: null
                    tokenizedSession:
                      active: true
                      authenticator_assurance_level: aal2
                      tokenized: <jwt>
          headers:
            Set-Cookie:
              description: >-
                Clears the pending vos_mfa_challenge cookie. During password
                recovery, also updates the recovery cookie for the
                password-reset step.
              schema:
                type: string
        '400':
          description: >-
            Invalid code format (invalid_code), or rejected code/request
            (invalid_mfa_request).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
        '401':
          description: Session is no longer valid (session_invalid). Restart login.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
        '403':
          description: >-
            Request origin or session authentication requirements rejected
            (origin_not_allowed, session_invalid, session_refresh_required,
            session_aal2_required).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
        '410':
          description: >-
            Challenge cookie missing/expired (challenge_expired), or challenge
            no longer valid (flow_expired). Restart login or session resumption.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
        '429':
          description: Too many authentication requests (rate_limited).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
        '502':
          description: >-
            Two-factor authentication could not complete (mfa_incomplete,
            mfa_service_unavailable).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
      security:
        - mfaChallengeCookie: []
      servers:
        - url: https://platform.verolabs.co
components:
  schemas:
    AuthMfaVerifyRequest:
      description: >-
        One second-factor proof. Choose a method listed in the challenge
        response.
      oneOf:
        - $ref: '#/components/schemas/AuthTotpVerifyRequest'
        - $ref: '#/components/schemas/AuthBackupCodeVerifyRequest'
      discriminator:
        propertyName: method
        mapping:
          totp: '#/components/schemas/AuthTotpVerifyRequest'
          lookup_secret: '#/components/schemas/AuthBackupCodeVerifyRequest'
    AuthAuthenticatedResponse:
      type: object
      description: >-
        Completed authentication. The JWT is issued only after all required
        authentication factors pass.
      properties:
        status:
          type: string
          enum:
            - authenticated
          description: Indicates that authentication is complete and the JWT can be used.
        sessionToken:
          type: string
          description: >-
            Account session token. Keep it confidential. Use it for session
            resumption; use jwt for REST API authorization.
        jwt:
          type: string
          description: >-
            Bearer JWT for protected REST API requests. Send it as
            Authorization: Bearer <jwt>.
        session:
          description: Active authenticated session.
          allOf:
            - $ref: '#/components/schemas/AuthSession'
        identity:
          description: Account identity, or null if absent.
          allOf:
            - $ref: '#/components/schemas/AuthIdentity'
        tokenizedSession:
          description: Authenticated session containing the JWT in tokenized.
          allOf:
            - $ref: '#/components/schemas/AuthSession'
      required:
        - status
        - sessionToken
        - jwt
        - session
        - identity
        - tokenizedSession
      additionalProperties: false
    AuthError:
      type: object
      properties:
        error:
          type: string
          description: Machine-readable error code or error category.
        message:
          type: string
          description: Human-readable error message.
        status:
          type: integer
          format: int32
          description: HTTP status code of this error response.
      required:
        - error
        - message
        - status
      description: >-
        Authentication error envelope. Use the HTTP status and error code to
        select the next action.
    AuthTotpVerifyRequest:
      type: object
      description: Verify the current six-digit authenticator code.
      properties:
        method:
          type: string
          enum:
            - totp
          description: >-
            Select authenticator-code verification. Must be available in the
            challenge methods.
        code:
          type: string
          minLength: 6
          maxLength: 6
          pattern: ^[0-9]{6}$
          example: '012345'
          description: Exactly six digits as a string, including any leading zeros.
      required:
        - method
        - code
      additionalProperties: false
    AuthBackupCodeVerifyRequest:
      type: object
      description: Verify an unused saved backup code.
      properties:
        method:
          type: string
          enum:
            - lookup_secret
          description: >-
            Select backup-code verification. Must be available in the challenge
            methods.
        code:
          type: string
          minLength: 1
          description: >-
            An unused saved backup code. Submit the complete code as a string. A
            successful verification consumes it.
      required:
        - method
        - code
      additionalProperties: false
    AuthSession:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the record.
        active:
          type: boolean
          description: Indicates whether the session is active.
        authenticated_at:
          type: string
          format: date-time
          description: Timestamp when the session was authenticated.
        expires_at:
          type: string
          format: date-time
          description: Timestamp when the session expires.
        devices:
          type: array
          items:
            $ref: '#/components/schemas/AuthSessionDevice'
          description: Devices associated with the authenticated session.
        identity:
          $ref: '#/components/schemas/AuthIdentity'
        tokenized:
          type: string
          description: Bearer JWT issued for REST API calls.
        authenticator_assurance_level:
          type: string
          enum:
            - aal1
            - aal2
          description: >-
            Authentication assurance level: aal1 after first-factor
            authentication; aal2 after successful two-factor authentication.
      description: >-
        Authenticated session details. tokenized contains the Bearer JWT when
        present.
      additionalProperties: true
    AuthIdentity:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the record.
        traits:
          type: object
          additionalProperties: true
          description: Account attributes returned with the authenticated session.
      description: >-
        Account identity returned with the authenticated session, or null if no
        identity is returned.
      additionalProperties: true
      nullable: true
    AuthSessionDevice:
      type: object
      properties:
        ip_address:
          type: string
          description: IP address reported for the session device.
        location:
          type: string
          description: Location metadata reported for the session device.
        user_agent:
          type: string
          description: User agent reported for the session device.
      description: AuthSessionDevice schema.
  securitySchemes:
    mfaChallengeCookie:
      type: apiKey
      in: cookie
      name: vos_mfa_challenge
      description: >-
        Pending two-factor challenge cookie returned by login or session
        resumption. Use a cookie jar; do not construct or modify its value.

````

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