Magic links

Send and verify passwordless links through authenticated server or public token-only flows.

PrerequisitesAuth Apps overview
  • Delivery channel is determined by the configured magic_link_delivery.delivery_template_id category (email or sms) in the portal.
  • Email template: provide email in the request body (or rely on upserted user.email).
  • SMS template: provide phone (+ optional phone_country_code) or upserted user.phone.
  • Send/resend endpoints return { ok: true, sent: true } even when the destination is unknown — this prevents email/phone enumeration.
  • S2S verify (.../providers/magic_link/verify) requires knowing externalUserId.
  • Public verify (POST /auth/apps/:appId/magic-link/verify) needs only the token; strict IP rate limit (15 req/min).
  • Invalid, expired, or reused tokens return 400 with AUTH_MAGIC_LINK_INVALID (or related code) without revealing whether the destination exists.
  • App config may include success_redirect_url and failure_redirect_url returned on successful verify.


  1. Configure magic_link_policy, delivery templates, and content in the Cliodot portal
  2. POST .../providers/magic_link/enroll — send first link
  3. End user clicks link; your app calls verify with the token (S2S or public endpoint)
  4. On success, issue your own session

Default policies (overridable per app in the portal):

Setting Default
TOTP digits 6
TOTP period 30 seconds
TOTP algorithm sha1
TOTP window 1
Max verification attempts 5
Lockout duration 15 minutes
Enrollment TTL 15 minutes
Recovery code count 10

OTP Delivery Field Mapping#

Auth Apps separates transport fields (populated on every send), message template variables, and connector meta (user-defined).

Delivery templates and message templates are configured in the Cliodot portal. At runtime you may override content per send with custom_subject and custom_body.

Standard delivery fields#

Email field SMS field Variable
To Phone {{delivery.to}} / {{delivery.phone}}
CC {{delivery.cc}}
BCC {{delivery.bcc}}
Subject {{delivery.subject}}
Message Message {{delivery.message}}
HTML {{delivery.body_html}}
Text Text {{delivery.body_text}}
Magic link URL Magic link URL {{delivery.magic_link_url}}
Attachments Attachments {{delivery.attachments}}

Flat aliases: {{to}}, {{subject}}, {{message}}, {{phone}}, {{html}}, {{text}}.

Message template variables#

{{code}}, {{magic_link_url}}, {{magic_link_expiration_minutes}}, {{user.display_name}}, {{user.email}}, {{user.external_user_id}}, {{app.name}}, {{expires_minutes}}, {{sender_name}}, {{sender_email}}

Content priority at send: runtime custom_subject / custom_body → app inline custom (portal) → message template slug (portal) → system default.

Connector meta#

Map connector-specific inputs with {{meta.your_key}}:

  • Static values: configured on the auth app in the portal (email_otp_delivery.meta_values, etc.)
  • Per-send override: { "meta": { "campaign_id": "login" } } in runtime request body

  • Delivery channel is determined by the configured magic_link_delivery.delivery_template_id category (email or sms) in the portal.
  • Email template: provide email in the request body (or rely on upserted user.email).
  • SMS template: provide phone (+ optional phone_country_code) or upserted user.phone.
  • Send/resend endpoints return { ok: true, sent: true } even when the destination is unknown — this prevents email/phone enumeration.
  • S2S verify (.../providers/magic_link/verify) requires knowing externalUserId.
  • Public verify (POST /auth/apps/:appId/magic-link/verify) needs only the token; strict IP rate limit (15 req/min).
  • Invalid, expired, or reused tokens return 400 with AUTH_MAGIC_LINK_INVALID (or related code) without revealing whether the destination exists.
  • App config may include success_redirect_url and failure_redirect_url returned on successful verify.

API#

Base path: /auth

All endpoints (except public magic-link verify) require app credentials and are rate-limited to 30 requests/minute per IP + path + app + user.


Users#

Upsert User

Method PUT
Path /auth/apps/:appId/users/:externalUserId
Auth aak_ API key or App ID + secret
Description Upsert user metadata before or during MFA enrollment.

Request body (all optional)

Field Type
email string
phone string
phone_country_code string
display_name string
metadata object

Sample success response 200

{
 "ok": true,
 "user": {
   "_id": "auth_user_507f1f77bcf86cd799439012",
   "tenant_id": "tenant_456",
   "auth_app_id": "auth_app_507f1f77bcf86cd799439011",
   "external_user_id": "user_123",
   "email": "user@example.com",
   "display_name": "Jane Doe",
   "metadata": { "department": "engineering" },
   "created_at": "2026-07-09T10:30:00.000Z",
   "updated_at": "2026-07-09T10:30:00.000Z"
 }
}

