This document provides instructions on how to authenticate users with Dynamic and use Crossmint’s APIs to create a wallet, mint an NFT, and display the contents of the wallets.

Developer documentation

Demo of this flow :

Dynamic Doc -

Crossmint Doc -

Authenticating Users with Dynamic

The user authentication process with Dynamic for our use case consists of two essential steps: generating a One-Time Password (OTP) and submitting the OTP for verification. The following instructions show how to use Dynamic’s API for these tasks. Dynamic will register new users or return an existing user if they have gone through the registration process before. You can view user details on your Dynamic dashboard.

To begin, create an account on and retrieve your keys from the Dashboard.

Then from your Dashboard

  1. Open the the Email, Social & Embedded Wallets section.

  2. Enable Email sign up.

Generating an OTP

Now, you can setup a site that takes an email address as an input and then takes an OTP as an input.

Once you have that you can start sending an OTP(One-Time-Password) to the user’s email address.

You can find the reference for this call here

Here is the curl command that you can use to create an OTP:

curl -X POST '<environment_id>/emailVerifications/create' \
-H 'accept: application/json' \
-H 'content-type: application/json' \
-d '{
    "email": "<email>"

The API call will return a verificationUUID, which will be used in the subsequent step. Replace <email> with the actual email of the user & the <environment_id> with your environment id from your Dynamic dashboard.

//Response on OTP Generation
    "email": "[email protected]",
    "verificationUUID": "bf4c7a1a-9411-4835-adce-c28eabc7f4dc"

Submitting OTP for authentication

Now we will need to verify the OTP sent to the user’s email address.

You can find the reference for this call here

Here is the curl command you can use to verify the OTP that was sent to a user :

curl -X POST '<environment_id>/emailVerifications/signin' \
-H 'accept: application/json' \
-H 'content-type: application/json' \
-d '{
    "verificationUUID": "<verificationUUID>",
    "verificationToken": "<OTP>"

If all the details were correct this API call will return the authenticated user object along with a JWT token. Replace <verificationUUID> with the UUID from the previous step, and <OTP> with the OTP sent to the user’s email. You can use the JWT token to manage sessions, authorize the user, and sign in the user.

