Web API Reference

Web API Reference

#Overview

The Magic SDK for Javascript is your entry-point to secure, passwordless authentication for your application. This guide will cover some important topics for getting started with Javascript APIs and to make the most of Magic's features.

#Getting Started

The Magic class is the entry-point to the Magic SDK. It must be instantiated with a Magic publishable key.

#Installation

To use Magic in your application, install the magic-sdk dependency.

note

⁠If you're integrating with OAuth, OpenID or WebAuthn, additional dependencies are needed. You'll find the installation instructions in their dedicated sections within this documentation.

NPM
Yarn
01⁠npm install magic-sdk

#Constructor

#Magic()

Configure and construct your Magic SDK instance.

Parameter

Type

Definition

apiKey

String

Your publishable API key retrieved from the Magic Dashboard.

options.locale?

String

Customize the language of Magic's modal, email and confirmation screen. See Localization for more.

options.testMode?

Boolean

Enable testMode to assert the desired behavior through the email address you provide to loginWithMagicLink without having to go through the auth flow.

options.network?

String | Object

(String): A representation of the connected Ethereum network (mainnet or goerli).

⁠(Object): A custom Ethereum Node configuration with the following shape:

rpcUrl (String): A URL pointing to your custom Ethereum Node.⁠⁠

chainId? (Number): Some Node infrastructures require you to pass an explicit chain ID. If you are aware that your Node requires this configuration, pass it here as an integer.

options.endpoint?

String

A URL pointing to the Magic <iframe> application.

options.deferPreload?

Boolean

An optional flag to delay the loading of the Magic Iframe's static assets until an SDK function is explicitly invoked. ⁠⁠⁠Set this to true if latency bottlenecks are a concern.

options.useStorageCache?

Boolean

An optional flag to allow the usage of the local storage as cache. Currently it is only used for faster calls to isLoggedIn. When set to true, the magic.user.onUserLoggedOut event listener needs to be used.

#Initialization

Javascript
01import { Magic } from 'magic-sdk';
02
03let magic;
04
05// Construct with an API key:
06magic = new Magic('PUBLISHABLE_API_KEY');
07
08// Construct with an API key and locale:
09magic = new Magic('PUBLISHABLE_API_KEY', { locale: 'es' });
10
11// Construct with an API key and testMode enabled:
12magic = new Magic('PUBLISHABLE_API_KEY', { testMode: true });
13
14// Construct with an API key and defer the loading of the Magic Iframe's assets
15magic = new Magic('PUBLISHABLE_API_KEY', { deferPreload: true });
16
17// Construct with an API key plus options:
18magic = new Magic('PUBLISHABLE_API_KEY', { network: 'goerli', endpoint: '...' });
19
20// Construct with API key and custom node options:
21const customNodeOptions = {
22  rpcUrl: 'https://polygon-rpc.com', // your ethereum, polygon, or optimism mainnet/testnet rpc URL
23  chainId: 137 // corresponding chainId for your rpc url
24}
25
26magic = new Magic('PUBLISHABLE_API_KEY', { 
27  network: customNodeOptions, // connected to Polygon Mainnet!
28});

#Global Methods

Global methods and properties are accessible on the Magic SDK instance itself.

#preload

Starts downloading the static assets required to render the Magic iframe context.

note

As of magic-sdk version 21.0.0, the SDK constructor will preload the iframe's static assets by default, unless the deferPreload flag is passed into the constructor options. See Release Notes

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY', { deferPreload: true });
04
05// ...
06
07magic.preload;

#Arguments

  • None

#Returns

  • Promise<void>: A Promise that resolves to indicate the <iframe> is ready for requests

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05magic.preload().then(() => console.log('Magic <iframe> loaded.'));

#Auth Module

The Auth Module and it's members are accessible on the Magic SDK instance by the auth property.

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05magic.auth;
06magic.auth.loginWithMagicLink;
07magic.auth.loginWithEmailOTP;
08magic.auth.loginWithSMS;
09magic.auth.loginWithCredential;
10⁠magic.auth.updateEmailWithUI;

#loginWithMagicLink

Authenticate a user passwordlessly using a "magic link" sent to the specified user's email address.

note

Only available with Dedicated Wallet.

#Arguments

  • email (String): The user email to log in with
  • redirectURI (String): You can provide a redirect URI that Magic will point to after the user clicks their email link. Don't forget to call loginWithCredential at the specified redirect location! ⁠ ⁠Note: If you are securing a resource server and have your own signup flow after this call resolves, be mindful of where you're calling signup in your implementation to avoid potential concurrency issues!
  • showUI? (Boolean): If true, show an out-of-the-box UI to accept the OTP from user

#Returns

  • PromiEvent<string | null>: The promise resolves upon authentication request success and rejects with a specific error code if the request fails. The resolved value is a Decentralized ID token with a default 15-minute lifespan.

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05// log in a user by their email
06try {
07  await magic.auth.loginWithMagicLink({ email: '[email protected]' });
08} catch {
09  // Handle errors if required!
10}
11
12// log in a user by their email, without showing an out-of-the box UI.
13try {
14  await magic.auth.loginWithMagicLink({ email: '[email protected]', showUI: false });
15} catch {
16  // Handle errors if required!
17}

#Error Handling

Relevant Error Codes

To achieve a fully white-labeled experience, you will need to implement some custom error handling according to your UI needs. Here's a short example to illustrate how errors can be caught and identified by their code:

Javascript
01import { Magic, RPCError, RPCErrorCode } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05try {
06  await magic.auth.loginWithMagicLink({ email: '[email protected]', showUI: false });
07} catch (err) {
08  if (err instanceof RPCError) {
09    switch (err.code) {
10      case RPCErrorCode.MagicLinkFailedVerification:
11      case RPCErrorCode.MagicLinkExpired:
12      case RPCErrorCode.MagicLinkRateLimited:
13      case RPCErrorCode.UserAlreadyLoggedIn:
14        // Handle errors accordingly :)
15        break;
16    }
17  }
18}

#Events

Event NameDefinition
email-not-deliverableDispatched if the magic link email is unable to be delivered.
email-sentDispatched when the magic link email has been successfully sent from the Magic Link server.
retryDispatched when the user restarts the flow. This can only happen if showUI: true.

#loginWithEmailOTP

Authenticate a user passwordlessly using an email one-time code sent to the specified user's email address.

note

Only available with Dedicated Wallet.

#Arguments

  • email (String): The user email to log in with
  • showUI? (Boolean): If true, show an out-of-the-box UI to accept the OTP from user
  • deviceCheckUI? (Boolean): The default value is true. It shows Magic branded UI securing sign-ins from new devices. If set to false, the UI will remain hidden. However, this the false value only takes effect when you have also set the showUI: false. ⁠Available since [email protected].