Common errors: 401 AUTH_UNAUTHORIZED_APP, 403 AUTH_APP_DISABLED, 429 AUTH_RATE_LIMITED

cURL

curl -X PUT "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"email": "user@example.com", "display_name": "Jane Doe", "metadata": {"department": "engineering"}}'

MFA Status#

Get MFA Status

Method GET
Path /auth/apps/:appId/users/:externalUserId/mfa/status
Auth App credentials
Description Get MFA enrollment status for a user across all factors.

Sample success response 200

{
 "ok": true,
 "external_user_id": "user_123",
 "mfa_enabled": true,
 "factors": [
   {
     "factor_type": "totp",
     "status": "active",
     "activated_at": "2026-07-09T10:45:00.000Z",
     "recovery_codes_remaining": 8
   }
 ]
}

Common errors: 401 AUTH_UNAUTHORIZED_APP, 429 AUTH_RATE_LIMITED

cURL

curl "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/mfa/status" \
 -H "Authorization: Bearer YOUR_APP_API_KEY"

TOTP#

Enroll TOTP

Method POST
Path /auth/apps/:appId/users/:externalUserId/mfa/totp/enroll
Auth App credentials
Description Start TOTP enrollment. Returns secret and QR code once.

Request body

Field Type Required
label string No
reset boolean No

Sample success response 200

{
 "ok": true,
 "enrollment_id": "auth_enr_507f1f77bcf86cd799439013",
 "status": "pending",
 "factor_type": "totp",
 "secret": "YOUR_TOTP_SECRET",
 "otpauth_url": "otpauth://totp/Acme%20Admin:user_123?secret=YOUR_TOTP_SECRET&issuer=Acme%20Admin&digits=6&period=30",
 "qr_code_data_url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
 "pending_expires_at": "2026-07-09T12:00:00.000Z"
}

Common errors: 409 AUTH_ENROLLMENT_ALREADY_ACTIVE, 404 AUTH_APP_NOT_FOUND

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/mfa/totp/enroll" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"label": "user@example.com"}'

Confirm TOTP Enrollment

Method POST
Path /auth/apps/:appId/users/:externalUserId/mfa/totp/confirm
Auth App credentials
Description Confirm enrollment with the first valid 6-digit TOTP code from the authenticator app.

Request body: code (string, required)

Sample success response 200

{
 "ok": true,
 "verified": true,
 "enrollment_status": "active",
 "activated_at": "2026-07-09T10:45:00.000Z"
}

Common errors: 400 AUTH_INVALID_CODE, 410 AUTH_ENROLLMENT_EXPIRED, 409 AUTH_ENROLLMENT_PENDING

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/mfa/totp/confirm" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"code": "123456"}'

Verify TOTP

Method POST
Path /auth/apps/:appId/users/:externalUserId/mfa/totp/verify
Auth App credentials
Description Verify TOTP code during login. Call after your backend validates the user's password.

Request body: code (string, required)

Sample success response 200

{
 "ok": true,
 "verified": true,
 "method": "totp",
 "enrollment_status": "active",
 "verified_at": "2026-07-09T11:30:00.000Z",
 "recovery_codes_remaining": 8
}

Common errors: 400 AUTH_INVALID_CODE, 409 AUTH_REPLAY_DETECTED, 423 AUTH_USER_LOCKED, 404 AUTH_MFA_NOT_ENABLED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/mfa/totp/verify" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"code": "654321"}'

Disable TOTP

Method POST
Path /auth/apps/:appId/users/:externalUserId/mfa/totp/disable
Auth App credentials
Description Disable TOTP MFA for a user.

Sample success response 200

{
 "ok": true,
 "disabled": true
}

Common errors: 404 AUTH_MFA_NOT_ENABLED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/mfa/totp/disable" \
 -H "Authorization: Bearer YOUR_APP_API_KEY"

Reset TOTP

Method POST
Path /auth/apps/:appId/users/:externalUserId/mfa/totp/reset
Auth App credentials
Description Reset TOTP secret and start new enrollment. Invalidates existing recovery codes.

Request body: label (optional string)

Sample success response 200

{
 "ok": true,
 "enrollment_id": "auth_enr_507f1f77bcf86cd799439014",
 "status": "pending",
 "factor_type": "totp",
 "secret": "YOUR_TOTP_SECRET",
 "otpauth_url": "otpauth://totp/Acme%20Admin:user_123?secret=YOUR_TOTP_SECRET&issuer=Acme%20Admin&digits=6&period=30",
 "qr_code_data_url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
 "pending_expires_at": "2026-07-09T12:00:00.000Z"
}

