If you want to build NFTs in the Stacks ecosystem and leverage Bitcoin’s security, there are a number of tools out there to make your life easier. In fact, we have our own NFT tutorial at Hiro to get you started.
But the reality is that in order to launch your NFT project, you will likely need to work with the Stacks API to read data from the blockchain.
What Is the Stacks API?
As you may know, Stacks Nodes continuously produce blocks on the Stacks blockchain, and within those blocks are transactions and events.
The Stacks API is a system that indexes all of that blockchain data into a Postgres database. Every time a block or microblock is produced, we receive it on the API, process it, and save that data in the database.
We provide easy access to this data through JSON endpoints. Some of the data you can consume from this database are:
- Accounts
- Transactions
- Block information
- Smart contracts
- Proof of Transfer status, and more
This product is designed for the broader Stacks ecosystem. The API is fully open source, and we aim to do fast releases. We continuously push new code and want to make it easy for people to deploy the API on their own infrastructure.
In particular, this system is designed for a few types of users:
- Stacks developers, including Clarity developers, NFT creators, and more
- Applications built on Stacks, including DeFi protocols, marketplaces, onchain analytics tools, and more
- Hiro products, including the Hiro Wallet and the Stacks Explorer. If you’ve used these tools, you’ve used the API behind the scenes.
Today, we service 400M requests per month and deliver 99.97% availability in the Stacks API. As an NFT creator, let’s get into some of the data you can surface through the Stacks API.
Breaking Down NFT Endpoints
Historically, the API has served very basic data about the blockchain, such as information about blocks and transactions, but we want to create endpoints that give you more processed data that is hard to get by yourself. Recently, we created 3 new NFT endpoints that we believe will be useful to any NFT creator.
NFT history
This endpoint allows you to see a history of all events that involve one particular NFT asset. This endpoint retrieves all blockchain events and is useful for pulling information like trade history, marketplace listings, chain of custody (list of owners), and more.
A sample call for this endpoint looks like:
When calling this endpoint, we expect two arguments: an asset_identifier (the machine name of that NFT collection) and the value (which specifies what NFT from that collection you want).
You can add another argument to this call that will return the complete transaction object instead of just the transaction ID. This object contains additional information like the smart contract that was called, what function arguments were used, the fees paid in that transaction and more. This additional data will let you see things like the price the NFT was listed for, the price it was ultimately purchased at, and more.
NFT holdings
This endpoint lets you retrieve all NFTs owned by a specific STX address or smart contract (smart contracts can hold NFTs too). You can also filter this information by the collection you are looking for. For example, if you wanted to have proof-of-ownership, where users must have an NFT to gain access to something, you can query that through this endpoint. You can also use this endpoint for marketplace profiles, game character item lists, see addresses with the most listings, and more.
A sample call for this endpoint looks like:
When calling this endpoint, we need one argument: the principal (an identifier for the STX address or smart contract).
NFT mint
This endpoint allows you to retrieve all mint events for an NFT collection. For example, if you want to see how many NFTs have been minted in a new collection launch and how many are left, you can see that here. You can also see what addresses minted the most and get mint statistics (how long did it take for the mint to run out).
A sample call for this endpoint looks like:
When calling this endpoint, we need one argument, the asset_identifier, which signifies which NFT collection you want to query information on.
To learn more about these 3 endpoints, you can learn more about them on our blog and in our documentation.
Performance Optimizations
In order for us to give this data to you through the API, we have to do a lot of computation. On blockchains, you can have very different circumstances that produce duplicate data or transactions that get reorganized (if the blockchain was reorganized for example). We store all of that data, and there’s a massive amount of it.
In order to determine ownership of an NFT, for example, we have to do a lot of calculations to determine which transactions were valid/invalid and which events actually got written into the blockchain. To do this, we have to dedicate a lot of CPU power to query the database.
As you can imagine, this creates room for improvements, and we recently made some changes to the API that improve its performance.
Database Caching
This was one of the first optimizations we did. Every time we receive a new block in the Stacks blockchain from a Stacks node, we precalculate which addresses own which NFTs, right now.
This allows us to save this data in a materialized view in the Postgres database. This makes the endpoint very fast for queries on the NFT holdings endpoint. We have also been working on improving indexing in the Postgres database for better response time too.
Chain Tip Cache Headers
Another improvement involves chain tip cache headers. Now everytime we receive a new block, we take that block hash and use that as the etag on all the responses that we return to users.
Obviously, blockchain data doesn’t change until we receive the next block, so there is no point in recalculating the same response if we haven’t received new information. This means if we receive a request from some user, and we have already provided a response to someone else with the same etag, signaling it was sent within the same block, we can now just forward that same request instead of re-running the calculations again.
This caching layer exists at the CDN level and offers much better response time and performance.
Faster Deployments
We are working hard on this improvement: it’s not done yet. This work involves a couple of improvements, including adding run modes that allow our users to run the API with different configurations. For example, if you are only interested in running an instance of the API to query the database and you aren’t interested in the API endpoints, you will be able to do that.This run configurations will allow you to spin up API instances with limited functionality (customized to your needs) more quickly
We are also working on faster event imports. Every time we release a new version of the API, we have to give it the entire blockchain history so that it reaches a correct state with the new database schema. As you can imagine, this is a slow process. Today, it can take upwards of a week, sometimes longer. We are working on making that much faster than it is today.
Future Plans
Our GitHub backlog is totally full. We have a lot going on and need help to get it all down. Plug: we’re hiring. But here’s a preview of 3 new features that I am excited about:
NFT Socket Updates
This will allow you to subscribe to real-time events that affect one NFT asset. For example, let’s say you are building a game where you want to detect when a character changes from one user to another in a transfer. With this feature, you can get this update as it happens instead of having to wait to query the database or our API.
As another example, let’s say you are building a marketplace and you want to look at an NFT in a bidding war, this feature will allow you receive those different bid events in real time and show them on your marketplace.
These sockets will be really helpful for us as well and will help us reduce traffic on the API and make it more efficient.
Statistics Endpoints
We are noticing that our community is very interested in statistics around mempool transactions. How busy is the mempool? Which transactions are valid? Which transactions are just replace by fee?
This new endpoint will provide data for asset distribution on Stacks, whether fungible or non-fungible, among other data sets. This endpoint will be useful for unchain analytics.
OpenAPI Improvements
We enable our community to launch their own instances of the API, but we don’t offer much support in terms of documentation. For example, right now we provide a JavaScript client, but some community members write code in different languages, whether that be Java, Ruby, PHP, or something else.
We want to generate clients as our community needs them. We hope this improvement will give us more traffic and help us serve more developers.
Conclusion
That’s everything you need to know about the API at a high level. If you’re curious to learn more, you can dig into our API documentation here, and if you’d like to join the conversation and contribute, you can find the Stacks API repo on GitHub here.
If you want to be inspired by entrepreneurs pushing the boundaries of NFTs on Stacks, learn how Gamma is empowering NFT creators and how Byzantion built an NFT order book.
Then, when you are ready to kickstart your journey into Web3 development, download our free guide to developing smart contracts.