#Returns

  • PromiEvent<string | null>: The promise resolves upon authentication request success and rejects with a specific error code if the request fails. The resolved value is a Decentralized ID token with a default 15-minute lifespan.

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05// log in a user by their email
06try {
07  await magic.auth.loginWithEmailOTP({ email: '[email protected]' });
08} catch {
09  // Handle errors if required!
10}
11
12// log in a user by their email, without showing an out-of-the box UI.
13try {
14  await magic.auth.loginWithEmailOTP({ email: '[email protected]', showUI: false });
15} catch {
16  // Handle errors if required!
17}

#Event Handling

Relevant Events

A white-label OTP login flow is available when passing showUI: false to this login method. Here's a short example to illustrate listening for and emitting events during the login flow:

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05try {
06  // Initiate login flow
07  const handle = magic.auth.loginWithEmailOTP({ email: "[email protected]", showUI: false, deviceCheckUI: false });
08
09  handle
10  .on('email-otp-sent', () => {
11    // The email has been sent to the user
12
13    // Prompt the user for the OTP
14    const otp = window.prompt('Enter Email OTP');
15
16    // Send the OTP for verification
17    handle.emit('verify-email-otp', otp);
18  })
19  .on('invalid-email-otp', () => {
20    // User entered invalid OTP
21
22    /* 
23      Have the user retry entering the OTP.
24      Then emit the "verify-email-otp" event with the OTP.
25    */
26
27    /*
28      You may limit the amount of retries and
29      emit a "cancel" event to cancel the login request.
30    */
31
32    // cancel login request
33    handle.emit('cancel');
34  })
35  .on('done', (result) => {
36    // is called when the Promise resolves
37
38    // convey login success to user
39    alert('Login complete!');
40		
41    // DID Token returned in result
42    const didToken = result;
43  })
44  .on('error', (reason) => {
45    // is called if the Promise rejects
46    console.error(reason);
47  })
48  .on('settled', () => {
49    // is called when the Promise either resolves or rejects
50  }) 
51
52  /**
53   * Device Verification Events
54   */
55  .on('device-needs-approval', () => {
56    // is called when device is not recognized and requires approval
57  })
58  .on('device-verification-email-sent', () => {
59    // is called when the device verification email is sent 
60  })
61  .on('device-approved', () => {
62    // is called when the device has been approved
63  })
64  .on('device-verification-link-expired', () => {
65    // is called when the device verification link is expired
66    // Retry device verification
67    handle.emit('device-retry');
68  });
69
70  /*
71     In typescript, you may use DeviceVerificationEventOnReceived types for strong typing
72  */ 
73  /* 
74     You may use 'cancel' from white-label otp event 
75     to terminate the unresolved request
76  */
77} catch (err) {
78  // handle errors
79}

#Events

Email OTP

Event NameDefinition
email-otp-sentDispatched when the OTP email has been successfully sent from the Magic server.
verify-email-otpEmit along with the OTP to verify the code from user.
invalid-email-otpDispatched when the OTP sent fails verification.

cancel

Emit to cancel the login request.

Device Verification

Event NameDefinition
device-needs-approvalDispatched when the device is unrecognized and requires user approval
device-verification-email-sentDispatched when the device verification email is sent
device-approvedDispatched when the user has approved the unrecongized device

device-verification-link-expired

Dispatched when the email verification email has expired

device-retry

Emit to restart the device registration flow

#Error Handling

To achieve a fully white-labeled experience, you will need to implement some custom error handling according to your UI needs. Here's a short example to illustrate how errors can be caught and identified by their code:

Javascript
01import { Magic, RPCError, RPCErrorCode } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05try {
06  await magic.auth.loginWithEmailOTP({ email: '[email protected]' });
07} catch (err) {
08  if (err instanceof RPCError) {
09    switch (err.code) {
10      case RPCErrorCode.MagicLinkExpired
11      case RPCErrorCode.UserAlreadyLoggedIn:
12        // Handle errors accordingly :)
13        break;
14    }
15  }
16}

#loginWithSMS

Authenticate a user passwordlessly using a one-time code sent to the specified phone number.

List of Currently Blocked Country Codes

note

Only available with Dedicated Wallet.

#Arguments

  • phoneNumber (String): E.164 formatted phone number

#Returns

  • PromiEvent<string | null>: The promise resolves upon authentication request success and rejects with a specific error code if the request fails. The resolved value is a Decentralized ID token with a default 15-minute lifespan.

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05// log in a user by their phone number
06try {
07  await magic.auth.loginWithSMS({ '+14151231234' });
08} catch {
09  // Handle errors if required!
10}

#Error Handling

Relevant Error Codes

To achieve a fully white-labeled experience, you will need to implement some custom error handling according to your UI needs. Here's a short example to illustrate how errors can be caught and identified by their code:

Javascript
01import { Magic, RPCError, RPCErrorCode } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05try {
06  await magic.auth.loginWithSMS({ phoneNumber: "+14151231234" });
07} catch (err) {
08  if (err instanceof RPCError) {
09    switch (err.code) {
10      case RPCErrorCode.AccessDeniedToUser:
11      case RPCErrorCode.MagicLinkRateLimited:
12      case RPCErrorCode.UserAlreadyLoggedIn:
13        // Handle errors accordingly :)
14        break;
15    }
16  }
17}

#loginWithCredential

Authenticate a user via a "Magic Credential," a special, one-time-use DID Token created by the user to hydrate their authentication between page reloads. For example: when executing the loginWithMagicLink flow with a redirectURI specified, you can invoke this method to complete the authentication "callback," similar in principal to OAuth 2.0 flows.

If given no arguments, this method will parse the credential token automatically from window.location.search.

note

Only available with Dedicated Wallet.

