OnFinality Unified NFT API
OnFinality’s Unified NFT API will provide access to NFTs and their metadata for all popular standards across the Polkadot and Kusama ecosystems and beyond, in a single, simple request.
The OnFinality NFT API will just be the first Unified API offered by OnFinality, with plans to expand to transactions, staking, and more.
The highly flexible GraphQL Unified API includes
Collections
NFTs
Transactions
Metadata
We welcome all feedback at support@onfinality.io
Have fun 🥳
Why GraphQL?
The NFT universe is a weird and wonderful place. We couldn’t begin to imagine all possible use cases, so the flexibility of GraphQL gives you complete access without restrictions
Supported Networks/Standards
The Beta Unified NFT API includes the following networks and standards, with plans to expand rapidly
Network | Chain ID | Standard | Status |
---|
Acala
| 787
| EVM ERC-721 | LIVE |
EVM ERC-1155 | LIVE |
Astar | 592
| EVM ERC-721 | LIVE |
EVM ERC-1155 | LIVE |
Shiden | 336
| EVM ERC-721 | LIVE |
EVM ERC-1155 | LIVE |
Moonbeam | 1284
| EVM ERC-721 | LIVE |
EVM ERC-1155 | LIVE |
Moonriver | 1285
| EVM ERC-721 | LIVE |
EVM ERC-1155 | LIVE |
📧
We’d love to hear from you, contact support@onfinality.io to put in a request for more networks and standards!
Coming Soon
WASM PSP34
Substrate Uniques
Substrate NFTs
Substrate ormlNFT
How to Connect
Public Endpoint
GraphQL Endpoint (Beta): https://nft-beta.api.onfinality.io/public
The Beta version of our public endpoint is intended for development, experimentation, and validation purposes. It should not be used in a production environment
A public rate limit is applied, contact support@onfinality.io to receive a higher rate limit
Playground
http://nft-beta.onfinality.io
Schema
The complete schema is available here https://github.com/OnFinality-io/api-nft/blob/main/schema.graphql
GraphQL Schema
CODE
enum ContractType {
ERC721,
ERC1155
}
enum StatusType {
PENDING,
PROCESSING,
COMPLETED,
FAILED,
UNKNOWN,
INVALID
}
type AnyJson @jsonField {
# Need a value for codegen but type is any
_: String
}
type Nft @entity {
id: ID! #CollectionID-TokenId
tokenId: String! @index
amount: BigInt! #1 for Erc721. 1155 semi-fungible has other values
collection: Collection!
minted_block: BigInt! @index# Should be bigInt
minted_timestamp: BigInt! # unix epoch timestamp
minter_address: String! @index # event transaction from
current_owner: String! @index # event args to
metadata: Metadata
}
type Collection @entity {
id: ID! # chainID-contract adddress
network: Network!
contract_address: String! @index # event address
created_block: BigInt! @index
created_timestamp: BigInt! @index# unix epoch timestamp
creator_address: String! # event transaction from
total_supply: BigInt!
name: String
symbol: String
contract_type: ContractType! # e.g. ERC721, RMRK Hardcode
# floor_price: Int # Later on
}
type Transfer @entity {
id: ID!
tokenId: String! @index
amount: BigInt! # Same as with NFT
network: Network!
block: BigInt! @index
timestamp: BigInt! @index
transaction_hash: String! @index# event transaction hash
nft: Nft
from: String! @index
to: String! @index
}
type Network @entity {
id: ID!
}
type Metadata @entity {
id: ID! # hashed metadata_uri
metadata_uri: String!
raw: AnyJson
metadata_status: StatusType!
name: String
symbol: String
token_uri: String
image_uri: String
description: String
}
type Address @entity {
id: ID! #network account address ?
network: Network!
account: Account #optinal for now
}
type Account @entity {
"""Id is a base58 encoded public key"""
id: ID! # base58 encoded public key (only substrate chains ?)
addresses: [Address] @derivedFrom(field: "account") # addresses
}
Tips
All addresses and contracts are in lower case. Convert to lower case before querying to avoid performance issues
NFT IDs are in the format [network id]-[contract id]-[nft id]
E.g.
”592-0x1b57c69838cdbc59c8236dda73287a4780b4831f-1001”
Example Queries & Responses
Paste these queries into https://nft-beta.onfinality.io and press play ▶️
Get NFTs for Collection
Request
CODE
{
nfts(
first: 20
filter: {
collection: {
contractAddress: {
equalTo: "0xd59fc6bfd9732ab19b03664a45dc29b8421bda9a"
}
}
}
) {
nodes {
mintedBlock
tokenId
currentOwner
metadata {
metadataUri
metadataStatus
imageUri
description
name
raw
}
}
}
}
Response
CODE
{
"data": {
"collections": {
"nodes": [
{
"nfts": {
"nodes": [
{
"mintedBlock": "442806",
"tokenId": "1",
"currentOwner": "0xf5aff98659f5934a4f5ed1e23da81996d140ff40",
"metadata": {
"metadataUri": "ipfs://QmS3VmXBrVFRRdkSSBfgbRB5mzVdnANNdGaZPyo69BMwsR/hidden.json",
"metadataStatus": "COMPLETED",
"imageUri": "ipfs://QmNMjVu59ouiuMFdpMqJny8SRfoLP118zrVQFKQpYt6g6g/hidden.png",
"description": "AstarDegens Collection (revealed when minted out)",
"name": "AstarDegens (Hidden)",
"raw": {
"name": "AstarDegens (Hidden)",
"image": "ipfs://QmNMjVu59ouiuMFdpMqJny8SRfoLP118zrVQFKQpYt6g6g/hidden.png",
"description": "AstarDegens Collection (revealed when minted out)"
}
}
},
...
}
}
}
}
}
Get NFTs for Wallet Address (All Networks)
Request
CODE
{
nfts(
first: 20
filter: {
currentOwner: {
equalTo: "0xf5aff98659f5934a4f5ed1e23da81996d140ff40"
},
}
) {
nodes {
mintedBlock
tokenId
currentOwner
metadata {
metadataUri
metadataStatus
imageUri
description
name
raw
}
collection {
networkId
}
}
}
}
Response
CODE
{
"data": {
"nfts": {
"nodes": [
{
"mintedBlock": "1931736",
"tokenId": "1939",
"currentOwner": "0xf5aff98659f5934a4f5ed1e23da81996d140ff40",
"metadata": {
"metadataUri": "ipfs://bafybeiaxax2xbml3dxdr2ohcrovgiwmpxyd4bykjl37sbn4ujqs7htr26u/1939.json",
"metadataStatus": "COMPLETED",
"imageUri": "ipfs://bafybeiezmgo7mthlzygckiugpbytvuhsqs4nxvzhs7rbwslgqbxla2kczi/1939.png",
"description": "COSMIZE×Astar Degens collabo NFT",
"name": "Astar Degens Desk 1939",
"raw": {
"name": "Astar Degens Desk 1939",
"image": "ipfs://bafybeiezmgo7mthlzygckiugpbytvuhsqs4nxvzhs7rbwslgqbxla2kczi/1939.png",
"tokenId": 1939,
"attributes": [
{
"value": "Gray Gorilla",
"trait_type": "Body"
},
{
"value": "Sherrif Hat",
"trait_type": "Hat"
},
{
"value": "Purple Wedge Shield",
"trait_type": "Shield"
},
{
"value": "Big Blue Sunglass",
"trait_type": "Sunglass"
}
],
"description": "COSMIZE×Astar Degens collabo NFT",
"external_url": "https://cosmize.io/item/AstarDegens-Desk/1939"
}
},
"collection": {
"networkId": "592"
}
},
...
]
}
}
Get NFTs for Wallet Address (Single Network)
Request
CODE
{
nfts(
first: 20
filter: {
currentOwner: {
equalTo: "0xf5aff98659f5934a4f5ed1e23da81996d140ff40"
},
collection: {networkId: {equalTo: "592"}}}
) {
nodes {
mintedBlock
tokenId
currentOwner
metadata {
metadataUri
metadataStatus
imageUri
description
name
raw
}
}
}
}
Response
CODE
{
"data": {
"nfts": {
"nodes": [
{
"mintedBlock": "1931736",
"tokenId": "1939",
"currentOwner": "0xf5aff98659f5934a4f5ed1e23da81996d140ff40",
"metadata": {
"metadataUri": "ipfs://bafybeiaxax2xbml3dxdr2ohcrovgiwmpxyd4bykjl37sbn4ujqs7htr26u/1939.json",
"metadataStatus": "COMPLETED",
"imageUri": "ipfs://bafybeiezmgo7mthlzygckiugpbytvuhsqs4nxvzhs7rbwslgqbxla2kczi/1939.png",
"description": "COSMIZE×Astar Degens collabo NFT",
"name": "Astar Degens Desk 1939",
"raw": {
"name": "Astar Degens Desk 1939",
"image": "ipfs://bafybeiezmgo7mthlzygckiugpbytvuhsqs4nxvzhs7rbwslgqbxla2kczi/1939.png",
"tokenId": 1939,
"attributes": [
{
"value": "Gray Gorilla",
"trait_type": "Body"
},
{
"value": "Sherrif Hat",
"trait_type": "Hat"
},
{
"value": "Purple Wedge Shield",
"trait_type": "Shield"
},
{
"value": "Big Blue Sunglass",
"trait_type": "Sunglass"
}
],
"description": "COSMIZE×Astar Degens collabo NFT",
"external_url": "https://cosmize.io/item/AstarDegens-Desk/1939"
}
}
},
...
]
}
}
Get Transfers for Wallet Address (All Networks)
Request
CODE
{
transfers(
first: 20
filter: {
or: [
{to: {equalTo: "0xf5aff98659f5934a4f5ed1e23da81996d140ff40"}},
{from: {equalTo: "0xf5aff98659f5934a4f5ed1e23da81996d140ff40"}}
]
})
{
nodes {
nft {
collection {
contractAddress
}
tokenId
}
timestamp
from
to
transactionHash
network {
id
}
}
}
}
Response
CODE
{
"data": {
"transfers": {
"nodes": [
{
"nft": {
"collection": {
"contractAddress": "0xd59fc6bfd9732ab19b03664a45dc29b8421bda9a"
},
"tokenId": "1"
},
"timestamp": "1645544268",
"from": "0xc779ceb0853fa7ab6a38c587c1cfc702e4603d9b",
"to": "0xf5aff98659f5934a4f5ed1e23da81996d140ff40",
"transactionHash": "0x1b85af43d6584f29475e70ba179a53d274f5abfa15bac38ed395a827cee83435",
"network": {
"id": "592"
}
},
...
]
}
}
}
Get Transfers for Wallet Address (Single Network)
Request
CODE
{
transfers(
first: 20
filter: {networkId: {equalTo: "592"},
or: [{
to: {equalTo: "0xf5aff98659f5934a4f5ed1e23da81996d140ff40"}},
{from: {equalTo: "0xf5aff98659f5934a4f5ed1e23da81996d140ff40"}}]}
) {
nodes {
nft {
collection {
contractAddress
}
tokenId
}
timestamp
from
to
transactionHash
}
}
}
Response
CODE
{
"data": {
"transfers": {
"nodes": [
{
"nft": {
"collection": {
"contractAddress": "0xd59fc6bfd9732ab19b03664a45dc29b8421bda9a"
},
"tokenId": "1"
},
"timestamp": "1645544268",
"from": "0xc779ceb0853fa7ab6a38c587c1cfc702e4603d9b",
"to": "0xf5aff98659f5934a4f5ed1e23da81996d140ff40",
"transactionHash": "0x1b85af43d6584f29475e70ba179a53d274f5abfa15bac38ed395a827cee83435"
},
...
]
}
}
}
Count NFTs in Collection
Request
CODE
{
nfts(filter: {collection: {contractAddress: {equalTo: "0xd59fc6bfd9732ab19b03664a45dc29b8421bda9a"}}}) {
totalCount
}
}
Response
CODE
{
"data": {
"nfts": {
"totalCount": 10000
}
}
}
Count Transfers for Collection
Request
CODE
{
transfers(
filter: {nft: {collection: {contractAddress: {equalTo: "0xd3e93ff701fee4402e91b63bbdb06aad125cbd4c"}}}}
) {
totalCount
}
}
Response
CODE
{
"data": {
"transfers": {
"totalCount": 2142
}
}
}
Count Transfers for NFT
Request
CODE
{
transfers(filter: {
nftId: {equalTo: "592-0xd59fc6bfd9732ab19b03664a45dc29b8421bda9a-1"}
}) {
totalCount
}
}
Response
CODE
{
"data": {
"transfers": {
"totalCount": 2
}
}
}
Get Current Owners for Collection
Request
CODE
{
collections(
first: 20
filter: {contractAddress: {equalTo: "0xd59fc6bfd9732ab19b03664a45dc29b8421bda9a"}}) {
nodes {
nfts {
nodes {
id
currentOwner
}
}
}
}
}
Response
CODE
{
"data": {
"collections": {
"nodes": [
{
"nfts": {
"nodes": [
{
"id": "592-0xd59fc6bfd9732ab19b03664a45dc29b8421bda9a-1",
"currentOwner": "0xf5aff98659f5934a4f5ed1e23da81996d140ff40"
},
...
]
}
}
]
}
}
}
Best Practices
For optimal performance and responsible use of our shared resources, we recommend:
❌ Avoid using the equalToInsensitive
filter, which has poor performance.
✅ Convert addresses to lower case and use the equalTo
filter
✅ Use pagination, e.g. first: 10