# Get Usage Source: https://docs.crossmint.com/api-reference/admin/get-usage get /v1-alpha1/projects/{projectId}/usage Get usage data for a project. **API scope required** `projects:usage.read` # Get Action Status Source: https://docs.crossmint.com/api-reference/common/get-action-status get /2022-06-09/actions/{actionId} Use this API to poll for the status of asynchonous actions such as NFT mints, transfers, etc. **API scope required**: `nfts.create` The shape of the data property in the `200` response for this API depends on the type of action initially performed. For example, minting/burning an NFT, creating/updating a collection or template, or NFT transfers. The `action` property will indicate the type of action originally performed and will be one of: * `nfts.create` * `nfts.delete` * `nfts.update` * `collections.create` * `collections.update` * `wallets:nfts.transfer` # Check Token Support Source: https://docs.crossmint.com/api-reference/headless/check-token-support GET /v1-alpha2/tokens/{tokenLocator} Get a token by its locator # Create Order Source: https://docs.crossmint.com/api-reference/headless/create-order post /2022-06-09/orders Creates a new order that can be used to complete a headless checkout. **API scope required**: `orders.create` # Edit Order Source: https://docs.crossmint.com/api-reference/headless/edit-order patch /2022-06-09/orders/{orderId} Edit an existing order. You can update the recipient, the payment method, and/or the locale. **API scope required**: `orders.update` # Get Order Source: https://docs.crossmint.com/api-reference/headless/get-order get /2022-06-09/orders/{orderId} Get specific order by ID. **API scope required**: `orders.read` # Introduction Source: https://docs.crossmint.com/api-reference/introduction Explore the APIs and test them live from the browser This section provides a detailed guide for each of the APIs, with sample code and responses. ## Testing the APIs from the browser The reference pages allow you to call the APIs directly from the browser. To get started: 1. Create a developer account on the [Staging](https://staging.crossmint.com/console) or [Production](https://www.crossmint.com/console) consoles. Read more about the environments [here](/introduction/platform/staging-vs-production). 2. Create an [API key](/introduction/platform/api-keys) from the `API keys` tab on the console, with the permissions required for the APIs you want to use. 3. From the page of your API of choice, insert the right API key in the authorization slot, introduce the different parameters, and call "Send". 4. (Optional) To call APIs in the production environment, find the API endpoint selector (`⌄`) next to the endpoint URL, and change it to `www.crossmint.com/api`. The following guide will show you how to create a wallet and mint an NFT into it within 5 minutes. For this, make sure your API key has the scopes `wallets.create`, and `nfts.create`. Follow the next steps to create a wallet within 5 minutes: Navigate to create wallet endpoint screenshot with light theme Navigate to create wallet endpoint screenshot with dark theme Set environment URL screenshot Set environment URL screenshot Set x-api-key screenshot Set x-api-key screenshot You may add any additional properties. Each API reference page includes the full list of properties and admissible values. Set body params screenshot with light theme Set body params screenshot with dark theme Scroll back to the top of the page and click the blue `Send` button to trigger the API call. Send request screenshot with light theme Send request screenshot with dark theme Here is an example response object: create user wallet response screenshot with light theme create user wallet response screenshot with dark theme **Success!** The next guide will show you how to mint an NFT into this wallet and view the content. In the previous guide, you created a wallet. Now you will deliver an NFT into it and read the wallet's content. {/* prettier-ignore */}

Open in a new tab here: /api-reference/minting/nfts/mint-nft

Mint NFT in api playground screenshot with light theme Mint NFT in api playground screenshot with light theme
This is a default collection associated to your account. You can create new ones using the [Create Collections](/minting/nfts/integrate/create-collections) API. Enter collectionId screenshot with light theme Enter collectionId screenshot with dark theme The selector to choose between the different metadata option can be hard to spot. Look closely at the screenshots below to see where it is. Select EVM metadata URL option screenshot with light theme Select EVM metadata URL option screenshot with dark theme
Enter metadata URL screenshot with light theme Enter metadata URL screenshot with dark theme
You can provide your own or use this example URL: ```bash metadata URL https://bafkreidbf4jpxpecwezjbagwmua5qv62ifhhtzsspoml7zls6iq6ms4byi.ipfs.nftstorage.link/ ``` ```json example JSON { "name": "Crossmint Test NFT", "description": "Created with the Crossmint minting API", "image": "https://bafkreiexjl6kw4khdxkrt6dojgacscnzvrys47t472l2t7d6r2ss65kifq.ipfs.nftstorage.link/", "external_url": "https://docs.crossmint.com", "attributes": [ { "trait_type": "contract", "value": "ERC-721" }, { "trait_type": "background", "value": "black" } ] } ```
This URL must point to a valid JSON file that adheres to [EVM metadata standards](/minting/nfts/integrate/define-metadata). Enter metadata url screenshot with light theme Enter metadata url screenshot with dark theme
There are two options for the `recipient` parameter. The first enables minting to an email address. The second enables minting directly to a wallet address. ```javascript email recipient // format email:: // example email:testy@crossmint.xyz:polygon ``` ```javascript wallet recipient // format :
// example polygon:0x0359Cd99FD20e853a85489DFC93EaDFeF7461590 ```
Enter your own email address on this step and you can login to see your NFT in the Crossmint wallet later, which can be accessed from [crossmint.com](https://crossmint.com) or [staging.crossmint.com](https://staging.crossmint.com) if you are in staging. Set recipient screenshot with light theme Set recipient screenshot with dark theme This will prevent unnecessary uploading of files that are already pinned to IPFS. {/* prettier-ignore */}

Crossmint has a 10MB re-upload size limit. For larger files, upload your media to IPFS, create a metadata.json as shown above, submit the metadata file's URL, and ensure `reuploadLinkedFiles` is set to `false`.

The default option is `true`.

Set reuploadLinkedFiles to false screenshot with light theme Set reuploadLinkedFiles to false screenshot with dark theme
Scroll back to the top of the page and click the blue `Send` button to trigger the API call. Click send screenshot with light theme Click send screenshot with dark theme Here is an example response object: mint nft example response screenshot with light theme mint nft example response screenshot with dark theme If you followed this guide closely you can view the NFT in the staging wallet at [https://staging.crossmint.com/user/collection](https://staging.crossmint.com/user/collection). If you minted directly to a wallet address you can view the NFT in that application. Ensure you are accessing it from a testnet if you used staging. ## Next Steps Test any other API directly from the reference page. You can find more information about the products on the [documentation guides](/introduction). # Create IP Asset Source: https://docs.crossmint.com/api-reference/ip/create-ip-asset post /v1/ip/collections/{collectionId}/ipassets Create a new IP Asset **API scope required**: `nfts.create` This API is still under development. Contact support for early access.{" "} # Create IP Asset (Idempotent) Source: https://docs.crossmint.com/api-reference/ip/create-ip-asset-idempotent put /v1/ip/collections/{collectionId}/ipassets/{customerFacingId} Create a new IP Asset with a pre-computed id, or get an existing one if the id already exists **API scope required**: `nfts.create` This API is still under development. Contact support for early access.{" "} # Create IP Collection Source: https://docs.crossmint.com/api-reference/ip/create-ip-collection post /v1/ip/collections Create a new collection with a pre-computed id, or get an existing one if the id already exists **API scope required**: `collections.create` This API is still under development. Contact support for early access. # Create IP Collection (Idempotent) Source: https://docs.crossmint.com/api-reference/ip/create-ip-collection-idempotent put /v1/ip/collections/{collectionId} Create a new collection with a pre-computed id, or get an existing one if the id already exists **API scope required**: `collections.create` This API is still under development. Contact support for early access. # Get All IP Collections Source: https://docs.crossmint.com/api-reference/ip/get-all-ip-collections get /v1/ip/collections Get all collections associated with the Developer Project **API scope required**: `collections.read` This API is still under development. Contact support for early access. # Get IP Action Source: https://docs.crossmint.com/api-reference/ip/get-ip-action get /v1/ip/actions/{actionId} Get an action by its id **API scope required**: `nfts.create` This API is still under development. Contact support for early access. # Get IP Asset Source: https://docs.crossmint.com/api-reference/ip/get-ip-asset get /v1/ip/collections/{collectionId}/ipassets/{customerFacingId} Get a single IP Asset **API scope required**: `nfts.read` This API is still under development. Contact support for early access.{" "} # Get IP Assets in Collection Source: https://docs.crossmint.com/api-reference/ip/get-ip-assets get /v1/ip/collections/{collectionId}/ipassets Get all IP Assets in a collection **API scope required**: `nfts.read` This API is still under development. Contact support for early access.{" "} # Get IP Collection Source: https://docs.crossmint.com/api-reference/ip/get-ip-collection get /v1/ip/collections/{collectionId} Get a collection by its id deployed on the Story chain **API scope required**: `collections.read` This API is still under development. Contact support for early access. # Get IP Asset Graph Source: https://docs.crossmint.com/api-reference/ip/get-ip-graph get /v1/ip/graph/{ipAssetId} Get the graph of an IP Asset, by default it will fetch the first level of parents and children (depth = 1). You can customize the depth using the query parameter 'depth' to a maximum of 3. Maximum 100 parents or children will be returned for each level. The ipAssetId parameter should be the Story Protocol asset ID (not the Crossmint ID). Must start with '0x' followed by hexadecimal characters. **API scope required**: `nfts.read` This API is still under development. Contact support for early access.{" "} # Get IP Asset License Source: https://docs.crossmint.com/api-reference/ip/get-ip-license get /v1/ip/licenses/{ipassetId} Get the licenses of an IP Asset The ipassetId parameter should be the Story Protocol asset ID (not the Crossmint ID). Must start with '0x' followed by hexadecimal characters. **API scope required**: `nfts.read` This API is still under development. Contact support for early access.{" "} # Update IP Asset Source: https://docs.crossmint.com/api-reference/ip/update-ip-asset patch /v1/ip/collections/{collectionId}/ipassets/{customerFacingId} Update an existing IP Asset **API scope required**: `nfts.update` This API is still under development. Contact support for early access.{" "} # Create Collection Source: https://docs.crossmint.com/api-reference/minting/collection/create-collection post /2022-06-09/collections/ Create a collection that you can mint NFTs/SFTs from **API scope required**: `collections.create` # Create Collection (Idempotent) Source: https://docs.crossmint.com/api-reference/minting/collection/create-collection-idempotent put /2022-06-09/collections/{collectionId} Create a collection that you can mint NFTs/SFTs from. This API is idempotent, if you call it multiple times with the same ID, only one will be created. **API scope required**: `collections.create` # Get All Collections Source: https://docs.crossmint.com/api-reference/minting/collection/get-all-collections get /2022-06-09/collections/ List all collections created under the current Crossmint project **API scope required**: `collections.read` For Solana collections the `onChain.contractAddress` property will be named `onChain.mintAddress` {/* overriding response here because the auto parsing of deeply nested yaml leaves out too much */} ```json 200 { "results": [ { "id": "bb691876-edb3-404c-af3e-c019b8e2ed2c", "metadata": { "name": "Test Collection", "description": "Test", "imageUrl": "ipfs://QmVocoiYXZLAtheEHV3VF8w4pa68bkPutT8cQZdMrrpzxh", "symbol": "XMINT" }, "fungibility": "non-fungible", "onChain": { "chain": "polygon", "type": "erc-721", "contractAddress": "0x9564bD85f3D5677D86244dDb06F06bbD22D9d0DB" }, "supplyLimit": 95, "payments": { "price": "0.001", "recipientAddress": "0x6C3b3225759Cbda68F96378A9F0277B4374f9F06" } } ] } ``` # Get Base URI Source: https://docs.crossmint.com/api-reference/minting/collection/get-base-uri get /v1-alpha1/minting/collections/{collectionId}/base-uri Get the Base URI of a collection as it appears onchain. **API scope required**: `collections.read` # Get Collection Info Source: https://docs.crossmint.com/api-reference/minting/collection/get-collection get /2022-06-09/collections/{collectionId} Get information about a specific collection. **API scope required**: `collections.read` For Solana collections the `onChain.contractAddress` property will be named `onChain.mintAddress` # Get Royalties Configuration Source: https://docs.crossmint.com/api-reference/minting/collection/get-royalties-configuration get /v1-alpha1/minting/collections/{collectionId}/royalties Fetch the royalty configuration for a collection, from its current state in the blockchain. This API is only supported on EVM chains. If you call GET too soon after PUT/DELETE, you may not yet see your latest changes, as they can take a few seconds to record on the blockchain. **API scope required**: `collections.read` # Get Transferability Source: https://docs.crossmint.com/api-reference/minting/collection/get-transferability get /v1-alpha1/minting/collections/{collectionId}/transferable Get the transferable status of a collection. This API is supported on EVM and Aptos chains. You must contact sales to gain access to this API. **API scope required**: `collections.read` # Remove Royalties Source: https://docs.crossmint.com/api-reference/minting/collection/remove-royalties delete /v1-alpha1/minting/collections/{collectionId}/royalties Remove all royalties from a given collection. No new NFT sales will yield royalties to the creator. This API is only supported on EVM Chains. **API scope required**: `collections.update` # Set Base URI Source: https://docs.crossmint.com/api-reference/minting/collection/set-base-uri put /v1-alpha1/minting/collections/{collectionId}/base-uri Update the Base URI of a collection. Setting the baseURI enables excluding the metadata param when minting. Tokens minted without the metadata param will have a tokenURI of: `{BASE_URI}/{TOKEN_ID}` This API is currently only supported on EVM Chains. **API scope required**: `collections.update` # Set Royalties Source: https://docs.crossmint.com/api-reference/minting/collection/set-royalties put /v1-alpha1/minting/collections/{collectionId}/royalties Configure royalties for all NFTs in a collection. This API is only supported for EVM chains and implements the EIP-2981 standard. **API scope required**: `collections.update` # Set Transferability Source: https://docs.crossmint.com/api-reference/minting/collection/set-transferability put /v1-alpha1/minting/collections/{collectionId}/transferable Update the transferable status of a collection. This API is supported on EVM and Aptos chains. You must contact sales to gain access to this API. **API scope required**: `collections.update` # Update Collection Source: https://docs.crossmint.com/api-reference/minting/collection/update-collection patch /2022-06-09/collections/{collectionId} Update the sales details of a collection **API scope required**: `collections.update` # Burn NFT Source: https://docs.crossmint.com/api-reference/minting/nfts/burn-nft delete /2022-06-09/collections/{collectionId}/nfts/{id} Burn a minted NFT. **API scope required**: `nfts.delete` # Edit NFT Source: https://docs.crossmint.com/api-reference/minting/nfts/edit-nft patch /2022-06-09/collections/{collectionId}/nfts/{id} Edit a minted NFT's metadata on IPFS. If you are using a custom baseURI, invoking this will overwrite the specific tokenURI for the edited token. **API scope required**: `nfts.update` # Get All NFTs Source: https://docs.crossmint.com/api-reference/minting/nfts/get-nfts get /2022-06-09/collections/{collectionId}/nfts Get a list of all the NFTs in a given collection. **API scope required**: `nfts.read` # Mint NFT Source: https://docs.crossmint.com/api-reference/minting/nfts/mint-nft post /2022-06-09/collections/{collectionId}/nfts Mint your NFTs and deliver them to a web3 wallet or an email address **API scope required**: `nfts.create` # Mint NFT with ID Source: https://docs.crossmint.com/api-reference/minting/nfts/mint-nft-idempotent put /2022-06-09/collections/{collectionId}/nfts/{id} This pathway allows you to mint NFTs and guarantee idempotency to ensure you never double mint for the same NFT. **API scope required**: `nfts.create` Subsequent requests to this endpoint with the same `id` in the path will ***not*** mint additional NFTs. Furthermore, the success responses (with status code 200) will be different once the initial request has completed and includes the metadata for the minted NFT. ```json EVM { "id": "", "metadata": { "name": "", "image": "", "description": "" }, "onChain": { "status": "", "tokenId": "", "owner": "", "txId": "", "contractAddress": "", "chain": "" }, "actionId": "" } ``` ```json Solana { "id": "", "metadata": { "name": "", "symbol": "", "description": "", "seller_fee_basis_points": 0, "image": "", "attributes": [], "properties": {} }, "onChain": { "status": "success", "mintHash": "", "txId": "", "owner": "", "chain": "solana" }, "actionId": "" } ``` # Mint SFT Source: https://docs.crossmint.com/api-reference/minting/nfts/mint-sft post /2022-06-09/collections/{collectionId}/sfts Mint your SFTs and deliver them to a web3 wallet or an email address **API scope required**: `nfts.create` # Mint Status Source: https://docs.crossmint.com/api-reference/minting/nfts/mint-status get /2022-06-09/collections/{collectionId}/nfts/{id} Get the status and associated information for a mint operation. **API scope required**: `nfts.read` ```json 200 EVM { "id": "", "metadata": { "name": "", "image": "", "description": "" }, "onChain": { "status": "success", "tokenId": "", "owner": "", "txId": "", "contractAddress": "", "chain": "polygon" }, "action": "https://staging.crossmint.com/api/2022-06-09/actions/" } ``` ```json 200 Solana { "id": "", "metadata": { "name": "", "symbol": "", "seller_fee_basis_points": 0, "properties": {}, "description": "", "image": "", "attributes": [] }, "onChain": { "status": "success", "mintHash": "", "txId": "", "owner": "", "chain": "solana" }, "action": "https://staging.crossmint.com/api/2022-06-09/actions/" } ``` # Create Template Source: https://docs.crossmint.com/api-reference/minting/template/create-template post /2022-06-09/collections/{collectionId}/templates Create a token template, that NFTs or SFTs may be minted from **API scope required**: `nfts.create` # Create Template with ID Source: https://docs.crossmint.com/api-reference/minting/template/create-template-idempotent put /2022-06-09/collections/{collectionId}/templates/{templateId} Create a token template with preconfigured metadata **API scope required**: `nfts.create` # Delete Template Source: https://docs.crossmint.com/api-reference/minting/template/delete-template delete /2022-06-09/collections/{collectionId}/templates/{templateId} Delete a Token template. **API scope required**: `nfts.delete` # Edit Template Source: https://docs.crossmint.com/api-reference/minting/template/edit-template patch /2022-06-09/collections/{collectionId}/templates/{templateId} Edit a Token template. **API scope required**: `nfts.update` # Get All Templates Source: https://docs.crossmint.com/api-reference/minting/template/get-all-templates get /2022-06-09/collections/{collectionId}/templates Get all of the templates for a collection **API scope required**: `nfts.read` # Get Template Source: https://docs.crossmint.com/api-reference/minting/template/get-template get /2022-06-09/collections/{collectionId}/templates/{templateId} Fetch the contents of a token template. **API scope required**: `nfts.read` # Issue Credential Source: https://docs.crossmint.com/api-reference/verifiable-credentials/credentials/issue-credential post /v1-alpha1/credentials/templates/{templateId}/vcs Issue a credential and deliver it to a wallet or email address. **API scope required** `credentials.create` # Get Credential by Credential ID Source: https://docs.crossmint.com/api-reference/verifiable-credentials/credentials/retrieve-credential-by-id get /v1-alpha1/credentials/{id} Get a verifiable credential by the ID associated with it. This ID will have the format: `urn:uuid:`. For example: `urn:uuid:64f9877d-a19a-4205-8d61-f8c2abed5766` **API scope required** `credentials.read`. This enpoint will work also with a client side API key. # Get Credential by NFT ID Source: https://docs.crossmint.com/api-reference/verifiable-credentials/credentials/retrieve-credential-by-nft get /v1-alpha1/credentials/templates/{collectionId}/nfts/{id}/credentials Get a verifiable credential by the ID associated with the minted NFT. This ID will have the format: ``. For example: `d7eb777b-e9b4-4f34-ab5f-ce199111166a` **API scope required** `credentials.read`. This endpoint will not work with a client side API key. # Get Credential by NFT Locator Source: https://docs.crossmint.com/api-reference/verifiable-credentials/credentials/retrieve-credential-by-nft-locator get /v1-alpha1/nfts/{nftLocator}/credentials Get a verifiable credential by the NFT locator. This locator will have the format: `::`. For example: `polygon:0x1234abcde...:1` **API scope required** `credentials.read`. This enpoint will work also with a client side API key. # null Source: https://docs.crossmint.com/api-reference/verifiable-credentials/credentials/retrieve-credential-nfts get /api/v1-alpha1/wallets/{walletLocator}/credential_nfts # Revoke Credential Source: https://docs.crossmint.com/api-reference/verifiable-credentials/credentials/revoke-credential DELETE /v1-alpha1/credentials/{id} Revoke a verifiable credential by the credential ID. This involves burning the associated nft. This ID will have the format: `urn:uuid:`. For example: `urn:uuid:64f9877d-a19a-4205-8d61-f8c2abed5766` **API scope required** `credentials.create`. # Verify Credential Source: https://docs.crossmint.com/api-reference/verifiable-credentials/credentials/verify-credential post /v1-alpha1/credentials/verification/verify Verify that a verifiable credential is valid. **API scope required** `credentials.read` It is impractical to use the API Playground to verify a credential. Instead you can copy the sample code for your preferred language in the righthand sidebar and fill in the JSON of the credential you intend to verify. Here is an example of how to verify a credential using javascript: ```javascript verifyVC.js const options = { method: "POST", headers: { "X-API-KEY": "YOUR_API_KEY", "Content-Type": "application/json", }, body: '{"credential": {"id":"urn:uuid:e31316b6-3be1-49af-a95f-c7f4c3f52aa1","credentialSubject":{"course":"Blockchain 101","passed":true,"id":"did:polygon:0x6C3b3225759Cbda68F96378A9F0277B4374f9F06"},"expirationDate":"2034-02-03","nft":{"tokenId":"1","chain":"polygon","contractAddress":"0xdC444A3F4768185497Dae6250E2F348b99bE89F3"},"issuer":{"id":"did:polygon:0xa22CaDEdE67c11dc1444E507fDdd9b831a67aBd1"},"type":["VerifiableCredential","65c15243e9bee8deac219d57"],"issuanceDate":"2024-02-05T23:21:32.641Z","@context":["https://www.w3.org/2018/credentials/v1","https://github.com/haardikk21/ethereum-eip712-signature-2021-spec/blob/main/index.html","DUMMY_CROSSMINT/65c15243e9bee8deac219d57"],"proof":{"verificationMethod":"did:polygon:0xa22CaDEdE67c11dc1444E507fDdd9b831a67aBd1#ethereumAddress","ethereumAddress":null,"created":"2024-02-05T23:22:24.058Z","proofPurpose":"assertionMethod","type":"EthereumEip712Signature2021","proofValue":"0x748a55d9770cbc6ef16689f0d9547355e288bcce03a8949a32d2aac59244cb9e08cbf54c960bc00d133fc51e6651a4ac1366aeda320dd121777118a4e74980631b","eip712":{"domain":{"name":"Krebit","version":"0.1","chainId":4,"verifyingContract":"0xD8393a735e8b7B6E199db9A537cf27C61Aa74954"},"types":{"VerifiableCredential":[{"name":"@context","type":"string[]"},{"name":"type","type":"string[]"},{"name":"id","type":"string"},{"name":"issuer","type":"Issuer"},{"name":"credentialSubject","type":"CredentialSubject"},{"name":"issuanceDate","type":"string"},{"name":"expirationDate","type":"string"},{"name":"nft","type":"Nft"}],"CredentialSubject":[{"name":"id","type":"string"},{"name":"course","type":"string"},{"name":"passed","type":"bool"}],"Issuer":[{"name":"id","type":"string"}],"Nft":[{"name":"tokenId","type":"string"},{"name":"contractAddress","type":"string"},{"name":"chain","type":"string"}]},"primaryType":"VerifiableCredential"}}}}', }; // note the gigantic VC JSON string in the body property fetch("https://staging.crossmint.com/api/v1-alpha1/credentials/verification/verify", options) .then((response) => response.json()) .then((response) => console.log(response)) .catch((err) => console.error(err)); ``` ```json 200 valid { "isValid": true, "error": null } ``` ```json 200 revoked { "isValid": false, "error": "Credential Revoked" } ``` ```json 200 expired { "isValid": false, "error": "Credential expired at " } ``` ```json 200 invalid_proof { "isValid": false, "error": "Invalid proof" } ``` # Create Credential template Source: https://docs.crossmint.com/api-reference/verifiable-credentials/templates/create-template post /v1-alpha1/credentials/templates/ Create a template, similar to an NFT collection, for issuing verifiable credentials. **API scope required** `credentials:template.create` # Create Credential Type with Name Source: https://docs.crossmint.com/api-reference/verifiable-credentials/types/create-named-type put /v1-alpha1/credentials/types/{typeName} Create or import a type with a given name. This is how you define a custom credential schema. **API scope required** `credentials.create` # Create Credential Type Source: https://docs.crossmint.com/api-reference/verifiable-credentials/types/create-type post /v1-alpha1/credentials/types Create or import a credential type with a random UUID. This is how you define a custom credential schema. **API scope required** `credentials.create` # Get a Credential Type Source: https://docs.crossmint.com/api-reference/verifiable-credentials/types/get-type get /v1-alpha1/credentials/types/{typeName} Get the schema of a given type by name (or id) **API scope required** `credentials.read` # Approve Signature Source: https://docs.crossmint.com/api-reference/wallets/approve-signature post /2022-06-09/wallets/{walletLocator}/signatures/{signatureId}/approvals Submit approval for a signature to sign a message or typed data. **API scope required**: `wallets:signatures.create` # Approve Transaction Source: https://docs.crossmint.com/api-reference/wallets/approve-transaction post /2022-06-09/wallets/{walletLocator}/transactions/{transactionId}/approvals Submit approval signature for a pending transaction. Required for transactions using external signers. **API scope required**: `wallets:transactions.sign` # Create Signature Source: https://docs.crossmint.com/api-reference/wallets/create-signature post /2022-06-09/wallets/{walletLocator}/signatures Creates a new signature for signing messages or typed data. **API scope required**: `wallets:signatures.create` # Create Transaction Source: https://docs.crossmint.com/api-reference/wallets/create-transaction post /2022-06-09/wallets/{walletLocator}/transactions Creates a new transaction for the specified wallet. Transaction will be automatically broadcast once it has all necessary approvals. **API scope required**: `wallets:transactions.create` # Create Wallet Source: https://docs.crossmint.com/api-reference/wallets/create-wallet post /2022-06-09/wallets Creates a new wallet of specified type. If called with an idempotency key or for a user who already has a wallet, returns existing wallet. When linkedUser is provided, subsequent calls with the same linkedUser will return the existing wallet. Supports both custodial and non-custodial wallet types. **API scope required**: `wallets.create` # Fund Wallet Source: https://docs.crossmint.com/api-reference/wallets/fund-wallet post /v1-alpha2/wallets/{walletLocator}/balances Send funds to a wallet. **API scope required**: `wallets.fund` This endpoint is only available in **staging** and only supports USDC and USDXM. # Get NFTs from Wallet Source: https://docs.crossmint.com/api-reference/wallets/get-nfts-from-wallet get /2022-06-09/wallets/{identifier}/nfts Fetch the NFTs in a provided wallet **API scope required**: `wallets:nfts.read` This API enables fetching the NFTs for a provided wallet address and chain. The response will be slightly different between EVM, Solana, and other wallets. See the example responses to the right. {/* The below section overrides the response examples in the .yaml file because mintlify doesn't parse out multiple options */} ```json 200 EVM [ { "chain": "", "contractAddress": "", "tokenId": "", "metadata": { "attributes": [], "collection": {}, "description": "", "image": "", "animation_url": "", "name": "" }, "locator": "", "tokenStandard": "" } ] ``` ```json 200 EVM (with subscription) [ { "chain": "", "contractAddress": "", "tokenId": "", "metadata": { "attributes": [], "collection": {}, "description": "", "image": "", "animation_url": "", "name": "" }, "locator": "", "tokenStandard": "", "subscription": { "expiresAt": "" } } ] ``` ```json 200 Solana [ { "chain": "", "mintHash": "", "metadata": { "name": "", "description": "", "image": "", "attributes": [] }, "locator": "" } ] ``` {/* prettier-ignore */} {/* ```json 200 Cardano [ { "chain": "", "assetId": "", "metadata": { "assetId": "", "name": "", "description": "", "image": "", "attributes": [] }, "locator": "" } ] ``` prettier-ignore \*/} ```json 400 { "error": "" } ``` # Get Signature Source: https://docs.crossmint.com/api-reference/wallets/get-signature get /2022-06-09/wallets/{walletLocator}/signatures/{signatureId} Retrieves details about a specific signature by its ID. **API scope required**: `wallets:signatures.read` # Get All Signatures Source: https://docs.crossmint.com/api-reference/wallets/get-signatures get /2022-06-09/wallets/{walletLocator}/signatures Retrieves all signatures associated with the specified wallet. **API scope required**: `wallets:signatures.read` # Get Delegated Signer Source: https://docs.crossmint.com/api-reference/wallets/get-signer get /2022-06-09/wallets/{walletLocator}/signers/{signer} Retrieve details about a specific delegated signer by its locator. **API scope required**: `wallets.read` # Get Transaction Source: https://docs.crossmint.com/api-reference/wallets/get-transaction get /2022-06-09/wallets/{walletLocator}/transactions/{transactionId} Retrieves the current status and details of a specific transaction. **API scope required**: `wallets:transactions.read` # Get Wallet Transactions Source: https://docs.crossmint.com/api-reference/wallets/get-transactions get /2022-06-09/wallets/{walletLocator}/transactions Retrieves all transactions associated with the specified wallet. **API scope required**: `wallets:transactions.read` # Get Wallet Balance Source: https://docs.crossmint.com/api-reference/wallets/get-wallet-balance get /v1-alpha2/wallets/{walletLocator}/balances Get the balance of a wallet for a given chain and currency **API scope required**: `wallets:balance.read` # Get Wallet By Locator Source: https://docs.crossmint.com/api-reference/wallets/get-wallet-by-locator get /2022-06-09/wallets/{walletLocator} Retrieves a wallet by its locator (address or user identifier and wallet type) **API scope required**: `wallets.read` # Register Delegated Signer Source: https://docs.crossmint.com/api-reference/wallets/register-delegated-key post /2022-06-09/wallets/{walletLocator}/signers Register a delegated key for a smart wallet with optional restrictions around permissions and expiry date. **API scope required**: `wallets.create` # Transfer Token Source: https://docs.crossmint.com/api-reference/wallets/transfer-token post /unstable/wallets/{walletLocator}/tokens/{tokenLocator}/transfers Sends a token of any type from this wallet to a recipient # Customization Source: https://docs.crossmint.com/authentication/customization Customize the authentication flow and email templates With Crossmint Auth, you can customize the authentication flow and email templates with your brand's identity. ## Modal Customization The `CrossmintAuthProvider` component allows you to customize the authentication modal appearance and content. ```tsx By continuing, you agree to our Terms of Service and{" "} Privacy Policy

} appearance={{ spacingUnit: "8px", borderRadius: "12px", colors: { inputBackground: "#fffdf9", buttonBackground: "#fffaf2", border: "#835911", background: "#FAF5EC", textPrimary: "#5f2c1b", textSecondary: "#835911", textLink: "#1400cb", danger: "#ff3333", accent: "#602C1B", }, }} > {children}
``` ### Modal props | Prop | Type | Description | | -------------------- | --------------------- | -------------------------------------------------------------------- | | `authModalTitle` | `string` | Custom title displayed at the top of the authentication modal | | `termsOfServiceText` | `string \| ReactNode` | Custom terms of service text displayed below the authentication form | | `appearance` | `UIConfig` | Styling configuration for the modal (see example above) | The modal will also use your display name configured in the Crossmint Console. To learn more, see the "Email Customization" section below. ## Embedded Login For a more integrated experience, you can use our embedded login component, which offers flexibility to display the login form in your own modal or as part of a split login screen. ```tsx import { EmbeddedAuthForm, useAuth } from "@crossmint/client-sdk-react-ui"; export default function Home() { const { user, status } = useAuth(); // "in-progress" | "logged-in" | "logged-out" return
{status === "logged-in" ? user.email : }
; } ``` ## Email Customization Email OTP is a login method that allows users to sign in to your app using their email address. They receive a one-time code via email that they can use to log in. You can customize the email template to align with your brand's identity. We **strongly recommend** doing so, as it increases user trust and security. To modify the email template: 1. In the Crossmint Console, click on Settings, and navigate to the **Branding** tab. 2. Here, you can customize: * The **logo** displayed in the email with your logo. * The **display name** textbox to include your brand's name. When customizing email text, avoid using terms like "airdrop", "token", or "crypto" as these can trigger spam filters and hurt email deliverability. ![Customize email template](https://mintlify.s3.us-west-1.amazonaws.com/crossmint/images/minting/delivery-email.jpg) # Introduction Source: https://docs.crossmint.com/authentication/introduction A user management solution tightly integrated with all other Crossmint products Authenticate users using web3 or traditional sign-in methods: * **Email OTP**: passwordless sign-in using a one time code delivered to the user's email. * **Social Accounts**: Sign in with Google, Apple, X, and more. * **Farcaster**: using the [Sign In With Farcaster (SIWF) standard](https://github.com/farcasterxyz/protocol/discussions/110). * **External wallets**: connect with crypto wallets for Web3 authentication. ## Key Characteristics Optionally create or link user wallets with all your user accounts, to have a single, unified identity system across your backend and web3 app. Authorize calls to your backend services, and to any of Crossmint's products: minting, payments, subscriptions, etc. Setup is quick and easy. Launch your app in under 5 minutes. ## Get started Log-in your first user in less than 5 minutes. More detailed guide on how to integrate wallets upon user login. Get and update user information. Contact our sales team for advanced support. # Login Methods Source: https://docs.crossmint.com/authentication/login-methods Customize how users can log in to your app Crossmint Auth supports the following login methods: * **Email OTP**: passwordless sign-in using a one time code delivered to the user's email. * **Social Accounts**: Sign in with Google, X, Farcaster, and more. * **External wallets**: connect with crypto wallets for Web3 authentication. Use `"web3"` for all wallets, `"web3:evm-only"` for Ethereum-compatible wallets only, or `"web3:solana-only"` for Solana wallets only. To customize which login methods are shown to your users, use the `loginMethods` prop when initializing Crossmint Auth. By default, only email and Google are enabled. ```tsx app/providers/Providers.tsx "use client"; import { CrossmintProvider, CrossmintAuthProvider } from "@crossmint/client-sdk-react-ui"; export default function Providers({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` # Quickstart ⚡ Source: https://docs.crossmint.com/authentication/quickstart Sign up your first user in 5 minutes See a full working example with auth and wallets. Run the following command to install the SDK: Add the necessary Crossmint providers to your app. ```tsx next.js "use client"; import { CrossmintProvider, CrossmintAuthProvider, CrossmintWalletProvider, } from "@crossmint/client-sdk-react-ui"; export function Providers({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` ```tsx create-react-app import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import { CrossmintProvider, CrossmintAuthProvider, CrossmintWalletProvider, } from "@crossmint/client-sdk-react-ui"; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( ); ``` ```tsx next.js "use client"; import { useAuth } from "@crossmint/client-sdk-react-ui"; export function AuthButton() { const { login, logout, user, jwt } = useAuth(); return (
{user == null ? ( ) : ( )}

User: {user?.userId}

Email: {user?.email ?? "None"}

Phone Number: {user?.phoneNumber ?? "None"}

Farcaster username: {user?.farcaster?.username ?? "None"}

Google display name: {user?.google?.displayName ?? "None"}

JWT: {jwt}

); } ``` ```tsx create-react-app import { useAuth } from "@crossmint/client-sdk-react-ui"; export function AuthButton() { const { login, logout, user, jwt } = useAuth(); return (
{user == null ? ( ) : ( )}

User: {user?.userId}

Email: {user?.email ?? "Not email"}

Phone Number: {user?.phoneNumber ?? "Not phone number"}

Farcaster username: {user?.farcaster?.username ?? "None"}

Google display name: {user?.google?.displayName ?? "None"}

JWT: {jwt}

); } ```
## Launching in Production For production, the steps are almost identical, but some changes are required: 1. Create a developer account on the [production console](https://www.crossmint.com/console) 2. Create a production client API key on the [API Keys](https://www.crossmint.com/console/projects/apiKeys) page with the API scopes `users.create`, `users.read`, `wallets.read` 3. Replace your test API key with the production key ## Next steps * Read and update [user information](/authentication/user-profile) * Use [webhooks](/authentication/webhooks) to get notified when a user signs up * [Create Smart Wallets on sign up](/wallets/quickstarts/client-side-wallets) # Secure Cookies Source: https://docs.crossmint.com/authentication/security Learn how to securely store Crossmint Auth cookies in your application Authentication tokens are accessible to client-side JavaScript by default through non-HttpOnly cookies. For stronger security, you can store tokens in HttpOnly cookies, which are accessible only on the server side. This setup requires custom routes for refreshing tokens and logging out, using utilities from `@crossmint/server-sdk`. ## 1. Configure Cookie Options When initializing the server SDK, configure secure cookie options: ```typescript import { createCrossmint, CrossmintAuth } from "@crossmint/server-sdk"; const crossmint = createCrossmint({ apiKey: process.env.SERVER_CROSSMINT_API_KEY }); const crossmintAuth = CrossmintAuth.from(crossmint, { cookieOptions: { httpOnly: true, secure: true, // Only send cookies over HTTPS domain: ".yourdomain.com", // Optional: specify cookie domain }, }); ``` **Note:** The `httpOnly` flag only applies to the refresh token. The session JWT remains accessible to client-side JavaScript since it's needed for API calls. ## 2. Custom Routes Implementation ### Token Refresh Route ```typescript import { createCrossmint, CrossmintAuth } from "@crossmint/server-sdk"; import { NextRequest } from "next/server"; const crossmint = createCrossmint({ apiKey: process.env.SERVER_CROSSMINT_API_KEY! }); const crossmintAuth = CrossmintAuth.from(crossmint); export async function POST(request: NextRequest) { return await crossmintAuth.handleCustomRefresh(request); } ``` ```typescript import express from "express"; import { createCrossmint, CrossmintAuth } from "@crossmint/server-sdk"; const app = express() const crossmint = createCrossmint({ apiKey: process.env.SERVER_CROSSMINT_API_KEY! }); const crossmintAuth = CrossmintAuth.from(crossmint); app.post("/api/auth/refresh", async (req, res) => { await crossmintAuth.handleCustomRefresh(req, res); res.end(); }); ``` ### Logout Route ```typescript import { createCrossmint, CrossmintAuth } from "@crossmint/server-sdk"; import { NextRequest } from "next/server"; const crossmint = createCrossmint({ apiKey: process.env.SERVER_CROSSMINT_API_KEY! }); const crossmintAuth = CrossmintAuth.from(crossmint); export async function POST(request: NextRequest) { return await crossmintAuth.logout(request); } ``` ```typescript import express from "express"; import { createCrossmint, CrossmintAuth } from "@crossmint/server-sdk"; const app = express() const crossmint = createCrossmint({ apiKey: process.env.SERVER_CROSSMINT_API_KEY! }); const crossmintAuth = CrossmintAuth.from(crossmint); app.post("/api/auth/logout", async (req, res) => { await crossmintAuth.logout(req, res); res.end(); }); ``` ## 3. Client Configuration Configure the client SDK to use your custom routes: ```typescript import { createCrossmint, CrossmintAuth } from "@crossmint/client-sdk-auth"; const crossmint = createCrossmint({ apiKey: process.env.NEXT_PUBLIC_CLIENT_CROSSMINT_API_KEY! }); const crossmintAuth = CrossmintAuth.from(crossmint, { refreshRoute: "/api/auth/refresh", logoutRoute: "/api/auth/logout" }); ``` ```typescript {children} ``` **Note:** Depending on the framework you're using, you might need to set the whole URL in the `refreshRoute` and `logoutRoute` options. # Server-Side Rendering (SSR) Source: https://docs.crossmint.com/authentication/ssr Integrate Crossmint Auth on the server-side for user authentication and management export const CreateApiKey = ({client, scopes, useJwt}) => { const scopeStr = (scope, index) => { if (index === scopes.length - 1) { return {scope}; } else { return {scope} , ; } }; const localHostInAuthOrigin = client ? "http://localhost:3000" : ""; return

Navigate to the "Integrate" section on the left navigation bar, and ensure you're on the "API Keys" tab.

Within the {client ? "Client-side" : "Server-side"} keys section, click the "Create new key" button in the top right.

{client ?

On the authorized origins section, enter http://localhost:3000 and click "Add origin".

: ""}

Next, check the scopes labeled {scopes.map((scope, index) => {scopeStr(scope, index)})}.

{useJwt ?

Check the "JWT Auth" box.

: ""}

Finally, create your key and save it for subsequent steps.

; }; Crossmint Auth provides a flexible and simple authentication solution for your crypto server-side applications. This guide covers how to integrate and use Crossmint Auth across various server-side frameworks. ## Overview Our server SDK allows you to: * Manage user sessions * Retrieve user profiles * Verify JSON Web Tokens (JWTs) ## Installation First, install the Crossmint Server SDK: ```bash npm install @crossmint/server-sdk ``` ## Initialization To use Crossmint Auth, you need to initialize it with your Server API key. This API requires the `users.read` scope. ```typescript import { createCrossmint, CrossmintAuth } from "@crossmint/server-sdk"; const crossmint = createCrossmint({ apiKey: process.env.SERVER_CROSSMINT_API_KEY }); const crossmintAuth = CrossmintAuth.from(crossmint); ``` ## Core Functionality ### Session Management The `getSession` method validates or refreshes a user's session based on their JWT and refresh token. ```typescript const { jwt, refreshToken, userId } = await crossmintAuth.getSession(req, res); ``` This method: 1. Fetches the current JWT and refresh token from the cookies with keys `crossmint-jwt` and `crossmint-refresh-token`. 2. Checks if the current JWT is valid 3. Refreshes the session if needed 4. Stores the new JWT and refresh token in cookies 5. Returns new auth materials and the user ID For other frameworks that do not expose standard request and response objects, such as Next.js using the App Router, you can pass in an object with `jwt` and `refreshToken` properties instead: ```typescript middleware.ts import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; import { createCrossmint, CrossmintAuth } from "@crossmint/server-sdk"; export async function middleware(request: NextRequest) { // Skip middleware for API routes and static files if (request.nextUrl.pathname.startsWith("/api") || request.nextUrl.pathname.startsWith("/_next")) { return NextResponse.next(); } const response = NextResponse.next(); const jwt = request.cookies.get("crossmint-jwt")?.value; const refreshToken = request.cookies.get("crossmint-refresh-token")?.value; if (refreshToken == null) { return response; } try { const crossmint = createCrossmint({ apiKey: process.env.SERVER_CROSSMINT_API_KEY || "", }); const crossmintAuth = CrossmintAuth.from(crossmint); const { jwt: newJwt, refreshToken: newRefreshToken } = await crossmintAuth.getSession({ jwt, refreshToken, }); // Only update response cookies if tokens have changed if (newJwt !== jwt || newRefreshToken.secret !== refreshToken) { response.cookies.set("crossmint-jwt", newJwt); response.cookies.set("crossmint-refresh-token", newRefreshToken.secret); } } catch (_) { // If auth fails, clear cookies and redirect to home response.cookies.delete("crossmint-jwt"); response.cookies.delete("crossmint-refresh-token"); } return response; } ``` ```typescript getAuthSession.ts import { cookies } from "next/headers"; import { createCrossmint, CrossmintAuth } from "@crossmint/server-sdk"; export async function getAuthSession() { const cookieStore = await cookies(); const jwt = cookieStore.get("crossmint-jwt")?.value; const refreshToken = cookieStore.get("crossmint-refresh-token")?.value; if (refreshToken == null) { return; } try { const crossmint = createCrossmint({ apiKey: process.env.SERVER_CROSSMINT_API_KEY || "", }); const crossmintAuth = CrossmintAuth.from(crossmint); const session = await crossmintAuth.getSession({ jwt, refreshToken, }); return session; } catch (_) { return; } } ``` ```typescript page.tsx import { getAuthSession } from "@/hooks/auth"; import { createCrossmint, CrossmintAuth } from "@crossmint/server-sdk"; export default async function ProtectedRoute() { const session = await getAuthSession(); const userId = session?.userId; if (userId != null) { // Fetch user data or perform authorized actions const crossmint = createCrossmint({ apiKey: process.env.SERVER_CROSSMINT_API_KEY || "", }); const crossmintAuth = CrossmintAuth.from(crossmint); const userData = await crossmintAuth.getUser(userId); return
Welcome, {userData.email}!
; } // Handle unauthenticated state return
Please log in to access this page.
; } ```
For Express.js applications, you can create middleware to handle authentication: ```typescript import express from "express"; const app = express(); const authMiddleware = async (req, res, next) => { try { const { jwt, refreshToken, userId } = await crossmintAuth.getSession(req, res); req.user = { userId }; next(); } catch (error) { res.status(401).json({ error: "Authentication failed" }); } }; app.use(authMiddleware); app.get("/protected", (req, res) => { res.json({ message: "Protected route", userId: req.user.userId }); }); ``` For a basic Node.js server: ```typescript import http from "http"; const server = http.createServer(async (req, res) => { if (req.url === "/protected") { try { const { userId } = await crossmintAuth.getSession(req, res); const userData = await crossmintAuth.getUser(userId); res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ message: "Authenticated", user: userData })); } catch (error) { res.writeHead(401, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Authentication failed" })); } } else { res.writeHead(404); res.end(); } }); server.listen(3000); ```
### User Profile Retrieval Fetch user details using the `getUser` method: ```typescript const user = await crossmintAuth.getUser(userId); ``` This provides access to user information such as email, phone number, and connected accounts (e.g., Google, Farcaster). ### JWT Verification Verify JWTs independently using the `verifyCrossmintJwt` method: ```typescript const decodedJwt = crossmintAuth.verifyCrossmintJwt(token); ``` This is useful for validating tokens in middleware or specific endpoints. We expose our public keys for this purpose at [https://www.crossmint.com/.well-known/jwks.json](https://www.crossmint.com/.well-known/jwks.json). # User Profile Source: https://docs.crossmint.com/authentication/user-profile Retrieve user profile data such as email or social login metadata Crossmint Auth provides a way to retrieve and update user profile data, such as email, social login metadata, and more. The user object contains the following information: * `userId`: User's unique identifier. * `email`: User's email address. * `phoneNumber`: User's phone number. * `google`: User's Google account data. * `farcaster`: User's Farcaster account data. Google Account data contains: * `name`: User's Google display name. * `picture`: User's Google profile picture URL. Farcaster Account data contains: * `fid`: User's Farcaster ID. * `username`: User's Farcaster username. * `bio`: User's Farcaster bio. * `displayName`: User's Farcaster display name. * `pfpUrl`: User's Farcaster profile image URL. * `custody`: User's FID custody address. * `verifications`: List of the user's verified addresses. ## Reading User Data This API requires the `users.read` scope. * **Server side**: Requires a server-side API key. * **Client side**: Requires a client-side API key, and a logged in user. ### Server-side For server-side operations, use the `@crossmint/server-sdk` that provides a `getUser` function to fetch user information. ```typescript import { createCrossmint, CrossmintAuth } from "@crossmint/server-sdk"; const crossmint = createCrossmint({ apiKey: SERVER_API_KEY }); const crossmintAuth = CrossmintAuth.from(crossmint); async function getUser(userId: string) { try { const user = await crossmintAuth.getUser(userId); console.log("User data:", user); } catch (error) { console.error("Error fetching user data:", error); } } ``` ### Response Format ```json { "userId": "123", "email": "test@test.com", // Optional (if user was created with email) "phoneNumber": "123456789", // Optional (if user was created with phone number) "google": { "name": "John Doe", "picture": "https://example.com/picture.jpg" }, "farcaster": { "fid": "123", "username": "johndoe", "bio": "Hello, I'm John Doe", "displayName": "John Doe", "pfpUrl": "https://example.com/pfp.jpg", "custody": "0x1234567890123456789012345678901234567890", "verifications": ["0x1234567890123456789012345678901234567890"] } } ``` ### Client-side Use the `useAuth` react hook from `@crossmint/client-sdk-react-ui` to access the user object. If you would like to use a different framework, [contact support](https://help.crossmint.com/hc/en-us/requests/new) ```typescript React import { useAuth } from "@crossmint/client-sdk-react-ui"; function User() { const { user } = useAuth(); if (!user) { return
Loading user...
; } return (

User

User ID: {user.userId}

Email: {user.email}

Phone Number: {user.phoneNumber}

Google Name: {user.google?.name}

Google Picture: {user.google?.picture}

Farcaster FID: {user.farcaster?.fid}

Farcaster Username: {user.farcaster?.username}

Farcaster Bio: {user.farcaster?.bio}

Farcaster Display Name: {user.farcaster?.displayName}

Farcaster PFP URL: {user.farcaster?.pfpUrl}

Farcaster Custody: {user.farcaster?.custody}

Farcaster Verifications: {user.farcaster?.verifications}

); } ``` # User Webhooks Source: https://docs.crossmint.com/authentication/webhooks Crossmint provides webhooks to notify your application about important user-related events. Below are the details of the available webhooks ### Webhook Events #### `users.created` This webhook is triggered when a new user is created. ##### Payload ```json { "type": "users.created", "status": "success", "data": { "userId": "123", // User's identifier "email": "test@test.com", // Optional (if user was created with email) "phoneNumber": "123456789" // Optional (if user was created with phone number) } } ``` #### `users.updated` This webhook is triggered when a user's email or phone number is successfully updated. ##### Payload ```json { "type": "users.updated", "status": "success", "data": { "actionId": "1234", // Update action identifier "userId": "123", // User identifier "oldEmail": "test@test.com", // Optional (if user was created with email) "newEmail": "test2@test2.com", // Optional (if user was created with email) "oldPhoneNumber": "123456789", // Optional (if user was created with phone number) "newPhoneNumber": "987654321" // Optional (if user was created with phone number) } } ``` ### Handling Webhooks To handle webhooks, you need to set up an endpoint in your application that can receive HTTP POST requests from Crossmint. Here's an example of how you might handle a webhook in a Node.js application: ```javascript // Example webhook handler app.post("/webhooks", (req, res) => { const event = req.body; switch (event.type) { case "users.created": handleUserCreated(event.data); break; case "users.updated": handleUserUpdated(event.data); break; default: console.log(`Unhandled event type: ${event.type}`); } res.sendStatus(200); }); ``` # Changelog Timeline Source: https://docs.crossmint.com/changelog/timeline A complete history of Crossmint's product updates and new features **[Support for sign in with Ethereum and Solana on Crossmint Auth](/changelog/2025-04-03)** Users can now log in with external ethereum and solana wallets, and obtain a Crossmint JWT token for authorization against any backend and Crossmint APIs `features` wallets **[Enhanced Solana Transaction Signing](/changelog/2025-04-03-1)** Fixed signing for keypair in Solana sendTransaction method. This improvement ensures more reliable transaction signing when using Solana keypairs. `improvements` wallets **[Support for cNFT v2 on Core Collections](/changelog/2025-03-27)** Added support for minting cNFT v2 on Core collections, expanding the platform's NFT creation capabilities. This enhancement allows users to perform more sophisticated operations with cNFTs such as burning, freezing and transferring as a collection owner. `features` minting **[Passkey Support for Delegated Signers](/changelog/2025-03-25)** Added passkey support as a delegated signer option for EVM wallets, enhancing security and user experience. This feature allows users to use passkeys as an authentication method for wallet operations. `features` wallets **[New Default Project Form](/changelog/2025-03-24)** Added a new default project form to improve the console onboarding experience. This allows users to easily set their project name on creation, instead of having a default name assigned to them. `features` console **[SUI Chain Integration](/changelog/2025-03-14)** Added support for SUI chain integration. This new chain integration enables users to create and manage collections, mint NFTs, and perform transactions using SUI chain. `new` chains **[Delegated Signer Support for Solana Smart Wallets](/changelog/2025-02-26)** Enhanced Solana smart wallet capabilities with delegated signer support, enabling more flexible wallet management and mainnet functionality. `features` wallets **[Managed Collections Support for Avalanche Blockchain](/changelog/2025-02-18-1)** Added support for managed collections on the Avalanche blockchain, expanding our multi-chain capabilities for NFT management. `features` chains **[Walrus Storage Integration: Decentralized Storage for NFT Metadata](/changelog/2025-02-12)** Introduced Walrus Network as a new decentralized storage solution for efficient and scalable NFT metadata hosting across multiple blockchains. `new` infrastructure **[Sui Blockchain Support for Custodial Wallets](/changelog/2025-01-15)** Added support for Sui blockchain in Custodial Wallets V2, enabling wallet creation and management for this emerging blockchain. `features` wallets **[ApeCoin Chain Integration](/changelog/2025-01-08)** Added support for ApeCoin chain with native APE currency integration. This new chain integration enables users to create and manage collections, mint NFTs, and perform transactions using APE as the native currency. `new` chains **[EVM MPC Wallet Signature Support](/changelog/2025-01-08-4)** Added signature functionality for EVM MPC wallets, enhancing the security and capabilities of our wallet infrastructure for Ethereum Virtual Machine compatible chains. `features` wallets, security **[Enhanced Wallet Security with Fund Amount Metrics](/changelog/2025-01-08-3)** Implemented comprehensive metrics tracking for custodial wallet funding to enhance security monitoring and prevent potential treasury drainage risks. `improvements` wallets, security **[Enhanced Stable Wallets SDK and API Compatibility](/changelog/2025-01-08-2)** Improved SDK and API compatibility for stable wallets, ensuring seamless integration and enhanced functionality across the platform. `improvements` wallets **[Hosted v3 Documentation Update](/changelog/2025-01-08-1)** Updated platform documentation to make hosted v3 the default, improving accessibility and organization of developer resources. `changed` infrastructure **[Scroll Chain Mainnet Launch](/changelog/2025-01-07)** Launched full mainnet support for Scroll chain, enabling NFT minting and collection management with proven transaction capability on the Scroll network. `new` chains **[Send email delivery notifications to NFT recipients](/changelog/2024-09-16)** New feature allowing customizable email notifications to be sent to NFT recipients when minting, with support for different locales and branding options `feature` minting **[Sponsor fees for users on the checkout](/changelog/2024-07-26)** Added support for sponsor fee calculations during the checkout process `new` checkout **[Launching Orders: See who purchased your NFTs from the Console](/changelog/2024-06-05)** New feature allowing creators to track and view NFT purchase orders directly from the Console interface `new` console **[Crossmint now supports SKALE](/changelog/2024-05-30)** Launch of SKALE blockchain support for wallet creation, NFT collections, and minting on both testnet and mainnet environments `new` chains **[Adding Support for NFT Checkout on Apex Protocol](/changelog/2024-04-30)** Integration of NFT Checkout functionality for Apex Protocol smart contracts, enabling credit card and crypto payments `new` checkout **[Deprecating Polygon Mumbai and Releasing Polygon Amoy support on Staging](/changelog/2024-04-04)** Transition from Polygon Mumbai to Polygon Amoy testnet with timeline for Mumbai deprecation and Amoy integration `changed` chains **[New: You can now update compressed NFTs in Solana](/changelog/2024-02-15)** Added support for updating compressed NFTs on Solana blockchain with same pricing as minting operations `new` minting **[Addition of a new webhook for the third party contracts deployed and imported on Crossmint.](/changelog/2024-02-09)** New webhook event 'nfts.create.failed' added to track failed minting attempts for third-party contracts `new` minting **[Releasing Sepolia support on all EVM L2s](/changelog/2024-02-01)** Addition of Sepolia testnet support for all EVM chains and phased deprecation plan for Goerli testnet across all networks `new` chains **[Event identifiers property renamed on the Webhook payload](/changelog/2024-01-11)** Breaking changes to webhook event type names requiring updates to handle both old and new event identifiers for collection and NFT operations `changed` infrastructure **[Announcing Branded Checkout v2](/changelog/2023-11-30)** Launch of new modular checkout system with improved user experience and feature customization options for all Crossmint projects `improvement` checkout **[Pay with crypto is now available with Embedded Checkout](/changelog/2023-11-22)** Added support for cross-chain cryptocurrency payments in Embedded Checkout alongside existing credit card payment option `feature` checkout **[Deprecating Support for Arbitrum on the Staging Developer Console](/changelog/2023-11-15)** Announcement of the deprecation of Arbitrum support in the staging developer console environment `changed` chains **[Contract creation is now self-serve for Optimism](/changelog/2023-11-07)** Users can now create and deploy contracts on Optimism through a self-service process `new` chains **[Minting API is now self-serve for four more EVM chains](/changelog/2023-10-31)** Self-serve Minting API support expanded to include Base, Optimism, Arbitrum, and Avalanche chains `feature` chains **[Support for Highlight.xyz on Crossmint](/changelog/2023-10-28)** Added integration support for Highlight.xyz NFT marketplace on the Crossmint platform `new` **[Treasury Contract Upgrade](/changelog/2023-10-14)** Details of the Treasury smart contract upgrade and its new features `improvement` infrastructure # Crossmint help Source: https://docs.crossmint.com/cli/help List all commands and provides the help documentation for a given command Run the following command from your terminal to list all commands ```` crossmint help ``` ## Options ``` $ crossmint --help # Display help for command, including the supported flags $ crossmint -h # Display help for command, including the supported flags ``` ## Example ``` Usage: crossmint [options] [command] Crossmint CLI Tool Options: -V, --version output the version number -h, --help display help for command Commands: keys API Keys management commands login Login to Crossmint logout Logout from Crossmint projects Project management commands whoami Show current user and environment help [command] display help for command ``` ```` # Get started with the Crossmint CLI Source: https://docs.crossmint.com/cli/install Manage and configure your Crossmint projects directly from the command line export const ExternalLink = ({href}) => { return ; }; The Crossmint CLI is a command-line tool that allows you to interact with Crossmint directly from your terminal. It uses [homebrew](https://brew.sh/) and works on macOS and Linux. ### Prerequisites * You'll need to have [Hombrew](https://brew.sh/) installed. ## Installing Crossmint CLI To download and install Crossmint CLI, run the following command from your terminal: ```bash brew tap crossmint/tap brew install crossmint ``` To update Crossmint CLI run: ``` brew update brew upgrade crossmint ``` ## Command Reference The Crossmint CLI provides the following commands: | Command | Description | | ------------------------------------------------------------------------- | ------------------------------------------------------------- | | `crossmint login` | Login to Crossmint | | `crossmint logout` | Logout from Crossmint | | `crossmint whoami` | Show current user and environment | | `crossmint help` | List and explains all commands | | `crossmint keys create` | Create a new API Key | | `crossmint keys list [type]` | List all API Keys (optionally filter by type: server\|client) | | `crossmint keys delete ` | Delete an API Key | | `crossmint keys edit ` | Edit the scopes of an API Key | | `crossmint projects create` | Create a new project | | `crossmint projects select` | Select a project | | `crossmint projects details` | Show project details | Refer to the individual command documentation for more detailed information on each command. # Crossmint keys create Source: https://docs.crossmint.com/cli/keys/create Create a new API key The keys create command allows you to create a new API key for your Crossmint project. To use it, run the following command from your terminal ```bash crossmint keys create ``` **Server-side keys** are view-once in Production, make sure to copy your API key secret when it’s displayed, as it won’t be shown again. **Client-side keys** require selecting the app type and adding allowed origins—use domain URLs for web or package/bundle IDs for mobile. ## Example Start the API key creation process: ```bash crossmint keys create ``` Select the type of key you want to create: ``` ? Select Key Usage: (Use arrow keys) Server side > Client side ``` For client-side keys, select the application type: ``` ? Select client platform: (Use arrow keys) > Web Mobile ``` Specify the allowed origins for your key. * For web enter the domain, eg: [https://crossmint.com](https://crossmint.com) * For mobile enter your Android Package name or IOS Bundle ID, eg: com.company.appname Enter multiple domains or app identifiers separated by a comma. ``` ? Enter whitelisted domain or localhost (e.g., https://www.yourdomain.com) (separate multiple domains with a comma): https://www.crossmint.com ``` Select the scopes you want to add to the key by pressing space. Once you are ready, press enter to create the key: ``` ? Select scopes for client key: ● Read wallet (wallets.read) ● Create wallet (wallets.create) ○ Create Transaction (wallets.transactions.create) ○ Sign Transaction (wallets.transactions.sign) ○ Read Transactions (wallets.transactions.read) ○ Create Wallet Signatures (wallets.signatures.create) ``` The CLI will display the created API key information, this includes the Key ID and Client Secret: ``` ✅ API Key created successfully! Key ID: 67ff9c388687868382... 🔒 Key Secret: ck_production_3218u5TFZMGkK16uLbKfxDsJ4xtwSd2xtZRa9A8cbe64oRMe1J148XTGbuSvqmxB4k9TspLUAbKyt2RTqbArGBdkvARxkCg8S1tgwb4ie3gUNFw74vTuCUhSpu7ojkjGxY6epj... ``` # Crossmint keys delete Source: https://docs.crossmint.com/cli/keys/delete Delete an API key The keys delete command allows you to delete an existing API key from your Crossmint project. To use it, run the following command from your terminal ```bash crossmint keys delete ``` Where `` is the ID of the API key you want to delete. You can get the key id by running `keys list` command ## Example Delete an API key: ```bash crossmint keys delete sk_test_abcd1234 ``` You will be prompted to confirm the deletion: ``` ? Are you sure you want to delete this API key? This action cannot be undone. (y/N) ``` After confirming, you'll see a success message: ``` ✅ API Key deleted successfully! ``` **Note:** Once an API key is deleted, any applications or services using that key will no longer be able to authenticate with the Crossmint API. # Crossmint keys edit Source: https://docs.crossmint.com/cli/keys/edit Edit an API key The keys edit command allows you to modify the scopes of an existing server API key. To use it, run the following command from your terminal ```bash crossmint keys edit ``` Where `` is the ID of the API key you want to edit. You can get the key id by running `keys list` command. ## Example Edit an API key: ```bash crossmint keys edit sk_test_abcd1234 ``` For client-side keys, edit the allowed origins for your key. Press `` for editing or `` for confirming the value. * For web enter the domain, eg: [https://crossmint.com](https://crossmint.com) * For mobile enter your Android Package name or IOS Bundle ID, eg: com.company.appname Enter multiple domains or app identifiers separated by a comma. ``` ? Enter whitelisted domain or localhost (e.g., https://www.yourdomain.com) (separate multiple domains with a comma): Press to edit or to confirm current value (https://www.crossmint.com) ``` The CLI will display the current scopes and prompt you to select new ones: ``` Current scopes: Wallets ? Select the new scopes for this key: (Press to select, to toggle all, to invert selection, and to proceed) ❯◉ Wallets ◉ Minting ◯ Payments ◯ Authentication ``` After selecting the new scopes, you'll see a confirmation message: ``` ✅ API Key updated successfully! ``` Note: This command only works for server API keys, as client API keys do not have configurable scopes. # Crossmint keys list Source: https://docs.crossmint.com/cli/keys/list List all API keys The keys list command displays all API keys associated with your Crossmint project. To use it, run the following command from your terminal ```bash crossmint keys list [type] ``` Where `[type]` is an optional parameter to filter keys by type (server or client). ## Example List all API keys: ```bash crossmint keys list ``` ``` ========= 1. Key ID: 67d444369323ea298a4ef9f8 Key Secret: ******************4jTa Type Server Created By guille.a@paella.dev Created 3/14/2025, 3:59:02 PM Scopes wallets.read, wallets.create, wallets:transactions.create, wallets:transactions.sign, wallets:transactions.read, wallets:signatures.create, wallets:signatures.read, wallets:nfts.read, wallets:balance.read, wallets.fund, wallets:messages.sign ========= 2. Key ID: 679217c403723242bd87d3e75 Key Secret: ck_production_AGUysPdnSg3rW2opefTqWAbfXRaCLtEBiYCSNL7 Jbm9L Type Client Created 1/23/2025, 11:19:48 AM Scopes wallets.read, wallets.create, wallets:nfts.read, wallets:transactions.create Whitelisted App IDs com.company.appname ========= ``` List only server API keys: ```bash crossmint keys list server ``` ``` ========= 1. Key ID: 67d444369bbbea298a4ef932 Key Secret: ******************4jTa Type Server Created By guille.a@paella.dev Created 3/14/2025, 3:59:02 PM Scopes wallets.read, wallets.create, wallets:transactions.create, wallets:transactions.sign, wallets:transactions.read, wallets:signatures.create, wallets:signatures.read, wallets:nfts.read, wallets:balance.read, wallets.fund, wallets:messages.sign ========= ``` # Crossmint login Source: https://docs.crossmint.com/cli/login Authenticate to the Crossmint platform The login command authenticates you with the Crossmint platform. It allows you to access your account and manage API keys and projects through the CLI. To use it, run the following command from your terminal ```bash crossmint login ``` ## Example Start the login process: ```bash crossmint login ``` Select an environment: ``` ? Select environment: (Use arrow keys) > Production Staging ``` The CLI will open a browser window to authorize your device. If you're not signed in to Crossmint in the browser, you'll need to login first. Once the device is authorized, you can close the browser and return to the terminal. ![Authorize Device Success](https://mintlify.s3.us-west-1.amazonaws.com/crossmint/images/console/authorize-device-success.png) ``` ✅ Login successful! You are now authenticated in the Production environment. ``` You'll then be prompted to select a project: ``` ? Select a project: (Use arrow keys) > My Project Website Integration Mobile App ``` # Crossmint logout Source: https://docs.crossmint.com/cli/logout Sign out from the Crossmint platform The logout command signs you out from the Crossmint platform by removing your session token from local storage. To use it, run the following command from your terminal ```bash crossmint logout ``` ## Example Sign out from Crossmint: ```bash crossmint logout ``` After running the command, you'll see a confirmation message: ``` ✅ Logout successful! You are no longer authenticated. ``` After logging out, you will need to use the `login` command to authenticate again before using other commands that require authentication. # Crossmint projects create Source: https://docs.crossmint.com/cli/projects/create Create a new project in Crossmint The projects create command allows you to create a new project in your Crossmint account. To use it, run the following command from your terminal ```bash crossmint projects create [options] ``` ## Options | Option | Description | | ------------------- | ------------------------ | | `-n, --name ` | Give your project a name | ## Example Create a new project: ```bash crossmint projects create ``` You'll be prompted to enter a name for the project: ``` ? Enter project name: My New Project ``` After entering a name, you'll see a confirmation message: ``` ✔ ✅ Project created successfully! 📌 Project Details: Name: New Project ID: 4b0392a3-35c3-458c-a43e-32d2cdc65eda ``` You'll be ask to confirm if you want to select the created project for subsequent commands. ```` ? Do you want to select this project? (Y/n) ``` You can also specify the project name directly using the `--name` option: ```bash crossmint projects create --name "My New Project" ``` ```` # Crossmint projects details Source: https://docs.crossmint.com/cli/projects/details View details of a project The projects details command displays information about the currently selected project. To use it, run the following command from your terminal ```bash crossmint projects details ``` ## Example View details of the current project: ```bash crossmint projects details ``` You'll see the information about your project: ``` 📌 Project Details: Name: New Project ID: f5e37bee-1a81-4df1-8081-7670eee2a629 Wallet Type: Custodial ``` This command is useful for verifying which project you're currently working with and viewing its basic information. # Crossmint projects select Source: https://docs.crossmint.com/cli/projects/select Select a project to work with The projects select command allows you to choose which Crossmint project you want to work with for subsequent commands. To use it, run the following command from your terminal ```bash crossmint projects select ``` ## Example Select a project: ```bash crossmint projects select ``` You'll be presented with a list of your projects: ``` ? Select a project: (Use arrow keys) > My New Project Website Integration Mobile App Test Project ``` After selecting a project, you'll see a confirmation message: ``` ✅ Project My New Project selected ``` After selecting a project, commands that require a project context (like API key management) will use the selected project. # Crossmint whoami Source: https://docs.crossmint.com/cli/whoami Display current user, environment and selected project The whoami command displays information about the currently authenticated user, the environment you're working in and the selected project. To use it, run the following command from your terminal ```bash crossmint whoami ``` ## Example Check your current authentication status: ```bash crossmint whoami ``` You'll see output showing your email and environment: ``` You are logged in to 🍀Crossmint as: user@example.com - Environment: Production - Selected Project: My New Project ``` This command is useful for verifying your authentication status, checking which environment and project you're working in. # About Crossmint Source: https://docs.crossmint.com/introduction/about-crossmint Crossmint is an all-in-one platform to integrate wallets, stablecoins, and other blockchain primitives into your product, AI agent, or app. ## Explore the products Create wallets for users, agents, and companies. Authenticate users with email, socials, or wallets. Sell tokens and 1 billion physical products. Fund wallets with stablecoins or crypto. Mint, distribute, and manage tokens at scale. Issue and verify W3C credentials. ## Explore the solutions Add stablecoins into any product or flow Turn agents into economic actors Register IP rights with Story Protocol ## What makes Crossmint unique? * **One suite for all your needs**, so you don't have to orchestrate 5-10 vendors. In addition to the products above, Crossmint saves you from separate integrations with RPCs, data APIs, AML screening providers, KYC, and other ancilliary providers, offering everything you need in a fully integrated platform. * **Best-in-class UX for your users**: no gas fees, passphrases, transaction approval prompts, or other blockchain gimmicks. * **Easy-to-use APIs**, which don't presume any blockchain experience, to get you started in minutes. Crossmint optionally takes care of gas fees and bills you in fiat, so you don't have to touch crypto or set up a treasury wallet. * **No-code dashboards** for anyone in your team to manage the program - even if they aren't technical. * **Bank-grade security**: battle-tested and trusted by major financial institutions and Fortune 500 companies like Santander Bank and Nestlé. SOC2 Type II, VASP licensed, and MiCA-ready. * **No vendor lock-in**: change providers anytime with minimal user disruption. ## More resources # Using AI Assistants Source: https://docs.crossmint.com/introduction/ai-assistants Integrate faster with Crossmint by ingesting the docs into your AI-based code helpers (like Cursor, GitHub Copilot, etc.). {" "} AI assistant ready docs ## Integrate with Cursor 1. Navigate to Cursor Settings > Features > Docs 2. Select "Add new doc" and paste the following URL: ``` https://docs.crossmint.com/llms-full.txt ``` 3. Use `@docs -> Crossmint` to reference Crossmint's docs in your code. # Getting Started Source: https://docs.crossmint.com/introduction/getting-started Before you can start integrating Crossmint into your application, you need to create a Crossmint account and set up a new project in the Staging Console. This guide will walk you through those steps. Open Crossmint's [staging console](https://staging.crossmint.com/console) and create an account **Ready for launch?** When it's time to go live, simply create an account in the [production console](https://www.crossmint.com/console) and replicate the resources you need. If you've just created an account for the first time, you'll be taken directly to project creation process. Add the name to your project and continue. In the [overview of your project](https://staging.crossmint.com/console/overview) you will find the client and server API keys you need to integrate Crossmint into your application. Now that your project is created in the Console, you can start integrating Crossmint products into your application. Create wallets for users, agents, and companies. Authenticate users with email, socials, or wallets. Sell tokens and 1 billion physical products. Fund wallets with stablecoins or crypto. Mint, distribute, and manage tokens at scale. Issue and verify W3C credentials. # Account Verification Source: https://docs.crossmint.com/introduction/platform/account-verification Learn how to get your account and collection verified Enabling certain Crossmint products requires a quick seller KYC and collection review: | Product | Requirement | | --------------- | -------------------------------------------------------------------------------------------- | | Tokenization | No review required | | Wallets | No review required | | Fiat Checkout | Quick seller KYC & Collection Review (only for primary sales. Not required for marketplaces) | | Crypto Checkout | Collection Review required. No KYC required. | | Claims Page | Quick seller KYC & Collection Review | Reviews are only required in production. Staging does not require account or collection review for any product. Please note that each distinct project you create via the Crossmint Console will require a separate review. Confirm that your collection is submitted for verification with all of the relevant project details to ensure timely review. If your collection is still early in development, please refer to our [staging environment](https://staging.crossmint.com/console) for all testing. Reviews can take up to 3 business days. For faster reviews, consider upgrading to the Pro subscription plan, where reviews are expedited under 24hrs. Upgrade from the [billing tab](https://www.crossmint.com/console/billing) of the console. ### Account Verification To enable credit card payments on primaries or set up a hosted claims page, sellers are required to complete a quick KYC. You only have to verify a project once, and can create as many collections as you wish within that project. New projects require additional verification. Cross-chain payments do not require account verification. Sellers on marketplaces are also not required to KYC. Account Verification requires a valid government ID and a selfie. Ensure all photos are well lit but without glare, and uncover your face removing eyewear and pulling long hair behind ears. Crossmint offers a collection registration API and tools to verify creators and collections at scale. To learn more, [contact us](https://www.crossmint.com/contact/sales). ### Collection Verification Crossmint reviews all collections (a) sold using Crossmint's checkout or (b) airdropped using the "hosted claims page" product. To start the review, open your collection page in the Crossmint console, look for the "Verification Status" card in the left navbar, and click on "Verify now" in the collection entry. Ensure your collection meets Crossmint's [content policy](https://www.crossmint.com/content-policy), and that all the information provided is up to date and truthful. Reviews take up to 72hrs, or 24hrs for Pro subscribers. Crossmint does not support the sale of securities, investment contracts, or any of the other categories specified on the content policy. Crossmint offers a collection registration API and tools to verify collections at scale. To learn more, [contact us](https://www.crossmint.com/contact/sales). # Client-side Keys Source: https://docs.crossmint.com/introduction/platform/api-keys/client-side How to create and use client-side API keys ## Create a Client-side Key Navigate to the API Keys section of the developer console and click the "Create new key" button in the client-side keys section. * [Staging API Keys](https://staging.crossmint.com/console/projects/apiKeys) * [Production API Keys](https://www.crossmint.com/console/projects/apiKeys) create client-side API key in Crossmint developer console ### Setting Authorized Origins Client-side keys are exposed in the application and thus require additional security measures. The minimum requirement is to whitelist URLs that requests can be sent from. Client-side keys support two types of origins: #### Web Origins For web applications, you need to add the domains that requests will be sent from. In development, you'll need to add the local domain you test your application from. This is commonly `http://localhost` followed by a port number such as `3000`, `5173`, etc. For example, when developing with NextJS, the default origin you need to authorize is `http://localhost:3000`. The expected format for web origins is a full URL with protocol, such as `https://www.yourdomain.com` or `http://localhost:3000`. #### Mobile App Identifiers For mobile applications, you need to add the bundle identifiers for iOS apps or package names for Android apps. The expected format is: * iOS: Bundle ID (e.g., `com.company.appname`) * Android: Package name (e.g., `com.company.appname`) You can only register either web origins or mobile app identifiers for a single API key, not both. If you need both types, you'll need to create separate API keys. When you create a production API key you will need to authorize your production domain or app identifiers to use the API key. You can add multiple authorized domains or app identifiers for an API key to make requests from. Type in the domain or app identifier that you want to authorize and then click the "+ Add new origin" button. add authorized origin to API key in Crossmint developer console ### Select Scopes Within the modal that opens, toggle the required scopes you want to enable. You may need to expand an accordion for the product area you're working on to expose additional scope options. select client-side API scopes in Crossmint developer console For more information on API Key scopes visit the scopes page or the API Reference. Complete list of available API scopes Detailed docs for all API endpoints ### JWT Authentication Finally, select the option to require a JWT if your application or use case requires it. Enabing this setting will require that users are authenticated to permit API requests. enable JWT Authentication in Crossmint developer console The [Wallets SDK](/sdk-reference/wallets/overview) requires this option to be enabled. It is optional for other client side APIs. For more information on the options, refer to the [JWT Authentication](/introduction/platform/api-keys/jwt-authentication) section. If you choose to enable the JWT Authentication for your client-side API key, there are additional configurations that must be made. You can choose between Crossmint authentication (easiest), third party auth providers such as Dynamic, Auth0, Stytch, Privy or Firebase (medium), or integrating with custom solutions where you generate your own JWTs (advanced). You can find more information and guidance in the [JWT Authentication](/introduction/platform/api-keys/jwt-authentication) section. *** ## Using a Client-side Key There are a few different approaches to using a client-side key. The most common option is passing it to the `init` function for a supported SDK. There are also some cases where you'll pass the key as a header in a raw API call from custom code, similar to how a server-side key works. ### Initializing an SDK The most common way you'll leverage a client-side API key is by passing it to the `init` function for a supported SDK. See the examples below. ```typescript smartWalletInit.ts import { SmartWalletSDK } from "@crossmint/client-sdk-smart-wallet"; const sdk = SmartWalletSDK.init({ clientApiKey: process.env.NEXT_PUBLIC_CLIENT_SIDE_KEY, }); ``` ```typescript credentialsInit.ts import * as sdk from '@crossmint/client-sdk-verifiable-credentials'; sdk.CrossmintAPI.init(process.env.NEXT_PUBLIC_CLIENT_SIDE_KEY); ``` ```tsx authExample.tsx import { CrossmintProvider, CrossmintAuthProvider } from "@crossmint/client-sdk-react-ui"; export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( {children} ); } ``` ### Direct API Call From Client The Headless Checkout is one example where you may be writing custom API calls from your application to create orders. In this case, you set the client-side API key as a header named `X-API-KEY`, much like you would when making a server-side API call. ```typescript const createOrder = async (orderInput: any) => { try { const res = await fetch(`https://staging.crossmint.com/api/2022-06-09/orders`, { method: "POST", headers: { "Content-Type": "application/json", "x-api-key": process.env.NEXT_PUBLIC_CLIENT_SIDE_KEY, }, body: JSON.stringify(orderInput), }); const order = await res.json(); setOrder(order.order); setClientSecret(order.clientSecret); } catch (e) { console.error(e); throw new Error("Failed to create order"); } }; ``` # JWT Authentication Source: https://docs.crossmint.com/introduction/platform/api-keys/jwt-authentication Enable advanced security for client-side API Keys JWT-based authentication is a mechanism in which you can authorize a call to a Crossmint API, scoping such calls to impact resources related to a single end-user on your platform. You have three options available when enabling this option. 1. **Crossmint Authentication** - With an easy to use react SDK you can add user creation and authentication to your application. Crossmint handles the generation of JWTs and you're able to quickly create a robust application with user access controls. 2. **Third Party Authentication providers** - There are several quality authentication providers in the market and you may already be using one of them. You can continue to use your existing auth tooling and enable Crossmint Wallets on top of them with minimal changes. 3. **Custom JWT** - This option is for providers not yet included with turn-key support or custom built solutions where you issue your own JWTs. You must be able to provide a JWKS endpoint to enable Crossmint to authenticate tokens. Crossmint's Wallets SDK ***requires*** JWT Authentication be enabled. ## Crossmint Authentication This option makes the most sense if you're starting a new application and do not have a pre-existing auth provider. You may also want to swap out your existing auth provider if you wish to consolidate your API providers and handle everything with Crossmint. To use this option, select the Crossmint Auth option within the JWT Authentication section of the API keys page in the Developer Console. select Crossmint Auth in Crossmint developer console ## Third Party Authentication For projects that have already implemented authentication using one of the supported providers, you can provide Crossmint with the appropriate project/environment/app ID from the settings page of the third party. Supported providers include: Dynamic, Auth0, Stytch, Privy, and Firebase. To use this option, select the 3P Auth providers option, then choose your provider from the dropdown. Next, you'll need to find the appropriate ID that your provider gives you to identify your project. This can typically be found within the settings pane of their web interface. select third party Auth in Crossmint developer console ## Custom JWT Auth If your project is using an auth provider not listed in the 3P providers list or is a home-grown JWT solution, you can choose the Custom tokens option. You will need to be able to provide a JWKS endpoint that Crossmint can use to authenticate the JWTs. select third party Auth in Crossmint developer console For a detailed guide on implementing this approach, check out the [Custom JWT Authentication Guide](/introduction/platform/api-keys/custom-jwt-auth-guide). # Overview Source: https://docs.crossmint.com/introduction/platform/api-keys/overview Get your keys in seconds and start building API keys are required to authorize requests against the Crossmint APIs. By using an API key, Crossmint knows which project is making the call, and can deduct credits from your balance. ## Staging vs. Production Keys First, determine if you need a staging (testing) or production API key. Generate API keys for testing in the staging developer console Generate API keys for going live in the production developer console ## Server-side vs. Client-side Keys Server-side API keys are used in server-to-server communications or in code running on a server. These keys are not exposed to the end users and can have broader permissions because they are considered more secure, being stored and used in controlled environments. The majority of Crossmint APIs require a server-side API key. For a comprehensive list of APIs available refer to the [API Reference](/api-reference/introduction). Client-side API keys are used in code that runs on the client-side, such as in web browsers or mobile apps. These keys are exposed to the end user and are therefore less secure. They typically have more restrictive permissions to minimize security risks. When creating a client-side API key, you also need to configure authorized origins that are allowed to make calls to the endpoint. Client-side keys are required for building with the [Wallets SDK](/sdk-reference/wallets/overview), Authentication, and [Headless Checkout](/payments/headless/overview). You can also perform some custodial wallet actions with these key types. Finally, the [Verifiable Credentials SDK](/verifiable-credentials/introduction) also offers some features via client-side keys. ## More information Information about standard rate limits and exceptions Complete list of available API scopes How to create and use server-side API keys How to create and use client-side API keys # Rate Limits Source: https://docs.crossmint.com/introduction/platform/api-keys/rate-limits Understand the throughput available for API calls Rate limits prevent individual users from clogging the network. If a limit is exceeded, Crossmint will respond with HTTP 429 and require a brief waiting period before making additional requests. [Contact us](https://www.crossmint.com/contact/sales) if you need higher rate limits. ### Base Limits | Method(s) | Rate Limit | | --------- | ----------------------------------- | | POST | 120 requests per minute per project | | PUT | Same as above | | PATCH | Same as above | | DELETE | Same as above | | GET | 360 requests per minute per project | ### Exceptions | API | Route | Method | Rate Limit | | ------------------------------------------------------------------------ | ----------------------------------------------------------- | ------ | ------------------- | | [Mint NFT](/api-reference/minting/nfts/mint-nft) | /api/2022-06-09/collections/\{collectionId}/nfts | POST | 600 req/min/project | | [Mint NFT (Idempotent)](/api-reference/minting/nfts/mint-nft-idempotent) | /api/2022-06-09/collections/\{collectionId}/nfts/\{nftName} | PUT | 600 req/min/project | | [Collection Info](/api-reference/minting/collection/get-collection) | /api/2022-06-09/collections/\{collectionId} | GET | 600 req/min/project | | [Mint Status](/api-reference/minting/nfts/mint-status) | /api/2022-06-09/collections/\{collectionId}/nfts/\{id} | GET | 600 req/min/project | # Scopes Source: https://docs.crossmint.com/introduction/platform/api-keys/scopes Enabling required permissions for API calls Below is a complete list of the API scopes available. You can also find the scope a specific API requires in the [API Reference](/api-reference/introduction) section. ## Wallet APIs | Scope | Description | Server Key | Client Key | | ----------------------------- | -------------------------------------------------- | ---------- | ---------- | | `wallets.read` | Retrieve all wallets for a user. | ✅ | ✅ | | `wallets.create` | Create a wallet for a user. | ✅ | ✅ | | `wallets:nfts.read` | Fetch the NFTs owned by a specific wallet address. | ✅ | ✅ | | `wallets:balance.read` | Get the balance of a specific wallet address. | ✅ | ✅ | | `wallets:transactions.create` | Create a transaction from a user's wallet. | ✅ | ✅ | | `wallets:transactions.sign` | Sign a transaction from a user's wallet. | ✅ | ✅ | | `wallets:transactions.read` | Read transactions from a user's wallet. | ✅ | ✅ | | `wallets:signatures.create` | Create a signature for a wallet. | ✅ | ✅ | | `wallets:signatures.read` | Read a signature for a wallet. | ✅ | ✅ | | `wallets.fund` | Send funds to a wallet. | ✅ | ✅ | | `wallets:nfts.transfer` | Transfer an NFT from a user's wallet. | ✅ | | | `wallets:messages.sign` | Sign a message from a user's wallet. | ✅ | | When using the [Wallets SDK](/sdk-reference/wallets/overview) you ***must*** use a client-side API key. ## Authentication | Scope | Description | Server Key | Client Key | | -------------- | ------------------------------------- | ---------- | ---------- | | `users.create` | Create users / allow them to sign up. | | ✅ | | `users.read` | Get profile info for user accounts. | | ✅ | ## Tokenization (Minting) APIs | Scope | Description | Server Key | Client Key | | ------------------------------ | -------------------------------------------------------------------------- | ---------- | ---------- | | `nfts.create` | Mint your NFTs and deliver them to a wallet or to an email address. | ✅ | | | `nfts.update` | Update a minted NFT's metadata on IPFS (image, description, name...). | ✅ | | | `nfts.read` | Retrieve all metadata for an NFT. | ✅ | | | `nfts.delete` | Burn a specific NFT within a collection. | ✅ | | | `nfts.transfer` | Transfer an NFT to a different wallet. | ✅ | | | `collections.create` | Create a collection of NFTs. | ✅ | | | `collections.update` | Update information for an existing collection (image, name, royalties...). | ✅ | | | `collections.read` | Retrieve the information about a specific collection. | ✅ | | | `credentials.read` | Fetch credentials, some endpoints will only work with a server side key. | ✅ | ✅ | | `credentials.decrypt` | Decrypt credentials, mainly used by our client side SDK. | ✅ | ✅ | | `credentials:templates.create` | Create a template for your credentials. | ✅ | | | `credentials.create` | Issue your credentials and create credential types | ✅ | | | `credentials.delete` | Revoke a credential issued to a subject. | ✅ | | ## Checkout APIs | Scope | Description | Server Key | Client Key | | --------------- | ----------------------------------------------- | ---------- | ---------- | | `orders.create` | Create an order for headless checkout. | ✅ | ✅ | | `orders.read` | Get an existing order for headless checkout. | ✅ | ✱ | | `orders.update` | Update an existing order for headless checkout. | ✅ | ✱ | When updating or reading order status from the client-side, you must pass the `clientSecret` returned in the create-order call as an `authorization` header. The `clientSecret` provides the authorization and an API Key is not required in this use case. See [this guide](/payments/headless/guides/client-or-server#client-side-example-code) in the Headless Checkout docs. ## Project Administration | Scope | Description | Server Key | Client Key | | --------------------- | ------------------------------------------------- | ---------- | ---------- | | `billing.readonly` | Get balance in credits for a project. | ✅ | | | `projects:usage.read` | Get usage for the different products in a project | ✅ | | # Server-side Keys Source: https://docs.crossmint.com/introduction/platform/api-keys/server-side How to create and use server-side API keys **Server-side API keys must be stored securely!** Enable only the scopes you need, and no more, and do NOT expose your keys on the frontend of your app, or your github code repository. ## Create a Server-side Key Navigate to the API Keys section of the developer console and click the "Create new key" button in the server-side keys section. * [Staging API Keys](https://staging.crossmint.com/console/projects/apiKeys) * [Production API Keys](https://www.crossmint.com/console/projects/apiKeys) create server-side API key in Crossmint developer console ### Select Scopes **Production server-side keys follow a "view once" policy** When you create a server-side API key in the production environment, the key secret will only be shown once during creation. After you close the dialog or navigate away, **you will not be able to view the key secret again.** Within the modal that opens, toggle the required scopes on and click the "Create server key" button at the bottom. You may need to expand an accordion for the product area you're working on to expose additional scope options. select server-side API scopes in Crossmint developer console You can determine the scopes you need by visiting the API reference page for the API(s) you need to interact with. Complete list of available API scopes Detailed docs for all API endpoints ## Using a Server-side Key If you're using the [API Playground](/api-reference) you can add your API key in the Authorization section and this will set it as a header when making the request. Set x-api-key screenshot Set x-api-key screenshot When calling the APIs from server-side code, you set the `X-API-KEY` header however the target language or library expects it. See some examples below: ```bash cURL curl --request POST \ --url https://staging.crossmint.com/api/v1-alpha1/wallets \ --header 'Content-Type: application/json' \ --header 'X-API-KEY: YOUR_API_KEY' \ --data '{ "email": "test@test.com", "chain": "polygon-amoy" }' ``` ```javascript JavaScript const options = { method: 'POST', headers: { 'X-API-KEY': 'YOUR_API_KEY', 'Content-Type': 'application/json' }, body: '{ "email":"test@test.com", "chain":"polygon-amoy" }' }; fetch('https://staging.crossmint.com/api/v1-alpha1/wallets', options) .then(response => response.json()) .then(response => console.log(response)) .catch(err => console.error(err)); ``` All of the API routes in the [API Reference](/api-reference/introduction) include code examples for many popular programming languages. # Project and Team Management Source: https://docs.crossmint.com/introduction/platform/projects-and-user-management Manage your projects and their members ## Managing Projects A project is a group of token collections, user wallets, API keys, billing information, and more. If you are working with different teams or clients, you can create different projects to seggregate sensitive information and tool access. Alternatively, you can issue different API keys within the same project, but bear in mind they will share the same billing account. Every developer account automatically includes a project named `Default Project`. You can create new projects and alternate between them using the selector within the console, as illustrated in the screenshot below. {" "} Crossmint developer console overview map ## Privacy Policy Projects have an option to register a link to your company's privacy policy. If set, this link will be shown to your users when they're using any Crossmint-managed user interface, such as the Checkout, where user information is collected. A privacy policy is required by law if you want to later those users' personally identifiable information, such as their email address. If you don't already have a privacy policy, you can generate and host one using tools like [Termly](https://termly.io/). > **Note:** Failure to add a privacy policy will result in email addresses being hidden. #### Cases Requiring a Privacy Policy to Access User Data | Use Case | Privacy Policy Required | | ---------------------------- | ----------------------- | | Payments (payment button) | Yes | | Payments (embedded checkout) | Yes | | Payments (headless checkout) | No | | Mint API or console | No | | Wallet APIs or console | No | ### Steps to Add a Privacy Policy Link 1. \**Go to the General Settings tab* * Access the Settings page from the sidear. 2. **Include the Privacy Policy Link** Include Privacy Policy link * In the project settings, locate the section for adding a privacy policy. * Paste the URL of your privacy policy generated from Termly or any other source. 4. **Verify Email Visibility** * After adding the privacy policy link, check to ensure that email addresses are now visible. * If the link is not included, emails will remain hidden to protect user data. Following these steps will ensure compliance with data protection laws and enable the visibility of email addresses in your project settings. *** ## FAQs Crossmint requires your project's privacy policy to comply with data protection laws and ensure the privacy and security of user data. Without it, email addresses and other sensitive information will be hidden. Older users who joined before the privacy policy was added haven't accepted the new policy. Therefore, their identifiers remain hidden. Deleting the privacy policy is restricted to ensure compliance with data protection laws and maintain user privacy and security. Projects can be shared across multiple team members. You can add new members from the Members tab on the console. All members get the same permissions, except for the ability to delete other members, which only belongs to the creator of the project. In order to invite a member to a project, they must already have a Crossmint account within that same environment. {/* prettier-ignore */} If you need to remove a team member, submit a ticket with Crossmint support. # Staging vs Production Environments Source: https://docs.crossmint.com/introduction/platform/staging-vs-production Crossmint's console and first-party wallet operate in two different environments: * **Staging:** free, for testing. * **Production:** for your live projects. Blockchain operations incur credit costs. You may access them from [https://staging.crossmint.com](https://staging.crossmint.com), and [https://www.crossmint.com](https://www.crossmint.com). Staging provides free self-serve access to most functionality. ## Differences between the Environments | | **Staging** | **Production** | | ------------ | -------------------------------------------------------------- | ------------------------------------------------------ | | URL | [https://staging.crossmint.com](https://staging.crossmint.com) | [https://www.crossmint.com](https://www.crossmint.com) | | Payments | Test credit cards | Accepts real credit cards | | API Credits | Free to test (no API credits required) | API credits required for some endpoints | | Verification | Checkout does not require KYC or collection verification | Checkout requires KYC and collection verification | | Blockchains | Testnets like Sepolia, and Amoy | Mainnets | ## FAQ No, collections created in one environment will not appear in the other. Typically, you would start developing your project in staging, and replicate and launch in production when you feel ready. # Add an Endpoint Source: https://docs.crossmint.com/introduction/platform/webhooks/add-endpoint Configure an endpoint to receive webhook messages. To add an endpoint, provide a URL you control and select the event types you want to listen to. 1. Navigate to the Webhooks page in the console. 2. Click **Add Endpoint**. 3. Provide the URL where you want to receive messages. 4. Select the event types you want to listen to. 5. Click **Create**. ![Add an endpoint](https://mintlify.s3.us-west-1.amazonaws.com/crossmint/images/console/webhooks/add-endpoint.png) ### FAQs There are many events available to subscribe to from all our products. Some examples include: * Collection creation * NFT minting * NFT edits * Transaction confirmations * Transaction failures You can see the full list of events in the Crossmint Console, under Integrate > Webhooks and the **Event Catalog** tab. To verify a webhook request is legitimate, you need to verify the signature and timestamp. You can learn more about it in the [Verify webhooks](/introduction/platform/webhooks/verify-webhooks) section. Crossmint automatically retries webhooks if your endpoint doesn't acknowledge its receipt, or throws an error. We will attempt to deliver the webhook 8 times: * Immediately * 5 seconds * 5 minutes * 30 minutes * 2 hours * 5 hours * 10 hours * 10 hours (in addition to the previous) If, after these attempts, we're unable to deliver the message, we will mark it as failed. Inside the Webhooks page, you can manually resend the webhook. ![Resend a webhook](https://mintlify.s3.us-west-1.amazonaws.com/crossmint/images/console/webhooks/retry-webhook.png) To indicate that a webhook has been processed, return a 2xx (status code 200-299) response to the webhook message within a 15 seconds timeframe. Some typical reasons why webhooks fail are: * Check that the enpdpoint URL is correct and that it's expecting a POST request * Check that the endpoint is reachable from the public internet. Make sure that CSRF protection is disabled for this endpoint. * Check that the endpoint is returning a 2xx response code * Check that the payload signature and timestamp are verified correctly. Remember not to modify the body string of the webhook before processing it. # Overview Source: https://docs.crossmint.com/introduction/platform/webhooks/overview Listen for updates in mints, edits, collection creations, and other async events Creating NFT collections, minting, and editing NFTs require sending operations to a blockchain. Transaction confirmation on the blockchain can take a few seconds, but during network congestion, it may take several minutes. Webhooks allow you to stay up to date on the status of these asynchronous operations. Some cases where you may want to listen for transaction confirmations include: * Notifying your customers via email that their NFT is ready to access * Updating your database with the NFT ID for the user * Showing on your website that the mint has been successful Webhooks are how services notify each other of events. At their core, they are simply POST requests to a pre-determined endpoint. The endpoint can be any URL you choose, and you can [add them from the console](/introduction/platform/webhooks/add-endpoint). # Verify Webhooks Source: https://docs.crossmint.com/introduction/platform/webhooks/verify-webhooks Verify the signature and timestamp when processing webhooks Because of the way webhooks work, attackers can impersonate services by simply sending a fake webhook to an endpoint. Think about it: it’s just an HTTP POST from an unknown source. This can create a potential security vulnerability for many applications, or at the very least, a source of errors. To prevent this, Crossmint signs every webhook and its metadata with a unique key for each endpoint. Use this signature to verify that the webhook indeed comes from Crossmint, and process it only if it does. You can get the signing key secret from the Webhooks page in the console. To find it, go to the endpoint details and look for the Signing Secret section. ![Signing Secret](https://mintlify.s3.us-west-1.amazonaws.com/crossmint/images/console/webhooks/signing-secret.png) We are going to use the Svix open-source library to verify webhooks. First, install the relevant libraries for your language: ```js Javascript npm install svix // Or yarn add svix ``` ```py Python pip install svix ``` ```rust Rust http = "1.0.0" svix = "1.20.0" ``` ```go Go go get github.com/svix/svix-webhooks/go ``` ```java Java // Gradle: Add this dependency to your project's build file: implementation "com.svix:svix:0.x.y" // Maven: Add this dependency to your project's POM file: com.svix svix 0.x.y ``` ```kotlin Kotlin // Gradle: Add this dependency to your project's build file: implementation "com.svix.kotlin:svix-kotlin:0.x.y" // Maven: Add this dependency to your project's POM file: com.svix.kotlin svix-kotlin 0.x.y ``` ```ruby Ruby gem install svix ``` ```csharp C# dotnet add package Svix ``` ```php PHP composer require svix/svix ``` ```bash CLI # On macOS install via Homebrew: brew install svix/svix/svix # On Linux install via Scoop: scoop bucket add svix https://github.com/svix/scoop-svix.git scoop install svix ``` Next, verify webhooks using the code below. The payload is the raw (string) body of the request, and the headers are the headers passed in the request. You need to use the **raw request body** when verifying webhooks, as the cryptographic signature is sensitive to even the slightest changes. Watch out for frameworks that parse the request as JSON and then stringify it, as this will break the signature verification. See examples below for how to get the raw request body with different frameworks. Remember to get the signature secret from the endpoint details in the console. ```js Javascript import { Webhook } from "svix"; const secret = "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"; // These were all sent from the server const headers = { "svix-id": "msg_p5jXN8AQM9LWM0D4loKWxJek", "svix-timestamp": "1614265330", "svix-signature": "v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=", }; const payload = '{"test": 2432232314}'; const wh = new Webhook(secret); // Throws on error, returns the verified content on success const payload = wh.verify(payload, headers); ``` ```py Python from svix.webhooks import Webhook secret = "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw" # These were all sent from the server headers = { "svix-id": "msg_p5jXN8AQM9LWM0D4loKWxJek", "svix-timestamp": "1614265330", "svix-signature": "v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=", } payload = '{"test": 2432232314}' wh = Webhook(secret) # Throws on error, returns the verified content on success payload = wh.verify(payload, headers) ``` ```rust Rust use svix::webhooks::Webhook; let secret = "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw".to_string(); let mut headers = http::HeaderMap::new(); headers.insert("svix-id", "msg_p5jXN8AQM9LWM0D4loKWxJek"); headers.insert("svix-timestamp", "1614265330"); headers.insert( "svix-signature", "v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=", ); let payload = b"{\"test\": 2432232314}"; let wh = Webhook::new(&secret)?; wh.verify(&payload, &headers)?; // returns Ok on success, Err otherwise ``` ```go Go import ( svix "github.com/svix/svix-webhooks/go" ) secret := "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw" // These were all sent from the server headers := http.Header{} headers.Set("svix-id", "msg_p5jXN8AQM9LWM0D4loKWxJek") headers.Set("svix-timestamp", "1614265330") headers.Set("svix-signature", "v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=") payload := []byte(`{"test": 2432232314}`) wh, err := svix.NewWebhook(secret) err := wh.Verify(payload, headers) // returns nil on success, error otherwise ``` ```java Java import com.svix.Webhook; String secret = "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"; // These were all sent from the server HashMap> headerMap = new HashMap>(); headerMap.put("svix-id", Arrays.asList("msg_p5jXN8AQM9LWM0D4loKWxJek")); headerMap.put("svix-timestamp", Arrays.asList("1614265330")); headerMap.put("svix-signature", Arrays.asList("v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=")); HttpHeaders headers = HttpHeaders.of(headerMap, BiPredicate) String payload = "{\"test\": 2432232314}"; Webhook webhook = new Webhook(secret); webhook.verify(payload, headers) // throws WebhookVerificationError exception on failure. ``` ```kotlin Kotlin import com.svix.kotlin.Webhook val secret = "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"; // These were all sent from the server val headersMap = mapOf( "svix-id" to listOf("msg_p5jXN8AQM9LWM0D4loKWxJek"), "svix-timestamp" to listOf("1614265330"), "svix-signature" to listOf("v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=") ) val headers = HttpHeaders.of(headersMap) { _, _ -> true } val payload = "{\"test\": 2432232314}"; val webhook = Webhook(secret); webhook.verify(payload, headers) // throws WebhookVerificationError exception on failure. ``` ```ruby Ruby require 'svix' # These were all sent from the server headers = { "svix-id" => "msg_p5jXN8AQM9LWM0D4loKWxJek", "svix-timestamp" => "1614265330", "svix-signature" => "v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=" } payload = '{"test": 2432232314}' wh = Svix::Webhook.new("whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw") # Raises on error, returns the verified content on success json = wh.verify(payload, headers) ``` ```csharp C# using Svix; using System.Net; // These were all sent from the server var headers = new WebHeaderCollection(); headers.Set("svix-id", "msg_p5jXN8AQM9LWM0D4loKWxJek"); headers.Set("svix-timestamp", "1614265330"); headers.Set("svix-signature", "v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE="); var payload = "{\"test\": 2432232314}"; var wh = new Webhook("whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw/Je4ZJEGP1QFb"); // Throws on error wh.Verify(payload, headers); ``` ```php PHP // import using composers autoload require_once('vendor/autoload.php'); // or manually require_once('/path/to/svix/php/init.php'); // These were all sent from the server $payload = '{"test": 2432232314}'; $header = array( 'svix-id' => 'msg_p5jXN8AQM9LWM0D4loKWxJek', 'svix-timestamp' => '1614265330', 'svix-signature' => 'v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=', ); // Throws on error, returns the verified content on success $wh = new \Svix\Webhook('whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw'); $json = $wh->verify($payload, $header); ``` ```bash CLI export SVIX_AUTH_TOKEN="AUTH_TOKEN" svix verify --secret whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw --msg-id msg_p5jXN8AQM9LWM0D4loKWxJek --timestamp 1614265330 --signature v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE= '{"test": 2432232314}' ``` This is a manual verification process. We recommend using a library to verify webhooks automatically. If you need to verify manually, follow these instructions. Each webhook call includes three headers with additional information that are used for verification: * `svix-id`: The unique message identifier for the webhook message. This identifier is unique across all messages, but will be the same when the same webhook is resent (e.g., due to a previous failure). * `svix-timestamp`: Timestamp in seconds since epoch. * `svix-signature`: The Base64 encoded list of signatures (space delimited). ### Constructing the Signed Content The content to sign is composed by concatenating the ID, timestamp, and payload, separated by the full-stop character (`.`). In code, it will look something like this: ```js const signedContent = `${svix_id}.${svix_timestamp}.${body}`; ``` Where `body` is the raw body of the request. The signature is sensitive to any changes, so even a small change in the body will cause the signature to be completely different. This means that you should not change the body in any way before verifying. Ensure you use the **raw request body** for verification. Parsing and re-stringifying JSON will alter the content and cause verification failure. ### Determining the Expected Signature We use HMAC with SHA-256 to sign webhooks. To calculate the expected signature, HMAC the `signedContent` from above using the base64 portion of your signing secret (this is the part after the `whsec_` prefix) as the key. For example, if your secret is `whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw`, use `MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw`. For example, this is how you can calculate the signature in Node.js: ```js const crypto = require('crypto'); const signedContent = `${svix_id}.${svix_timestamp}.${body}`; const secret = "whsec_5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH"; // Need to base64 decode the secret const secretBytes = Buffer.from(secret.split('_')[1], "base64"); const signature = crypto .createHmac('sha256', secretBytes) .update(signedContent) .digest('base64'); console.log(signature); ``` This generated signature should match one of the ones sent in the `svix-signature` header. The `svix-signature` header is a list of space-delimited signatures with version identifiers. The list is typically one item but can contain multiple signatures, like this: ``` v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE= v1,bm9ldHUjKzFob2VudXRob2VodWUzMjRvdWVvdW9ldQo= v2,MzJsNDk4MzI0K2VvdSMjMTEjQEBAQDEyMzMzMzEyMwo= ``` Make sure to remove the version prefix and delimiter (e.g. `v1,`) before verifying the signature. Please note that to compare the signatures it's recommended to use a constant-time string comparison method in order to prevent timing attacks. ### Verify timestamp We include the timestamp of the attempt in the `svix-timestamp` header. Compare this timestamp against your system timestamp to ensure it’s within an acceptable tolerance to prevent replay attacks. # Supported Chains Source: https://docs.crossmint.com/introduction/supported-chains Tap into 40+ chains in one single integration Refer to the table below to see which chains are supported for which product categories. | Blockchain | │ | Smart Wallets | MPC Wallets | Minting | Checkout | Onramp | Mainnet Label | Testnet Label | | :---------------- | :-: | :-----------: | :---------: | :-----: | :------: | :----: | :----------------: | :------------------------: | | Apex | │ | - | - | - | ✅ | ✅ | `apex` | - | | Atleta | │ | ✱ | ✅ | ✅ | ✅ | ✅ | `atleta` | `atleta-testnet` | | ApeChain | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `apechain` | `curtis` | | Aptos | │ | ✱ | ✅ | ✅ | ✱ | ✱ | `aptos` | `aptos` | | Arbitrum One | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `arbitrum` | `arbitrum-sepolia` | | Arbitrum Nova | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `arbitrumnova` | `arbitrum-sepolia` | | Astar | │ | ✱ | ✅ | ✅ | ✅ | ✅ | `astar-zkevm` | `zkyoto` | | Avalanche | │ | ✱ | ✅ | ✅ | ✅ | ✅ | `avalanche` | `avalanche-fuji` | | Avalanche Subnets | │ | ✱ | ✱ | ✱ | ✱ | ✱ | `avalanche-subnet` | `avalanche-subnet-testnet` | | Base | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `base` | `base-sepolia` | | Boss | │ | - | - | - | ✅ | - | `boss` | - | | BSC | │ | ✅ | ✱ | ✱ | ✱ | ✱ | `bsc` | `bsc-testnet` | | Chiliz | │ | ✱ | ✅ | ✅ | ✅ | ✅ | `chiliz` | `chiliz-spicy-testnet` | | Coti | │ | ✱ | ✅ | ✅ | ✅ | ✅ | `coti` | `coti-testnet` | | Ethereum | │ | ✅ | ✅ | ✱ | ✅ | ✅ | `ethereum` | `ethereum-sepolia` | | Hedera EVM | │ | - | ✅ | ✅ | ✅ | ✅ | `hedera` | `hedera-testnet` | | Mantle | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `mantle` | `mantle-testnet` | | Mode | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `mode` | `mode-sepolia` | | Monad | │ | ✱ | ✱ | ✱ | ✱ | ✱ | `monad` | `monad-testnet` | | Optimism | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `optimism` | `optimism-sepolia` | | Polygon | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `polygon` | `polygon-amoy` | | Rari | │ | ✱ | ✅ | ✅ | ✅ | ✅ | `rari` | `rari-testnet` | | Sei | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `sei-pacific-1` | `sei-atlantic-2-testnet` | | Scroll | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `scroll` | `scroll-sepolia` | | Solana | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `solana` | `solana` | | Shape | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `shape` | `shape-sepolia` | | SKALE | │ | ✱ | ✅ | ✅ | ✅ | ✅ | `skale-nebula` | `skale-nebula-testnet` | | Soneium | │ | ✱ | ✅ | ✅ | ✅ | ✅ | `soneium` | `soneium-minato-testnet` | | Story | │ | ✅ | ✅ | ✅ | ✱ | ✱ | `story-mainnet` | `story-testnet` | | Sui | │ | ✱ | ✱ | ✅ | ✱ | ✱ | `sui` | - | | U2U | │ | ✱ | ✅ | ✅ | ✅ | ✅ | `u2u` | `u2u-testnet` | | Xion | │ | ✱ | ✅ | ✅ | ✅ | ✅ | `xion` | `xion-testnet` | | Xai | │ | ✱ | ✅ | ✅ | ✅ | ✅ | `xai` | `xai-sepolia-testnet` | | Zenchain | │ | ✱ | ✅ | ✅ | ✅ | ✅ | `zenchain` | `zenchain-testnet` | | Zora | │ | ✅ | ✅ | ✅ | ✅ | ✅ | `zora` | `zora-sepolia` | | Other EVM chains | │ | ✱ | ✱ | ✱ | ✱ | ✱ | | | **Legend:** * ✅ Supported * ✱ Available, but not self-serve. [Contact us](https://www.crossmint.com/contact/sales) to request it for your project. * `-` Not supported Notes: * Fungible token checkout available self service only in Solana. [Contact us](https://www.crossmint.com/contact/sales) for other chains. Contact us. We launch new chains regularly and yours is likely in the pipeline. ## Testnets You can access testnets by using the [staging console](https://staging.crossmint.com/console). Read more about the different environments [here](/introduction/platform/staging-vs-production). Please refer to the supported chains table above for details about which testnet the staging environment targets. If there is not a specific testnet listed for a chain it is not supported in staging. # Introduction Source: https://docs.crossmint.com/minting/introduction Mint and distribute tokens at scale, reliably Minting API **It takes months to build secure and reliable minting infrastructure:** 1. Write and maintain token smart contracts 2. Build a backend for orchestrating all blockchain transactions 3. Securely administer keys and crypto balances 4. Add queueing, batching, RPC redundancy, priority/gas fee estimations, e2e observability... **Crossmint manages all of this for you via a suite of APIs to create, update, delete and manage tokens of any type through REST APIs, available on any chain.** ## Key Characteristics Easiest developer experience in the market. Launch today. Forget about smart contracts, IPFS, wallet and key management... Let Crossmint handle all the infrastructure, or combine it with your own. SOC-II certified, audited smart contracts, and keys guarded by Fireblocks. Handle millions of tokens an hour and save on customer support. Tap into 40+ chains with one single integration. ## Quickstarts Mint unique digital assets you can own, transfer, and verify authentically in under 5 minutes Mint limited sets of identical digital assets in under 5 minutes Mint credentials that users control, share, and verify anywhere in under 5 minutes. Mint IP credentials for creators to secure their work, in under 5 minutes. ## Get Started Get API keys and manage collections. Test any API in seconds directly from the docs. Contact our sales team for advanced support. ## FAQs No, you can migrate providers anytime, transfering ownership of the smart contracts to an external wallet. Yes, you can transfer ownership at any time. However, note that Crossmint APIs (eg. minting, editing NFTs) may stop working on that contract unless you whitelist Crossmint on the contract to continue executing those actions. If you transfer ownership of the contract to your own wallet, you are responsible for ensuring the security of that wallet. When you create an account, Crossmint automatically creates a gas station to manage network fees on your behalf. You will be billed in fiat and Crossmint will ensure you never run out of funds to support customer operations. This eliminates the need to build a cryptoaccounting system, execute recurring and expensive crypto purchases, holding the FX risk, and automating treasury operations. When you create an account, Crossmint will automatically create a dedicated MPC vault to secure your token contracts which you can manage via API. You get one vault per project, in case you are working with multiple teams. You can transfer ownership of the contracts to an external wallet at any time. # Bring Your Own Contract Source: https://docs.crossmint.com/minting/nfts/integrate/bring-your-own-contract Use Crossmint's infrastructure with your own smart contract Crossmint allows you to use your own smart contract while leveraging our infrastructure for minting NFTs. This guide will walk you through the process of integrating your custom smart contract with Crossmint. ## Prerequisites Before you can use your own smart contract with Crossmint, ensure that: 1. Your smart contract has a **free minting function** that allows Crossmint to mint NFTs without paying for gas. 2. Your smart contract complies with the **ERC721 standard** (for NFTs) or **ERC1155 standard** (for SFTs). Currently, this feature is only available for EVM chains. Support for Solana and other chains is coming soon. ## Integration Guide ### 1. Register Your Smart Contract First, you need to register your smart contract with Crossmint: ```bash cURL curl --request POST \ --url https://staging.crossmint.com/api/2022-06-09/collections/custom \ --header 'Content-Type: application/json' \ --header 'X-API-KEY: ' \ --data '{ "chain": "polygon", "contractAddress": "0x123...", "metadata": { "name": "My Custom Collection", "description": "A collection using my own smart contract" } }' ``` ### 2. Contract Review After registering your contract, the Crossmint team will review it to ensure compatibility with our infrastructure. This typically takes 1-2 business days. During the review process, we'll verify that your contract has the necessary free minting function and complies with the required standards. ### 3. Mint NFTs Once your contract is approved, you can start minting NFTs using the Crossmint API: ```bash cURL curl --request POST \ --url https://staging.crossmint.com/api/2022-06-09/collections/{collectionId}/nfts \ --header 'Content-Type: application/json' \ --header 'X-API-KEY: ' \ --data '{ "recipient": "polygon:0x123...", "contractFunction": { "name": "mintTo", "params": [ { "name": "to", "type": "address", "value": "$RECIPIENT_ADDRESS" }, { "name": "tokenId", "type": "uint256", "value": "1" } ] } }' ``` The `$RECIPIENT_ADDRESS` placeholder will be automatically replaced with the recipient's address by Crossmint. ## Contract Function Parameters When using your own smart contract, you need to specify the contract function to call and its parameters: * **name**: The name of the function in your smart contract that mints NFTs. * **params**: An array of parameters to pass to the function. * **name**: The parameter name as defined in your smart contract. * **type**: The parameter type (e.g., address, uint256, string). * **value**: The value to pass to the parameter. You cannot pass custom metadata as a parameter. Metadata is controlled at the smart contract level when using your own contract. ## Example: Minting with a Custom Contract Here's an example of minting an NFT using a custom contract with a `mintTo` function: ```javascript const apiKey = "YOUR_API_KEY"; const collectionId = "your-custom-collection-id"; const env = "staging"; // or "www" for production const recipient = "polygon:0x123..."; // Recipient's wallet address const url = `https://${env}.crossmint.com/api/2022-06-09/collections/${collectionId}/nfts`; const options = { method: "POST", headers: { accept: "application/json", "content-type": "application/json", "x-api-key": apiKey, }, body: JSON.stringify({ recipient, contractFunction: { name: "mintTo", params: [ { name: "to", type: "address", value: "$RECIPIENT_ADDRESS", }, { name: "tokenId", type: "uint256", value: "42", }, ], }, }), }; fetch(url, options) .then((response) => response.json()) .then((data) => console.log("NFT minted:", data)) .catch((error) => console.error("Error minting NFT:", error)); ``` ## Best Practices When using your own smart contract with Crossmint: 1. **Test Thoroughly**: Test your contract integration in the staging environment before moving to production. 2. **Function Visibility**: Ensure your minting function has the appropriate visibility and access controls. 3. **Gas Optimization**: Optimize your contract to minimize gas costs for minting operations. 4. **Error Handling**: Implement proper error handling in your contract to provide meaningful error messages. ## FAQs Yes, you can use an existing deployed contract as long as it meets the prerequisites mentioned above. Your contract must have a function that allows Crossmint to mint NFTs without paying for gas. If your contract doesn't have this, you'll need to modify it or deploy a new version. Yes, you can still use Crossmint's email delivery system with your own contract. Just specify an email recipient in the mint request. Token ID management depends on your contract implementation. You can either pass a specific token ID as a parameter or let your contract handle token ID assignment internally. # Configure Admin Functions Source: https://docs.crossmint.com/minting/nfts/integrate/configure-admin-functions Manage token controls including admin burn and admin transfer Crossmint provides admin functions that allow you to control your NFTs throughout their lifecycle. ## Admin Transfer The NFT Admin Transfer API allows collection owners to transfer NFTs between user wallets. Admin transfers only work for Solana cNFTs. [Contact us](https://www.crossmint.com/contact/sales) if you want to access to this API. ## Admin Burn The [Burn NFT API](/api-reference/minting/nfts/burn-nft) allows collection owners to permanently remove NFTs from circulation. Once an NFT is burned, this action cannot be reversed. ## Requirements To use admin functions: 1. Your collection must be of a supported type (Solana cNFTs for transfers, Solana cNFTs or EVM for burns) 2. Your API key must have the appropriate scopes (`nfts.transfer` for transfers, `nfts.delete` for burns) 3. You must be the collection owner or have admin privileges # Create Collections Source: https://docs.crossmint.com/minting/nfts/integrate/create-collections Deploy smart contracts and NFT collections A collection is a container of NFTs, used by applications like marketplaces and wallets to group NFTs together. Crossmint allows you to create managed collections via API or directly from the console. Crossmint has a library of pre-audited smart contracts which work for most major use cases. However, you can also [bring your own contract](/minting/nfts/integrate/bring-your-own-contract) if you already have one. Crossmint supports non-fungible and semi-fungible tokens (editions), free and paid mints, and builds on open ERC and Metaplex standards. On EVM chains, ERC-721 and ERC-1155 contracts are supported, while on Solana, Metaplex standard programs and compressed NFT programs are supported. See the list of supported blockchains [here](/introduction/supported-chains) ## 1. Create and Deploy an NFT collection The first time you mint an NFT on a specific blockchain, Crossmint will assign it, and any subsequent mints, to a default collection for that chain. You can create additional collections from the console or in a single API call (requires the API key scope `collections.create`): ```bash cURL curl --request POST \ --url https://staging.crossmint.com/api/2022-06-09/collections/ \ --header 'content-type: application/json' \ --header 'x-api-key: ' \ --data ' { "chain": "polygon", "metadata": { "name": "A new collection", "imageUrl": "https://www.crossmint.com/assets/crossmint/logo.png", "description": "A new collection with its own dedicated smart contract" } } ' ``` The collection details you provide will be displayed to your customers on marketplaces and other interfaces. If you intend to sell the NFTs in your collection, read the guide on [how to enable payments](/minting/nfts/integrate/list-for-sale) first. ## 2. Check the status of your collection It takes a few seconds (up to a minute, depending on the blockchain and how congested it is) to deploy a collection. You can use the following API to check collection status API to check what the status of a collection is. For example: ```bash cURL curl --request GET \ --url https://staging.crossmint.com/api/2022-06-09/collections/default-solana \ --header 'x-client-secret: ' \ --header 'x-project-id: ' ``` ## 3. List all collections under your project ```bash cURL curl --request GET \ --url https://staging.crossmint.com/api/2022-06-09/collections/ \ --header 'x-client-secret: ' \ --header 'x-project-id: ' ``` Test any API in seconds directly from the docs. Contact our sales team for support. # Define Metadata Source: https://docs.crossmint.com/minting/nfts/integrate/define-metadata Understand NFT metadata standards & storage options Metadata in the context of NFTs includes essential information such as the name, description, and media (e.g., images, videos) associated with the asset. ### Metadata Standards Collection and NFT metadata (e.g. title, description, image) must be specified in JSON format and follow industry conventions to ensure it renders appropriately across wallets and marketplaces. Crossmint supports rich metadata like audio, video, and HTML. To include rich metadata, simply populate `animation_url` as specified in the links below. Crossmint's standard plan has a **10mb** file size limit. For larger uploads, you must upgrade to a [premium plan](https://www.crossmint.com/contact/sales) or handle the upload yourself. Metadata standards differ slightly across blockchains: EVM chains follow the OpenSea standard. Refer to their official documentation to see what attributes can be included and how. Note that `name` and `image` are mandatory fields. ```json EVM Metadata Example { "name": "Crossmint Test NFT", "description": "Created with the Crossmint minting API", "image": "https://bafkreiexjl6kw4khdxkrt6dojgacscnzvrys47t472l2t7d6r2ss65kifq.ipfs.nftstorage.link/", "external_url": "https://docs.crossmint.com", "attributes": [ { "trait_type": "background", "value": "black" }, { "trait_type": "flavor", "value": "minty" } ] } ``` Solana follows the Metaplex Metadata Standard. For more information, refer to the official Metaplex documentation - see the JSON structure section. ```json Solana Metadata Example { "name": "Crossmint Test NFT", "symbol": "XMINT", "description": "Created with the Crossmint minting API", "seller_fee_basis_points": 5000, "image": "https://bafkreiexjl6kw4khdxkrt6dojgacscnzvrys47t472l2t7d6r2ss65kifq.ipfs.nftstorage.link/", "attributes": [ { "trait_type": "background", "value": "black" }, { "trait_type": "flavor", "value": "minty" } ], "properties": { "files": [ { "uri": "https://bafkreiexjl6kw4khdxkrt6dojgacscnzvrys47t472l2t7d6r2ss65kifq.ipfs.nftstorage.link/", "type": "image/png" } ], "category": "image", "creators": [ { "address": "xm2Mc3HEd2bGJXeqJEBrek4bj79gxzYkBaEobnpFraH", "share": 100 } ] } } ``` Aptos follows the Aptos Legacy Token Standard. For more information, refer to the official Aptos Documentation - see the JSON structure section. ```json Aptos Metadata Example { "name": "Crossmint Test NFT", "description": "Aptos Attributes Test", "image": "https://www.arweave.net/abcd5678?ext=png", "animation_url": "https://www.arweave.net/efgh1234?ext=mp4", "external_url": "https://petra.app/", "attributes": [ { "trait_type": "web", "value": "yes" }, { "trait_type": "mobile", "value": "yes" }, { "trait_type": "extension", "value": "yes" } ], "properties": { "files": [ { "uri": "https://www.arweave.net/abcd5678?ext=png", "type": "image/png" }, { "uri": "https://watch.videodelivery.net/9876jkl", "type": "unknown", "cdn": true }, { "uri": "https://www.arweave.net/efgh1234?ext=mp4", "type": "video/mp4" } ], "category": "video" } } ``` ## Crossmint Metadata Storage Metadata must be stored somewhere to be accessible and verifiable on the blockchain. Crossmint automatically uploads and validates metadata for you on decentralized storage solutions, ensuring a seamless minting experience. ### Supported Storage Providers Crossmint supports two primary storage providers: * **IPFS (InterPlanetary File System)** (Default): A widely adopted decentralized storage standard ensuring compatibility across blockchain ecosystems by enabling peer-to-peer file storage and retrieval. * **Walrus Network**: A new decentralized storage solution designed for efficient and scalable metadata hosting. Walrus is currently not supported for EVM NFT templates. If you are interested in using **Arweave** for metadata storage, please contact us for further information. ### Configuring Storage By default, Crossmint uses IPFS to store metadata and media. However, if you prefer to use Walrus, you can configure this in the [Crossmint Console](https://staging.crossmint.com/console) under **Settings > General**. ![Storage Providers](https://mintlify.s3.us-west-1.amazonaws.com/crossmint/images/minting/storage-providers.png) {" "} If you prefer to upload and manage media files independently, you can pass a direct URL to the [Mint API](/api-reference/minting/nfts/mint-nft) and set the `reuploadLinkedFiles` flag to `false`. This prevents Crossmint from automatically reuploading media files to decentralized storage. *** ## FAQs You may store any text and image file. Additionally, you may include multi-media files such as GLTF, GLB, WEBM, MP4, M4V, OGV, and OGG, along with the audio-only extensions MP3, WAV, and OGA. Please stored them as `animation_url`. In addition, `animation_url` also supports HTML pages, allowing you to build rich experiences and interactive NFTs using JavaScript canvas, WebGL, and more. Scripts and relative paths within the HTML page are also supported. However, access to browser extensions is not supported. The maximum file size is 10mb. For larger files, you must upgrade to an enterprise plan or upload the metadata yourself and pass the URI to the API. Yes. You must handle the upload yourself and pass the URL to the API. # List for Sale Source: https://docs.crossmint.com/minting/nfts/integrate/list-for-sale Configure royalties and marketplace profiles for your NFT collections When selling NFTs on secondary markets, you can configure royalties to receive a percentage of each sale and optimize your collection's marketplace profile to attract buyers. ## Sell Tokens The [minting guide](/minting/nfts/integrate/mint-tokens) showed you how to create NFTs. In this guide you will learn how to enable Crossmint's Checkout so you can sell them to your customers using cryptocurrency or credit card. ### How It Works * You can set a price in crypto (ETH, MATIC, SOL or USDC). * For imported and secondary collections, payouts arrive instantly. For managed collections, payouts arrive after a 24-hour withholding period. * Your customers can pay with crypto or credit card. * You pay credits for NFT gas, user pays only for the item. ### Configure a Collection for Sale 1. [Create an NFT collection](/minting/nfts/integrate/create-collections) and navigate to it in the console. 2. Upload NFT "templates" for all the NFTs you wish to list for sale. You can do so from the "NFTs" tab in the console, or by using [the API](/api-reference/minting/template/create-template). 3. Navigate to the `Checkout` entry on the navbar in the collections page. Follow the wizard to enable payments. 4. (Production only) [Verify your account and collection](/introduction/platform/account-verification). Not required in staging. 5. Share the url or QR code with your users. **Enable at collection creation time** Pass a `payments` object to the [Collection Creation API](/api-reference/minting/collection/create-collection) with the `price`, `recipientAddress` and `currency`. You can optionally set up a `supplyLimit` to cap the collection supply. The following snippet creates a new sales-enabled collection: ```bash cURL curl --request POST \ --url https://staging.crossmint.com/api/2022-06-09/collections/ \ --header 'Content-Type: application/json' \ --header 'X-API-KEY: ' \ --data '{ "chain": "polygon", "fungibility": "non-fungible", "metadata": { "description": "This is a sample NFT collection", "imageUrl": "https://www.crossmint.com/assets/crossmint/logo.png", "name": "Sample NFT Collection", }, "payments": { "price": "", "recipientAddress": "", "currency": "usdc" }, "supplyLimit": 123 }' ``` **Enable on an existing collection** If you had already created a collection, use the [Update Collection API](/api-reference/minting/collection/update-collection) to enable sales on it. Enabling sales in production requires [verifying your account](/introduction/platform/account-verification). *** ### Set Up a Checkout Now that your collection accepts payments, the next step is to integrate one of Crossmint's [Checkout](/payments/introduction) variants into your app or website, and start accepting sales. There are two ways to integrate: Add a button to your site which opens a checkout in a pop-up or new tab. Insert a checkout inside your site for maximum control over the user experience. ## Set Collection Royalties With royalties, you can receive revenue when your NFTs are traded on secondary markets. Crossmint allows you to configure royalties for a collection via API and (soon) directly from the console. You just have to specify the % of royalties and where you want those funds to be sent. Royalties are defined at the collection level, not at the NFT level. Updating the royalties of a collection will update all NFTs, including the ones which have already been minted. This API follows royalty standards compatible with virtually all marketplaces. However, note that some marketplaces have determined to not honor royalties, so transactions occuring there may not generate additional revenue. Available self-serve for ERC-721 collections in EVM chains. Please [contact us](https://www.crossmint.com/contact/sales) for ERC-1155 or Solana support. | Endpoint | Description | | | :------------------------------------------------------------------------- | :---------------------- | :- | | [Add / Edit Royalties](/api-reference/minting/collection/set-royalties) | Add or edit royalties | | | [Get Royalty Information](/api-reference/minting/collection/get-royalties) | Get royalty information | | | [Disable Royalties](/api-reference/minting/collection/disable-royalties) | Disable royalties | | ### Add / Edit Royalties To add or edit royalties for a collection, use the following API endpoint: ```bash cURL curl --request POST \ --url https://staging.crossmint.com/api/v1-alpha1/minting/collections/{collectionId}/royalties \ --header 'Content-Type: application/json' \ --header 'X-API-KEY: ' \ --data '{ "recipients": [ { "address": "0x123...", "percentage": 5 } ] }' ``` ### Get Royalty Information To retrieve the current royalty configuration for a collection: ```bash cURL curl --request GET \ --url https://staging.crossmint.com/api/v1-alpha1/minting/collections/{collectionId}/royalties \ --header 'X-API-KEY: ' ``` ### Disable Royalties To disable royalties for a collection: ```bash cURL curl --request DELETE \ --url https://staging.crossmint.com/api/v1-alpha1/minting/collections/{collectionId}/royalties \ --header 'X-API-KEY: ' ``` ## Implementation Examples ```javascript // Example: Setting up royalties for a new collection const apiKey = "YOUR_API_KEY"; const collectionId = "your-collection-id"; const env = "staging"; // or "www" for production // Define royalty recipients const royaltyRecipients = [ { address: "0x123abc...", // Creator wallet basisPoints: 5 // 5% royalty }, { address: "0x456def...", // Community fund wallet basisPoints: 2.5 // 2.5% royalty } ]; // Set up royalties const url = `https://${env}.crossmint.com/api/v1-alpha1/minting/collections/{collectionId}/royalties`; const options = { method: "POST", headers: { "Content-Type": "application/json", "X-API-KEY": apiKey }, body: JSON.stringify({ recipients: royaltyRecipients }) }; fetch(url, options) .then(response => response.json()) .then(data => console.log("Royalties configured:", data)) .catch(error => console.error("Error configuring royalties:", error)); ``` ## Marketplace Profile Optimizing your collection's profile on marketplaces like OpenSea, Rarible, and others can significantly impact your NFT sales and visibility. At this time, updating your collection profile on OpenSea, Rarible, and other marketplaces requires manual work and is limited to enterprise clients. ### Key Marketplace Profile Elements When working with our enterprise team to configure your marketplace profile, consider these important elements: 1. **Collection Banner**: A high-quality banner image that represents your brand 2. **Collection Logo**: A distinctive logo that's recognizable at small sizes 3. **Collection Description**: A compelling description of your project and its value 4. **External Links**: Links to your website, social media, and community channels 5. **Category Tags**: Appropriate categories that help collectors discover your NFTs ## FAQs Royalty enforcement varies by marketplace. Some marketplaces like OpenSea have made royalties optional, while others still enforce them. Crossmint implements royalties according to blockchain standards, but cannot guarantee enforcement across all marketplaces. No, royalties are set at the collection level and apply to all NFTs within that collection. If you need different royalty structures, consider creating separate collections. Royalty changes take effect immediately for new listings. For existing listings on marketplaces, the timing depends on how frequently each marketplace refreshes metadata. While technically there's no upper limit, most marketplaces and collectors expect royalties between 2.5% and 10%. Setting royalties too high may discourage secondary market activity. # Manage Delivery Source: https://docs.crossmint.com/minting/nfts/integrate/manage-delivery Configure recipient options and customize email delivery notifications Crossmint provides flexible options for delivering NFTs to recipients and customizing the delivery experience. This guide covers how to specify different types of recipients and how to customize the email notifications they receive. ## Specify Recipients You can deliver NFTs to three kinds of recipients when using minting APIs: * [Wallet address](#send-nft-to-wallet-address): directly specify a wallet address, which could be a user owned wallet (e.g. MetaMask, Phantom, etc.) or a wallet you manage. * [Email address](#send-nft-to-email-address): in this modality, Crossmint automatically generates a secure MPC backed custodial wallet for the email, and delivers the NFT inside. * [User identifier](#send-nft-by-userid): in this modality, Crossmint automatically generates a wallet and associates it with an user ID from your application, and delivers the NFT inside. You must build the interface for users to access this wallet. Check out the [create-wallet](/api-reference/wallets/create-wallet) endpoint in the API reference if you wish to pre-create a wallet prior to invoking the mint API. ### Send NFT to Wallet Address To mint an NFT directly to an existing blockchain address, the following `recipient` format is used: ```bash :
``` For a full list of chain names, refer to the [Supported Chains](/introduction/supported-chains) page. #### Examples * EVM: `polygon:0x123...` * Solana: `solana:3Q5...` * Aptos: `aptos:0x0f07...` ### Send NFT to Email Address To mint an NFT and send it to an email address, the following `recipient` format is used: ```bash email:: ``` #### Examples * EVM: `email:demo@test.com:polygon` * Solana: `email:demo@test.com:solana` Minting to an email address is not currently supported on Aptos. The NFT can then be accessed by logging into Crossmint with the specified email address: * for `staging/testnet` NFTs: [https://staging.crossmint.com/user/collection](https://staging.crossmint.com/user/collection) * for `mainnet` NFTs: [https://www.crossmint.com/user/collection](https://www.crossmint.com/user/collection) ### Send NFT to a Twitter/X account To mint an NFT to a Twitter/X account, the following `recipient` format is used: ```bash twitter:: ``` #### Examples * EVM: `twitter:@username:polygon` * Solana: `twitter:@username:solana` ### Send NFT by `userId` This method allows you to deliver NFTs by directly specifying the user identifier of the recipient in your system. Crossmint will fetch a custodial wallet linked to that user identifier inside your project or, if none exists, create one on the fly. Then the NFT will be delivered there. This way, you don't need to keep a mapping between your user identifiers and their wallets, just pass your user id and crossmint takes care of the rest. Wallets created with the `userId` option cannot be accessed by logging into Crossmint.com. To mint an NFT to this type of recipient, follow this format: ```bash userId:: ``` #### Examples * EVM: `userId:user1234:polygon` * Solana: `userId:user1234:solana` ## Customize Delivery Emails Email delivery notifications can be customized to align with your branding and communication needs. This section will walk you through how to configure your email template. ### Edit the email template To adjust the visual presentation and branding of your email notifications: 1. In the Crossmint Console, click on Settings, and navigate to the **Branding** tab. 2. Select **Deliver NFT via email** from the dropdown options. 3. Here, you can customize: * The **logo** displayed in the email with your logo. This will default to Crossmint's logo, unless specified otherwise. * The main **button's color** . This will default to #04AA6D (Crossmint's green). * The **display name** textbox to include your brand's name. This will be empty, by default. As you make adjustments, you can preview the changes. Once satisfied, save your changes and now they will apply to all future minting email notifications, related to this project. Emails now reflect your project's brand identity while providing essential delivery information to recipients. ![Customize email template](https://mintlify.s3.us-west-1.amazonaws.com/crossmint/images/minting/delivery-email.jpg) ### Enable email delivery You should make sure email delivery notifications are enabled for the customized email to reach your users. For new projects created after [Sep 16,2024](/changelog/2024-09-16), the "sendNotification" parameter is set to `true` by default, meaning mint recipients will automatically receive email notifications. For legacy projects, created before Sep 16 2024, "sendNotification" is set to `false` until March 14, 2025. If you choose so, you can enable email notifications for legacy projects by explicitly turning the feature on via API or via the Console. #### Console To send email notifications to NFT recipients: 1. Navigate to an **unminted NFT** part of a Collection in the Crossmint Console. 2. Click on the **more options** button and select **Mint & send NFT**. 3. Ensure the **Notify recipient via email** option is selected. 4. Enter the **recipient's email address** and press Mint. The recipient will receive an email delivery notification for their newly minted NFT. #### API To do the same programmatically, you can configure two new parameters: 1. **sendNotification** (boolean): Determines whether the recipient will receive an email notification. * Default value: `true` for new projects created after Sep 16, 2024. * For legacy projects (created before Sep 16, 2024), this feature will default to `false` until March 14, 2025, unless explicitly set to `true`. 2. **locale** (string): Specifies the language for the email content. Default is `en-US` for English. We support all locales (i.e. "es-ES" for Spanish). ## FAQs Yes, recipients can manage their email preferences through their Crossmint account settings. If an email address is invalid, the NFT will still be minted but the notification will fail to deliver. The NFT will be associated with the email address in Crossmint's system, but the recipient won't receive a notification. Currently, each API call mints to a single recipient. For bulk operations, you'll need to make multiple API calls. See the [Mint In Bulk](/minting/nfts/integrate/mint-in-bulk) guide for more information. Crossmint doesn't currently provide delivery tracking for email notifications. For critical notifications, consider implementing your own email delivery system alongside Crossmint's. # Mint In Bulk Source: https://docs.crossmint.com/minting/nfts/integrate/mint-in-bulk Scale your NFT operations with bulk minting capabilities Crossmint's infrastructure is designed to handle high-volume minting operations efficiently, allowing you to scale your NFT projects to serve thousands or even millions of users. ## Enterprise Solutions For enterprise customers with very high volume requirements, Crossmint offers additional capabilities: Enterprise bulk minting features are available for high-volume projects. Please [contact us](https://www.crossmint.com/contact/sales) to discuss your specific requirements. ## Bulk Minting Capabilities Crossmint's platform offers several advantages for bulk minting operations: * **High Throughput**: Mint thousands of NFTs per hour with optimized transaction batching * **Cost Efficiency**: Reduce gas costs through intelligent transaction scheduling * **Queue Management**: Automatic handling of transaction queues and retries * **Observability**: Track the status of all minting operations in real-time * **Gas Optimization**: Automatic gas price adjustments based on network conditions ## Bulk Minting via Crossmint Console The Crossmint Console provides an easy-to-use interface for uploading and minting NFTs in bulk. Here's how to use it: ### Step 1: Access the Batch Upload Feature In the Crossmint Console, navigate to your collection and select the "Batch upload" option. ![Batch Upload Option](https://mintlify.s3.us-west-1.amazonaws.com/crossmint/images/minting/batch-upload.png) ### Step 2: Prepare Your Metadata Before uploading your assets, you need to prepare them properly: 1. You can upload up to 1,000 NFT collectibles at once 2. Download the example CSV file provided by Crossmint to use as a template 3. Prepare your metadata according to the template format ![Batch Upload Interface](https://mintlify.s3.us-west-1.amazonaws.com/crossmint/images/minting/batch-upload-file.png) ### Step 3: Upload Your Metadata CSV 1. Add a CSV file named `metadata.csv` with your NFT metadata 2. Click the "Upload CSV" button to upload your prepared file ![Batch Upload Interface](https://mintlify.s3.us-west-1.amazonaws.com/crossmint/images/minting/batch-upload-media.png) ### Step 4: Upload Media Files 1. Prepare your NFT media files (images, animations, videos) 2. Crossmint supports various formats (PNG, JPEG, GIF etc.) 3. Each file must be under 10MB in size 4. All media files should be in the same folder, not in subfolders 5. Click "Upload media files" to upload your prepared media ![Batch Upload Interface](https://mintlify.s3.us-west-1.amazonaws.com/crossmint/images/minting/batch-upload-ready.png) ### Step 5: Complete the Upload After uploading both your metadata CSV and media files, click the "Upload" button to start the batch minting process. ![Batch Upload Interface](https://mintlify.s3.us-west-1.amazonaws.com/crossmint/images/minting/batch-upload-processed.png) ## Monitoring Bulk Operations When minting in bulk, it's essential to track the status of your operations: 1. **Webhooks**: Set up [webhooks](/minting/nfts/integrate/webhooks-and-status-apis) to receive real-time notifications about mint completions and failures 2. **Status API**: Use the [action status API](/minting/nfts/integrate/webhooks-and-status-apis) to check the status of individual minting operations 3. **Console Dashboard**: Monitor your minting operations through the Crossmint Console # Mint Tokens Source: https://docs.crossmint.com/minting/nfts/integrate/mint-tokens Create and distribute tokens at scale To mint and airdrop unique digital assets, you can follow the guide on the [Quickstart](/minting/quickstarts/nfts). For more detail, please check the [API reference](/api-reference/minting/nfts/mint-nft). You can watch a quick video tutorial for this [here](https://youtu.be/yYJRW35zqUQ?si=b6PQTbZ7zqYVGwXw). SFTs (semifungible tokens) follow the ERC-1155 standard. Each token is a replica of a predefined template. Each collection (smart contract) can contain multiple templates, which can contain many tokens. To get started, it's recommended to read the [Introduction](/minting/introduction) for general information on how the minting product works. This API only supports EVM chains self-serve. Contact us if you need support for another chain. ## 1. Create an SFT collection to hold your templates ```bash cURL curl --request POST \ --url https://staging.crossmint.com/api/2022-06-09/collections \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data ' { "chain": "polygon", "fungibility": "semi-fungible", "metadata": { "name": "My New Collection", "imageUrl": "https://www.crossmint.com/assets/crossmint/logo.png", "description": "A new collection with its own dedicated smart contract" } }' ``` ```json JSON { "id": "5263650e-6d43-4ed3-9e31-0cf593d076a4", "metadata": { "name": "Test Collection", "description": "Test", "imageUrl": "https://cdn.io/metadata.json", "symbol": "XMINT" }, "fungibility": "semi-fungible", "onChain": { "chain": "polygon", "type": "erc-1155" }, "actionId": "5263650e-6d43-4ed3-9e31-0cf593d076a4" } ``` ## 2. Create a template within that collection ```bash cURL curl --request POST \ --url https://staging.crossmint.com/api/2022-06-09/collections/{COLLECTION_ID}/templates \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data ' { "onChain": { "tokenId": "2" }, supply: { limit: 10 }, "metadata": { "name": "My template", "image": "https://www.crossmint.com/assets/crossmint/logo.png", "description": "A new token template for my ERC1155 collection" } }' ``` ```json JSON { "templateId": "58b0c1aa-e457-48dd-bb55-5a27e6a92f74", "metadata": { "name": "My template", "image": "ipfs://bafkreigbqsmxzkbjgbwtj6exfdt5z3t3swgoysf7hr6vjzddqnmykj6x2u", "description": "A new token template for my ERC1155 collection" }, "onChain": { "tokenId": "1" }, "supply": { "limit": "10", "minted": "0" } } ``` ## 3. Mint an SFT from a template Mint SFTs from the template and send them to wallets or email addresses. ```bash cURL curl --request POST \ --url https://staging.crossmint.com/api/2022-06-09/collections/{COLLECTION_ID}/sfts \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --header 'x-api-key: YOUR_API_KEY' \ --data ' { "templateId": "58b0c1aa-e457-48dd-bb55-5a27e6a92f74", "recipient": "email:user@example.com:polygon", "amount": 1 }' ``` ```json JSON { "actionId": "a91c15e3-60f2-4a45-bf1a-cee508981667", "action": "nfts.create", "status": "pending", "data": { "chain": "polygon", "collection": { "id": "84e3d617-9c1b-4e7a-9686-522a9ea7c520", "contractAddress": "0x9b8ab8949bd7E73E61945b88F7fe12151f98ad3C" }, "recipient": { "walletAddress": "0xcFDc00Cf926A5053f9Cdf004e6DF17e6dEB2E146", "email": "testy@crossmint.com" }, "token": { "id": "a91c15e3-60f2-4a45-bf1a-cee508981667" } }, "startedAt": "2024-01-02T22:05:01.000Z", "resource": "https://staging.crossmint.com/api/2022-06-09/actions/a91c15e3-60f2-4a45-bf1a-cee508981667" } ``` **All set!** To confirm delivery, use the [transaction status API](/minting/nfts/integrate/webhooks-and-status-apis) or set up a [webhook](/minting/nfts/integrate/webhooks-and-status-apis). ## What are Compressed NFTs? Compressed NFTs are a new standard on the Solana blockchain, for minting NFTs with the lowest cost amongst L1 and L2 blockchains, and the highest throughput (thousands of NFTs per second). Read more details about how it works [here](https://www.metaplex.com/posts/expanding-digital-assets-with-compression-for-nfts). Using this standard to mint NFTs is extremely complicated if you manage everything on your own. On top of the intrinsic complexity usually required to mint a regular NFT, compressed NFTs require deploying and managing Merkle trees, batching, and dealing with nascent infrastructure. Crossmint also supports updating the NFT metadata after minting. Please refer to this [doc page](/minting/nfts/integrate/update-nfts). Here's where Crossmint can help: we've done all the hard work so that minting compressed NFTs is no harder than minting regular ones: all it takes is a single API call, and you can even use one of Crossmint's no-code tools to do so. ## Current Protocol Limitations * There's a 10-30 second delay between when an NFT is minted and it shows in wallets. ## How to use the Minting API with Compressed NFTs The Minting API for Compressed NFTs is exactly the same as for regular NFTs, but it only works on the Solana blockchain. POST `https://staging.crossmint.com/api/2022-06-09/collections//nfts` You can mint both compressed and non-compressed NFTs on the same collection. ```bash cURL curl --request POST \ --url https://staging.crossmint.com/api/2022-06-09/collections/default-solana/nfts \ --header 'Content-Type: application/json' \ --header 'X-API-KEY: ' \ --data '{ "recipient": "solana:VALID_SOLANA_WALLET_ADDRESS", "metadata": { "name": "Crossmint Example NFT", "image": "https://www.crossmint.com/assets/crossmint/logo.png", "description": "My NFT created via the mint API!" }, "compressed": true, "reuploadLinkedFiles": false }' ``` The above will return an NFT ID. Use it in the next call to retrieve the mint status. ```bash cURL curl --request GET \ --url https://staging.crossmint.com/api/2022-06-09/collections/{COLLECTION_ID}/nfts/{YOUR_NFT_ID} \ --header 'X-API-KEY: X_API_KEY' ``` Be sure to replace: * `X_API_KEY`, `{COLLECTION_ID}` and `{YOUR_NFT_ID}` * Recipient: change `VALID_WALLET_ADDRESS` with the wallet you want to send the NFT to * Metadata: add the name, image, and description. Other explorers, like Solscan, still have not added support. There are two ways to set the transferrability of NFTs: 1. Defining it at the smart contract level 2. If you are using custodial wallets, enabling or disabling transfers from the frontend If you want to configure it at the smart contract level, see the following endpoints: | Endpoint | Chain | Description | | ---------------------------------------------------------------------------- | ------------- | --------------------------------- | | [Set Transferability](/api-reference/minting/collection/set-transferability) | EVM and Aptos | Set transferability to on or off | | [Get Transferability](/api-reference/minting/collection/get-transferability) | EVM and Aptos | Get transferability configuration | For Solana or other non-EVM chain support, [contact us](https://www.crossmint.com/contact/sales) *** The API also has an idempotent version which prevents you from calling the same API action multiple times and mitigates the risk of unwanted NFT duplicates. ## Advanced Guides # Pricing Source: https://docs.crossmint.com/minting/nfts/integrate/pricing Crossmint Mint API Pricing ## Chain operations pricing *All values shown in USD.* | Chain | Create Collection | Update Collection | Mint NFTs | Update Royalty | Update Metadata | | :-------------- | ----------------: | ----------------: | -----------: | -------------: | --------------: | | Aptos | \$0.10 | Not supported | \$0.01 | Not supported | Not supported | | Arbitrum\* | \$0.03 + gas | \$0.03 + gas | \$0.03 + gas | \$0.03 + gas | \$0.03 + gas | | Arbitrum Nova\* | \$0.01 + gas | \$0.01 + gas | \$0.01 + gas | \$0.01 + gas | \$0.01 + gas | | Avalanche\* | \$0.10 + gas | \$0.10 + gas | \$0.10 + gas | \$0.10 + gas | \$0.10 + gas | | Base\* | \$0.08 + gas | \$0.08 + gas | \$0.08 + gas | \$0.08 + gas | \$0.08 + gas | | BSC\* | \$0.01 + gas | \$0.01 + gas | \$0.01 + gas | \$0.01 + gas | \$0.01 + gas | | Chiliz | \$1 | \$0.20 | \$0.50 | \$0.20 | \$0.20 | | Mode | \$0.05 | \$0.05 | \$0.05 | \$0.05 | \$0.05 | | Optimism\* | \$0.06 + gas | \$0.06 + gas | \$0.06 + gas | \$0.06 + gas | \$0.06 + gas | | Polygon | \$0.50 | \$0.50 | \$0.10 | \$0.50 | \$0.05 | | Rari | \$0.20 | \$0.20 | \$0.20 | \$0.20 | \$0.20 | | Sei | \$0.05 | \$0.01 | \$0.01 | \$0.01 | \$0.01 | | Shape | \$2 | \$2 | \$2 | \$2 | \$2 | | Solana | \$8 | Not supported | \$0.02 | Not supported | \$0.02 | | Skale Nebula | \$0.01 | \$0.01 | \$0.01 | \$0.01 | \$0.01 | | Viction | \$0.01 | \$0.01 | \$0.01 | \$0.01 | \$0.01 | | Xai | \$0.01 | \$0.01 | \$0.01 | \$0.01 | \$0.01 | | Zora\* | \$0.08 + gas | \$0.08 + gas | \$0.08 + gas | \$0.08 + gas | \$0.08 + gas | \*For some chains (Arbitrum, Arbitrum Nova, Avalanche, Base, BSC, Optimism, and Zora), gas fees are added to the base price. Gas fees are determined at the time the operation is submitted and depend on blockchain network congestion. For more details, or to discuss custom pricing for large operations volumes, [contact our sales team](https://www.crossmint.com/contact/sales). # Set up a Claims Page Source: https://docs.crossmint.com/minting/nfts/integrate/set-up-a-claims-page Deploy a website for your users to come claim your NFTs The [minting guide](/minting/nfts/integrate/mint-tokens) showed you how to create NFTs. In this guide you will learn how to set up a website where users can claim those NFTs into their wallets, for free. ## Key Characteristics * **Easy to set up**: no coding required. * **No wallet required**: users can claim an NFT to their existing wallet, or, if they didn't have one, enter an email address and have a wallet created on the fly. * **Bot protection**: comes with signature protected mint function, reCAPTCHA, Cloudflare rate-limiting, and optional password protection. * **Blockchain-less UX**: users don't need to sign any transaction, nor pay gas fees. If you want users to pay the gas fees when claiming a token, you can do so by [enabling payments](/minting/nfts/integrate/list-for-sale) for your collection with a price of 0. ## Guide