#Arguments

  • credentialOrQueryString (String): A credential token or a valid query string (prefixed with ? or #). By default, this method will look for the a credential token on the magic_credential key of window.location.search.

#Returns

  • PromiEvent<string | null>: The promise resolves upon authentication request success and rejects with a specific error code if the request fails. The resolved value is a Decentralized ID token with a default 15-minute lifespan.

#Example

From your login page:

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05try {
06  await magic.auth.loginWithMagicLink({
07    email: '[email protected]',
08    redirectURI: 'https://yourdomain.com/your/magic/link/callback',
09  });
10
11  // When the user clicks their magic link, they will be logged-in here
12  // and in the "callback" context.
13} catch {
14  // Handle errors if required!
15}

From your authentication callback page:

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05try {
06  await magic.auth.loginWithCredential();
07} catch {
08  // Handle errors if required!
09}
10
11// You can also provide the credential yourself
12try {
13  await magic.auth.loginWithCredential('iamacredentialtoken');
14} catch {
15  // Handle errors if required!
16}
17
18// You can also provide the credential as a query string
19try {
20  await magic.auth.loginWithCredential(window.location.search);
21} catch {
22  // Handle errors if required!
23}

#updateEmailWithUI

Initiates the update email flow that allows a user to change their email address.

note

Only available with Dedicated Wallet.

#Arguments

  • email (String): The new email to update to

  • showUI? (Boolean): If true, shows an out-of-the-box pending UI which includes instructions on which step of the confirmation process the user is on. Dismisses automatically when the process is complete.

#Returns

  • PromiEvent<boolean>: The promise resolves with a true boolean value if update email is successful and rejects with a specific error code if the request fails

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('API_KEY');
04
05// Initiates the flow to update a user's current email to a new one.
06try {
07  ...
08  /* Assuming user is logged in */
09  await magic.auth.updateEmailWithUI({ email: '[email protected]' });
10} catch {
11  // Handle errors if required!
12}
13
14/**
15 * Initiates the flow to update a user's current email to a new one,
16 * without showing an out-of-the box UI.
17 */
18try {
19  /* Assuming user is logged in */
20  await magic.auth.updateEmailWithUI({ email: '[email protected]', showUI: false });
21} catch {
22  // Handle errors if required!
23}

#Event Handling

A white-label update email flow is available when passing showUI: false to this method. The white-label flow is only supported in Magic SDK v22.0.0 and above. Here's a short example to illustrate listening for and emitting events during the flow:

Javascript
01import { 
02  Magic, 
03  RecencyCheckEventOnReceived,
04  RecencyCheckEventEmit,
05  UpdateEmailEventOnReceived,
06  UpdateEmailEventEmit,
07} from 'magic-sdk';
08
09const magic = new Magic('API_KEY');
10
11try {
12  /* Initiates update email flow to update a user's current email to a new one */
13  const handle = await magic.auth.updateEmailWithUI({ 
14⁠    email: '[email protected]',
15    showUI: false,
16  });
17
18  /*
19    Recency Check Events & Emit
20  */
21
22  let recencyCheckRetries = 5;
23
24  handle
25  .on(RecencyCheckEventOnReceived.EmailSent, () => {
26// Email OTP has been sent to the user's primary email
27
28    // Prompt the user for the OTP
29    const otp = window.prompt('Primary Email OTP');
30
31    // Send the OTP for verification
32    handle.emit(RecencyCheckEventEmit.VerifyEmailOtp, otp);
33  })
34  .on(RecencyCheckEventOnReceived.PrimaryAuthFactorVerified, () => {
35    window.alert('Primary Factor has been verified');
36  })
37  .on(RecencyCheckEventOnReceived.EmailNotDeliverable, () => {
38    // Email OTP was undeliverable to user's primary email
39
40    // Cancel update email request
41    handle.emit(RecencyCheckEventEmit.Cancel);
42    window.alert('Email Not Deliverable');
43  })
44  .on(RecencyCheckEventOnReceived.InvalidEmailOtp, () => {
45    // User entered invalid OTP; you may limit retries and cancel the request
46
47    if (!recencyCheckRetries) {
48      // Cancel update email request
49      alert('Too many attempts');
50      handle.emit(RecencyCheckEventEmit.Cancel);
51    } else {
52      const otp = window.prompt(
53        `Invalid code, Please enter OTP again. Retries left: ${recencyCheckRetries}`,
54      );
55      recencyCheckRetries--;
56
57      // Send the OTP for verification
58      handle.emit(RecencyCheckEventEmit.VerifyEmailOtp, otp);
59    }
60  });
61
62  /*
63    Update Email Events & Emit
64  */
65
66  let updateEmailRetries = 5;
67
68  handle
69  .on(UpdateEmailEventOnReceived.EmailSent, () => {
70// Email OTP has been sent to the user's secondary email
71
72    // Prompt the user for the OTP
73    const otp = window.prompt('Enter new Email OTP');
74
75    // Send the OTP for verification
76    handle.emit(UpdateEmailEventEmit.VerifyEmailOtp, otp);
77  })
78  .on(UpdateEmailEventOnReceived.InvalidEmail, () => {
79    // Email OTP was undeliverable to user's secondary email
80
81    const newEmail = window.prompt('Invalid Email, Enter a new Email');
82    
83    // Try same or new email address
84    handle.emit(
85      UpdateEmailEventEmit.RetryWithNewEmail,
86      newEmail || email,
87    );
88  })
89  .on(UpdateEmailEventOnReceived.EmailAlreadyExists, () => {
90    // Account already exists for new email address
91
92    const newEmail = window.prompt('Email address already in use, Enter a different Email');
93    
94    // Try same or new email address
95    handle.emit(
96      UpdateEmailEventEmit.RetryWithNewEmail,
97      newEmail || email,
98    );
99  })
100  .on(UpdateEmailEventOnReceived.InvalidEmailOtp, () => {
101    // User entered invalid OTP; you may limit retries and cancel the request
102
103    if (!updateEmailRetries) {
104      // Cancel update email request
105      alert('Too many attempts');
106      handle.emit(UpdateEmailEventEmit.Cancel);
107    } else {
108      const otp = window.prompt(
109        `Invalid code, Please enter OTP again. Retries left: ${updateEmailRetries}`,
110      );
111      updateEmailRetries--;
112
113      // Send the OTP for verification
114      handle.emit(UpdateEmailEventEmit.VerifyEmailOtp, otp);
115    }
116  })
117
118  handle
119  .on('error', () => {
120    // is called if the Promise rejects
121
122    alert('Error occurred');
123  });
124
125  const res = await handle;
126  console.log(res);
127  alert('Email Updated');
128} catch {
129  // Handle errors if required!
130}

#Error Handling

Relevant Error Codes

To achieve a fully white-labeled experience, you will need to implement some custom error handling according to your UI needs. Here's a short example to illustrate how errors can be caught and identified by their code:

Javascript
01import { Magic, RPCError, RPCErrorCode } from 'magic-sdk';
02
03const magic = new Magic('API_KEY');
04
05try {
06  await magic.auth.updateEmailWithUI({ email: '[email protected]', showUI: false });
07} catch (err) {
08  if (err instanceof RPCError) {
09    switch (err.code) {
10      case RPCErrorCode.UpdateEmailFailed:
11        // Handle errors accordingly :)
12        break;
13    }
14  }
15}

#Wallet Module

The Wallet Module and it's members are accessible on the Magic SDK instance by the wallet property. ⁠ ⁠Note: The Wallet Module is currently only compatible with Ethereum, Polygon, Flow (no NFTs), and Optimism.

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05magic.wallet;
06magic.wallet.connectWithUI;
07magic.wallet.showUI;
08magic.wallet.showAddress;
09magic.wallet.showBalances;
10magic.wallet.showNFTs;
11magic.wallet.showSendTokensUI;
12magic.wallet.showOnRamp; // enterprise only
13magic.wallet.getProvider;

#connectWithUI

Renders a simple login form UI to collect the user's email address and authenticate them passwordlessly using a one-time passcode (OTP) sent to their email address they input.

#Arguments

  • None

#Returns

  • A promiEvent which returns an String[] when resolved: An array of user accounts that are connected, with the first element being the current public address of the user. You can read more on PromiEvents here.

#Example

Javascript
01import { Magic } from "magic-sdk"
02
03const accounts = await magic.wallet.connectWithUI();
04
05/* Optionally, chain to the id token creation event if needed and configured */
06magic.wallet.connectWithUI().on('id-token-created', (params) => {
07 const { idToken } = params
08 console.log(idToken)
09 // send to your resource server for validation
10 // ...
11});

#Events

Event Name

Definition

id-token-created

Returns an object containing a short lived, time bound ID token that can be used to verify the ownership of a user's wallet address on login.

Read more about this token and how to use it.

#showUI

Displays the fully navigable wallet to the user that adheres to the toggled configurations on your developer dashboard’s Widget UI tab. ⁠ ⁠This is only supported for users who login with email or Google and not third party wallets such as metamask. User must be signed in for this method to return or else it will throw an error.

#Arguments

  • None

#Returns

  • Promise which resolves when the user closes the window

⁠Optionally, add a .on() handler to catch the disconnect event emitted when the user logs out from the wallet widget.

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05await magic.wallet.showUI()

#showAddress

Displays an iframe with the current user’s wallet address in a QR Code.

#Arguments

  • None

#Returns

  • Promise which resolves when the user closes the window

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05await magic.wallet.showAddress()

#showBalances

Displays an iframe that displays the user’s token balances from the currently connected network.

#Arguments

  • None

#Returns

  • Promise which resolves when the user closes the window

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05await magic.wallet.showBalances()

#showNFTs

Displays an iframe that shows the user’s NFTs in both an aggregated and detailed individual view. Supported only on Ethereum and Polygon. Ensure this is enabled in your developer dashboard via the ‘Widget UI’ tab.

#Arguments

  • None

#Returns

  • Promise which resolves when the user closes the window

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05await magic.wallet.showNFTs()

#showSendTokensUI

Displays an iframe with UI to help the user transfer tokens from their account to another address.

#Arguments

  • None

#Returns

  • Promise which resolves when the user closes the window

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05await magic.wallet.showSendTokensUI()

#showOnRamp

Displays an iframe modal with various on ramp providers for the user to purchase crypto from directly to their wallet.

To use the fiat on ramp for Dedicated Wallet apps, you will need to contact us to KYB with the payment provider prior to use. Once approved, ensure this toggle is enabled in your developer dashboard via the ‘Widget UI’ tab.

#Arguments

  • None

#Returns

  • Promise which resolves when the user closes the window

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05await magic.wallet.showOnRamp()

#getProvider

This method is introduced in [email protected] and must be used to get the current provider if third party wallets are enabled. If not using third party wallets, we suggest using magic.rpcProvider.

#Arguments

  • None

#Returns

  • Object: The rpc provider of the wallet a user is currently logged in with (MetaMask, Coinbase Wallet or Magic)

Important: To ensure rpc requests are routed to the correct wallet, developers must re-fetch the provider object using getProvider() and re-initialize the web3.js or ethers.js instance any time a user logs in, logs out, or disconnects their wallet.

#Web3.js/Ethers.js

Web3.js
Ethers.js
01import { Magic } from "magic-sdk"
02import Web3 from 'web3';
03
04const magic = new Magic('PUBLISHABLE_API_KEY', { 
05  network: "goerli",
06});
07
08const provider = await magic.wallet.getProvider();
09
10const web3 = new Web3(provider);
11
12const accounts = await magic.wallet.connectWithUI();
13
14// Listen for events
15web3.currentProvider.on('accountsChanged', handleAccountsChanged);
16web3.currentProvider.on('chainChanged', handleChainChanged);

#User Module

The User Module and it's members are accessible on the Magic SDK instance by the user property.

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05magic.user;
06magic.user.getIdToken;
07magic.user.generateIdToken;
08magic.user.getInfo;
09magic.user.isLoggedIn;
10magic.user.logout;
11magic.user.showSettings;
12magic.user.requestInfoWithUI;

#getIdToken

Generates a Decentralized Id Token which acts as a proof of authentication to resource servers.

note

Only available with Dedicated Wallet.

#Arguments

  • lifespan? (Number): Will set the lifespan of the generated token. Defaults to 900s (15 mins).

#Returns

  • PromiEvent<string>: Base64-encoded string representation of a JSON tuple representing

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05// Assumes a user is already logged in
06try {
07  const idToken = await magic.user.getIdToken();
08} catch {
09  // Handle errors if required!
10}

#generateIdToken

Generates a Decentralized ID token with optional serialized data.

note

Only available with Dedicated Wallet.

#Arguments

  • lifespan? (Number): Will set the lifespan of the generated token. Defaults to 900s (15 mins).
  • attachment? (String): Will set a signature of serialized data in the generated token. Defaults to "none".

#Returns

  • PromiEvent<string>: Base64-encoded string representation of a JSON tuple representing [proof, claim]

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05// Assumes a user is already logged in
06try {
07  const idToken = await magic.user.generateIdToken({ attachment: 'SERVER_SECRET' });
08} catch {
09  // Handle errors if required!
10}

#getInfo

Retrieves information for the authenticated user.

#Arguments

  • None

#Returns

  • PromiEvent<string>:
    • issuer (String): The Decentralized ID of the user. In server-side use-cases, we recommend this value to be used as the user ID in your own tables.
    • email (String): Email address of the authenticated user
    • phoneNumber (String): The phone number of the authenticated user
    • publicAddress (String): The authenticated user's public address (a.k.a.: public key)
    • walletType (String): Information about the wallet the user is currently signed in with ('magic' | 'metamask' | 'coinbase_wallet')
    • isMfaEnabled (Boolean): Whether or not multi-factor authentication is enabled for the user
    • recoveryFactors (Array): Any recovery methods that have been enabled (ex. [{ type: 'phone_number', value: '+99999999' }])
note

When calling this method while connected with a 3rd party wallet (MetaMask, Coinbase Wallet), only the walletType will be returned.

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05// Assumes a user is already logged in
06try {
07  const userInfo = await magic.user.getInfo();
08} catch {
09  // Handle errors if required!
10}

#isLoggedIn

Checks if a user is currently logged in to the Magic SDK.

#Arguments

  • None

#Returns

  • PromiEvent<boolean>

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05try {
06  const isLoggedIn = await magic.user.isLoggedIn();
07  console.log(isLoggedIn); // => `true` or `false`
08} catch {
09  // Handle errors if required!
10}

#logout

Logs out the currently authenticated Magic user

#Arguments

  • None

#Returns

  • PromiEvent<boolean>

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05try {
06  await m.user.logout();
07  console.log(await magic.user.isLoggedIn()); // => `false`
08} catch {
09  // Handle errors if required!
10}

#showSettings

Displays an iframe with the current user’s settings. Allows for users to update their email address, enable multi-factor authentication, and add a recovery factor.

note

Only available with Dedicated Wallet. Access to MFA and account recovery require paid add-ons.

#Arguments

  • page? (String): Optional argument to deeplink to a specific page ('mfa' | 'update-email' | 'recovery')

#Returns

  • Promise which resolves when the user closes the window

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05try {
06  await magic.user.showSettings();
07} catch {
08  // Handle errors if required!
09}
10
11// Deeplink to MFA view
12try {
13  await magic.user.showSettings({ page: 'mfa' });
14} catch {
15  // Handle errors if required!
16}

#requestInfoWithUI

restricted availability

Universal wallets will soon be merged with Dedicated Wallets into a single product line. Universal apps created before February 7, 2024 will work as expected with no change. See our blog post to learn more.

Displays the wallet widget within an iframe that prompts the user to consent to sharing information with the requesting dApp with OpenID profile scopes. Currently, the only profile scope that can be requested is a verified email. Collecting a verified email address from third-party wallet users (MetaMask, Coinbase Wallet, etc.) is a premium feature but included in the free trial period (see pricing). User must be signed in for this method to return or else it will throw an error.

note

Only available with Universal Wallet.

#Arguments

  • scope? (Object): The object containing requested OpenID profile scopes
    • email?: String : If the user should be prompted to provide them email as a required or optional field

#Returns

  • A promise which returns an Object: Contains result of the requested scopes.
    • email?: String: The email of the user if they consented to providing it in the UI

#Example

Javascript
01import { Magic } from "magic-sdk"
02
03// after user has already logged in
04const userInfo = await magic.user.requestInfoWithUI({ scope: { email: "required" }})
05console.log(userInfo.email); // the user's email if they consented.

#onUserLoggedOut

When the useStorageCache is enabled, there might be situations where the isLoggedIn function returns true despite the user being logged out. In such instances, an event will be emitted after a few milliseconds, providing an opportunity to manage the user's logged-out state, such as when a session expires.

note

Only necessary with when the useStorageCache option is set to true.

#Arguments

  • callback ((isLoggedOut: boolean) => void): The callback function when the event is emitted

#Returns

  • A function that can be called to unsubscribe from the event

#Example

Javascript
01import { Magic } from "magic-sdk"
02
03// Create Magic instance with useStorageCache set to true
04const magic = new Magic('PUBLISHABLE_API_KEY', {
05  useStorageCache: true
06});
07
08magic.user.onUserLoggedOut((isLoggedOut: boolean) => {
09  // Do something when user is logged out
10  navigation.navigate('LoginScreen')
11})

#OAuth Module

The OAuth Module and it's members are accessible on the Magic SDK instance by the oauth property.

To use the OAuth Module in your application, install @magic-ext/oauth along with magic-sdk.

Javascript
01import { Magic } from 'magic-sdk';
02import { OAuthExtension } from '@magic-ext/oauth';
03
04const magic = new Magic('PUBLISHABLE_API_KEY', {
05  extensions: [new OAuthExtension()],
06});
07
08magic.oauth;
09magic.oauth.loginWithRedirect;
10magic.oauth.getRedirectResult;

#loginWithRedirect

Starts the OAuth 2.0 login flow.

note

Only available with Dedicated Wallet.

#Arguments

  • provider (String): The OAuth provider being used for login
  • redirectURI (String): A URL a user is sent to after they successfully log in
  • scope? (Array): Defines the specific permissions an application requests from a user

#Returns

  • None

#Valid Providers

NameArgumentExample

Google

'google'

Google demo

Facebook

'facebook'

Facebook demo

Twitter

'twitter'

Twitter Demo

Apple

'apple'

Apple demo

Discord

'discord'

Discord demo

GitHub

'github'

GitHub demo

LinkedIn

'linkedin'

LinkedIn demo

Bitbucket

'bitbucket'

Bitbucket demo

GitLab

'gitlab'

GitLab demo

Twitch

'twitch'

Twitch demo

Microsoft

'microsoft'

Microsoft demo

#Example

Javascript
01import { Magic } from 'magic-sdk';
02import { OAuthExtension } from '@magic-ext/oauth';
03
04const magic = new Magic('PUBLISHABLE_API_KEY', {
05  extensions: [new OAuthExtension()],
06});
07
08await magic.oauth.loginWithRedirect({
09  provider: '...' /* 'google', 'facebook', 'apple', etc. */,
10  redirectURI: 'https://your-app.com/your/oauth/callback',
11  scope: ['user:email'] /* optional */,
12});

#getRedirectResult

Returns the final OAuth 2.0 result.

note

Only available with Dedicated Wallet.

#Arguments

  • None

#Returns

  • PromiEvent<object>:
    • magic (Object): Information about the authenticated Magic user. Comprised of idToken and userMetadata.
    • oauth (Object): Information about the authenticated OAuth user. Comprised of accessToken, provider, scope, userHandle, and userInfo.

#Example

Javascript
01import { Magic } from 'magic-sdk';
02import { OAuthExtension } from '@magic-ext/oauth';
03
04const magic = new Magic('PUBLISHABLE_API_KEY', {
05  extensions: [new OAuthExtension()],
06});
07
08const result = await magic.oauth.getRedirectResult();
09
10// Result has the following interface
11interface OAuthRedirectResult {
12  magic: {
13    idToken: string;
14    userMetadata: MagicUserMetadata;
15  },
16  oauth: {
17    provider: string;
18    scope: string[];
19    accessToken: string;
20    userHandle: string;
21    userInfo: ...;
22  }
23};

#NFT Module

The NFT Module and it's members are accessible on the Magic SDK instance by the nft property.

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05magic.nft;
06⁠magic.nft.checkout;
07magic.nft.purchase;
08magic.nft.transfer;

#checkout

Initiates an NFT Checkout using PayPal, allowing users to use Fiat currency to purchase NFTs.

#Arguments

  • contractId (String): The ID from Magic identifing the Smart Contract. This ID will be sent to you by your Magic Customer Success representative.
  • name (String): The name of the contract or NFT used in the Checkout UI to tell the user what they are purchasing
  • imageUrl (String): A URL for the NFT image that will be shown to the user in the UI. For NFTs revealed after purchase, you may use any placeholder image.
  • tokenId (String): The ID of the token to transfer. For ERC721 contracts, use tokenId = "0".
  • quantity? (Number): Number of tokens the user will purchase. If not provided, quantity will be 1.
  • walletAddress? (String): The on-chain address of the user's wallet, where the NFT will be delivered after purchase and minting. If not provided, the user's Magic Wallet address will be used.

#Returns

  • PromiEvent<boolean>: The promise resolves with a true boolean value if the purchase is successful and rejects with a specific error code if the request fails

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05// Initiates the flow to purchase an NFT.
06try {
07  ...
08  /* Assuming user is logged in */
09  await magic.nft.checkout({
10    contractId: "abcd-efgh-1111-2222",
11    name: "My NFT Drop",
12    imageUrl: "https://nft-cdn.alchemy.com/matic-mumbai/1234",
13    quantity: 1,
14    tokenId: "0",
15    walletAddress: "0xabcdefg",
16  });
17} catch {
18  // Handle errors if required!
19}

#purchase

Initiates a purchase of a specified NFT.

#Arguments

  • nft: This contains all of the NFT meta information
    • name (String): NFT name
    • imageUrl (String): NFT image URL
    • blockchainNftId (String): NFT ID
    • contractAddress (String): NFT smart contract address
    • network (String): Network name
    • platform (String): Platform name
    • type (String): Type
  • identityPrefill: This contains all of the user prefill meta information
    • firstName (String): The user's first name
    • lastName (String): The user's last name
    • emailAddress (String): The user's email address
    • dateOfBirth (String): The user's date of birth in YYYY-MM-DD format
    • phone (String): The user's phone number
    • address: This contains all of the user address meta information
      • street1 (String): The user's street address
      • street2 (String): Additional street address information
      • city (String): City of user address
      • regionCode (String): Region code for country subdivisions
      • postalCode (String): Postal code of user's address
      • countryCode (String): Country code of user's address

#Returns

  • PromiEvent<boolean>: The promise resolves with a true boolean value if the transfer is successful and rejects with a specific error code if the request fails

#transfer

Initiates a transfer of a specified NFT.

#Arguments

  • contractAddress (String): The on-chain address of the NFT Smart Contract that holds the NFT
  • tokenId (String): The ID of the token to transfer
  • quantity? (Number): Number of tokens to transfer. If not provided, defaults to 1 token and allows use to override in the Transfer UI.
  • recipient? (String): The on-chain address of the wallet or contract you want to send the NFT to. If not provided, user will input in the Transfer UI.

#Returns

  • PromiEvent<boolean>: The promise resolves with a true boolean value if the transfer is successful and rejects with a specific error code if the request fails

#Example

Javascript
01import { Magic } from 'magic-sdk';
02
03const magic = new Magic('PUBLISHABLE_API_KEY');
04
05// Initiates the flow to transfer a user's NFT.
06try {
07  ...
08  /* Assuming user is logged in */
09  await magic.nft.transfer({
10    contractAddress: '0xABCD',
11    tokenId: 1,
12  });
13} catch {
14  // Handle errors if required!
15}

#OpenID Module

note

This module requires an enterprise agreement. For more details click here.

The OpenID Module and it's members are accessible on the Magic SDK instance by the openid property.

To use the OpenID Module in your application, install @magic-ext/oidc along with magic-sdk.

Javascript
01import { Magic } from 'magic-sdk';
02import { OpenIdExtension } from '@magic-ext/oidc';
03
04const magic = new Magic('PUBLISHABLE_API_KEY', {
05  extensions: [new OpenIdExtension()],
06});
07
08magic.openid;
09magic.openid.loginWithOIDC;

#loginWithOIDC

Authenticate users via your preferred OIDC client.

note

Only available with Dedicated Wallet.

#Arguments

  • jwt (String): The OIDC token from your identity provider
  • providerId (String): An alphanumeric ID provided by Magic after successful configuration of your identity provider

#Returns

  • PromiEvent<string | null>: The promise resolves upon authentication request success and rejects with a specific error code if the request fails. The resolved value is a Decentralized ID token with a default 15-minute lifespan.

#Example

Javascript
01import { Magic } from 'magic-sdk';
02import { OpenIdExtension } from '@magic-ext/oidc';
03
04const magic = new Magic('PUBLISHABLE_API_KEY', {
05  extensions: [new OpenIdExtension()],
06});
07
08const DID = await magic.openid.loginWithOIDC({
09  // this oidcToken comes from the identity provider
10  jwt: oidcToken,
11  // this providerId is provided by Magic
12  providerId: myProviderId,
13});

#WebAuthn Module

The WebAuthn Module and it's members are accessible on the Magic SDK instance by the webauthn property.

To use the WebAuthn Module in your application, install @magic-ext/webauthn along with magic-sdk.

Javascript
01import { Magic } from 'magic-sdk';
02import { WebAuthnExtension } from '@magic-ext/webauthn';
03
04const magic = new Magic('PUBLISHABLE_API_KEY', {
05  extensions: [new WebAuthnExtension()],
06});
07
08magic.webauthn;
09magic.webauthn.registerNewUser;
10magic.webauthn.login;
11magic.webauthn.getMetadata;
12magic.webauthn.registerNewDevice;
13magic.webauthn.updateInfo;
14magic.webauthn.unregisterDevice;

#registerNewUser

Registers a new WebAuthn user.

note

Only available with Dedicated Wallet.

#Arguments

  • username (String): The username to register with
  • nickname? (String): The nickname of the WebAuthn device the user wants to set

#Returns

  • PromiEvent<string | null>: The promise resolves upon authentication request success and rejects with a specific error code if the request fails. The resolved value is a Decentralized ID token with a default 15-minute lifespan.

#Example

Javascript
01import { Magic } from 'magic-sdk';
02import { WebAuthnExtension } from '@magic-ext/webauthn';
03
04const magic = new Magic('YOUR API KEY', {
05  extensions: [new WebAuthnExtension()],
06});
07
08// register a user by their username
09try {
10  const token = await magic.webauthn.registerNewUser({ username: 'username' });
11} catch (e) {
12  // Handle errors if required!
13}
14
15// log in a user by their username and set webauthn device nickname.
16try {
17  const token = await magic.webauthn.registerNewUser({ username: 'username', nickname: 'nickname' });
18} catch (e) {
19  // Handle errors if required!
20}

#Error

Javascript
01import { Magic, SDKErrorCode } from 'magic-sdk';
02import { WebAuthnExtension } from '@magic-ext/webauthn';
03
04const magic = new Magic('YOUR API KEY', {
05  extensions: [new WebAuthnExtension()],
06});
07
08try {
09  await magic.webauthn.registerNewUser({ username: 'username' });
10} catch (err) {
11  if (err instanceof SDKErrorCode) {
12    switch (err.code) {
13      case SDKErrorCode.WebAuthnNotSupported:
14      case SDKErrorCode.WebAuthnCreateCredentialError:
15        // Handle errors accordingly :)
16        break;
17    }
18  }
19}

#login

Logs in a registered WebAuthn user.

note

Only available with Dedicated Wallet.

#Arguments

  • username (String): The username to log in with

#Returns

  • PromiEvent<string | null>: The promise resolves upon authentication request success and rejects with a specific error code if the request fails. The resolved value is a Decentralized ID token with a default 15-minute lifespan.

#Example

Javascript
01import { Magic } from 'magic-sdk';
02import { WebAuthnExtension } from '@magic-ext/webauthn';
03
04const magic = new Magic('YOUR API KEY', {
05  extensions: [new WebAuthnExtension()],
06});
07
08// login a user by their username
09try {
10  const token = await magic.webauthn.login({ username: 'username' });
11} catch (e) {
12  // Handle errors if required!
13}

#Error

Javascript
01import { Magic, SDKErrorCode } from 'magic-sdk';
02import { WebAuthnExtension } from '@magic-ext/webauthn';
03
04const magic = new Magic('YOUR API KEY', {
05  extensions: [new WebAuthnExtension()],
06});
07
08try {
09  await magic.webauthn.login({ username: 'username' });
10} catch (err) {
11  if (err instanceof SDKErrorCode) {
12    switch (err.code) {
13      case SDKErrorCode.WebAuthnNotSupported:
14      case SDKErrorCode.WebAuthnCreateCredentialError:
15        // Handle errors accordingly :)
16        break;
17    }
18  }
19}

#getMetadata

Returns information about the currently logged in user.

note

Only available with Dedicated Wallet.

#Arguments

  • None

#Returns

  • PromiEvent<object | null>: an object containing the WebAuthn devices information and username of the authenticated user
    • devicesInfo (Array): List of devices info contains device ID, device nickname, transport, user agent
    • username (String): Username of the authenticated user

#Example

Javascript
01import { Magic, SDKErrorCode } from 'magic-sdk';
02import { WebAuthnExtension } from '@magic-ext/webauthn';
03
04const magic = new Magic('YOUR API KEY', {
05  extensions: [new WebAuthnExtension()],
06});
07
08// Initiates the flow to get webauthn metadata for current account.
09try {
10  const metadata = await magic.webauthn.getMetadata();
11
12  /* webauthn metadata
13       {
14         "devicesInfo": [
15           {
16             "id": "EjI_EFJhB6cdCj6rHPRHUcFCn6NnywALuWjQyPe0_dI=",
17             "nickname": "",
18             "transport": "internal",
19             "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36"
20           }
21         ],
22         "username": "username"
23       }
24    */
25} catch (e) {
26  // Handle errors if required!
27}

#registerNewDevice

Registers a new WebAuthn device.

note

Only available with Dedicated Wallet.

#Arguments

  • nickname (String): The nickname of the WebAuthn device the user wants to set

#Returns

  • PromiEvent<boolean>: The promise resolves with a true boolean value if register webauthn device is successful and rejects with a specific error code if the request fails.

#Example

Javascript
01import { Magic, SDKErrorCode } from 'magic-sdk';
02import { WebAuthnExtension } from '@magic-ext/webauthn';
03
04const magic = new Magic('YOUR API KEY', {
05  extensions: [new WebAuthnExtension()],
06});
07
08// Initiates the flow to a new WebAuthn Device for current account.
09try {
10  await magic.webauthn.registerNewDevice('new device nickname');
11} catch (e) {
12  // Handle errors if required!
13}

#Error

Javascript
01import { Magic, SDKErrorCode } from 'magic-sdk';
02import { WebAuthnExtension } from '@magic-ext/webauthn';
03
04const magic = new Magic('YOUR API KEY', {
05  extensions: [new WebAuthnExtension()],
06});
07
08try {
09  await magic.webauthn.registerNewDevice('new device nickname');
10} catch (err) {
11  if (err instanceof SDKErrorCode) {
12    switch (err.code) {
13      case SDKErrorCode.WebAuthnNotSupported:
14      case SDKErrorCode.WebAuthnCreateCredentialError:
15        // Handle errors accordingly :)
16        break;
17    }
18  }
19}

#updateInfo

Allows a user to update their device nickname.

note

Only available with Dedicated Wallet.

#Arguments

  • nickname (String): The nickname of the WebAuthn device the user wants to set
  • id (String): The WebAuthn ID returned from getMetaData function's devicesInfo field

#Returns

  • PromiEvent<boolean>: The promise resolves with a true boolean value if update webauthn device nickname is successful and rejects with a specific error code if the request fails

#Example

Javascript
01import { Magic, SDKErrorCode } from 'magic-sdk';
02import { WebAuthnExtension } from '@magic-ext/webauthn';
03
04const magic = new Magic('YOUR API KEY', {
05  extensions: [new WebAuthnExtension()],
06});
07
08// Initiates the flow to update WebAuthn Device's nickname.
09try {
10  await magic.webauthn.updateInfo({ id, nickname });
11} catch (e) {
12  // Handle errors if required!
13}

#unregisterDevice

Unregisters a user's device.

note

Only available with Dedicated Wallet.

#Arguments

  • id (String): The WebAuthn ID returned from getMetaData function's devicesInfo field

#Returns

  • PromiEvent<boolean>: The promise resolves with a true boolean value if unregister webauthn device is successful and rejects with a specific error code if the request fails

#Example

Javascript
01import { Magic, SDKErrorCode } from 'magic-sdk';
02import { WebAuthnExtension } from '@magic-ext/webauthn';
03
04const magic = new Magic('YOUR API KEY', {
05  extensions: [new WebAuthnExtension()],
06});
07
08// Initiates the flow to unregister WebAuthn Device.
09try {
10  /* Assuming user is logged in */
11  await magic.webauthn.unregisterDevice(id);
12} catch (e) {
13  // Handle errors if required!
14}

#Response and Error Handling

There are three types of error class to be aware of when working with Magic's client-side JavaScript SDK:

  • SDKError: Raised by the SDK to indicate missing parameters, communicate deprecation notices, or other internal issues. A notable example would be a MISSING_API_KEY error, which informs the required API key parameter was missing from new Magic(...).
  • RPCError: Errors associated with specific method calls to the Magic <iframe> context. These methods are formatted as JSON RPC 2.0 payloads, so they return error codes as integers. This type of error is raised by methods like AuthModule.loginWithMagicLink.
  • ExtensionError: Errors associated with method calls to Magic SDK Extensions. Extensions are an upcoming/experimental feature of Magic SDK. More information will be available once Extensions are officially released.

#SDKError

The SDKError class is exposed for instanceof operations.

Javascript
01import { SDKError } from 'magic-sdk';
02
03try {
04  // Something async...
05catch (err) {
06  if (err instanceof SDKError) {
07    // Handle...
08  }
09}

SDKError instances expose the code field which may be used to deterministically identify the error. Additionally, an enumeration of error codes is exposed for convenience and readability:

Javascript
01import { SDKErrorCode } from 'magic-sdk';
02
03SDKErrorCode.MissingApiKey;
04SDKErrorCode.ModalNotReady;
05SDKErrorCode.MalformedResponse;
06// and so forth...
07// Please reference the `Enum Key` column of the error table below.

#Error Codes

Enum KeyDescription
MissingApiKeyIndicates the required Magic API key is missing or invalid.
ModalNotReadyIndicates the Magic iframe context is not ready to receive events. This error should be rare and usually indicates an environmental issue or improper async/await usage.
MalformedResponseIndicates the response received from the Magic iframe context is malformed. We all make mistakes (even us), but this should still be a rare exception. If you encounter this, please be aware of phishing!
InvalidArgumentRaised if an SDK method receives an invalid argument. Generally, TypeScript saves us all from simple bugs, but there are validation edge cases it cannot solve—this error type will keep you informed!
ExtensionNotInitializedIndicates an extension method was invoked before the Magic SDK instance was initialized. Make sure to access extension methods only from the Magic SDK instance to avoid this error.

IncompatibleExtension

Indicates that incompatible extensions were detected during the initialization of the Magic SDK. The error message specifies the incompatible extensions and their compatibility requirements based on the current Magic SDK version and platform environment.

#RPCError

The RPCError class is exposed for instanceof operations:

Javascript
01import { RPCError } from 'magic-sdk';
02
03try {
04  // Something async...
05catch (err) {
06  if (err instanceof RPCError) {
07    // Handle...
08  }
09}

RPCError instances expose the code field which may be used to deterministically identify the error. Additionally, an enumeration of error codes is exposed for convenience and readability:

Javascript
01import { RPCErrorCode } from 'magic-sdk';
02
03RPCErrorCode.MagicLinkExpired;
04RPCErrorCode.UserAlreadyLoggedIn;
05RPCErrorCode.ParseError;
06RPCErrorCode.MethodNotFound;
07RPCErrorCode.InternalError;
08// and so forth...
09// Please reference the `Enum Key` column of the error table below.

#Magic Link Error Codes

CodeEnum KeyDescription
-10000MagicLinkFailedVerificationThe magic link failed verification, possibly due to an internal service error or a generic network error.
-10001MagicLinkExpiredThe user clicked their magic link after it had expired (this can happen if the user takes more than 10 minutes to check their email).
-10002MagicLinkRateLimitedIf the showUI parameter is set to false, this error will communicate the email rate limit has been reached. Please debounce your method calls if this occurs.
-10006MagicLinkInvalidRedirectURLIf using the redirectURI parameter for the magic link flow, this error is recevied if the provided value is invalid for some reason.
-10003UserAlreadyLoggedInA user is already logged in. If a new user should replace the existing user, make sure to call logout before proceeding.
-10004UpdateEmailFailedAn update email request was unsuccessful, either due to an invalid email being supplied or the user canceled the action.
-10005UserRequestEditEmailThe user has stopped the login request because they want to edit the provided email.

-10010

InactiveRecipient

The recipient account is currently inactive. The user should verify and activate their account to resolve this issue.

-10011

AccessDeniedToUser

User access is denied. The user lacks the necessary permissions or credentials to perform the requested action.

-10015

RedirectLoginComplete

The redirect login process has been successfully completed.

#Standard JSON RPC 2.0 Error Codes

CodeEnum KeyDescription
-32700ParseErrorInvalid JSON was received by the server. An error occurred on the server while parsing the JSON text.
-32600InvalidRequestThe JSON sent is not a valid Request object.
-32601MethodNotFoundThe method does not exist / is not available.
-32602InvalidParamsInvalid method parameter(s).
-32603InternalErrorInternal JSON-RPC error. These can manifest as different generic issues (i.e.: attempting to access a protected endpoint before the user is logged in).

#ExtensionError

The ExtensionError class is exposed for instanceof operations:

Typescript
01import { ExtensionError } from 'magic-sdk';
02
03try {
04  // Something async...
05catch (err) {
06  if (err instanceof ExtensionError) {
07    // Handle...
08  }
09}

ExtensionError instances expose the code field which may be used to deterministically identify the error. Magic SDK does not export a global enumeration of Extension error codes. Instead, Extension authors are responsible for exposing and documenting error codes relevant to the Extension's use-case.

#PromiEvents

Magic SDK provides a flexible interface for handling methods which encompass multiple "stages" of an action. Promises returned by Magic SDK resolve when a flow has reached finality, but certain methods also contain life-cycle events that dispatch throughout. We refer to this interface as a PromiEvent. There is prior art to inspire this approach in Ethereum's Web3 standard.

PromiEvent is a portmanteau of Promise and EventEmitter. Browser and React Native SDK methods return this object type, which is a native JavaScript Promise overloaded with EventEmitter methods. This value can be awaited in modern async/await code, or you may register event listeners to handle method-specific life-cycle hooks. Each PromiEvent contains the following default event types:

  • "done": Called when the Promise resolves. This is equivalent to Promise.then.
  • "error": Called if the Promise rejects. This is equivalent to Promise.catch.
  • "settled": Called when the Promise either resolves or rejects. This is equivalent to Promise.finally.

Look for additional event types documented near the method they relate to. Events are strongly-typed by TypeScript to offer developer hints and conveniant IDE auto-complete.

Typescript
01const req = magic.auth.loginWithMagicLink({ email: '[email protected]' });
02
03req
04  .on('email-sent', () => {
05    /* ... */
06  })
07  .then(DIDToken => {
08    /* ... */
09  })
10  .once('email-not-deliverable', () => {
11    /* ... */
12  })
13  .catch(error => {
14    /* ... */
15  })
16  .on('error', error => {
17    /* ... */
18  });

#EVM RPC Methods

Magic supports the following EVM RPC Methods that can be called through a web3 provider library such as web3.js or ethers.js.

Note: starting from [email protected], eth_accounts will return an empty array if no user is logged in, instead of prompting the login form. To prompt the login form, use connectWithUI().

  • eth_accounts
  • get_balance
  • eth_estimateGas
  • eth_gasPrice
  • eth_sendTransaction
  • personal_sign
  • eth_signTypedData_v3
  • eth_signTypedData_v4

#Examples

#Re-authenticate Users

A user's Magic SDK session persists up to 7 days by default, so re-authentication is usually friction-less.

Note: the session length is customizable by the developer through the Magic dashboard.

Before re-authenticating a user, install the Magic Client SDK​.

Typescript
01import { Magic } from 'magic-sdk';
02const magic = new Magic('PUBLISHABLE_API_KEY');
03
04const email = '[email protected]';
05
06if (await magic.user.isLoggedIn()) {
07  const didToken = await magic.user.getIdToken();
08
09  // Do something with the DID token.
10  // For instance, this could be a `fetch` call
11  // to a protected backend endpoint.
12  document.getElementById('your-access-token').innerHTML = didToken;
13} else {
14  // Log in the user
15  const user = await magic.auth.loginWithMagicLink({ email });
16}

#Resources

#Versions

All changes to the SDK are covered in our latest release notes.