This is a short tutorial on how to mint ERC-721 NFTs with custom metadata as a part of a Typescript application.

In our example, we will be minting NFTs with custom metadata for each new token. The main API route we need is /api/v1/erc721/mint which allows us to set the metadata of a new token in the same request as minting via the metadata field. Starting with the image of the NFT, we first need to store our intended file in the cloud if we have not yet already.

1. Upload NFT media

For convenience, the ability to upload NFT media is provided out of the box. Using the /api/v1/nft/uploadMedia route, we can provide our file and receive back a mediaUrl. Please not that this is not required if you already have the url of your media.

const formData = new FormData();
formData.append("media", "./path/image");

let imageUrl = "";
await fetch("https://groupos.xyz/api/v1/nft/uploadMedia", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.GROUPOS_API_KEY}`,
  },
  body: formData,
}).then((data) => {
  imageUrl = data.mediaUrl;
});

2. Mint NFT with metadata

Now that we’ve stored our image in the cloud, we can mint our NFT. Using the /api/v1/erc721/mint route, we can submit our NFT contract and desired recipient address and receive back a transaction hash for the pending mint. Depending on your NFT’s network, confirmation can take seconds or minutes.

const nft = {
  chainId: 5, // goerli testnet
  contractAddress: "0x...",
};
const userAddress = "0x...";

let nftMintTransactionHash = "";
await fetch("https://groupos.xyz/api/v1/erc721/mint", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.GROUPOS_API_KEY}`,
  },
  body: JSON.stringify({
    chainId: nft.chainId,
    contractAddress: nft.contractAddress,
    recipientAddress: userAddress,
    metadata: {
      mediaUrl: imageUrl,
    },
  }),
}).then((data) => {
  nftMintTransactionHash = data.transactionHash;
});

3. Query minted NFTs

Now that we’ve minted our NFT, we can query our minted tokens for confirmation. Using the /api/v1/erc721/tokens route, we can query the list of all owners and also tokens for just our latest recipient.

let allTokens = [];
await fetch(
  "https://groupos.xyz/api/v1/erc721/tokens" +
    new URLSearchParams({
      chainId: nft.chainId,
      contractAddress: nft.contractAddress,
    }),
  {
    method: "GET",
    headers: {
      Authorization: `Bearer ${process.env.GROUPOS_API_KEY}`,
    },
  }
).then((data) => {
  allTokens = data.tokens;
});

let userTokens = [];
await fetch(
  "https://groupos.xyz/api/v1/erc721/tokens" +
    new URLSearchParams({
      chainId: nft.chainId,
      contractAddress: nft.contractAddress,
      ownerAddress: userAddress,
    }),
  {
    method: "GET",
  }
).then((data) => {
  userTokens = data.tokens;
});

Other considerations

This quickstart demo best serves for server-side use cases given the exposure of your API key. When building a client-side application, it is recommended to keep these API calls in your own internal backend implementation that your frontend calls instead with your own custom authentication.