In this quickstart you will learn how to create and manage intellectual property (IP) assets.
Contact
sales to enable this API on your project.
What are IP credentials?
IP credentials are onchain records of intellectual property rights and authorship, enabled by Story Protocol’s infrastructure and issued using Crossmint’s APIs.
Integration steps
1. Create a Developer Account
To get started, create a developer account in the Crossmint Staging Console . Open that link, sign in, and accept the dialog to continue.
2. Get an API Key
Once you log in to the console, the next step is to create an API key .
Click the "Integrate" tab and click on the "API Keys" option on top.
Within the “Server-side keys” section, click the “Create new key” button in the top right.
Then, check the necessary scopes under the “Minting API” category: nfts.create
, nfts.read
, collections.create
, nfts.update
and create your key. Save this key for the next step.
3. Create an IP Collection
First, let’s create an IP collection to hold our IP assets:
const apiKey = "YOUR_API_KEY" ;
const env = "staging" ; // or "www"
const url = `https:// ${ env } .crossmint.com/api/v1/ip/collections` ;
const options = {
method: "POST" ,
headers: {
accept: "application/json" ,
"content-type" : "application/json" ,
"x-api-key" : apiKey ,
},
body: JSON . stringify ({
metadata: {
description: "A collection of intellectual property assets" ,
name: "My IP Collection" ,
symbol: "MPA" ,
},
chain: "story-testnet" ,
}),
};
fetch ( url , options )
. then (( res ) => res . json ())
. then (( json ) => console . log ( json ))
. catch (( err ) => console . error ( "error:" + err ));
Here is an example response returned from the API call above:
{
"id" : "7f5e653d-2c9d-4025-98c8-8245c128ad10" ,
"actionId" : "7f5e653d-2c9d-4025-98c8-8245c128ad10" ,
"metadata" : {
"name" : "My IP Collection" ,
"symbol" : "MPA" ,
"description" : "A collection of intellectual property assets"
},
"onChain" : {
"chain" : "story-testnet"
}
}
Save the collection id
from the response for the next step.
4. Create an IP Asset
Now, let’s create an IP asset within our collection:
const apiKey = "YOUR_API_KEY" ;
const env = "staging" ; // or "www"
const collectionId = "YOUR_COLLECTION_ID" ;
const url = `https:// ${ env } .crossmint.com/api/v1/ip/collections/ ${ collectionId } /ipassets` ;
const options = {
method: "POST" ,
headers: {
accept: "application/json" ,
"content-type" : "application/json" ,
"x-api-key" : apiKey ,
},
body: JSON . stringify ({
owner: "email:creator@example.com:story-testnet" ,
nftMetadata: {
name: "Snowflake Funk" ,
description: "A disco song for the winter holidays" ,
image: "https://cdn2.suno.ai/image_large_c001fd6e-d6cd-474f-a7b6-6e6a9b3e2515.jpeg" ,
},
ipAssetMetadata: {
title: "Snowflake Funk" ,
createdAt: "2025-02-11T11:13:00" ,
ipType: "music" ,
creators: [
{
name: "John Doe" ,
email: "john.doe@example.com" ,
crossmintUserLocator: "email:john.doe@example.com:story-testnet" ,
contributionPercent: 100 ,
},
],
media: [
{
name: "Snowflake Funk" ,
url: "https://cdn1.suno.ai/c001fd6e-d6cd-474f-a7b6-6e6a9b3e2515.mp3" ,
mimeType: "audio/mpeg" ,
},
],
attributes: [
{
key: "Suno Artist" ,
value: "InfluentialCoda427" ,
},
{
key: "Source" ,
value: "Suno.com" ,
},
],
},
}),
};
fetch ( url , options )
. then (( res ) => res . json ())
. then (( json ) => console . log ( json ))
. catch (( err ) => console . error ( "error:" + err ));
Here is an example response returned from the API call above:
{
"id" : "49b9e141-8fd8-45dc-9646-13a3439c6f20" ,
"actionId" : "49b9e141-8fd8-45dc-9646-13a3439c6f20" ,
"nftMetadata" : {
"name" : "Snowflake Funk" ,
"image" : "https://cdn2.suno.ai/image_large_c001fd6e-d6cd-474f-a7b6-6e6a9b3e2515.jpeg" ,
"description" : "A disco song for the winter holidays"
},
"ipAssetMetadata" : {
"title" : "Snowflake Funk" ,
"createdAt" : "2025-02-11T11:13:00" ,
"creators" : [
{
"name" : "John Doe" ,
"email" : "john.doe@example.com" ,
"crossmintUserLocator" : "email:john.doe@example.com:story-testnet" ,
"contributionPercent" : 100
}
],
"media" : [
{
"name" : "Snowflake Funk" ,
"url" : "https://cdn1.suno.ai/c001fd6e-d6cd-474f-a7b6-6e6a9b3e2515.mp3" ,
"mimeType" : "audio/mpeg"
}
],
"attributes" : [
{
"key" : "Suno Artist" ,
"value" : "InfluentialCoda427"
},
{
"key" : "Source" ,
"value" : "Suno.com"
}
],
"ipType" : "music"
},
"licenseTerms" : [
{
"type" : "non-commercial-social-remixing"
}
],
"onChain" : {
"chain" : "story-testnet" ,
"contractAddress" : "0x82a72DfFb175DF8AB6d3C2E3888D5314a50C30D0" ,
"status" : "pending"
}
}
Save the IP asset id
from the response for the next steps.
5. Retrieve an IP Asset
To retrieve an IP asset:
const apiKey = "YOUR_API_KEY" ;
const env = "staging" ; // or "www"
const collectionId = "YOUR_COLLECTION_ID" ;
const ipAssetId = "YOUR_IP_ASSET_ID" ;
const url = `https:// ${ env } .crossmint.com/api/v1/ip/collections/ ${ collectionId } /ipassets/ ${ ipAssetId } ` ;
const options = {
method: "GET" ,
headers: {
accept: "application/json" ,
"x-api-key" : apiKey ,
},
};
fetch ( url , options )
. then (( res ) => res . json ())
. then (( json ) => console . log ( json ))
. catch (( err ) => console . error ( "error:" + err ));
Here is an example response returned from the API call above:
{
"id" : "49b9e141-8fd8-45dc-9646-13a3439c6f20" ,
"actionId" : "49b9e141-8fd8-45dc-9646-13a3439c6f20" ,
"nftMetadata" : {
"name" : "Snowflake Funk" ,
"image" : "ipfs://QmYA9HyvoPmxvsMx216MFkoydtrA1sSxX5A5ixeu5S9VKF" ,
"description" : "A disco song for the winter holidays"
},
"ipAssetMetadata" : {
"title" : "Snowflake Funk" ,
"createdAt" : "2025-02-11T11:13:00" ,
"creators" : [
{
"name" : "John Doe" ,
"email" : "john.doe@example.com" ,
"crossmintUserLocator" : "email:john.doe@example.com:story-testnet" ,
"contributionPercent" : 100
}
],
"media" : [
{
"name" : "Snowflake Funk" ,
"url" : "https://cdn1.suno.ai/c001fd6e-d6cd-474f-a7b6-6e6a9b3e2515.mp3" ,
"mimeType" : "audio/mpeg"
}
],
"attributes" : [
{
"key" : "Suno Artist" ,
"value" : "InfluentialCoda427"
},
{
"key" : "Source" ,
"value" : "Suno.com"
}
],
"ipType" : "music"
},
"licenseTerms" : [
{
"type" : "non-commercial-social-remixing" ,
"uri" : ""
}
],
"onChain" : {
"chain" : "story-testnet" ,
"contractAddress" : "0x82a72DfFb175DF8AB6d3C2E3888D5314a50C30D0" ,
"status" : "success" ,
"ipAssetId" : "0xe20936B1C974E7C550b483243719A1B1886D2c6c" ,
"tokenId" : "1" ,
"txId" : "0x4e505bcd429960d3031bd8d1f27bb7ffd2cfa251498c12c16cf2375a14d2bd51" ,
"owner" : "0x1a042BBEFb116072E6AEF8304f9B7D15aA2b4BCF" ,
"explorerLink" : "https://aeneid.explorer.story.foundation/ipa/0xe20936B1C974E7C550b483243719A1B1886D2c6c"
}
}
6. Update an IP Asset
If needed, you can update an IP asset:
const apiKey = "YOUR_API_KEY" ;
const env = "staging" ; // or "www"
const collectionId = "YOUR_COLLECTION_ID" ;
const ipAssetId = "YOUR_IP_ASSET_ID" ;
const url = `https:// ${ env } .crossmint.com/api/v1/ip/collections/ ${ collectionId } /ipassets/ ${ ipAssetId } ` ;
const options = {
method: "PATCH" ,
headers: {
accept: "application/json" ,
"content-type" : "application/json" ,
"x-api-key" : apiKey ,
},
body: JSON . stringify ({
ipAssetMetadata: {
title: "Snowflake Funk" ,
createdAt: "2025-02-11T11:13:00" ,
ipType: "music" ,
creators: [
{
name: "John Doe" ,
email: "john.doe@example.com" ,
crossmintUserLocator: "email:john.doe@example.com:story-testnet" ,
contributionPercent: 90 ,
},
{
name: "Frank L" ,
crossmintUserLocator: "email:frank.l@example.com:story-testnet" ,
contributionPercent: 10 ,
},
],
},
}),
};
fetch ( url , options )
. then (( res ) => res . json ())
. then (( json ) => console . log ( json ))
. catch (( err ) => console . error ( "error:" + err ));
Here is an example response returned from the API call above:
{
"id" : "75a45061-febb-4344-84d6-959276a5696a" ,
"actionId" : "75a45061-febb-4344-84d6-959276a5696a" ,
"nftMetadata" : {
"name" : "Snowflake Funk" ,
"image" : "ipfs://QmYA9HyvoPmxvsMx216MFkoydtrA1sSxX5A5ixeu5S9VKF" ,
"description" : "A disco song for the winter holidays"
},
"ipAssetMetadata" : {
"title" : "Snowflake Funk" ,
"createdAt" : "2025-02-11T11:13:00" ,
"creators" : [ ... ],
"ipType" : "music"
},
"licenseTerms" : [ { "type" : "non-commercial-social-remixing" , "uri" : "" } ],
"onChain" : {
"chain" : "story-testnet" ,
"contractAddress" : "0x82a72DfFb175DF8AB6d3C2E3888D5314a50C30D0" ,
"status" : "pending"
}
}
Learn More
For more detailed information about IP assets, please refer to the API reference: