1. Docs
  2. API Reference
  3. Submit an email OTP to satisfy an in-flight MFA challenge

Submit an email OTP to satisfy an in-flight MFA challenge

POST/v1/identity/auth/mfa/challenge/email-otp/verify

Request body

  • challenge_tokenstring*

    Challenge token from the prior /login.

  • codestring*

    8-digit numeric code received via email.

  • remember_deviceboolean

    When true and the env's `mfa_trusted_device_days` > 0, issue a 'remember this device' cookie so future logins from this browser skip the MFA challenge.

Code samples

cURLJavaScriptPythonGo
curl -X POST "https://api.canopy.dev/v1/identity/auth/mfa/challenge/email-otp/verify" \
  -H "Content-Type: application/json" \
  -d '{
    "challenge_token": "string",
    "code": "12345678",
    "remember_device": false
  }'

Responses

200 Verifies the 8-digit code against the stored hash + TTL. Returns the full session on success with `amr: ['pwd', 'mfa', 'otp']`.
{
  "requires_application_selection": false,
  "requires_mfa_challenge": false,
  "expires_in": 0,
  "identity": {
    "id": "string",
    "email": "string",
    "first_name": "string",
    "last_name": "string"
  },
  "access_token": "string",
  "token_type": "string",
  "applications": [
    {
      "id": "string",
      "name": "string",
      "slug": "string"
    }
  ],
  "mfa_challenge": {
    "challenge_token": "string",
    "available_factors": [
      "totp"
    ],
    "expires_at": "2026-04-20T12:00:00.000Z"
  },
  "mfa_enrollment_pending": false,
  "grace_expires_at": "2026-04-20T12:00:00.000Z"
}

application/json

  • requires_application_selectionboolean*
  • requires_mfa_challengeboolean*

    True when the env requires MFA and the identity has ≥ 1 enrolled factor. The client must POST one of `/v1/identity/auth/mfa/challenge/*` with the supplied `mfa_challenge.challenge_token` to mint a session.

  • expires_innumber*
  • identityIdentityUserDto*
  • access_tokenstring
  • token_typestring
  • applicationsIdentityApplicationSummaryDto[]
  • mfa_challengeIdentityMfaChallengePromptDto
  • mfa_enrollment_pendingboolean

    True when the env requires MFA, the identity has not yet enrolled a factor, and the per-env grace timer has time on it. Session is fully issued; the client should nudge the user to enroll a factor before `grace_expires_at`.

  • grace_expires_atstring (date-time)

    Wall-clock deadline by which the identity must enroll a factor; after this, login is blocked with `mfa.enrollment_required` until an admin force-resets MFA.

401 Challenge token is missing, expired, already consumed, or locked after too many failed attempts

Returned object

On this page

Related endpoints

POSTSubmit a TOTP code to satisfy an in-flight MFA challenge
POSTRedeem a single-use recovery code to satisfy an in-flight MFA challenge
POSTGenerate WebAuthn authentication options for an in-flight MFA challenge
POSTSubmit a WebAuthn assertion to satisfy an in-flight MFA challenge
POSTTrigger an email OTP for an in-flight MFA challenge