> ## Documentation Index
> Fetch the complete documentation index at: https://docs.exclusivo.one/llms.txt
> Use this file to discover all available pages before exploring further.

# Marketplace API

> Public, read-only, no key. Collections, floors, listings, sales and tokens.

`https://exclusivo.one/v1`

No auth, `GET` only, CORS-open — so you can call it straight from a browser with
no backend.

## Endpoints

|                                              |                                                    |
| -------------------------------------------- | -------------------------------------------------- |
| `GET /v1`                                    | Index                                              |
| `GET /v1/openapi.json`                       | The OpenAPI 3.1 document                           |
| `GET /v1/collections`                        | [Browse collections](/api/marketplace/collections) |
| `GET /v1/collections/{id}`                   | [One collection](/api/marketplace/collections)     |
| `GET /v1/collections/{id}/floor`             | [Floor prices](/api/marketplace/collections#floor) |
| `GET /v1/collections/{id}/listings`          | [Active listings](/api/marketplace/listings)       |
| `GET /v1/collections/{id}/sales`             | [Sales history](/api/marketplace/sales)            |
| `GET /v1/tokens/{chain}/{address}/{tokenId}` | [One token](/api/marketplace/tokens)               |

```bash theme={"system"}
curl "https://exclusivo.one/v1/collections?chain=solana&limit=5"
```

## Envelopes

```json Success theme={"system"}
{
  "data": [ ],
  "pagination": { "hasMore": true, "nextCursor": "…" },
  "meta": { "stale": true }
}
```

`pagination` on lists. `meta` only appears when a source degraded.

```json Error theme={"system"}
{ "error": { "code": "not_found", "message": "Collection not found." } }
```

| Code             | Status |
| ---------------- | ------ |
| `bad_request`    | 400    |
| `not_found`      | 404    |
| `rate_limited`   | 429    |
| `upstream_error` | 502    |

## Three things that will catch you out

**A short page isn't the end.** Several endpoints cut the page first and drop
unusable rows afterwards, so `data.length` can be less than `limit` — even zero
— while `hasMore` is true. Always page on `hasMore` and `nextCursor`.

**Don't parse `collectionId`.** It looks like `<chain>_<contractAddress>`, but the
address half is lowercased for **every** chain including Solana. Solana base58 is
case-sensitive, so slicing a Solana `collectionId` gives you an invalid address.
Pass the id back to `/v1/collections/{id}` and read the real `contractAddress`
from there.

**Chains.** All eight are accepted: `solana`, `ethereum`, `polygon`, `base`,
`ink`, `apechain`, `abstract` and `robinhood`. Anything else is a `bad_request`.

## Prices

Always an object, never a bare number:

```json theme={"system"}
{
  "raw": "1250000000",
  "decimal": 1.25,
  "currency": "SOL",
  "usd": 284.5
}
```

|            |                                                            |
| ---------- | ---------------------------------------------------------- |
| `raw`      | Integer base units — wei or lamports — as a decimal string |
| `decimal`  | Human-readable native amount                               |
| `currency` | Native symbol                                              |
| `usd`      | Best effort. **`null`** when there's no price feed         |

Do arithmetic on `raw`. `decimal` loses precision on large wei values, and `usd`
can be null on any row.

## Address casing

EVM addresses come back lowercase. Solana base58 keeps its case — never
lowercase one, it stops being a valid address.

## Degrading rather than failing

Most endpoints are built to degrade. Sources are independently timed out, and a
failing one gives you null fields or a `meta.stale` flag with a `200`.

`/v1/collections/{id}`, `…/floor`, `…/listings` and the token endpoint **never
return 502**. Only `/v1/collections` and `…/sales` can.

`meta.stale` means a source was **unreachable**, not merely behind. EXC's own
Solana listings sync every couple of minutes and can lag by about that without
being flagged.

## Caching and limits

Responses are CDN-cached with `stale-while-revalidate`, so don't add
cache-busting parameters.

|                       |                |
| --------------------- | -------------- |
| List endpoints        | 120/min per IP |
| Single-item endpoints | 300/min per IP |

Separate counters. → [Rate limits](/api/rate-limits)
