switching clears the token & responses
No token
26

Turning on MFA with an authenticator app (TOTP)

Multi-factor authentication

An authenticated user enrols a TOTP authenticator (the totp method) and confirms it. Counterpart to phone-OTP enrolment (scenario 25).

  1. POST /v1/me/mfa/enroll → provisioningUri — render as a QR code for the authenticator app
  2. POST /v1/me/mfa/enroll/confirm → enables totp, returns recovery codes once (if first method)
POST/v1/me/mfa/enrollauthBegin TOTP MFA enrolment

No body. Returns a provisioningUri (otpauth://…). The secret is stored but UNCONFIRMED; re-calling enroll before confirm REPLACES the pending secret.

ℹ︎Field guide — what each value means & where it comes fromno inputs

No request body, no path/query params, no caller-set headers. Just send the call on a live authenticated session (the tester supplies the accessToken / Bearer and the gateway injects x-gateway-context). Returns a TOTP provisioningUri to render as a QR code; enrollment stays pending until confirmed via POST /v1/me/mfa/enroll/confirm. Calling again replaces any pending secret.

Bearer token
→ POST https://api.kerja.team/v1/me/mfa/enroll
↩︎Response guide — what comes back & what each value means2 fields

200 OK with the { data } envelope; response header Cache-Control: no-store (no Set-Cookie). Body carries a single TOTP provisioning URI used to begin (not yet activate) MFA enrollment.

dataobjectalways
Envelope object wrapping the enrollment result.
data.provisioningUristringalways
An otpauth://totp/... URI containing the unconfirmed TOTP secret and issuer. Render it as a QR code (or copy the embedded secret) into an authenticator app, then prove a code via POST /v1/me/mfa/enroll/confirm to activate MFA.
POST/v1/me/mfa/enroll/confirmauthConfirm TOTP MFA enrolment

The current TOTP code. Returns 8 one-time recovery codes if this is your first method — shown ONCE and not retrievable later (you can only regenerate a fresh set, scenario 27). After enabling, future logins carry an MFA hop; an mfa_totp challenge sends nothing — the code comes from the app, so no resend step applies.

⛓ Needs an out-of-band value?
Request body (JSON)
ℹ︎Field guide — what each value means & where it comes from1 field

Confirms TOTP enrollment by proving a live TOTP code, activating the method and setting hasMfaEnabled. Returns one-time recovery codes (shown once) ONLY when this is the user's FIRST MFA method — the pool is shared across methods, so enrolling TOTP beside an existing phone_otp method returns none. Needs an authenticated session (Authorization + gateway context handled by the tester). No path/query params or required custom headers. Enrollment not started, or a wrong code → 401 invalid_credentials.

codebodystringrequiredauthenticator
The current TOTP code from the user's MFA authenticator app (the one being enrolled). The user reads it from their app and types it; 1-32 chars. Proves possession of the TOTP secret so enrollment is confirmed, MFA is enabled, and recovery codes are issued.
Bearer token
→ POST https://api.kerja.team/v1/me/mfa/enroll/confirm
↩︎Response guide — what comes back & what each value means3 fields

200 OK with the standard { data } envelope; response header Cache-Control: no-store, no Set-Cookie. Body returns one-time recovery codes ONLY when this TOTP is the user's first MFA method (the pool is shared across methods) — shown once and never retrievable again; otherwise data carries no codes.

dataobjectalways
Envelope wrapper containing the enrollment-confirmation result.
data.recoveryCodesarrayconditional
Array of 8 one-time recovery codes — present only when this is the user's FIRST MFA method. These are shown only in this response (the server stores only hashed copies) and cannot be retrieved again — the client must display/store them now.
data.recoveryCodes[]stringconditional
A single one-time recovery code (e.g. "a1b2c3d4e5f6a7b8") usable once as an MFA fallback. Each is consumed on use; store securely as it is not recoverable.