> ## Documentation Index
> Fetch the complete documentation index at: https://docs.magic.link/llms.txt
> Use this file to discover all available pages before exploring further.

# Node SDK Reference

## Overview

The Magic SDK for Node is your entry-point to secure, passwordless authentication for your application. This guide will cover some important topics for getting started with Node 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 **secret** key.

### Installation

The Magic Admin Node SDK requires Node.js 18 or higher.

<CodeGroup>
  ```bash NPM icon="npm" theme={null}
  npm install @magic-sdk/admin
  ```

  ```bash Yarn icon="yarn" theme={null}
  yarn add @magic-sdk/admin
  ```
</CodeGroup>

### Constructor

`Magic.init()`

|                     |        |                                                                                                                                             |
| ------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Parameter           | Type   | Definition                                                                                                                                  |
| `secretApiKey`      | String | Your **secret** API Key retrieved from the Magic Dashboard.                                                                                 |
| `options.endpoint?` | String | A URL pointing to the Magic API. You should not need to provide this value except in case you are building highly custom integration tests. |
| `options.clientId?` | String | Your Magic client ID. If not provided, will be fetched automatically.                                                                       |

### Initialization

```javascript Node.js icon="node-js" theme={null}
const { Magic } = require('@magic-sdk/admin');

const magic = await Magic.init('SECRET_API_KEY');
```

## Token Module

The Token Module and its members are accessible on the Magic Admin SDK instance by the `token` property.

<Note>
  The token module does **not** make any API calls to the Magic server.
</Note>

### `getIssuer`

Extracts the `iss` from the [DID Token](/embedded-wallets/authentication/features/decentralized-id).

```javascript Node.js icon="node-js" theme={null}
magic.token.getIssuer(didToken)
```

**Arguments**

* `didToken` (String): A [Decentralized ID Token](/embedded-wallets/authentication/features/decentralized-id) generated by a Magic user on the client-side.

**Throws**

* `MalformedTokenError`: If the given DID Token is malformed

**Returns**

* A Decentralized ID (`iss`) of the Magic user who generated the DID Token

### `getPublicAddress`