Common errors: 404 AUTH_USER_NOT_FOUND

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/mfa/totp/reset" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"label": "user@example.com"}'

Recovery Codes#

Generate Recovery Codes

Method POST
Path /auth/apps/:appId/users/:externalUserId/mfa/recovery-codes
Auth App credentials
Description Generate backup recovery codes. Codes shown once; previous batch invalidated.

Sample success response 200

{
 "ok": true,
 "codes": [
   "YOUR_RECOVERY_CODE",
   "mnop-qrst-uvwx",
   "yzab-cdef-ghij",
   "klmn-opqr-stuv",
   "wxyz-abcd-efgh",
   "ijkl-mnop-qrst",
   "uvwx-yzab-cdef",
   "ghij-klmn-opqr",
   "stuv-wxyz-abcd",
   "efgh-ijkl-mnop"
 ],
 "batch_id": "auth_rcb_507f1f77bcf86cd799439016",
 "count": 10
}

Common errors: 404 AUTH_MFA_NOT_ENABLED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/mfa/recovery-codes" \
 -H "Authorization: Bearer YOUR_APP_API_KEY"

Verify Recovery Code

Method POST
Path /auth/apps/:appId/users/:externalUserId/mfa/recovery-codes/verify
Auth App credentials
Description Verify a one-time recovery code during login.

Request body: code (string, required)

Sample success response 200

{
 "ok": true,
 "verified": true,
 "method": "recovery_code",
 "enrollment_status": "active",
 "verified_at": "2026-07-09T11:35:00.000Z",
 "recovery_codes_remaining": 7
}

Common errors: 400 AUTH_RECOVERY_CODE_INVALID, 409 AUTH_RECOVERY_CODE_USED, 423 AUTH_USER_LOCKED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/mfa/recovery-codes/verify" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"code": "YOUR_RECOVERY_CODE"}'

Email OTP#

Provider path segment: email_otp. Shared request body fields for send endpoints (enroll, challenge, resend):

Field Type Description
email string Recipient email (or rely on upserted user)
custom_subject string Override message subject
custom_body string Override message body
cc string Email CC override
bcc string Email BCC override
attachments array Attachment overrides
meta object Connector meta overrides

Email OTP — Enroll

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/email_otp/enroll
Auth App credentials
Description Enroll email OTP and send first code via configured delivery template.

Sample success response 200

{
 "ok": true,
 "sent": true,
 "expires_at": "2026-07-09T12:10:00.000Z"
}

Queued send (resend_mode: queue during cooldown):

{
 "ok": true,
 "queued": true,
 "position": 2,
 "scheduled_at": "2026-07-09T12:02:00.000Z"
}

Common errors: 422 AUTH_DESTINATION_REQUIRED, 422 AUTH_METHOD_NOT_ENABLED, 429 AUTH_RESEND_COOLDOWN, 502 AUTH_DELIVERY_FAILED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/email_otp/enroll" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"email": "user@example.com", "custom_subject": "Your login code", "custom_body": "Enter {{code}} to sign in"}'

Email OTP — Challenge

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/email_otp/challenge
Auth App credentials
Description Request a new email OTP code (login challenge).

Request body: Same as enroll.

Sample success response 200

{
 "ok": true,
 "sent": true,
 "expires_at": "2026-07-09T12:10:00.000Z"
}

Common errors: 429 AUTH_RESEND_COOLDOWN, 429 AUTH_RESEND_QUEUE_FULL, 422 AUTH_DESTINATION_REQUIRED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/email_otp/challenge" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"email": "user@example.com"}'

Email OTP — Resend

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/email_otp/resend
Auth App credentials
Description Resend the current email OTP code.

Request body: Same as enroll.

Sample success response 200

{
 "ok": true,
 "sent": true,
 "expires_at": "2026-07-09T12:10:00.000Z"
}

Common errors: 429 AUTH_RESEND_COOLDOWN, 429 AUTH_RESEND_QUEUE_FULL

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/email_otp/resend" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"email": "user@example.com"}'

Email OTP — Verify

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/email_otp/verify
Auth App credentials
Description Verify email OTP code. Failed verification returns { ok: true, verified: false } without leaking validity details.

Request body: code (string, required)

Sample success response 200

{
 "ok": true,
 "verified": true,
 "method": "email_otp",
 "enrollment_status": "active",
 "verified_at": "2026-07-09T11:30:00.000Z"
}

Common errors: 410 AUTH_OTP_EXPIRED, 423 AUTH_USER_LOCKED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/email_otp/verify" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"code": "123456"}'

