Create a Dynamic NFT
Estimated completion time: 30 minutes.
A dynamic NFT is an NFT with traits and data that can be changed/updated based on external events.
Using our Minting APIs, you can create dynamic NFTs very easily. No previous blockchain experience needed - just follow along. ✌️
This tutorial covers:
-
How to mint an NFT
-
How to update the metadata of the NFT
-
How to automatically update the metadata of the NFT
Pre-requirements
- Sign up for your free API key
1. How to mint an NFT
Using our APIs you can deploy your own contract, upload files to IPFS, and mint an NFT.
Step A: Deploy your fully owned contract
Deploy a standard ERC-721 smart contract where your can mint your NFTs. Add your API key, set Content-Type as application/json
and fill parameters with your own values. Set metadata_updatable
as true
so that the metadata of the NFT can be changed as required.
For API reference and more code samples, see Deploy a contract for NFT products.
Deploy contract
curl --request POST \
--url https://api.nftport.xyz/v0/contracts \
--header 'Authorization: <<apiKey>>' \
--header 'Content-Type: application/json' \
--data '{
"chain": "polygon",
"name": "Polypunks",
"symbol": "PP",
"owner_address": "Your wallet address here",
"metadata_updatable": true
}'
import requests
url = "https://api.nftport.xyz/v0/contracts"
payload = {
"chain": "polygon",
"name": "Polypunks",
"symbol": "PP",
"owner_address": "Your wallet address here",
"metadata_updatable": True
}
headers = {
"Content-Type": "application/json",
"Authorization": "<<apiKey>>"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
const options = {
method: 'POST',
headers: {'Content-Type': 'application/json', Authorization: '<<apiKey>>'},
body: '{
"chain":"polygon",
"name":"Polypunks",
"symbol":"PP",
"owner_address":"Your wallet address here",
"metadata_updatable":true
}'
};
fetch('https://api.nftport.xyz/v0/contracts', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
After the transaction is confirmed and contract is deployed on chain, use the transaction_hash
from the previous response to retrieve your contract address. For API reference and more code examples, see Retrieve a deployed contract. You can also see your deployed contracts with List all your deployed contracts.
Get contract address of the deployed contract
curl --request GET \
--url 'https://api.nftport.xyz/v0/contracts/transaction_hash?chain=polygon' \
--header 'Authorization: <<apiKey>>' \
--header 'Content-Type: application/json'
import requests
url = "https://api.nftport.xyz/v0/contracts/transaction_hash"
querystring = {"chain":"polygon"}
headers = {
"Content-Type": "application/json",
"Authorization": "<<apiKey>>"
}
response = requests.request("GET", url, headers=headers, params=querystring)
print(response.text)
const options = {
method: 'GET',
headers: {'Content-Type': 'application/json', Authorization: '<<apiKey>>'}
};
fetch('https://api.nftport.xyz/v0/contracts/transaction_hash?chain=polygon', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
Step B: Upload your assets to IPFS
Upload your files to IPFS which makes your NFT storage decentralized and immutable. For API reference and more code samples, see Upload a file to IPFS. If you have multiple assets, for example, an image for every part of the day, then you should upload all the files to IPFS.
curl --request POST \
--url 'https://api.nftport.xyz/v0/files' \
--header 'Authorization: <<apiKey>>' \
--header 'Content-Type: multipart/form-data' \
--form 'file=@/path/to/file_to_upload.png;type=image/png'
import requests
file = open("image.png", "rb")
response = requests.post(
"https://api.nftport.xyz/v0/files",
headers={"Authorization": "<<apiKey>>"},
files={"file": file}
)
const fs = require('fs');
const fetch = require('node-fetch');
const FormData = require('form-data');
const form = new FormData();
const fileStream = fs.createReadStream('image.jpg');
form.append('file', fileStream);
const options = {
method: 'POST',
body: form,
headers: {
'Authorization': '<<apiKey>>',
},
};
fetch('https://api.nftport.xyz/v0/files', options)
.then(response => {
return response.json()
})
.then(responseJson => {
// Handle the response
console.log(responseJson);
})
Step C: Create and upload your NFT metadata to IPFS
Upload your metadata to IPFS which makes your NFT metadata decentralized and immutable. For API reference, full customization and more code samples, see Upload metadata to IPFS. If you have multiple assets, for example, an image for every part of the day, then you should create a different metadata file for every asset.
curl --request POST \
--url https://api.nftport.xyz/v0/metadata \
--header 'Authorization: <<apiKey>>' \
--header 'Content-Type: application/json' \
--data '{
"name": "Your NFT name",
"description": "Your NFT description",
"file_url": "URL of the file that you wish to turn into an NFT"
}'
import requests
url = "https://api.nftport.xyz/v0/metadata"
payload = {
"name": "Your NFT name",
"description": "Your NFT description",
"file_url": "The ipfs_url you got from the previous request response"
}
headers = {
"Content-Type": "application/json",
"Authorization": "<<apiKey>>"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
const options = {
method: 'POST',
headers: {'Content-Type': 'application/json', Authorization: '<<apiKey>>'},
body: '{
"name":"Your NFT name",
"description":"Your NFT description",
"file_url":"The ipfs_url you got from the previous request response"
}'
};
fetch('https://api.nftport.xyz/v0/metadata', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
Step D: Mint NFTs to your contract
Mint NFTs to the contract you just deployed. For API reference, full customization and more code samples, see Customizable minting.
curl --request POST \
--url https://api.nftport.xyz/v0/mints/customizable \
--header 'Authorization: <<apiKey>>' \
--header 'Content-Type: application/json' \
--data '{
"chain": "polygon",
"contract_address": "The contract address which you got from step 1 A",
"metadata_uri": "Metadata URI that you got from the response of uploading metadata to IPFS",
"mint_to_address": "Account address where the NFT will be sent. For example, your Metamask wallet address if you wish to send it to yourself"
}'
import requests
url = "https://api.nftport.xyz/v0/mints/customizable"
payload = {
"chain": "polygon",
"contract_address": "The contract address which you got from step 1 A",
"metadata_uri": "Metadata URI that you got from the response of uploading metadata to IPFS",
"mint_to_address": "Account address where the NFT will be sent. For example, your Metamask wallet address if you wish to send it to yourself"
}
headers = {
"Content-Type": "application/json",
"Authorization": "<<apiKey>>"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
const options = {
method: 'POST',
headers: {'Content-Type': 'application/json', Authorization: '<<apiKey>>'},
body: '{
"chain":"polygon",
"contract_address":"The contract address which you got from step 1 A",
"metadata_uri":"Metadata URI that you got from the response of uploading metadata to IPFS",
"mint_to_address":"Account address where the NFT will be sent. For example, your Metamask wallet address if you wish to send it to yourself"
}'
};
fetch('https://api.nftport.xyz/v0/mints/customizable', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
Get token ID of the minted NFT
curl --request GET \
--url 'https://api.nftport.xyz/v0/mints/transaction_hash?chain=polygon' \
--header 'Authorization: <<apiKey>>' \
--header 'Content-Type: application/json'
import requests
url = "https://api.nftport.xyz/v0/mints/transaction_hash"
querystring = {"chain":"polygon"}
headers = {
"Content-Type": "application/json",
"Authorization": "<<apiKey>>"
}
response = requests.request("GET", url, headers=headers, params=querystring)
print(response.text)
const options = {
method: 'GET',
headers: {'Content-Type': 'application/json', Authorization: '<<apiKey>>'}
};
fetch('https://api.nftport.xyz/v0/mints/transaction_hash?chain=polygon', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
Here's how our freshly minted NFT on Polygon looks like:
2. How to update the metadata of the NFT
Use our API to update the metadata of the NFT. For API reference and more code samples, see Update a minted NFT.
curl --request POST \
--url https://api.nftport.xyz/v0/mints/customizable \
--header 'Authorization: <<apiKey>>' \
--header 'Content-Type: application/json' \
--data '{
"chain": "polygon",
"contract_address": "The contract address which you got from step 1 a",
"token_id": "The token ID which you got from step 1 d",
"metadata_uri": "The new metadata uri with which you want your NFT to be linked"
}'
import requests
url = "https://api.nftport.xyz/v0/mints/customizable"
payload = {
"chain": "polygon",
"contract_address": "The contract address which you got from step 1 a",
"token_id": "The token ID which you got from step 1 D",
"metadata_uri": "The new metadata uri with which you want your NFT to be linked"
}
headers = {
"Content-Type": "application/json",
"Authorization": "<<apiKey>>"
}
response = requests.request("PUT", url, json=payload, headers=headers)
print(response.text)
const options = {
method: 'PUT',
headers: {'Content-Type': 'application/json', Authorization: '<<apiKey>>'},
body: '{"chain":"polygon","contract_address":"The contract address which you got from step 1 a","token_id":"The token ID which you got from step 1 D","metadata_uri":"The new metadata uri with which you want your NFT to be linked"}'
};
fetch('https://api.nftport.xyz/v0/mints/customizable', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
Here's how our updated NFT looks like:
3. How to automatically update the metadata of the NFT
You can create an AWS Lambda function (event-driven serverless computing platform by Amazon), to automatically trigger updates to your NFT's metadata. For example, if you want to change the NFT metadata based on the time of the day, you can setup the lambda function to get triggered every x hours. See AWS developer guide to learn more.
The AWS Lambda free tier includes one million free requests per month which is a lot more than the 3x30 = 90 requests we'll make per month.
Step A: Create a Lambda function
Create a basic Lambda function using the runtime of your choice. We'll be using Python 3.9 in this tutorial.
Step B: Update the metadata of the NFT using AWS Lambda
Replace the values of the variables as required - api_key
, metadata URIs, etc.
This updates the metadata of the NFT according to the time of the day. You can customize as you see fit. You can even use a weather API to set the NFT image according to the weather.
- 4 a.m. to 12 p.m. - Image A displayed in the morning
- 12 p.m. to 8 p.m. - Image B displayed during the afternnon
- 8 p.m. to 4 a.m. - Image C displayed at night
# lambda_function.py
import requests
import json
from datetime import datetime
API_KEY = "<<apiKey>>"
# Replace with your metadata URIs
MORNING_URI = "ipfs://QmcFQ7K8N1XgtQvU3fB8VFmc9jHBmvpMkvSiKrJsgWQ6Sj"
AFTERNOON_URI = "ipfs://QmTmcL1KWgj5q2QwPM2KmmP3kSExTAp25MLBxaf39sjP6S"
NIGHT_URI = "ipfs://QmdMqg9vYoG3p6FeQko3kLrGivQ6mgZQRgvbFR8SXhutUF"
URL = "https://api.nftport.xyz/v0/mints/customizable"
def lambda_handler(event, context):
time = datetime.now().hour
if time >=4 and time <12:
metadata_uri = MORNING_URI
elif time >=12 and time<20:
metadata_uri = AFTERNOON_URI
else:
metadata_uri = NIGHT_URI
# Replace with the contract_address you got from 1 A and token_ID from 1 D
payload = {
"chain":"polygon",
"contract_address": "0x5bc18431304b4218e2b2bffaa97e608f8e500544",
"token_id": "293425161759338263480",
"metadata_uri": metadata_uri
}
headers = {
"Content-Type": "application/json",
"Authorization": API_KEY
}
response = requests.request("PUT", URL, data=json.dumps(payload), headers=headers)
return {
'statusCode': 200,
'body': json.dumps(response.json())
}
Step C: Configure installations and upload files to AWS Lambda
Unfortunately, python requests library does not come pre installed and the vendored version of requests from Botocore will be removed soon. We'll therefore need to install requests to run our code.
On your local machine, create a folder and install requests inside it by adding -t
.
mkdir lambda && cd lambda
pip install requests -t .
Inside this folder create a file lambda_function.py
. The Lambda handler will look for this exact file during execution. Copy the code in step B and paste it into this file.
Zip all the files in the folder (do not zip the whole folder as the files should be at the root when unzipped inside Lambda) inlcuding the lambda_function.py
and the requests library, and upload it to AWS Lambda. Use the Upload from
button at the top right and then click .zip file
to upload your zipped file.
Your file structure should look like this :
Click the deploy
button to save the changes.
Step D: Setup a trigger to automatically call your lambda function
We'll setup a trigger to automate this process. Click Add trigger
to setup a trigger to call the lambda function.
Set the trigger configuration to EventBridge (CloudWatch Events). We'll set the rate as 8 hours since we are going to update the NFT metadata every 8 hours. Yo
u can customize the rate of fire as per your liking, see the guide here to know more.
Once you setup the trigger, the complete configuration should look like this.
Your dynamic NFT is ready to rock'n'roll 😎
How our dynamic NFT looks like:
You can see our dynamic NFT on Opensea. Click on the Refresh metadata
button on Opensea to get the updated NFT asset. The image displayed will depend on the time of the day (UTC).
Join the Community for Support and to Build Together
Join our Discord community if you need support from our team and a space to discuss NFT related topics, voice feature requests, and engage with other like-minded NFT developers.
Updated over 1 year ago