Gets the cryptographic [public address](https://support.blockchain.com/hc/en-us/articles/4417082520724-What-are-public-and-private-keys-and-how-do-they-work-) of the Magic User who generated the supplied DID Token.

```javascript Node.js icon="node-js" theme={null}
magic.token.getPublicAddress(didToken)
```

**Arguments**

* `didToken` (String): A Decentralized ID Token generated by a Magic user on the client-side

**Throws**

* `MalformedTokenError`: If the given DID Token is malformed

**Returns**

* The [public address](https://support.blockchain.com/hc/en-us/articles/4417082520724-What-are-public-and-private-keys-and-how-do-they-work-) of the Magic User who generated the DID Token. Currently, this value is associated with the Ethereum blockchain.

### `decode`

Decodes a DID Token from a Base64 string into a tuple of its individual components: `proof` and `claim`. This method allows you decode the DID Token and inspect the token. You can apply your own rules and validations on top of the current [Token.validate](#validate) method.

```javascript Node.js icon="node-js" theme={null}
magic.token.decode(didToken)
```

**Arguments**

* `didToken` (String): A Decentralized ID Token generated by a Magic user on the client-side

**Throws**

* `MalformedTokenError`: If the given DID Token is malformed

**Returns**

* `proof` (String): A digital signature that proves the validity of the given `claim`
* `claim` (Object): Unsigned data the user asserts. This should equal the `proof` after Elliptic Curve recovery. See [Decentralized ID Token Specification](/embedded-wallets/authentication/features/decentralized-id#decentralized-id-token-specification) for fields inside the `claim`.

The `claim` is automatically parsed to the following interface:

```javascript Node.js icon="node-js" theme={null}
interface Claim {
  iat: number; // Issued At Timestamp
  ext: number; // Expiration Timestamp
  iss: string; // Issuer of DID Token
  sub: string; // Subject
  aud: string; // Audience
  nbf: number; // Not Before Timestamp
  tid: string; // DID Token ID
  add: string; // (optional) Misc additional signed data
}
```

As a convenience, the above interface is available to your code in [TypeScript](https://www.typescriptlang.org/):

```javascript Node.js icon="node-js" theme={null}
import { Claim } from '@magic-sdk/admin';
```

### `validate`

Validates a DID token.

```javascript Node.js icon="node-js" theme={null}
await magic.token.validate(didToken)
```

**Arguments**

* `didToken` (String): A Decentralized ID Token generated by a Magic user on the client-side
* `attachment?` (String): Arbitrary, serialized data to be used for recovery of the `add` field on the Decentralized ID Token (Defaults to `"none"`)

**Throws**

* `MalformedTokenError`: If the given DID Token is malformed
* `TokenExpired`: If the given DID Token has expired
* `IncorrectSignerAddress`: If the given DID Token is invalid

**Returns**

* `Promise<void>`: The function will return if the specified DID token is authentic and not expired. If the token is forged or otherwise invalid, the function will throw a descriptive error.

## Users Module

### `getMetadataByIssuer`

Retrieves information about user by the supplied "issuer".

**Arguments**

* `issuer` (String): The user's Decentralized ID, which can be parsed using [`TokenModule.getIssuer`](#getissuer)

**Returns**

* A `MagicUserMetadata`: The `data` field contains all of the user meta information.
  * `issuer` (String): The user's Decentralized ID
  * `publicAddress` (String): The authenticated user's public address (a.k.a.: public key). Currently, this value is associated with the Ethereum blockchain.
  * `email` (String): The user's email address
  * `phoneNumber` (String | null): The user's phone number
  * `oauthProvider` (String | null): OAuth provider, if any
  * `wallets` (Object\[]): The multichain wallets of the authenticated user

### `getMetadataByPublicAddress`

Retrieves information about user by the supplied public address.

**Arguments**

* `publicAddress` (String): The user's Ethereum public address, which can be parsed using [`TokenModule.getPublicAddress`](#getpublicaddress)

**Returns**

* A `MagicUserMetadata`: The `data` field contains all of the user meta information.
  * `issuer` (String): The user's Decentralized ID
  * `publicAddress` (String): The authenticated user's public address (a.k.a.: public key). Currently, this value is associated with the Ethereum blockchain.
  * `email` (String): The user's email address
  * `phoneNumber` (String | null): The user's phone number
  * `oauthProvider` (String | null): OAuth provider, if any
  * `wallets` (Object\[]): The multichain wallets of the authenticated user

### `getMetadataByToken`

Retrieves information about user by the supplied DID Token.

**Arguments**

* `didToken` (String): A valid Decentralized ID Token generated client-side by a Magic user

**Returns**

* A `MagicUserMetadata`: The `data` field contains all of the user meta information.
  * `issuer` (String): The user's Decentralized ID
  * `publicAddress` (String): The authenticated user's public address (a.k.a.: public key). Currently, this value is associated with the Ethereum blockchain.
  * `email` (String): The user's email address
  * `phoneNumber` (String | null): The user's phone number
  * `oauthProvider` (String | null): OAuth provider, if any
  * `wallets` (Object\[]): The multichain wallets of the authenticated user

### `logoutByIssuer`

Logs a user out of all client-side Magic SDK sessions given the user's Decentralized ID.

**Arguments**

* `issuer` (String): The user's Decentralized ID, which can be parsed using [`TokenModule.getIssuer`](#getissuer)

**Returns**

* `Promise<void>`

### `logoutByPublicAddress`

Logs a user out of all client-side Magic SDK sessions given the user's public address.

**Arguments**

* `publicAddress` (String): The user's Ethereum [public address](https://support.blockchain.com/hc/en-us/articles/4417082520724-What-are-public-and-private-keys-and-how-do-they-work-) to log out via the Magic API.

**Returns**

* `Promise<void>`

### `logoutByToken`

Logs a user out of all client-side Magic SDK sessions given the user's DID token.

**Arguments**

* `didToken` (String): A valid Decentralized ID Token generated client-side by a Magic user

**Returns**

* `Promise<void>`

### Multichain Methods

The following multichain methods require the use of the enum `WalletType` that is exported from the Magic Admin SDK.

**Supported Networks**

* **EVM Compatible**: ETH, AVAX, CELO, HARMONY, ICON, ZILLIQA, HEDERA, CONFLUX, TERRA, TAQUITO, ED
* **Non-EVM**: SOLANA, POLKADOT, NEAR, FLOW, TEZOS, COSMOS, ALGOD, BITCOIN, HELIUM

### `getMetadataByIssuerAndWallet`

Retrieves information about user, including their multichain wallets, by the supplied issuer.

**Arguments**

* `issuer` (String): The user's Decentralized ID, which can be parsed using [`TokenModule.getIssuer`](#getissuer)
* `walletType` (WalletType): The wallet type. Must import `WalletType` from Admin SDK.

**Returns**

* A `MagicUserMetadata`: The `data` field contains all of the user meta information.
  * `issuer` (String): The user's Decentralized ID
  * `publicAddress` (String): The authenticated user's public address (a.k.a.: public key). Currently, this value is associated with the Ethereum blockchain.
  * `email` (String): The user's email address
  * `phoneNumber` (String | null): The user's phone number
  * `oauthProvider` (String | null): OAuth provider, if any
  * `wallets` (Object\[]): The multichain wallets of the authenticated user

### `getMetadataByPublicAddressAndWallet`

Retrieves information about user, including their multichain wallets, by the supplied public address.

**Arguments**

* `publicAddress` (String): The user's Ethereum public address, which can be parsed using [`TokenModule.getPublicAddress`](#getpublicaddress)
* `walletType` (WalletType): The wallet type. Must import `WalletType` from Admin SDK.

**Returns**

* A `MagicUserMetadata`: The `data` field contains all of the user meta information.
  * `issuer` (String): The user's Decentralized ID
  * `publicAddress` (String): The authenticated user's public address (a.k.a.: public key). Currently, this value is associated with the Ethereum blockchain.
  * `email` (String): The user's email address
  * `phoneNumber` (String | null): The user's phone number
  * `oauthProvider` (String | null): OAuth provider, if any
  * `wallets` (Object\[]): The multichain wallets of the authenticated user

### `getMetadataByTokenAndWallet`

Retrieves information about user, including their multichain wallets, by the supplied DID Token.

**Arguments**

* `didToken` (String): A valid Decentralized ID Token generated client-side by a Magic user
* `walletType` (WalletType): The wallet type. Must import `WalletType` from Admin SDK.

**Returns**

* A `MagicUserMetadata`: The `data` field contains all of the user meta information.
  * `issuer` (String): The user's Decentralized ID
  * `publicAddress` (String): The authenticated user's public address (a.k.a.: public key). Currently, this value is associated with the Ethereum blockchain.
  * `email` (String): The user's email address
  * `phoneNumber` (String | null): The user's phone number
  * `oauthProvider` (String | null): OAuth provider, if any
  * `wallets` (Object\[]): The multichain wallets of the authenticated user

**Example**

```javascript Node.js icon="node-js" theme={null}
const { Magic, WalletType } = require('@magic-sdk/admin');

const magic = await Magic.init('SECRET_API_KEY');

// Get user metadata for Solana wallet
const response = await magic.users.getMetadataByTokenAndWallet(
  "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ...",
  WalletType.SOLANA
);

console.log(`Solana wallet address: ${response.data.publicAddress}`);
```

## Utils Module

The Utils Module and its members are accessible on the Magic Admin SDK instance by the `utils` property.

### `parseAuthorizationHeader`

Extracts a DID token from an HTTP Authorization header.

**Arguments**

* `header` (String): A request authorization header passed in from the client-side application that looks like `Bearer WyIweG...n0iXQ==`

**Returns**

* `string`: The DID token embedded in the authorization header

**Example**

```javascript Node.js icon="node-js" theme={null}
const { Magic } = require('@magic-sdk/admin');

const magic = await Magic.init('SECRET_API_KEY');

// Extract token from Authorization header
const authHeader = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ...";
const didToken = magic.utils.parseAuthorizationHeader(authHeader);
```

### `validateTokenOwnership`

Validates that a user owns a specific NFT token for token gating functionality.

**Arguments**

* `didToken` (String): The DID token to validate
* `contractAddress` (String): The smart contract address of the NFT
* `contractType` (String): Either `'ERC721'` or `'ERC1155'`
* `rpcURL` (String): The RPC endpoint URL for the blockchain
* `tokenId` (String, optional): Required for ERC1155 contracts

**Returns**

* `Promise<Object>`: Response with validation result
  * `valid` (Boolean): Whether the user owns the token
  * `error_code` (String): Error code if validation fails
  * `message` (String): Human-readable error message

**Example**

```javascript Node.js icon="node-js" theme={null}
const { Magic } = require('@magic-sdk/admin');

const magic = await Magic.init('SECRET_API_KEY');

// Validate ERC721 token ownership
const result = await magic.utils.validateTokenOwnership(
  "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ...",
  "0x1234567890123456789012345678901234567890",
  "ERC721",
  "https://mainnet.infura.io/v3/YOUR_PROJECT_ID"
);

if (result.valid) {
  console.log("User owns the NFT!");
} else {
  console.log(`Validation failed: ${result.message}`);
}
```

## Errors & Warnings

### `SDKError`

The `SDKError` class is exposed for `instanceof` operations and provides structured error handling.

```javascript Node.js icon="node-js" theme={null}
const { Magic, SDKError, ErrorCode } = require('@magic-sdk/admin');

const magic = await Magic.init('SECRET_API_KEY');

try {
  // Validate a DID token
  await magic.token.validate(didToken);
  console.log("Token is valid!");
  
  // Get user metadata
  const userData = await magic.users.getMetadataByToken(didToken);
  console.log(`User email: ${userData.data.email}`);
  
} catch (err) {
  if (err instanceof SDKError) {
    switch (err.code) {
      case ErrorCode.TokenExpired:
        console.log("Token has expired, please login again");
        break;
      case ErrorCode.MalformedTokenError:
        console.log("Invalid token format");
        break;
      case ErrorCode.IncorrectSignerAddress:
        console.log("Token signature verification failed");
        break;
      case ErrorCode.ApiKeyMissing:
        console.log("API key is missing or invalid");
        break;
      default:
        console.log(`SDK Error: ${err.message}`);
    }
  } else {
    console.log(`Unexpected error: ${err.message}`);
  }
}
```

### Error Codes

|                          |                                                                                                                                            |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Enum Key                 | Description                                                                                                                                |
| `TokenExpired`           | The supplied DID Token is invalid due to an expired timestamp.                                                                             |
| `TokenCannotBeUsedYet`   | The `nbf` ("not before") field of the supplied DID Token is set in the future. By default, a 5 minute leeway is added to the timestamp.    |
| `IncorrectSignerAddress` | The supplied DID Token is invalid due to a mismatch between the signature origin and the claimed user public address.                      |
| `FailedRecoveryProof`    | The supplied DID Token could not be recovered using Elliptic Curve recovery.                                                               |
| `ApiKeyMissing`          | The API key required for a particular action is missing or malformed.                                                                      |
| `MalformedTokenError`    | The supplied DID Token could not be successfully parsed.                                                                                   |
| `ServiceError`           | An error occurred while communicating with the Magic API. Be sure to check the `data` property of the error object for additional context. |
| `ExpectedBearerString`   | The supplied DID token needs to be in the proper format of `Bearer {token}`                                                                |
| `AudienceMismatch`       | Audience does not match client ID. Please ensure your secret key matches the application which generated the DID token.                    |

### `data` & Nested Errors

For additional context about an error, the `SDKError.data` property contains an array of potentially illuminating metadata. At the moment, this property is reserved for service errors when communication to Magic APIs fail.

## Resources

* [GitHub Repository](https://github.com/magiclabs/magic-admin-js)
* [NPM Package](https://www.npmjs.com/package/@magic-sdk/admin)
* [Magic Dashboard](https://dashboard.magic.link)
