Skip to main content
Some API changes introduce breaking behavior. To prevent your integration from breaking unexpectedly, you control when to adopt new API behavior by setting a minimum API version in the dashboard. Go to Dashboard > Developers > API & SDK Keys to view and set your minimum API version. New environments default to the latest version. Existing environments remain on their current version until you opt in.

2026_04_01

Setting 2026_04_01 as your minimum version enables two security features:

Step-up authentication

Step-up authentication requires users to re-verify their identity before performing sensitive actions. Credential linking/unlinking and wallet export always require step-up verification. Wallet sign is optional and configurable.

Device registration

Device registration protects accounts from takeover by verifying users when they sign in from an unrecognized device. They receive an email verification link before being granted access. New users are registered automatically during signup with no extra friction.

Migrating from action-based MFA to step-up authentication

If you previously used action-based MFA to protect sensitive wallet operations, step-up authentication replaces and extends that functionality. The core concept is the same — require users to re-verify before sensitive actions — but step-up auth adds scoped elevated access tokens, re-authentication methods for non-MFA users, and automatic token handling by the SDK.

What changed

Action-based MFA (before)Step-up authentication (after)
HookuseMfa / useAuthenticatePasskeyMFAuseStepUpAuthentication
Token typeUnscoped MFA token (createMfaToken)Scoped elevated access token (requestedScopes)
Token handlingSDK-managed MFA tokenSDK-managed elevated access token (scoped JWT)
Who can verifyOnly users with MFA methods (TOTP/Passkey)All users — MFA methods, email OTP, SMS OTP, wallet signature, or social OAuth
ScopeNone — token accepted for any actionBound to specific scopes (wallet:export, wallet:sign, credential:link, credential:unlink)
ExpirationSingle-use, no time limitTime-limited (5 min single-use, 10 min multi-use)

Dashboard changes

No dashboard changes are required for the migration itself. Your existing action-based MFA event configuration (Waas Export, Waas Refresh, WaaS Sign, WaaS Reshare) carries over. The key dashboard action is accepting the minimum API version at Dashboard > Developers > API & SDK Keys. Once set to 2026_04_01, the backend enforces step-up authentication on all sensitive operations. Make sure your code is updated before accepting the minimum version.

Code migration: before and after

Using Dynamic’s built-in UI

BeforeusePromptMfaAuth with createMfaToken:
import { usePromptMfaAuth, useIsMfaRequiredForAction } from "@dynamic-labs/sdk-react-core";
import { MFAAction } from '@dynamic-labs/sdk-api-core';

const isMfaRequiredForAction = useIsMfaRequiredForAction();
const promptMfaAuth = usePromptMfaAuth();

const isMfaRequired = await isMfaRequiredForAction({
  mfaAction: MFAAction.WalletWaasExport,
});

if (isMfaRequired) {
  await promptMfaAuth({ createMfaToken: true });
}

await primaryWallet.exportWaasPrivateKey();
AfteruseStepUpAuthentication with requestedScopes:
import { useStepUpAuthentication } from '@dynamic-labs/sdk-react-core';
import { TokenScope } from '@dynamic-labs/sdk-api-core';

const { isStepUpRequired, promptStepUpAuth } = useStepUpAuthentication();

if (await isStepUpRequired({ scope: TokenScope.Walletexport })) {
  await promptStepUpAuth({
    requestedScopes: [TokenScope.Walletexport],
  });
}

// Token is stored — SDK attaches it automatically
await primaryWallet.exportWaasPrivateKey();

Headless TOTP

BeforeuseMfa with authenticateDevice and createMfaToken:
import { useMfa, useIsMfaRequiredForAction } from "@dynamic-labs/sdk-react-core";
import { MFAAction } from '@dynamic-labs/sdk-api-core';

const { authenticateDevice } = useMfa();
const isMfaRequiredForAction = useIsMfaRequiredForAction();

const requires = await isMfaRequiredForAction({
  mfaAction: MFAAction.WalletWaasExport,
});

if (requires) {
  await authenticateDevice({
    code: totpCode,
    createMfaToken: { singleUse: true },
  });
}
AfteruseStepUpAuthentication with verifyTotpMfa:
import { useStepUpAuthentication } from '@dynamic-labs/sdk-react-core';
import { TokenScope } from '@dynamic-labs/sdk-api-core';

const { isStepUpRequired, verifyTotpMfa } = useStepUpAuthentication();

if (await isStepUpRequired({ scope: TokenScope.Walletexport })) {
  await verifyTotpMfa({
    code: totpCode,
    requestedScopes: [TokenScope.Walletexport],
  });
}

Headless Passkey

BeforeuseAuthenticatePasskeyMFA with createMfaToken:
import {
  useAuthenticatePasskeyMFA,
  useGetPasskeys,
  useIsMfaRequiredForAction,
  useRegisterPasskey,
} from "@dynamic-labs/sdk-react-core";
import { MFAAction } from '@dynamic-labs/sdk-api-core';

const authenticatePasskeyMFA = useAuthenticatePasskeyMFA();
const getPasskeys = useGetPasskeys();
const registerPasskey = useRegisterPasskey();
const isMfaRequiredForAction = useIsMfaRequiredForAction();

const requires = await isMfaRequiredForAction({
  mfaAction: MFAAction.WalletWaasExport,
});

if (requires) {
  const passkeys = await getPasskeys();
  if (passkeys.length === 0) {
    await registerPasskey();
  }

  await authenticatePasskeyMFA({
    createMfaToken: { singleUse: false },
  });
}
AfteruseStepUpAuthentication with verifyPasskeyMfa:
import { useStepUpAuthentication } from '@dynamic-labs/sdk-react-core';
import { TokenScope } from '@dynamic-labs/sdk-api-core';

const { isStepUpRequired, verifyPasskeyMfa } = useStepUpAuthentication();

if (await isStepUpRequired({ scope: TokenScope.Walletexport })) {
  await verifyPasskeyMfa({
    requestedScopes: [TokenScope.Walletexport],
  });
}

Migration checklist

  1. Upgrade to React SDK 4.76.0 or later
  2. Replace useMfa / useAuthenticatePasskeyMFA / usePromptMfaAuth with useStepUpAuthentication
  3. Replace createMfaToken with requestedScopes using the appropriate TokenScope
  4. Replace useIsMfaRequiredForAction with isStepUpRequired
  5. Test the step-up flow end-to-end for each protected action
  6. Accept the minimum API version 2026_04_01 in your dashboard
For the full step-up authentication reference (all verification methods, scopes, token lifecycle), see Step-up authentication.

Action required

You must implement both features in your app before setting the minimum API version. Once enabled, the backend enforces these requirements immediately — users will see errors if your app doesn’t handle them. If you use Dynamic’s built-in widget UI (The Dynamic Widget with the React SDK, for example) you are all set, just upgrade to the latest version. If you have a headless integration, you need to build the verification UI yourself — start with the feature overviews, then check minimum SDK versions and per-SDK guides.

Feature overviews

Minimum SDK versions

These minimum versions include support for step-up authentication and device registration. Implement both flows before raising your minimum API version.
SDKMinimum version
React4.76.0
React Native4.76.0
JavaScript0.24.1
Flutter1.2.10
Kotlin1.0.8
Swift1.0.11

Implementation guides

SDKDevice registrationStep-up
ReactGuideGuide
React NativeGuideGuide
JavaScriptGuideGuide
FlutterOverviewGuide
KotlinOverviewOverview
SwiftOverviewOverview