//Valid response
    "jwt": "eyJhbGciOiJSUzI1NiIsIn.....c3RzIjpbXSwibWlzc2luZ19maWVsZHMiOltdLCJ2ZXJpZmllZF9jcmVkZW50aWFscyI6W10sImxhc3RfdmVyaWZpZWRfY3JlZGVudGlhbF9pZCI6IjQyM2FhNDFhLTQzNDUtNDIzMC05MjM2LTIwMjNjODc5MWEyNiIsImZpcnN0X3Zpc2l0IjoiMjAyMy0wNi0yN1QyMTo0ODoxOC43NTFaIiwibGFzdF92aXNpdCI6IjIwMjMtMDYtMjdUMjE6NDg6MTguNzUxWiIsIm5ld191c2VyIjpmYWxzZSwiaWF0IjoxNjg4NDg4NTM3LCJleHAiOjE2ODg0OTU3Mzd9.k6_UDshY1idbe6_MJ4pfYsvyYWtzKOplzjta2Eqt1tkekBdAGAFWM5VTUX4phZSKqVQq4b5lFO87nGiCtsdvIt-zwoUlyoL9VmWdPA9C1MWY-Aut0SL2hgDMqRWChSQKzz2ugd7z-Krt5ohg9RCmN4eaTsAdQTqLGLHNTGLilCw_vefjaK_jPsmKHlOlcZLUuhpd65sMt2zHvAePVNRpEfjIvZhGwuDWFivBd3ZhtkioAdio9n5o-x2OMOko94OA6ct9-L6UnMLfVVXLJSpJFCLo-c6wr0OXXgtGjyB5-gA5KFHM5xy6OGjCO-A2WaNudbToFX5ycHkYbuNkOVhae5ZBFklxaoLhvHFfYKvJaDOEub1QwZy8T_Hzzwo3YntWlzhZOqgPWnWBQyunImofNH_MRAZYPzdywnyIdK8JYV0kaZFN2Jmqa_tLjul2ZTZFbyFAVhcukWA_ng6_rF1QGGypNtYZSqRZF5gvEtc3KQNg0k2joGFx62S-AzPhEnNVbLnw-lAC-ch9n9nJrRjFMJ3qfNROh8PoUS8G-AKtd66cRUlejI0M-6L0E679VD8Rc2Ls2TzPp5uvaDLHJpIk3uXVwe6mvVEuKzBvgsIr5MYMmlyEgrUsOoJd3wKD20shDSkX9UGT6q1qXKx3CrIdMYk8QL5N_uM4r7YF2m8N1Go",
    "user": {
        "email": "[email protected]",
        "firstVisit": "2023-06-27T21:48:18.751Z",
        "id": "d9094197-de22-26b6-ac1a-7a8b3979cead",
        "lastVisit": "2023-06-27T21:48:18.751Z",
        "newUser": false,
        "projectEnvironmentId": "b428e4ec-5ab5-47bd-a26e-33401c0c9fd1",
        "verifiedCredentials": []

👉 Note: This flow is for server-side verification. Dynamic also provides a React SDK to perform this verification and returns a similar user object upon successful authentication. You can learn more about Dynamic’s React SDK here

Integrating with Crossmint

Generating a Wallet for Our Dynamic User

Reference :

Now that the user is authenticated via Dynamic, let’s create a wallet for them using Crossmint.

Here is the curl command to create a wallet from email address:

curl -X POST '' \
-H 'X-PROJECT-ID: <your_project_id>' \
-H 'X-CLIENT-SECRET: <your_secret_key>' \
-H 'Content-Type: application/json' \
-d '{
    "email": "<email>",
    "chain": "polygon" // Feel free to change this.

Replace <your_project_id> and <your_secret_key> with your project ID and secret key from your Crossmint dev console, and <email> with the email of the user for whom you are creating the wallet. This API call will return a publicKey that represents the user’s new wallet on the Polygon chain (for this example, we support multiple blockchains).

On successful wallet creation, the API response will look something like this:

    "chain": "polygon",
    "publicKey": "0xB364346FDb52e42CcC186b3BA3730cb4A27bA5B0"

👉 One you enter the email address / userid of the user our wallet API will automatically create a multi-chain MPC wallet for you.

Once a wallet is successfully generated and the user is signed in, you can use Crossmint’s APIs to do more things for your users.

Note : You’ll need these scopes enabled while creating an API for minting and wallet generation to work.

Further examples

Minting an NFT

Reference :

Now once a user is signed in, you can take these user’s to an NFT drop page and enable them to mint an NFT.

Here’s how you can mint an NFT for this user using Crossmint’s minting api

curl --request POST \
     --url<Collection_ID>/nfts \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
  "recipient": "email:[email protected]:polygon",
  "metadata": {
    "name": "NFT",
    "image": "",
    "description": "NFT created using Crossmint's mint API!"

On successful Mint, the API response will look something like this:

  "id": "74408f29-8d35-4686-9ca6-cd4a65186e7b",
  "onChain": {
    "status": "pending",
    "chain": "polygon",
    "contractAddress": "0x123456789...."

You can now store the NFT <id> in your database liked to this user’s wallet & in the future you can use other APIs from Crossmint to - Edit this NFT, Transfer NFT, sign a transaction from Crossmint’s wallet, create more collections or mint more NFTs …etc.

Displaying contents of a user’s wallet

Reference :

Now, you may want to show the user all the NFTs that their wallet holds. To do this, you can use Crossmint’s “fetch wallet contents” API. Here’s how:

curl --request GET \
     --url '<wallet_address>/nfts?page=1&perPage=20' \
     --header 'X-CLIENT-SECRET: <secret_key>' \
     --header 'X-PROJECT-ID: <project_id>' \
     --header 'accept: application/json'

Crossmint API Reference :

Wallet as a service doc -