Email OTP — Disable

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/email_otp/disable
Auth App credentials
Description Disable email OTP factor for a user.

Sample success response 200

{
 "ok": true,
 "disabled": true
}

Common errors: 404 AUTH_ENROLLMENT_NOT_FOUND, 404 AUTH_MFA_NOT_ENABLED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/email_otp/disable" \
 -H "Authorization: Bearer YOUR_APP_API_KEY"

Email OTP — Status

Method GET
Path /auth/apps/:appId/users/:externalUserId/providers/email_otp/status
Auth App credentials
Description Get email OTP factor enrollment status.

Sample success response 200

{
 "ok": true,
 "factor_type": "email_otp",
 "enrollment_status": "active",
 "mfa_enabled": true,
 "destination_masked": "u***@example.com"
}

cURL

curl "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/email_otp/status" \
 -H "Authorization: Bearer YOUR_APP_API_KEY"

SMS OTP#

Provider path segment: sms_otp. Shared request body fields for send endpoints:

Field Type Description
phone string Recipient phone number
phone_country_code string Country code (e.g. US)
custom_body string Override SMS body
meta object Connector meta overrides

SMS OTP — Enroll

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/sms_otp/enroll
Auth App credentials
Description Enroll SMS OTP and send first code via configured delivery template.

Sample success response 200

{
 "ok": true,
 "sent": true,
 "expires_at": "2026-07-09T12:05:00.000Z"
}

Common errors: 422 AUTH_DESTINATION_REQUIRED, 422 AUTH_METHOD_NOT_ENABLED, 429 AUTH_RESEND_COOLDOWN, 502 AUTH_DELIVERY_FAILED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/sms_otp/enroll" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"phone": "4155550100", "phone_country_code": "US"}'

SMS OTP — Challenge

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/sms_otp/challenge
Auth App credentials
Description Request a new SMS OTP code (login challenge).

Request body: Same as enroll.

Sample success response 200

{
 "ok": true,
 "sent": true,
 "expires_at": "2026-07-09T12:05:00.000Z"
}

Common errors: 429 AUTH_RESEND_COOLDOWN, 422 AUTH_DESTINATION_REQUIRED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/sms_otp/challenge" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"phone": "4155550100", "phone_country_code": "US"}'

SMS OTP — Resend

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/sms_otp/resend
Auth App credentials
Description Resend the current SMS OTP code.

Request body: Same as enroll.

Sample success response 200

{
 "ok": true,
 "sent": true,
 "expires_at": "2026-07-09T12:05:00.000Z"
}

Common errors: 429 AUTH_RESEND_COOLDOWN, 429 AUTH_RESEND_QUEUE_FULL

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/sms_otp/resend" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"phone": "4155550100"}'

SMS OTP — Verify

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/sms_otp/verify
Auth App credentials
Description Verify SMS OTP code.

Request body: code (string, required)

Sample success response 200

{
 "ok": true,
 "verified": true,
 "method": "sms_otp",
 "enrollment_status": "active",
 "verified_at": "2026-07-09T11:30:00.000Z"
}

Common errors: 410 AUTH_OTP_EXPIRED, 423 AUTH_USER_LOCKED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/sms_otp/verify" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"code": "123456"}'

SMS OTP — Disable

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/sms_otp/disable
Auth App credentials
Description Disable SMS OTP factor for a user.

Sample success response 200

{
 "ok": true,
 "disabled": true
}

Common errors: 404 AUTH_ENROLLMENT_NOT_FOUND

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/sms_otp/disable" \
 -H "Authorization: Bearer YOUR_APP_API_KEY"

SMS OTP — Status

Method GET
Path /auth/apps/:appId/users/:externalUserId/providers/sms_otp/status
Auth App credentials
Description Get SMS OTP factor enrollment status.

Sample success response 200

{
 "ok": true,
 "factor_type": "sms_otp",
 "enrollment_status": "active",
 "mfa_enabled": true,
 "destination_masked": "***0100"
}

cURL

curl "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/sms_otp/status" \
 -H "Authorization: Bearer YOUR_APP_API_KEY"

Shared request body fields for send endpoints (enroll, challenge, resend):

Field Type Description
email string For email delivery templates
phone string For SMS delivery templates
phone_country_code string Country code for SMS
custom_subject string Override subject (email)
custom_body string Override body
cc, bcc, attachments Email overrides
meta object Connector meta overrides

Magic Link — Enroll

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/magic_link/enroll
Auth App credentials
Description Enroll magic link and send first link via configured delivery template.

Sample success response 200

