raresats.net API
Listings API View as Markdown

List active listings

GET/api/market/listings

Active listings, one page at a time, filtered by row and seller and sorted by unit price, price or age. Read-only, no rate limit beyond the edge's.

Query parameters #

ParameterTypeRequiredDescription
rowstringnoOnly listings of this row (collection), e.g. uncommon, block9, black_rare. A label row (e.g. block9_1st_tx) lists every listing lying in it.
substringnoWith row: 1 also lists the row's rarer sub-categories (listings whose sats the row holds whole, e.g. alpha uncommons under uncommon). One of: 0, 1. Default: 0.
containsstringnoWith row: 1 also answers, apart, the listings holding only some sats of the row among others (in bundle: a Block 9 chunk holding one Block 9 palindrome under block9_palindrome) as contains (the first limit, in the asked sort and order; sort=unit orders them by total price, a bundle having no unit price of this row) and contains_total; only answers those alone as listings/total, paged by limit and offset. They are priced as the whole UTXO, never in the row's floor. One of: 0, 1, only. Default: 0.
sortstringnounit (unit price), price (listing price) or new (creation time). One of: unit, price, new. Default: unit.
orderstringnoasc or desc. Default: asc, except desc for sort=new. Ties: newest first, then by id. One of: asc, desc.
limitintegernoPage size, 1-200. Default: 50. (min 1, max 200)
offsetintegernoListings to skip, 0-1,000,000. Default: 0. (min 0, max 1000000)
sellerstringnoOnly listings by this seller address.

Example request #

cURL
curl 'https://raresats.net/api/market/listings?row=black_rare&sort=unit&order=asc&limit=2'
JavaScript
const response = await fetch('https://raresats.net/api/market/listings?row=black_rare&sort=unit&order=asc&limit=2');
const data = await response.json();
Python
import requests

data = requests.get("https://raresats.net/api/market/listings", params={"row": "black_rare", "sort": "unit", "order": "asc", "limit": 2}).json()

Response 200 #

FieldTypeDescription
listingsarray of ListingOne page of active listings, in the requested order.
totalintegerActive listings matching the filters (all pages).
as_ofobject | nullWhen every live listing was last checked against the chain ({height, checked_at}), or null.
as_of.heightinteger | nullBlock height
as_of.checked_atintegerUnix seconds
containsarray of ListingOnly with row and contains=1: the first limit active listings holding some sats of the row among others (in bundle, each in_bundle: true), by total price, the cheapest first. Never in listings, total or the row's floor.
contains_totalintegerOnly with contains=1: how many such listings there are (all pages; contains=only pages them).
Response
{
  "listings": [
    {
      "id": "1031931af1592e1c",
      "outpoint": "2fb6fb60ece3672924a373d7479d144d9ce4d3591185bfb5a00e62aedd53d3a9:0",
      "value": 546,
      "price": 60546,
      "unit_price": 60000,
      "row": "black_rare",
      "count": 1,
      "rows": {"black_rare": 1},
      "types": [
        {
          "types": ["black_rare", "omega"],
          "count": 1,
          "sats": [1657319999999999]
        }
      ],
      "sats": 1,
      "ranges": [[1657319999999999, 1657319999999999]],
      "years": {"2017": 1},
      "seller_address": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu",
      "payout_address": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu",
      "status": "active",
      "created_at": 1790952985,
      "updated_at": 1790952985,
      "txid": null,
      "signature_public": false,
      "sold_via": null,
      "offer_id": null,
      "best_offer": null
    }
  ],
  "total": 1,
  "as_of": {"height": 969001, "checked_at": 1790952985}
}

Errors #

{error, code}; see Errors for every code.

StatusCodeMeaning
400bad_addressAn address is not a mainnet address (or not one at all).
400bad_containscontains is not 0, 1 or only, or is set without row.
400bad_orderorder is not asc or desc.
400bad_paginglimit or offset out of range.
400bad_rowrow is not a row id.
400bad_sortsort is not unit, price or new.
400bad_subsub is not 0 or 1.
404retired_rowrow is a row the site retired (uncommon_2009, rare_2009): its listings are its parent row's. retired names the row and the parent and years to ask for.
Error (400)
{"error": "sort must be unit, price or new", "code": "bad_sort"}

Sorting and paging #

  • sort=unit (the default) orders by unit_price, the price per sat of the listing's own row: the way to find a collection's cheapest sats. sort=price orders by the listing price, sort=new by creation time.
  • order defaults to asc, except desc for sort=new (newest first). Equal values come newest first, then by id, so pages are stable.
  • Page with limit (1-200) and offset; total counts every match. Listings can sell or move between two pages; re-read the first page when it matters.

Filters #

  • row filters by a listing's own row. With sub=1 it also lists the row's rarer sub-categories (listings whose sats the row holds whole). A label row such as block9_1st_tx lists every listing lying in it.
  • contains=1 (with row) adds, apart, the listings that hold only some sats of the row among others (in bundle: a 330-sat Block 9 chunk holding one Block 9 palindrome, under block9_palindrome) as contains, the first limit by total price, with contains_total. Each is marked in_bundle: true with contains_count, its sats of the row. They are priced as the whole UTXO: their unit_price is their own row's, so they are never in listings, total or the row's floor. contains=only answers them alone as listings and total, paged by limit and offset.
  • seller lists one seller's active listings (the site's "My listings").
  • Only active listings are listed. A pending, sold, cancelled or moved listing is still readable by id (Get a listing).

To filter listings by mint year, mint day, birthday (month-day) or one rarer sub-category, use Query listings; see Filtering & birthday sats.