API reference
Tokens
Everything we know about a single NFT: who really owns it, what it is listed for, and what it last sold for — in one call, with the same shape on every chain.
Endpoint
/v1/tokens/{chain}/{address}/{tokenId}No query parameters. Everything is in the path, and the meaning of the last two segments differs between EVM and Solana.
# EVM: contract address, then token id
curl "https://exclusivo.one/v1/tokens/ethereum/0x8a90cab2b38dba80c64b7734e58ee1db38b8992e/4271"
# Solana: COLLECTION mint, then ASSET mint
curl "https://exclusivo.one/v1/tokens/solana/85Ghq5ExuySXEU4aExGs7d44udeGrF3bvF6GX8YsgaMe/9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"{
"data": {
"chain": "ethereum",
"contractAddress": "0x8a90cab2b38dba80c64b7734e58ee1db38b8992e",
"tokenId": "4271",
"mint": null,
"collectionId": "ethereum_0x8a90cab2b38dba80c64b7734e58ee1db38b8992e",
"name": "Doodle #4271",
"image": "https://exclusivo.one/api/image-proxy?url=…",
"rarity": { "rank": 812 },
"owner": {
"address": "0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03",
"kind": "wallet",
"label": null
},
"listing": {
"chain": "ethereum",
"contractAddress": "0x8a90cab2b38dba80c64b7734e58ee1db38b8992e",
"tokenId": "4271",
"mint": null,
"collectionId": "ethereum_0x8a90cab2b38dba80c64b7734e58ee1db38b8992e",
"price": { "raw": "2400000000000000000", "decimal": 2.4, "currency": "ETH", "usd": 7920.0 },
"seller": "0x9c8ff314c9bc7f6e59a9d9225fb22946427edc03",
"buyer": null,
"marketplace": "EXC",
"status": "active",
"expiresAt": "2026-08-25T20:44:03.000Z",
"timestamp": "2026-07-25T20:44:03.000Z",
"orderId": "ethereum_0x8a90cab2b38dba80c64b7734e58ee1db38b8992e_4271_1785412903117",
"tx": null
},
"lastSale": {
"price": { "raw": "1900000000000000000", "decimal": 1.9, "currency": "ETH", "usd": 6270.0 }
}
}
}An unlisted token returns listing: null; a token we have never seen trade returns lastSale: null. Addresses and ids above are illustrative examples. Cached for 30 seconds at the edge with a further 30 seconds of stale-while-revalidate; rate limited at 300 req/min.
Path parameters
| Segment | EVM chains | Solana |
|---|---|---|
{chain} | One of ethereum, polygon, base, ink, apechain, abstract. Matched case-insensitively. | solana |
{address} | The contract address. Must be a 0x-prefixed 40-hex address; case-insensitive, and echoed back lowercase. | The collection mint — not the asset. Base58, 32–44 characters, case-sensitive. |
{tokenId} | The token id as a decimal string. Up to 100 characters, so 256-bit ids are fine. | The asset mint — the individual NFT. Base58, case-sensitive. |
Solana takes two mints, and the order is not interchangeable
{address} is the collection mint and {tokenId} is the asset mint. Swapping them does not produce a validation error, because both are valid base58 — it produces a not_found. If a token you know exists returns 404, check the order before checking anything else.Validation and error codes
The chain and address are validated before any lookup, so a malformed request fails fast with bad_request rather than 404:
| Situation | Result |
|---|---|
An EVM chain with a non-0x address | bad_request — 400 |
solana with a 0x address | bad_request — 400 |
| An unknown chain, or an address that is neither a 0x address nor valid base58 | bad_request — 400 |
| A well-formed address for a token we have not indexed | not_found — 404 |
The tokenId segment is only length-checked, so an invalid Solana asset mint reaches the lookup and comes back as not_found rather than bad_request. Do not use the status code to decide whether an address is well-formed.
The beneficial owner
This is the field most likely to be wrong if you read it from anywhere else. When a Solana NFT is listed on Exclusivo, the asset moves into a single shared platform escrow wallet. Every listed NFT on the platform has the same on-chain holder. Magic Eden escrow wallets, M2 auction-house accounts and MMM pool addresses behave the same way, and on EVM a Seaport conduit approval leaves the holder unchanged but adds its own confusion.
owner resolves this: when a token is listed, the beneficial owner is the seller, whatever address happens to hold custody.
| owner.kind | owner.address | Means |
|---|---|---|
"wallet" | The address. | A real user wallet. Safe to display, safe to link to a profile, safe to compare against a connected wallet. |
"custody" | null | The asset sits in a recognised escrow with no listing naming a seller. The address is deliberately withheld and owner.label carries a human-readable state such as "In Exclusivo escrow". |
"unknown" | null | Nothing trustworthy to report. |
Never render a custody address as a user
owner.address from this endpoint, and treat a kind other than "wallet" as “no user to attribute this to”.Listing state
listing is the same cross-chain item object the listings endpoint returns, or null when the token is not listed. Two sources feed it, and which one won changes what some fields contain:
| Source | When | Notable differences |
|---|---|---|
| Exclusivo order book | EVM tokens with an active Exclusivo Seaport listing. Preferred whenever it exists. | marketplace is "EXC"; orderId is the order-book document id; timestamp is the real listing creation time. |
| Indexer overlay | Everything else — Solana, and external marketplaces on EVM. | marketplace names the source; orderId is the Seaport order hash where the source has one; timestamp is generated at response time and carries no meaning. |
listing.tx is always null on this endpoint. A listing is not a settlement, and on EVM it is not a transaction at all.
This is the one place a Seaport order hash surfaces
orderId for Exclusivo EVM rows. If you need the actual Seaport order hash for a token — to check validity against Seaport yourself — read it here, from an overlay-sourced listing. Note the trade-off: when a token has an Exclusivo listing, the order-book row wins and you get the internal id instead.Last sale
lastSale is an object containing exactly one field, price, or null when we have no recorded sale for the token.
"lastSale": {
"price": { "raw": "1900000000000000000", "decimal": 1.9, "currency": "ETH", "usd": 6270.0 }
}No timestamp, buyer, seller, or transaction
Field reference
| Field | Type | Notes |
|---|---|---|
chain | string | The chain you requested, normalized to lowercase. |
contractAddress | string | null | EVM contract, lowercase. Always null on Solana — the collection is identified by collectionId instead. |
tokenId | string | null | EVM token id as a decimal string. Always null on Solana. |
mint | string | null | Solana asset mint, base58 case preserved. Always null on EVM. |
collectionId | string | Canonical collection document id. Feed it back to any collection endpoint as {id}; do not parse an address out of it. |
name | string | null | Token name from metadata. |
image | string | null | Token image, usually proxied through our image service. |
rarity.rank | number | null | Rank 1 is rarest. Null when the collection has no computed rarity. The object itself is always present. |
owner.address | string | null | The beneficial owner. Null unless kind is "wallet". |
owner.kind | string | One of "wallet", "custody", "unknown". |
owner.label | string | null | Human-readable custody state. Non-null only when kind is "custody". |
listing | MarketItem | null | Active listing, or null when not listed. |
lastSale | object | null | Contains only price. |
Gotchas
collectionId is lowercased, even on Solana
The collection identifier is built by lowercasing the address. That is harmless on EVM and destructive on base58, so the suffix of a Solana collectionId is not a usable mint. It still round-trips as an {id} on the collection endpoints, which is its only purpose. To get the real collection mint back, call /v1/collections/{collectionId} and read contractAddress.
An overlay listing timestamp is not a listing time
When the listing comes from the indexer overlay — every Solana listing, and every external EVM listing — listing.timestamp is stamped when the response is built. It will always look like the listing was created moments ago. Sorting or ageing on it produces nonsense. Nothing in the response distinguishes the two sources directly, so infer it from marketplace and chain: anything that is not an EVM row with marketplace: "EXC" came from the overlay.
owner is not proof of current custody
For a listed token the owner is the seller, resolved from the listing rather than from a fresh chain read. If the listing data is stale — the Solana mirror runs on roughly a two-minute cycle — the seller shown may have already sold or delisted. This is the right answer for display; it is not a substitute for an on-chain ownership check before a transaction.
404 means not indexed, not non-existent
The lookup goes through our index. A token that exists on-chain in a collection we have not indexed returns not_found. If you are integrating a collection we do not carry yet, visiting its collection page on the site triggers indexing; email dev@psukhe.media if you need a batch onboarded.