{
 "ok": true,
 "sent": true,
 "expires_in": 900,
 "challenge_id": "auth_ml_ch_507f1f77bcf86cd799439020"
}

Common errors: 422 AUTH_METHOD_NOT_ENABLED, 422 AUTH_DESTINATION_REQUIRED, 429 AUTH_RESEND_COOLDOWN, 502 AUTH_DELIVERY_FAILED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/magic_link/enroll" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{
   "email": "user@example.com",
   "custom_subject": "Sign in to Acme",
   "custom_body": "Click {{magic_link_url}} to sign in. Expires in {{magic_link_expiration_minutes}} minutes."
 }'

Magic Link — Challenge

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/magic_link/challenge
Auth App credentials
Description Request a new magic link (login challenge).

Request body: Same as enroll.

Sample success response 200

{
 "ok": true,
 "sent": true,
 "expires_in": 900,
 "challenge_id": "auth_ml_ch_507f1f77bcf86cd799439021"
}

Common errors: 429 AUTH_RESEND_COOLDOWN, 422 AUTH_DESTINATION_REQUIRED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/magic_link/challenge" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"email": "user@example.com"}'

Magic Link — Resend

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/magic_link/resend
Auth App credentials
Description Resend magic link to the user.

Request body: Same as enroll.

Sample success response 200

{
 "ok": true,
 "sent": true,
 "expires_in": 900,
 "challenge_id": "auth_ml_ch_507f1f77bcf86cd799439022"
}

Common errors: 429 AUTH_RESEND_COOLDOWN

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/magic_link/resend" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"email": "user@example.com"}'

Magic Link — Verify (S2S)

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/magic_link/verify
Auth App credentials
Description Verify magic link token for a known user. Use when your backend handles the callback.

Request body: token (string, required) — base64url token from the link

Sample success response 200

{
 "ok": true,
 "verified": true,
 "method": "magic_link",
 "challenge_id": "auth_ml_ch_507f1f77bcf86cd799439020",
 "user_reference": "user_123",
 "success_redirect_url": "https://app.example.com/dashboard",
 "failure_redirect_url": "https://app.example.com/login?error=magic_link"
}

Common errors: 400 AUTH_MAGIC_LINK_INVALID, 400 AUTH_MAGIC_LINK_EXPIRED, 400 AUTH_MAGIC_LINK_ALREADY_USED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/magic_link/verify" \
 -H "Authorization: Bearer YOUR_APP_API_KEY" \
 -H "Content-Type: application/json" \
 -d '{"token": "base64url-token-from-link"}'

Magic Link — Disable

Method POST
Path /auth/apps/:appId/users/:externalUserId/providers/magic_link/disable
Auth App credentials
Description Disable magic link factor for a user.

Sample success response 200

{
 "ok": true,
 "disabled": true
}

Common errors: 404 AUTH_ENROLLMENT_NOT_FOUND

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/magic_link/disable" \
 -H "Authorization: Bearer YOUR_APP_API_KEY"

Magic Link — Status

Method GET
Path /auth/apps/:appId/users/:externalUserId/providers/magic_link/status
Auth App credentials
Description Get magic link factor enrollment status.

Sample success response 200

{
 "ok": true,
 "factor_type": "magic_link",
 "enrollment_status": "active",
 "mfa_enabled": true,
 "destination_masked": "u***@example.com"
}

cURL

curl "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/users/user_123/providers/magic_link/status" \
 -H "Authorization: Bearer YOUR_APP_API_KEY"

Verify Magic Link (Public)

Method POST
Path /auth/apps/:appId/magic-link/verify
Auth None (token only)
Description Public token-only verify endpoint. Strict IP rate limit: 15 requests/minute. Use when the end user's browser hits your callback directly.

Request body: token (string, required)

Sample success response 200

{
 "ok": true,
 "verified": true,
 "method": "magic_link",
 "challenge_id": "auth_ml_ch_507f1f77bcf86cd799439020",
 "user_reference": "user_123",
 "success_redirect_url": "https://app.example.com/dashboard",
 "failure_redirect_url": "https://app.example.com/login?error=magic_link"
}

Common errors: 400 AUTH_MAGIC_LINK_INVALID, 400 AUTH_MAGIC_LINK_EXPIRED, 400 AUTH_MAGIC_LINK_ALREADY_USED, 429 AUTH_RATE_LIMITED

cURL

curl -X POST "https://api.example.com/auth/apps/auth_app_507f1f77bcf86cd799439011/magic-link/verify" \
 -H "Content-Type: application/json" \
 -d '{"token": "base64url-token-from-link"}'