1
Start the MFA ceremony
Call the MFA method’s
init route to begin MFA enrollment or verification. For SMS, Privy sends
a 6-digit code to the user. For passkeys, Privy returns WebAuthn options for the user’s browser.2
Complete the MFA ceremony
Send the user’s code or passkey credential to the MFA method’s
verify route to complete MFA
enrollment or verification. Privy returns an MFA token.3
Use the MFA token
Send the MFA token on requests that require MFA, such as authorizing a wallet action.
Authentication
Every server-side MFA request needs three credentials:- Your app ID and app secret, as Basic auth. See REST API setup.
- The
privy-app-idheader. - The user’s access token or custom auth JWT, in the
privy-user-tokenheader.
401.
SMS
With SMS MFA, Privy texts a 6-digit code to the user’s phone number. Each code works once.Users with a phone number login account cannot enroll in SMS MFA. A phone number can secure login
or MFA, but not both.
Enrollment
To enroll a user in SMS MFA, callinit with the user’s phone number. Privy sends an enrollment code to that number. Call verify with the code the user received to complete MFA enrollment.
init requires a valid MFA token. See adding or replacing a method.
Verification
To verify a user’s SMS MFA credential, callinit to send a code to the user’s enrolled phone number. Call verify with the code the user received to complete MFA verification.
TOTP
With TOTP MFA, the user reads a 6-digit code from an authenticator app, like Google Authenticator or Authy. Each code works once.Enrollment
To enroll a user in TOTP MFA, callinit to create a secret. It returns the secret and an otpauth:// URI:
verify with a code from the user’s authenticator app to complete MFA enrollment.
init requires a valid MFA token. See adding or replacing a method.
Verification
To verify a user’s TOTP MFA credential, callverify with a code from the user’s authenticator app. TOTP has no init call, since the authenticator app generates codes.
Passkeys
With passkey MFA, the user verifies with a passkey in their browser. Your app’s server gets WebAuthn options from Privy and passes them to the browser. The browser runs the WebAuthn ceremony and returns a credential, which your app’s server sends to Privy. Bothinit calls take a relying_party: the origin where the user’s browser runs the ceremony. If your app has allowed domains, the origin must be one of them.
Privy uses snake_case keys in
options and credential, such as pub_key_cred_params and
raw_id. Browser WebAuthn libraries, like @simplewebauthn/browser, use camelCase. Convert the
keys in both directions. Note that client_data_json maps to clientDataJSON.Enrollment
To enroll a user in passkey MFA, callinit to get WebAuthn registration options. In the browser, pass the options to navigator.credentials.create() or startRegistration() from @simplewebauthn/browser. Call verify with the resulting credential to complete MFA enrollment.
init requires a valid MFA token. See adding or replacing a method.
Verification
To verify a user’s passkey MFA credential, callinit to get WebAuthn authentication options. In the browser, pass the options to navigator.credentials.get() or startAuthentication() from @simplewebauthn/browser. Call verify with the resulting credential to complete MFA verification.
MFA token
Everyverify call returns the same response:
string
The MFA token, a JWT proving the user completed MFA.
number
Unix timestamp in seconds when the MFA token expires. The app’s MFA verification
duration sets the lifetime.
object
The current user object, including
mfa_methods.mfa.enabled webhook.
Authorizing a wallet action
Your app’s server authorizes wallet actions on the user’s wallets with a user key. When the user has MFA enrolled, Privy requires an MFA token to issue that key. With a server SDK, pass the MFA token with the user’s JWT in the authorization context. The SDK requests the user key and signs the wallet action. With the REST API, send the MFA token in theprivy-mfa-token header when requesting the user key.
Adding or replacing a method
When the user already has MFA enrolled, enrollmentinit requires an MFA token issued in the last 30 seconds. To add or replace a method, complete MFA verification first. Start MFA enrollment right away with the new token.
A new SMS enrollment replaces the phone number. A new TOTP enrollment replaces the secret, so codes from the old authenticator app stop working. A new passkey enrollment adds a passkey.
Errors
Server SDKs raise these as errors with the same status codes.
For request and response schemas, see the MFA API reference.

