> ## 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.

# Listings

> Active listings for a collection, merged across EXC and outside marketplaces.

```http theme={"system"}
GET /v1/collections/{id}/listings
```

Active listings from EXC's own book and from outside marketplaces, deduplicated
per asset and sorted cheapest first. Where both have the same asset, the EXC row
wins.

| Parameter | Type    | Default |
| --------- | ------- | ------- |
| `limit`   | integer | `25`    |
| `cursor`  | string  | —       |

```bash theme={"system"}
curl "https://exclusivo.one/v1/collections/solana_abc123.../listings?limit=50"
```

## The window is bounded

<Warning>
  You get a snapshot of roughly the **250 cheapest** listings, and the cursor is an
  offset into that. Going past the ceiling returns a `400`, not an empty page.

  If you're trying to walk an entire book of thousands, this endpoint won't give
  you that. It gives you the cheap end.
</Warning>

## Staleness

EXC's own Solana listings come from a mirror that syncs every couple of minutes,
so they can lag the live book by about that much — and **that lag isn't
flagged**. `meta.stale` only fires when a source is unreachable, not when it's
merely behind.

Sources degrade rather than fail: a dead mirror gives you `meta.stale` and, on
Solana, an empty book. This endpoint never returns 502.

Errors: `400`, `404`, `429`.

## Response

```json theme={"system"}
{
  "data": [
    {
      "chain": "solana",
      "contractAddress": null,
      "tokenId": null,
      "mint": "7xKX…",
      "collectionId": "solana_abc123…",
      "price": { "raw": "1250000000", "decimal": 1.25, "currency": "SOL", "usd": 284.5 },
      "seller": "9aBc…",
      "buyer": null,
      "marketplace": "magic-eden",
      "status": "active",
      "expiresAt": null,
      "timestamp": "2026-08-20T09:00:00.000Z",
      "orderId": "…",
      "tx": null
    }
  ],
  "pagination": { "hasMore": true, "nextCursor": "25" }
}
```

| Field             |                                                     |
| ----------------- | --------------------------------------------------- |
| `contractAddress` | EVM contract, lowercase. `null` on Solana           |
| `tokenId`         | EVM token id as a decimal string. `null` on Solana  |
| `mint`            | Solana asset id, base58. `null` on EVM              |
| `marketplace`     | `EXC`, or the source slug — `opensea`, `magic-eden` |
| `status`          | `active`, `filled`, `cancelled`, `expired`, `sold`  |
| `price`           | See [prices](/api/marketplace#prices)               |

## orderId is opaque

It's a stable join key, but its format varies by source:

* EXC EVM listings carry an order-book document id — `<chain>_<contract>_<tokenId>_<epochMillis>`
* Solana and outside rows carry the mirror's id, and EXC Solana rows are prefixed `exclusivo_`
* Sale rows carry the id of the listing they came from, which can be `null`

Use it for equality and joins. Don't parse it.

## Which of these can be bought through us

All of them, as it happens — EXC, Magic Eden, Tensor and OpenSea listings are all
fillable in-app. → [Aggregated listings](/exc/marketplace/aggregated-listings)

## Paginating

```js theme={"system"}
async function cheapestListings(collectionId, max = 250) {
  const out = [];
  let cursor = null;

  do {
    const qs = new URLSearchParams({ limit: '50', ...(cursor ? { cursor } : {}) });
    const res = await fetch(
      `https://exclusivo.one/v1/collections/${collectionId}/listings?${qs}`
    );
    if (res.status === 400) break;          // past the window ceiling
    const { data, pagination } = await res.json();
    out.push(...data);
    cursor = pagination.hasMore ? pagination.nextCursor : null;
  } while (cursor && out.length < max);

  return out;
}
```
