Skip to main content
Methods on the email flow of a createAuthClient client. sendOtp emails the user a one-time code; verifyOtp exchanges it for a Dynamic user JWT.

sendOtp

Function Signature

auth.email.sendOtp(email: string): Promise<{ verificationUUID: string }>

Parameters

  • email (string) - The user’s email address. Dynamic sends the one-time code to it.

Returns

  • verificationUUID (string) - Identifies this verification attempt. Pass it to verifyOtp together with the code.

verifyOtp

Function Signature

auth.email.verifyOtp(params: {
  verificationUUID: string;
  code: string;
  sessionPublicKey?: string;
}): Promise<AuthResult>

Parameters

  • verificationUUID (string) - The value returned by sendOtp.
  • code (string) - The one-time code the user received by email. Collect it through your own channel; never log or persist it.
  • sessionPublicKey (string, optional) - Compressed P-256 public key hex from generateSessionKeyPair. Binds the session key into the minted JWT — required if you will use a session signer with authenticateJwt for backUpToDynamic flows.

Returns

  • Promise<AuthResult> - { jwt, expiresAt, userId }. Pass jwt to authenticateJwt; never log it.

Example

import { createAuthClient, generateSessionKeyPair } from '@dynamic-labs-wallet/node';

const auth = createAuthClient({ environmentId: 'your-environment-id' });
const { publicKeyHex, privateKeyJwk } = await generateSessionKeyPair();

const { verificationUUID } = await auth.email.sendOtp('user@example.com');

// The user receives the code by email; collect it through your own channel.
const { jwt, expiresAt } = await auth.email.verifyOtp({
  verificationUUID,
  code: otpCodeFromUser,
  sessionPublicKey: publicKeyHex,
});

Error Handling

try {
  const result = await auth.email.verifyOtp({ verificationUUID, code, sessionPublicKey });
} catch (error) {
  // - Wrong or expired code (401): "email OTP sign-in failed: the code or
  //   signature is invalid or expired"
  // - MFA-required account: "account requires MFA, which the headless auth
  //   client does not support"
  // - Cookie-auth environment: sign-in returned no JWT in the response body
  console.error('Sign-in failed:', error);
}
sendOtp and verifyOtp are rate limited per IP address (429 when exceeded) — see Rate Limit Policies.
Last modified on July 9, 2026