{
  "openapi": "3.1.0",
  "info": {
    "title": "raresats.net API",
    "version": "1.0.0",
    "summary": "Rare-sat marketplace and data API for Bitcoin mainnet.",
    "description": "The public JSON API behind https://raresats.net: a non-custodial marketplace for rare sats (listings, purchases, cancels) and the\nsite's market data (sales, sats, addresses, supply).\n\n- **Base URL:** `https://raresats.net`. No authentication and no API key.\n- **JSON only.** POST bodies are JSON with `content-type: application/json`, at most 256 KiB.\n- **Amounts** are integers in sats; unit prices are numbers to the hundredth of a sat. **PSBTs** are base64. **Mainnet** only.\n- **Errors** are `{error, code}` on the marketplace routes (`/api/market/*`) and `{error}` elsewhere.\n- **Rate limits:** 50 requests per 10 s per IP on `/api/*` (at the edge), and 30 POSTs a minute per client (IPv4 address or IPv6 /64).\n- POSTs carrying a foreign `Origin` are refused (403 `cross_origin`); server-side clients send none.\n\nGuides and per-endpoint pages: https://raresats.net/docs. Everything in one Markdown file: https://raresats.net/llms-full.txt."
  },
  "servers": [
    {
      "url": "https://raresats.net",
      "description": "Production (Bitcoin mainnet)"
    }
  ],
  "externalDocs": {
    "description": "Docs, guides and examples",
    "url": "https://raresats.net/docs"
  },
  "tags": [
    {
      "name": "Listings",
      "description": "Read the marketplace: listings, floors, activity, settings, fee rates."
    },
    {
      "name": "Trading",
      "description": "List, cancel and buy. Every money path is prepare, sign with your own wallet, submit."
    },
    {
      "name": "Offers",
      "description": "Bid on any tracked UTXO, listed or not; accept the offers on yours. Every money path is prepare, sign with your own wallet, submit."
    },
    {
      "name": "Wallet tools",
      "description": "Move your own UTXOs with your own wallet: extract rare sats, send them (or whole UTXOs, or N of a type), chop ranges, consolidate and multisend plain bitcoin, speed up or cancel. Prepare, sign every input, submit; the server never holds a key."
    },
    {
      "name": "Market data",
      "description": "Sales, sats and addresses, as the site shows them."
    },
    {
      "name": "Site feeds",
      "description": "The dashboard's own state: supply, rows, notable events, status."
    },
    {
      "name": "Chat & profiles",
      "description": "The site-wide chat and display names: read by anyone; sign in to post, and sign every name change, with BIP-322."
    }
  ],
  "x-error-codes": [
    {
      "code": "bad_address",
      "status": [
        400
      ],
      "description": "An address is not a mainnet address (or not one at all)."
    },
    {
      "code": "bad_addresses",
      "status": [
        400
      ],
      "description": "`addresses` must list 1 to 200 addresses."
    },
    {
      "code": "bad_bidder",
      "status": [
        400
      ],
      "description": "The offer's `bidder` is missing, not an object, or lacks `ordinals_public_key`."
    },
    {
      "code": "bad_buyer",
      "status": [
        400
      ],
      "description": "`buyer` is not an object."
    },
    {
      "code": "bad_config",
      "status": [
        500
      ],
      "description": "The marketplace is misconfigured."
    },
    {
      "code": "bad_contains",
      "status": [
        400
      ],
      "description": "`contains` is not 0, 1 or `only`, or is set without `row`."
    },
    {
      "code": "bad_expiry",
      "status": [
        400
      ],
      "description": "`expires_in` is not 86400, 259200, 604800 or 2592000 (seconds), `null` or `\"never\"`."
    },
    {
      "code": "bad_fee_rate",
      "status": [
        400
      ],
      "description": "`fee_rate` is not a positive number up to 5000."
    },
    {
      "code": "bad_id",
      "status": [
        400
      ],
      "description": "`id` is not a prepared purchase or transfer id."
    },
    {
      "code": "bad_ids",
      "status": [
        400
      ],
      "description": "`ids` / `listing_ids` is empty, too long, malformed, or lists an id twice."
    },
    {
      "code": "bad_items",
      "status": [
        400
      ],
      "description": "`items` is not a list of 1-50 UTXOs (or the PSBT lists more), or an item's `sats` is not null or a list of sat numbers."
    },
    {
      "code": "bad_json",
      "status": [
        400
      ],
      "description": "The body is not valid JSON."
    },
    {
      "code": "bad_message",
      "status": [
        400
      ],
      "description": "The cancel message is not `raresats.net cancel <ids> <unix seconds>` or names other listings than `ids`; or the registration message is not `raresats.net affiliate <address> <unix seconds>` for `address`."
    },
    {
      "code": "bad_nonce",
      "status": [
        422
      ],
      "description": "The login nonce was not handed out for this address, has expired (10 minutes) or was used: ask for a new one."
    },
    {
      "code": "bad_order",
      "status": [
        400
      ],
      "description": "`order` is not `asc` or `desc`."
    },
    {
      "code": "bad_outpoint",
      "status": [
        400
      ],
      "description": "Not an outpoint (`txid:vout`)."
    },
    {
      "code": "bad_outpoints",
      "status": [
        400
      ],
      "description": "`outpoints` lists none, or more than 100."
    },
    {
      "code": "bad_paging",
      "status": [
        400
      ],
      "description": "`limit` or `offset` out of range."
    },
    {
      "code": "bad_path",
      "status": [
        400
      ],
      "description": "The path is not valid percent-encoding."
    },
    {
      "code": "bad_payout",
      "status": [
        422
      ],
      "description": "A listed input is paired with an output that pays no address, or the payout address is the marketplace's fee address."
    },
    {
      "code": "bad_price",
      "status": [
        400
      ],
      "description": "A price is not a whole number of sats."
    },
    {
      "code": "bad_psbt",
      "status": [
        400
      ],
      "description": "Not a base64 PSBT, or one that does not parse."
    },
    {
      "code": "bad_public_key",
      "status": [
        400
      ],
      "description": "A public key is not hex, or not a valid secp256k1 key of the right size."
    },
    {
      "code": "bad_request",
      "status": [
        400
      ],
      "description": "The body is not a JSON object, or the engine refused a malformed request (e.g. a purchase submitted without its signed setup PSBT)."
    },
    {
      "code": "bad_row",
      "status": [
        400
      ],
      "description": "`row` is not a row id."
    },
    {
      "code": "bad_sequence",
      "status": [
        422
      ],
      "description": "A listed input is not signed with sequence 0xfffffffd."
    },
    {
      "code": "bad_sighash",
      "status": [
        422
      ],
      "description": "A signature uses the wrong sighash type (listings: 0x83; purchases: DEFAULT or ALL)."
    },
    {
      "code": "bad_signature",
      "status": [
        400,
        422
      ],
      "description": "400: `signature` is missing or too long. 422: a signature does not verify (cancel or registration message, listing or purchase input)."
    },
    {
      "code": "bad_sort",
      "status": [
        400
      ],
      "description": "`sort` is not `unit`, `price` or `new`."
    },
    {
      "code": "bad_status",
      "status": [
        400
      ],
      "description": "`status` is not `all` or a comma-separated list of offer statuses, or (wallet transfers) not `pending` or `all`."
    },
    {
      "code": "bad_structure",
      "status": [
        422
      ],
      "description": "The listing PSBT is not the expected layout (pairing, version 2, locktime 0, one seller, sequences), or a purchase would pay the fee address."
    },
    {
      "code": "bad_sub",
      "status": [
        400
      ],
      "description": "`sub` is not 0 or 1."
    },
    {
      "code": "bad_types",
      "status": [
        400
      ],
      "description": "`types` is not a comma-separated list of activity event types."
    },
    {
      "code": "bad_wallet_addresses",
      "status": [
        400
      ],
      "description": "`wallet_addresses` is not a list of at most 4 mainnet addresses."
    },
    {
      "code": "banned",
      "status": [
        403
      ],
      "description": "The address is banned from chat: it may not post or set a display name."
    },
    {
      "code": "bitcoind_unavailable",
      "status": [
        503
      ],
      "description": "bitcoind is not available."
    },
    {
      "code": "broadcast_unknown",
      "status": [
        503
      ],
      "description": "The broadcast's outcome is unknown: submit the same purchase or transfer again to settle it. Carries `txid`."
    },
    {
      "code": "busy",
      "status": [
        503
      ],
      "description": "Too many purchases, offers or transfers are being prepared: try again in a minute. Each client (IPv4 address or IPv6 /64) keeps its 10 latest prepared purchases, offers and transfers; an older one answers `unknown_purchase` / `unknown_offer` / `unknown_transfer`."
    },
    {
      "code": "changed",
      "status": [
        409
      ],
      "description": "The UTXO's value is not what the PSBT says, or (wallet tools) a UTXO, its sats or the transaction being replaced changed since prepare: prepare again."
    },
    {
      "code": "chat_busy",
      "status": [
        429
      ],
      "description": "Too many chat messages and names are being checked across the site right now (over the global cap of model calls a minute); wait `retry-after` seconds."
    },
    {
      "code": "chat_disabled",
      "status": [
        404
      ],
      "description": "Chat and display names are off on this server."
    },
    {
      "code": "config_changed",
      "status": [
        409
      ],
      "description": "The marketplace settings changed since this purchase or transfer was prepared (prepare it again), or since this offer was made (it is now `invalid`, reason `config_changed`)."
    },
    {
      "code": "conflict",
      "status": [
        409
      ],
      "description": "A listing or one of your UTXOs was spent meanwhile (lost race), or bitcoind would not replace a transaction already spending it (`insufficient fee`), or a transfer's inputs are spent by another transaction."
    },
    {
      "code": "cross_origin",
      "status": [
        403
      ],
      "description": "A POST from a browser on another site (a foreign `Origin`, or `sec-fetch-site: cross-site`). Server-side clients send no `Origin` and are not affected."
    },
    {
      "code": "duplicate",
      "status": [
        409
      ],
      "description": "The same message (ignoring case) from the same address within 2 minutes."
    },
    {
      "code": "duplicate_outpoint",
      "status": [
        400
      ],
      "description": "The same UTXO twice in one listing."
    },
    {
      "code": "dust_output",
      "status": [
        422
      ],
      "description": "A bought UTXO is below the dust limit of your ordinals address type: use a Taproot or native SegWit ordinals address."
    },
    {
      "code": "empty_text",
      "status": [
        422
      ],
      "description": "Nothing is left of the message once control, zero-width and bidi characters are dropped and spaces collapsed."
    },
    {
      "code": "engine_unavailable",
      "status": [
        503
      ],
      "description": "The trade engine is not available."
    },
    {
      "code": "expired",
      "status": [
        409
      ],
      "description": "The prepared purchase, offer or transfer expired, or the offer itself has: prepare it again."
    },
    {
      "code": "fee_rate_too_low",
      "status": [
        422
      ],
      "description": "`fee_rate` is below the current minimum (`GET /api/market/fees`)."
    },
    {
      "code": "fee_too_high",
      "status": [
        422
      ],
      "description": "The network fee would exceed the per-transaction cap (200,000 sats): lower the fee rate or move fewer."
    },
    {
      "code": "fees_unavailable",
      "status": [
        503
      ],
      "description": "No fee estimate is available."
    },
    {
      "code": "fork_behind",
      "status": [
        503
      ],
      "description": "The rare-sat index has not caught up with bitcoind: try again in a minute."
    },
    {
      "code": "fork_unavailable",
      "status": [
        503
      ],
      "description": "The rare-sat index is not available."
    },
    {
      "code": "funding_spent",
      "status": [
        409
      ],
      "description": "A UTXO of the bidder's that funds the offer was spent (or is no longer plain cardinal): the offer is no longer valid."
    },
    {
      "code": "future_message",
      "status": [
        422
      ],
      "description": "The cancel or registration message is dated more than 2 minutes ahead: check the clock."
    },
    {
      "code": "indexer_behind",
      "status": [
        503
      ],
      "description": "The ord indexer is catching up: try again shortly."
    },
    {
      "code": "inscribed",
      "status": [
        422
      ],
      "description": "The UTXO carries an inscription: only rare sats are listed; the wallet tools only send it whole."
    },
    {
      "code": "insufficient_funds",
      "status": [
        422
      ],
      "description": "The payment address's plain UTXOs cannot pay prices, fee, padding and network fee (or a transfer's fees). Carries `available`, `prices`, `platform_fee`."
    },
    {
      "code": "internal",
      "status": [
        500
      ],
      "description": "A server bug. Report it."
    },
    {
      "code": "invariant_violated",
      "status": [
        500
      ],
      "description": "A planned or finalized purchase or transfer broke an invariant (`violations`); nothing was broadcast."
    },
    {
      "code": "key_mismatch",
      "status": [
        422
      ],
      "description": "The public key does not control the address."
    },
    {
      "code": "legacy_address",
      "status": [
        422
      ],
      "description": "A legacy (P2PKH, `1…`) address: use Taproot or SegWit."
    },
    {
      "code": "listing_changed",
      "status": [
        409
      ],
      "description": "A listing's stored terms no longer match the plan: prepare it again."
    },
    {
      "code": "market_unavailable",
      "status": [
        503
      ],
      "description": "The marketplace is closed right now (its backends disagree on the network, or are unreachable)."
    },
    {
      "code": "method_not_allowed",
      "status": [
        405
      ],
      "description": "Wrong method for the route; the `allow` header lists the right ones."
    },
    {
      "code": "missing_signature",
      "status": [
        422
      ],
      "description": "An input that must be signed is not."
    },
    {
      "code": "moderated",
      "status": [
        422
      ],
      "description": "The AI moderation refused the chat message or display name; `category` says why (the message is not posted, the name not taken). Three refusals in 10 minutes mute the address for an hour (`until`)."
    },
    {
      "code": "moderation_unavailable",
      "status": [
        503
      ],
      "description": "The AI moderation could not check the text right now (timeout or model error): nothing was posted. Try again in a moment."
    },
    {
      "code": "muted",
      "status": [
        403
      ],
      "description": "The address is muted (by the AI moderation after repeated refusals: 3 in 10 minutes), or its network (an IPv4 address or IPv6 /48) is paused after 6 refusals within an hour, until `until`, unix seconds: it may not post or set a display name until then."
    },
    {
      "code": "name_address",
      "status": [
        422
      ],
      "description": "A display name must not look like an address (`bc1…`, base58) or a hash."
    },
    {
      "code": "name_change_too_soon",
      "status": [
        429
      ],
      "description": "A display name changes at most once in 24 hours; `next_change_at` says when."
    },
    {
      "code": "name_chars",
      "status": [
        422
      ],
      "description": "A display name uses only letters, digits, spaces and `_ . -`, and starts and ends with a letter or digit."
    },
    {
      "code": "name_length",
      "status": [
        422
      ],
      "description": "A display name is 3 to 24 characters."
    },
    {
      "code": "name_reserved",
      "status": [
        422
      ],
      "description": "The display name is reserved (raresats, admin, moderator, support, official, satoshi and the like)."
    },
    {
      "code": "name_taken",
      "status": [
        409
      ],
      "description": "Another address has that display name (compared without case, separators or look-alike digits), gave it up less than 7 days ago, or it was removed by a moderator and is never given out again."
    },
    {
      "code": "no_endpoint",
      "status": [
        404
      ],
      "description": "No such `/api/market/*` route."
    },
    {
      "code": "no_row",
      "status": [
        422
      ],
      "description": "The UTXO holds no sat of a market row."
    },
    {
      "code": "no_session",
      "status": [
        401
      ],
      "description": "No chat session: sign in (`POST /api/session`) and send its cookie."
    },
    {
      "code": "not_active",
      "status": [
        409
      ],
      "description": "A listing (or offer) is not active: being bought (or accepted), sold, cancelled, moved, expired or invalid. Carries `id` and `status`."
    },
    {
      "code": "not_admin",
      "status": [
        403
      ],
      "description": "Only a chat admin (`SUPPLY_CHAT_ADMINS`) may do that."
    },
    {
      "code": "not_bannable",
      "status": [
        422
      ],
      "description": "An admin cannot be banned."
    },
    {
      "code": "not_bidder",
      "status": [
        422
      ],
      "description": "An offer was not made by `address` (neither its payment nor its ordinals address)."
    },
    {
      "code": "not_found",
      "status": [
        404
      ],
      "description": "No such listing or offer. In chat: no such message. A display name to remove that does not exist."
    },
    {
      "code": "not_json",
      "status": [
        415
      ],
      "description": "A POST without `content-type: application/json`."
    },
    {
      "code": "not_listed",
      "status": [
        404
      ],
      "description": "That outpoint has no live listing."
    },
    {
      "code": "not_owner",
      "status": [
        422
      ],
      "description": "The UTXO does not belong to the seller address, or (wallet tools) to the owner's addresses, or the transfer was made by another wallet."
    },
    {
      "code": "not_seller",
      "status": [
        422
      ],
      "description": "A listing was not listed by `address`."
    },
    {
      "code": "offer_changed",
      "status": [
        409
      ],
      "description": "The offer's stored signatures no longer verify: it cannot be accepted."
    },
    {
      "code": "oracle_unavailable",
      "status": [
        503
      ],
      "description": "The ord oracle is not available."
    },
    {
      "code": "own_utxo",
      "status": [
        422
      ],
      "description": "The UTXO is held by one of the bidder's own addresses."
    },
    {
      "code": "pending",
      "status": [
        409
      ],
      "description": "The UTXO's listing is being bought, or an offer of it accepted, right now."
    },
    {
      "code": "price_too_high",
      "status": [
        422
      ],
      "description": "The price is above 21,000,000 BTC."
    },
    {
      "code": "price_too_low",
      "status": [
        422
      ],
      "description": "The price is at most the UTXO's own value, below 546 sats, or below the payout output's dust limit."
    },
    {
      "code": "psbt_mismatch",
      "status": [
        422
      ],
      "description": "The signed PSBT is not the prepared transaction."
    },
    {
      "code": "pubkey_mismatch",
      "status": [
        422
      ],
      "description": "The trade engine found the public key is not the address's key."
    },
    {
      "code": "rate_limited",
      "status": [
        429
      ],
      "description": "Over 30 POSTs a minute from your IPv4 address or IPv6 /64 (in chat, counted per IPv4 address or IPv6 /64: 30 writes and 20 login nonces a minute, 20 sign-ins and 10 display-name changes an hour; one message every 3 s and 20 a minute per address); wait `retry-after` seconds. With the AI moderation on, at most 6 messages and names a minute are checked per address and per IPv4 address or IPv6 /48."
    },
    {
      "code": "rejected",
      "status": [
        422
      ],
      "description": "bitcoind refused the transaction (`reason`)."
    },
    {
      "code": "replayed",
      "status": [
        409
      ],
      "description": "That cancel or registration message was used already."
    },
    {
      "code": "retired_row",
      "status": [
        404
      ],
      "description": "`row` 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."
    },
    {
      "code": "room_busy",
      "status": [
        429
      ],
      "description": "Over 5 chat messages a second across the whole chat; wait `retry-after` seconds."
    },
    {
      "code": "runes",
      "status": [
        422
      ],
      "description": "The UTXO carries runes (the wallet tools only send it whole)."
    },
    {
      "code": "spent",
      "status": [
        409
      ],
      "description": "The UTXO (or a listing's UTXO) is spent or does not exist."
    },
    {
      "code": "stale_message",
      "status": [
        422
      ],
      "description": "The cancel or registration message is more than 10 minutes old: sign a new one."
    },
    {
      "code": "suspicious_link",
      "status": [
        422
      ],
      "description": "A link in the message names a host that is not plain ASCII: look-alike letters from other scripts, punycode (`xn--`), or `user@host`. Write the link with its real host name."
    },
    {
      "code": "bad_topic",
      "status": [
        400
      ],
      "description": "A topic id that is not one: 1-32 of a-z, 0-9 and inner hyphens (and, to create one, not `main`). On a reply: a `topic` other than its root's."
    },
    {
      "code": "unknown_topic",
      "status": [
        404
      ],
      "description": "No such chat topic, or an archived one (which takes no new messages)."
    },
    {
      "code": "bad_topic_text",
      "status": [
        422
      ],
      "description": "A topic's name must be 1-40 characters, its description at most 140."
    },
    {
      "code": "topic_exists",
      "status": [
        409
      ],
      "description": "A topic (or an archived one) has that id already."
    },
    {
      "code": "too_many_topics",
      "status": [
        422
      ],
      "description": "At most 50 chat topics: archive one first."
    },
    {
      "code": "not_archivable",
      "status": [
        422
      ],
      "description": "General cannot be archived."
    },
    {
      "code": "text_too_long",
      "status": [
        422
      ],
      "description": "A chat message is at most 500 characters."
    },
    {
      "code": "too_large",
      "status": [
        413
      ],
      "description": "The body is over 256 KiB."
    },
    {
      "code": "too_many_items",
      "status": [
        422
      ],
      "description": "Too many UTXOs in a listing, or listings in a purchase (`max_bulk`); for a wallet transfer, too many rare sats (and the runs between them) to lay out in one UTXO: choose fewer."
    },
    {
      "code": "unchanged",
      "status": [
        409
      ],
      "description": "That is already the display name."
    },
    {
      "code": "unconfirmed",
      "status": [
        409
      ],
      "description": "The UTXO is not confirmed yet."
    },
    {
      "code": "unindexed",
      "status": [
        409
      ],
      "description": "The ord indexer does not know the UTXO yet."
    },
    {
      "code": "unknown_offer",
      "status": [
        404
      ],
      "description": "No such prepared offer (it expired, or the server restarted): prepare it again."
    },
    {
      "code": "unknown_purchase",
      "status": [
        404
      ],
      "description": "No such prepared purchase (it was dropped: your 11th prepared since, a busy server, or a restart): prepare it again."
    },
    {
      "code": "unsupported_address",
      "status": [
        422
      ],
      "description": "An address type the marketplace does not trade (only Taproot, native SegWit and nested SegWit)."
    },
    {
      "code": "unsupported_script",
      "status": [
        422
      ],
      "description": "The trade engine met a script type it does not support."
    },
    {
      "code": "untracked",
      "status": [
        422
      ],
      "description": "The UTXO holds no rare sat the index tracks (send it whole instead)."
    },
    {
      "code": "utxo_mismatch",
      "status": [
        409
      ],
      "description": "The PSBT's amount or script of a UTXO is not the chain's."
    },
    {
      "code": "utxos_required",
      "status": [
        500
      ],
      "description": "A server bug in listing verification."
    },
    {
      "code": "bad_kind",
      "status": [
        400
      ],
      "description": "`kind` is not one of the wallet tools (`extract`, `send`, `send_n`, `chop`, `consolidate`, `multisend`, `speedup`, `cancel`), or a send `mode` is unknown."
    },
    {
      "code": "bad_owner",
      "status": [
        400
      ],
      "description": "`owner` must give the payment and ordinals addresses and their public keys."
    },
    {
      "code": "bad_destination",
      "status": [
        422
      ],
      "description": "The destination (or a multisend recipient) is the marketplace's fee address, or missing."
    },
    {
      "code": "bad_type",
      "status": [
        400
      ],
      "description": "`type` (send N) is not a sat type, types joined with `+`, or `block9` / `450x`."
    },
    {
      "code": "bad_count",
      "status": [
        400
      ],
      "description": "`count` (send N) is not a whole number of sats of at least 1."
    },
    {
      "code": "bad_chop_size",
      "status": [
        400
      ],
      "description": "`chop_size` is not a whole number from 330 to 100,000,000."
    },
    {
      "code": "bad_split",
      "status": [
        400
      ],
      "description": "`split` (extract) is not `{type, per_output | chunks, trim?}`: an exact type combination that is not a whole range, `per_output` 1–2,000 or `chunks` 2–100 (exactly one), `trim` a boolean; or an item names `sats` (a split takes every sat of its type)."
    },
    {
      "code": "bad_sends",
      "status": [
        400
      ],
      "description": "`sends` must list 1-50 payments of `{address, value}`, each at least its address type's minimum (330, or 546 for P2SH and P2PKH)."
    },
    {
      "code": "payment_destination",
      "status": [
        422
      ],
      "description": "Rare sats, inscriptions or runes would go to your own payment address, which your wallet spends as plain bitcoin: send them to your ordinals address, or say `confirm_payment_destination: true`."
    },
    {
      "code": "address_too_large",
      "status": [
        422
      ],
      "description": "An owner address holds more than 5,000 outputs: the wallet tools cannot plan for it."
    },
    {
      "code": "not_plain",
      "status": [
        422
      ],
      "description": "A UTXO to consolidate is not plain bitcoin (it holds tracked, exotic or inscribed sats, or runes)."
    },
    {
      "code": "already_extracted",
      "status": [
        422
      ],
      "description": "The UTXO is extracted already (its rare sats sit in an output of their own)."
    },
    {
      "code": "split_chunk",
      "status": [
        422
      ],
      "description": "Skip code of an \"extract all\" over several UTXOs: the UTXO is a chunk a split on this site made (extracting it again would undo the split). Name it alone to extract it."
    },
    {
      "code": "not_enough_sats",
      "status": [
        422
      ],
      "description": "Your UTXOs do not hold `count` sats of that type that can be sent. Carries `available`."
    },
    {
      "code": "nothing_to_do",
      "status": [
        422
      ],
      "description": "Nothing to move: every item was skipped (`skipped`), or a consolidation has fewer than 2 UTXOs, or a chop leaves one piece."
    },
    {
      "code": "nothing_to_separate",
      "status": [
        422
      ],
      "description": "Extracting would leave the UTXO one output: its rare sats are apart already, or too close to its ends."
    },
    {
      "code": "keep_in_destination",
      "status": [
        422
      ],
      "description": "Exotic or unpicked tracked sats sit so close to a picked one that they would have to leave with it: send the whole UTXO instead."
    },
    {
      "code": "range_too_small",
      "status": [
        422
      ],
      "description": "A range chunk (send N of `block9` or `450x`) must be at least the destination's padding: 330 sats, 546 for P2SH and P2PKH."
    },
    {
      "code": "listed_public_alone",
      "status": [
        422
      ],
      "description": "A UTXO whose listing signature is public must be moved on its own (and fast)."
    },
    {
      "code": "inscribed_consolidate",
      "status": [
        422
      ],
      "description": "Inscribed UTXOs are sent whole and 1:1, never merged into one output."
    },
    {
      "code": "runes_multi",
      "status": [
        422
      ],
      "description": "At most one rune UTXO per transfer (except a whole send merged into one output)."
    },
    {
      "code": "dust_destination",
      "status": [
        422
      ],
      "description": "A whole UTXO is too small for the destination's address type."
    },
    {
      "code": "too_many_outputs",
      "status": [
        422
      ],
      "description": "The transfer would have more than 100 outputs: move fewer UTXOs at once."
    },
    {
      "code": "tx_too_large",
      "status": [
        422
      ],
      "description": "The transfer would exceed 100,000 vB: move fewer UTXOs at once."
    },
    {
      "code": "unknown_transfer",
      "status": [
        404
      ],
      "description": "No such transfer: an unknown or forgotten prepared id, or a txid the wallet tools did not build."
    },
    {
      "code": "not_pending",
      "status": [
        409
      ],
      "description": "The transfer to speed up or cancel is not waiting in the mempool any more (confirmed, replaced)."
    },
    {
      "code": "has_descendants",
      "status": [
        409
      ],
      "description": "A transaction spends the transfer's outputs already: it can no longer be replaced."
    },
    {
      "code": "offer_overlap",
      "status": [
        409
      ],
      "description": "Since the prepare, a planned input started funding one of your offers, or a UTXO the server picked got an offer: prepare the transfer again."
    },
    {
      "code": "nothing_to_cancel",
      "status": [
        409
      ],
      "description": "A cancel that could save nothing: the transfer was refused (never sent), or it (and, once dropped, every transfer it replaced) only pays your own addresses."
    },
    {
      "code": "replacement_fee_too_low",
      "status": [
        422
      ],
      "description": "The replacement pays too little to replace the pending transaction (BIP 125): raise the fee rate to at least `min_fee_rate`."
    }
  ],
  "paths": {
    "/api/market/listings": {
      "get": {
        "operationId": "listListings",
        "tags": [
          "Listings"
        ],
        "summary": "List active listings",
        "description": "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.",
        "parameters": [
          {
            "name": "row",
            "in": "query",
            "required": false,
            "description": "Only 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.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_]{1,64}$"
            },
            "example": "black_rare"
          },
          {
            "name": "sub",
            "in": "query",
            "required": false,
            "description": "With `row`: `1` also lists the row's rarer sub-categories (listings whose sats the row holds whole, e.g. alpha uncommons under `uncommon`).",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "0"
            }
          },
          {
            "name": "contains",
            "in": "query",
            "required": false,
            "description": "With `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.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1",
                "only"
              ],
              "default": "0"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "`unit` (unit price), `price` (listing price) or `new` (creation time).",
            "schema": {
              "type": "string",
              "enum": [
                "unit",
                "price",
                "new"
              ],
              "default": "unit"
            },
            "example": "unit"
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "description": "`asc` or `desc`. Default: `asc`, except `desc` for `sort=new`. Ties: newest first, then by id.",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            },
            "example": "asc"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1-200.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "example": 2
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Listings to skip, 0-1,000,000.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 1000000,
              "default": 0
            }
          },
          {
            "name": "seller",
            "in": "query",
            "required": false,
            "description": "Only listings by this seller address.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListingPage"
                },
                "example": {
                  "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
                  }
                }
              }
            }
          },
          "400": {
            "description": "A malformed query parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_sort": {
                    "summary": "Unknown sort",
                    "value": {
                      "error": "sort must be unit, price or new",
                      "code": "bad_sort"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`retired_row`: a retired row (`uncommon_2009`, `rare_2009`), whose listings are its parent row's; `retired` names the row and years.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "retired_row": {
                    "summary": "A retired row",
                    "value": {
                      "error": "row uncommon_2009 is retired: ask for row uncommon with years 2009",
                      "code": "retired_row",
                      "retired": {
                        "row": "uncommon_2009",
                        "successor": {
                          "row": "uncommon",
                          "years": [
                            2009
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "bad_row",
          "retired_row",
          "bad_sub",
          "bad_contains",
          "bad_sort",
          "bad_order",
          "bad_paging",
          "bad_address"
        ]
      },
      "post": {
        "operationId": "submitListing",
        "tags": [
          "Trading"
        ],
        "summary": "Submit a signed listing",
        "description": "Step 3 of listing: the PSBT from `POST /api/market/listings/prepare`, every input signed SIGHASH_SINGLE|ANYONECANPAY (0x83). Everything is checked again against the chain and every signature verified before anything is stored. A new listing of an outpoint already listed replaces the old one (whose signature is deleted).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitListingRequest"
              },
              "example": {
                "psbt": "cHNidP8BAF4CAAAAAWroye3nyLiwpcNzDMmz2aV449rKtugMlDF04UqR1gmLAAAAAAD9////AfhvAQAAAAAAIlEgqC8plE1luGrmteXMdeKU6tbFk5Gh7cXgFuNJjGf8e7sAAAAAAAEBK4gYAAAAAAAAIlEgqC8plE1luGrmteXMdeKU6tbFk5Gh7cXgFuNJjGf8e7sBAwSDAAAAARNBTRvH6V6M7UvHRHSt9rxehNgXWjFx339UPLBrpakZUHtJWYdSEjJcKWGz0mMAzAntUr45lEpONbwi2QRK4vGr6IMBFyCD3+haMVHSUXKQ2kYf4oFVke9p8rGKLOY/AWl6izExRQAA"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmitListingResponse"
                },
                "example": {
                  "listings": [
                    {
                      "id": "3324d08569806818",
                      "outpoint": "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0",
                      "value": 6280,
                      "price": 94200,
                      "unit_price": 14,
                      "row": "block9",
                      "count": 6280,
                      "rows": {
                        "block9": 6280,
                        "block9_1st_tx": 6280
                      },
                      "types": [
                        {
                          "types": [
                            "block9",
                            "nakamoto",
                            "vintage"
                          ],
                          "count": 6280,
                          "sats": [
                            45100023043,
                            45100023044,
                            45100023045
                          ]
                        }
                      ],
                      "sats": 6280,
                      "ranges": [
                        [
                          45100023043,
                          45100029322
                        ]
                      ],
                      "years": {
                        "2009": 6280
                      },
                      "seller_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "payout_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "status": "active",
                      "created_at": 1790952985,
                      "updated_at": 1790952985,
                      "txid": null,
                      "signature_public": false,
                      "sold_via": null,
                      "offer_id": null,
                      "best_offer": null
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "A signature does not verify",
                    "value": {
                      "error": "Listing signature (input 0): the signature does not verify",
                      "code": "bad_signature"
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "A backend is unavailable; retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "bad_psbt",
          "bad_items",
          "duplicate_outpoint",
          "bad_sequence",
          "bad_structure",
          "bad_signature",
          "bad_sighash",
          "missing_signature",
          "unsupported_script",
          "legacy_address",
          "unsupported_address",
          "bad_payout",
          "too_many_items",
          "spent",
          "changed",
          "utxo_mismatch",
          "not_owner",
          "unconfirmed",
          "untracked",
          "unindexed",
          "inscribed",
          "runes",
          "no_row",
          "bad_price",
          "price_too_low",
          "price_too_high",
          "pending",
          "fork_behind",
          "indexer_behind",
          "market_unavailable",
          "engine_unavailable",
          "bitcoind_unavailable",
          "fork_unavailable",
          "oracle_unavailable"
        ]
      }
    },
    "/api/market/listings/{id}": {
      "get": {
        "operationId": "getListing",
        "tags": [
          "Listings"
        ],
        "summary": "Get a listing",
        "description": "One listing by id, whatever its status (active, pending, sold, cancelled or moved).",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The listing id (16 hex characters).",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{16}$"
            },
            "example": "3324d08569806818"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Listing"
                },
                "example": {
                  "id": "3324d08569806818",
                  "outpoint": "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0",
                  "value": 6280,
                  "price": 94200,
                  "unit_price": 14,
                  "row": "block9",
                  "count": 6280,
                  "rows": {
                    "block9": 6280,
                    "block9_1st_tx": 6280
                  },
                  "types": [
                    {
                      "types": [
                        "block9",
                        "nakamoto",
                        "vintage"
                      ],
                      "count": 6280,
                      "sats": [
                        45100023043,
                        45100023044,
                        45100023045
                      ]
                    }
                  ],
                  "sats": 6280,
                  "ranges": [
                    [
                      45100023043,
                      45100029322
                    ]
                  ],
                  "years": {
                    "2009": 6280
                  },
                  "seller_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                  "payout_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                  "status": "active",
                  "created_at": 1790952985,
                  "updated_at": 1790952985,
                  "txid": null,
                  "signature_public": false,
                  "sold_via": null,
                  "offer_id": null,
                  "best_offer": null
                }
              }
            }
          },
          "404": {
            "description": "No such listing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Unknown id",
                    "value": {
                      "error": "no such listing",
                      "code": "not_found"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "not_found",
          "bad_path"
        ]
      }
    },
    "/api/market/listings/by-outpoint/{outpoint}": {
      "get": {
        "operationId": "getListingByOutpoint",
        "tags": [
          "Listings"
        ],
        "summary": "Get the listing of a UTXO",
        "description": "The live listing (active, or pending while a purchase is in the mempool) of one outpoint, or 404 `not_listed`.",
        "parameters": [
          {
            "name": "outpoint",
            "in": "path",
            "required": true,
            "description": "The UTXO, `txid:vout`.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}:\\d{1,10}$"
            },
            "example": "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Listing"
                },
                "example": {
                  "id": "3324d08569806818",
                  "outpoint": "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0",
                  "value": 6280,
                  "price": 94200,
                  "unit_price": 14,
                  "row": "block9",
                  "count": 6280,
                  "rows": {
                    "block9": 6280,
                    "block9_1st_tx": 6280
                  },
                  "types": [
                    {
                      "types": [
                        "block9",
                        "nakamoto",
                        "vintage"
                      ],
                      "count": 6280,
                      "sats": [
                        45100023043,
                        45100023044,
                        45100023045
                      ]
                    }
                  ],
                  "sats": 6280,
                  "ranges": [
                    [
                      45100023043,
                      45100029322
                    ]
                  ],
                  "years": {
                    "2009": 6280
                  },
                  "seller_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                  "payout_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                  "status": "active",
                  "created_at": 1790952985,
                  "updated_at": 1790952985,
                  "txid": null,
                  "signature_public": false,
                  "sold_via": null,
                  "offer_id": null,
                  "best_offer": null
                }
              }
            }
          },
          "400": {
            "description": "Not an outpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_outpoint": {
                    "summary": "Malformed",
                    "value": {
                      "error": "not an outpoint (txid:vout)",
                      "code": "bad_outpoint"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "The outpoint is not listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_listed": {
                    "summary": "Not listed",
                    "value": {
                      "error": "that outpoint is not listed",
                      "code": "not_listed"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "bad_outpoint",
          "not_listed",
          "bad_path"
        ]
      }
    },
    "/api/market/listings/by-outpoint": {
      "get": {
        "operationId": "getListingsByOutpoints",
        "tags": [
          "Listings"
        ],
        "summary": "Get the listings of many UTXOs",
        "description": "The batch form: the live listings of up to 100 outpoints at once, keyed by outpoint. Outpoints that are not listed are simply absent.",
        "parameters": [
          {
            "name": "outpoints",
            "in": "query",
            "required": true,
            "description": "1-100 outpoints (`txid:vout`), comma-separated.",
            "schema": {
              "type": "string"
            },
            "example": "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0,2fb6fb60ece3672924a373d7479d144d9ce4d3591185bfb5a00e62aedd53d3a9:0"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListingsByOutpoint"
                },
                "example": {
                  "listings": {
                    "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0": {
                      "id": "3324d08569806818",
                      "outpoint": "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0",
                      "value": 6280,
                      "price": 94200,
                      "unit_price": 14,
                      "row": "block9",
                      "count": 6280,
                      "rows": {
                        "block9": 6280,
                        "block9_1st_tx": 6280
                      },
                      "types": [
                        {
                          "types": [
                            "block9",
                            "nakamoto",
                            "vintage"
                          ],
                          "count": 6280,
                          "sats": [
                            45100023043,
                            45100023044,
                            45100023045
                          ]
                        }
                      ],
                      "sats": 6280,
                      "ranges": [
                        [
                          45100023043,
                          45100029322
                        ]
                      ],
                      "years": {
                        "2009": 6280
                      },
                      "seller_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "payout_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "status": "active",
                      "created_at": 1790952985,
                      "updated_at": 1790952985,
                      "txid": null,
                      "signature_public": false,
                      "sold_via": null,
                      "offer_id": null,
                      "best_offer": null
                    }
                  },
                  "as_of": {
                    "height": 969001,
                    "checked_at": 1790952985
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing, too many or malformed outpoints.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_outpoints": {
                    "summary": "None given",
                    "value": {
                      "error": "outpoints must list 1-100 outpoints",
                      "code": "bad_outpoints"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "bad_outpoints",
          "bad_outpoint"
        ]
      }
    },
    "/api/market/floors": {
      "get": {
        "operationId": "getFloors",
        "tags": [
          "Listings"
        ],
        "summary": "Get collection floors",
        "description": "For every row with active listings: its floor (the lowest unit price), how many listings and how many of its sats are listed.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Floors"
                },
                "example": {
                  "rows": {
                    "black_rare": {
                      "floor_unit": 12000,
                      "listed": 1,
                      "listed_sats": 1
                    },
                    "block9": {
                      "floor_unit": 14,
                      "listed": 1,
                      "listed_sats": 6280
                    }
                  },
                  "as_of": {
                    "height": 969001,
                    "checked_at": 1790952985
                  }
                }
              }
            }
          }
        },
        "x-error-codes": []
      }
    },
    "/api/market/config": {
      "get": {
        "operationId": "getMarketConfig",
        "tags": [
          "Listings"
        ],
        "summary": "Get marketplace settings",
        "description": "The marketplace's live settings: fee, fee address, marker, limits, and whether it is ready to trade. Read it before trading; the purchase is checked against the settings it was prepared with.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MarketConfig"
                },
                "example": {
                  "enabled": true,
                  "network": "mainnet",
                  "fee_bps": 250,
                  "min_fee": 546,
                  "fee_address": "bc1qycdj49gt04zvc07xyzzgsvgglc7qyhz8r3sfs6",
                  "op_return": "raresats.net",
                  "max_bulk": 20,
                  "padding_value": 600,
                  "max_listing_items": 50,
                  "cancel_prefix": "raresats.net cancel",
                  "affiliate_share_bps": 5000,
                  "affiliate_prefix": "raresats.net affiliate",
                  "affiliate_cookie_seconds": 86400,
                  "offer_cancel_prefix": "raresats.net cancel-offer",
                  "offer_expiries": [
                    86400,
                    259200,
                    604800,
                    2592000
                  ],
                  "offer_default_expiry": 604800,
                  "tools": {
                    "fee_sats": 1000,
                    "max_items": 50,
                    "max_outputs": 100,
                    "max_sends": 50,
                    "kinds": [
                      "extract",
                      "send",
                      "send_n",
                      "chop",
                      "consolidate",
                      "multisend",
                      "speedup",
                      "cancel"
                    ],
                    "pad": {
                      "default": 330,
                      "legacy": 546
                    }
                  },
                  "ready": true
                }
              }
            }
          }
        },
        "x-error-codes": []
      }
    },
    "/api/market/fees": {
      "get": {
        "operationId": "getMarketFees",
        "tags": [
          "Listings"
        ],
        "summary": "Get fee-rate choices",
        "description": "Network fee rates in sat/vB for a purchase: bitcoind's estimates for 6, 3 and 1 blocks, else mempool.space's; cached 30 seconds. `minimum` is the lowest `fee_rate` purchase/prepare accepts.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Fees"
                },
                "example": {
                  "slow": 2,
                  "normal": 4,
                  "fast": 8,
                  "minimum": 1,
                  "source": "bitcoind"
                }
              }
            }
          },
          "503": {
            "description": "No estimate is available.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "fees_unavailable": {
                    "summary": "No estimate",
                    "value": {
                      "error": "no fee estimate is available",
                      "code": "fees_unavailable"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "fees_unavailable"
        ]
      }
    },
    "/api/market/activity": {
      "get": {
        "operationId": "getActivity",
        "tags": [
          "Listings"
        ],
        "summary": "Get marketplace activity",
        "description": "Recent marketplace events, newest first: listed, cancelled and sold. Sales on other marketplaces are in `/api/sales`.",
        "parameters": [
          {
            "name": "row",
            "in": "query",
            "required": false,
            "description": "Only events of listings and offers under this row: its own, its sub-categories' and label's, and those holding some of its sats in a bundle (marked `sub` or `in_bundle`).",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_]{1,64}$"
            },
            "example": "black_rare"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Events, 1-200.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "example": 1
          },
          {
            "name": "types",
            "in": "query",
            "required": false,
            "description": "Comma-separated event types: `listed`, `cancelled`, `sold` (the default: those three), `offer_made`, `offer_cancelled`, `offer_accepted`.",
            "schema": {
              "type": "string"
            },
            "example": "sold,offer_accepted"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ActivityEvent"
                      },
                      "description": "Newest first."
                    }
                  },
                  "required": [
                    "events"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "events": [
                    {
                      "seq": 3,
                      "type": "sold",
                      "listing_id": "1031931af1592e1c",
                      "outpoint": "2fb6fb60ece3672924a373d7479d144d9ce4d3591185bfb5a00e62aedd53d3a9:0",
                      "row": "black_rare",
                      "count": 1,
                      "price": 60546,
                      "unit_price": 60000,
                      "seller_address": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu",
                      "txid": "6897451c42f02de2594abfdd6a5d4fcf4794a62cbbd9fbec1ec983893ddc5df4",
                      "time": 1790952985,
                      "seller": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu",
                      "buyer": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                      "affiliate": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "offer_id": null,
                      "bidder": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "A malformed query parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`retired_row`: a retired row (`uncommon_2009`, `rare_2009`), whose listings are its parent row's; `retired` names the row and years.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "retired_row": {
                    "summary": "A retired row",
                    "value": {
                      "error": "row uncommon_2009 is retired: ask for row uncommon with years 2009",
                      "code": "retired_row",
                      "retired": {
                        "row": "uncommon_2009",
                        "successor": {
                          "row": "uncommon",
                          "years": [
                            2009
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "bad_row",
          "retired_row",
          "bad_paging",
          "bad_types"
        ]
      }
    },
    "/api/market/listings/prepare": {
      "post": {
        "operationId": "prepareListing",
        "tags": [
          "Trading"
        ],
        "summary": "Prepare a listing PSBT",
        "description": "Step 1 of listing: checks each UTXO (confirmed, unspent, yours, tracked rare sats, no inscription or rune, a valid price) and returns the PSBT to sign with SIGHASH_SINGLE|ANYONECANPAY. Nothing is stored yet.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrepareListingRequest"
              },
              "example": {
                "seller_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                "seller_public_key": "0283dfe85a3151d2517290da461fe2815591ef69f2b18a2ce63f01697a8b313145",
                "payout_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                "items": [
                  {
                    "outpoint": "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0",
                    "price": 94200
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrepareListingResponse"
                },
                "example": {
                  "psbt": "cHNidP8BAF4CAAAAAWroye3nyLiwpcNzDMmz2aV449rKtugMlDF04UqR1gmLAAAAAAD9////AfhvAQAAAAAAIlEgqC8plE1luGrmteXMdeKU6tbFk5Gh7cXgFuNJjGf8e7sAAAAAAAEBK4gYAAAAAAAAIlEgqC8plE1luGrmteXMdeKU6tbFk5Gh7cXgFuNJjGf8e7sBAwSDAAAAARcgg9/oWjFR0lFykNpGH+KBVZHvafKxiizmPwFpeosxMUUAAA==",
                  "sign": [
                    {
                      "index": 0,
                      "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "sighash": 131
                    }
                  ],
                  "items": [
                    {
                      "outpoint": "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0",
                      "value": 6280,
                      "price": 94200,
                      "unit_price": 14,
                      "row": "block9",
                      "count": 6280
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "inscribed": {
                    "summary": "An inscribed UTXO",
                    "value": {
                      "error": "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0 carries an inscription: only rare sats are listed here",
                      "code": "inscribed",
                      "outpoint": "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0"
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "A backend is unavailable or catching up; retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "bad_address",
          "legacy_address",
          "unsupported_address",
          "key_mismatch",
          "bad_payout",
          "bad_items",
          "bad_outpoint",
          "duplicate_outpoint",
          "bad_price",
          "price_too_low",
          "price_too_high",
          "spent",
          "not_owner",
          "unconfirmed",
          "untracked",
          "unindexed",
          "inscribed",
          "runes",
          "no_row",
          "pending",
          "bad_public_key",
          "pubkey_mismatch",
          "unsupported_script",
          "too_many_items",
          "fork_behind",
          "indexer_behind",
          "market_unavailable",
          "engine_unavailable",
          "bitcoind_unavailable",
          "fork_unavailable",
          "oracle_unavailable"
        ]
      }
    },
    "/api/market/listings/cancel": {
      "post": {
        "operationId": "cancelListings",
        "tags": [
          "Trading"
        ],
        "summary": "Cancel listings",
        "description": "Takes active listings off sale with a BIP-322 signature by the seller address of `raresats.net cancel <id,id,…> <unix seconds>`. The stored signatures are deleted. A message is usable once and for 10 minutes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CancelRequest"
              },
              "example": {
                "ids": [
                  "3324d08569806818"
                ],
                "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                "message": "raresats.net cancel 3324d08569806818 1790949400",
                "signature": "AUBGQvdc2H+7HTo1njZ1vlDxoX6ncoehAGbaHcAY1FtfSNg7lmo8Ih3WGInhAH/snOUIb8DkwRSQxc2dOu911Z9E"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelResponse"
                },
                "example": {
                  "listings": [
                    {
                      "id": "3324d08569806818",
                      "outpoint": "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0",
                      "value": 6280,
                      "price": 94200,
                      "unit_price": 14,
                      "row": "block9",
                      "count": 6280,
                      "rows": {
                        "block9": 6280,
                        "block9_1st_tx": 6280
                      },
                      "types": [
                        {
                          "types": [
                            "block9",
                            "nakamoto",
                            "vintage"
                          ],
                          "count": 6280,
                          "sats": [
                            45100023043,
                            45100023044,
                            45100023045
                          ]
                        }
                      ],
                      "sats": 6280,
                      "ranges": [
                        [
                          45100023043,
                          45100029322
                        ]
                      ],
                      "years": {
                        "2009": 6280
                      },
                      "seller_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "payout_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "status": "cancelled",
                      "created_at": 1790952985,
                      "updated_at": 1790949401,
                      "txid": null,
                      "signature_public": false,
                      "sold_via": null,
                      "offer_id": null,
                      "best_offer": null
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "stale_message": {
                    "summary": "Old message",
                    "value": {
                      "error": "the cancel message is more than 10 minutes old: sign a new one",
                      "code": "stale_message"
                    }
                  },
                  "replayed": {
                    "summary": "Used already",
                    "value": {
                      "error": "that cancel message was used already",
                      "code": "replayed"
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "The trade engine is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "bad_ids",
          "bad_address",
          "bad_message",
          "bad_signature",
          "stale_message",
          "future_message",
          "not_found",
          "not_seller",
          "replayed",
          "not_active",
          "engine_unavailable"
        ]
      }
    },
    "/api/market/purchase/prepare": {
      "post": {
        "operationId": "preparePurchase",
        "tags": [
          "Trading"
        ],
        "summary": "Prepare a purchase",
        "description": "Step 1 of buying 1-20 listings: checks they are active and unspent, picks plain cardinal UTXOs of your payment address, and returns the PSBTs to sign (a setup PSBT first when you lack padding), the fee breakdown and an expiry. The plan is held 10 minutes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreparePurchaseRequest"
              },
              "example": {
                "listing_ids": [
                  "1031931af1592e1c"
                ],
                "buyer": {
                  "payment_address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                  "payment_public_key": "039b3b694b8fc5b5e07fb069c783cac754f5d38c3e08bed1960e31fdb1dda35c24",
                  "ordinals_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                  "ordinals_public_key": "03cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115"
                },
                "fee_rate": 4,
                "affiliate": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreparePurchaseResponse"
                },
                "example": {
                  "id": "5c9e5c410688cd85",
                  "purchase": {
                    "psbt": "cHNidP8BAP3lAQIAAAAEV/MhdPD/0sIHo8hX35p9GQud7geCW9jXa3hoAejEjgoAAAAAAP3///+3Sw6TNUSithUu7/zVH0UQDemfGc8HWcjxkuB/9nd1LAAAAAAA/f///6nTU92uYg6gtb+FEVnT5JxNFJ1H13OjJCln4+xg+7YvAAAAAAD9////VHDf42dMx3y1IrYZcBnC/YiD1iNsIqK5yRDtpRMrGUYAAAAAAP3///8JsAQAAAAAAAAXqRQ/tulYEuV7tGkfmkpiiGKmGk92m4ciAgAAAAAAACJRIKYIafDbzx3GWcnOy6+AUBNeqejNxIcFPx3GiAlJ3GhMguwAAAAAAAAWABTAzrzWw9PKjHXcXsYuvlUzDvkQ4vUCAAAAAAAAIlEgrfKcXTOb9Ymo27aSDRsOplytPApoV4riNE46JGW7F/D1AgAAAAAAACJRIKgvKZRNZbhq5rXlzHXilOrWxZORoe3F4BbjSYxn/Hu7WAIAAAAAAAAXqRQ/tulYEuV7tGkfmkpiiGKmGk92m4dYAgAAAAAAABepFD+26VgS5Xu0aR+aSmKIYqYaT3abh3hIAQAAAAAAF6kUP7bpWBLle7RpH5pKYohiphpPdpuHAAAAAAAAAAAOagxyYXJlc2F0cy5uZXQAAAAAAAEBIFgCAAAAAAAAF6kUP7bpWBLle7RpH5pKYohiphpPdpuHAQQWABT5kGeayv4lwnYVNztAvyJEbST/RAABASBYAgAAAAAAABepFD+26VgS5Xu0aR+aSmKIYqYaT3abhwEEFgAU+ZBnmsr+JcJ2FTc7QL8iRG0k/0QAAQEfIgIAAAAAAAAWABTAzrzWw9PKjHXcXsYuvlUzDvkQ4gABASDwSQIAAAAAABepFD+26VgS5Xu0aR+aSmKIYqYaT3abhwEEFgAU+ZBnmsr+JcJ2FTc7QL8iRG0k/0QAAAAAAAAAAAAA",
                    "sign": [
                      {
                        "index": 0,
                        "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf"
                      },
                      {
                        "index": 1,
                        "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf"
                      },
                      {
                        "index": 3,
                        "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf"
                      }
                    ]
                  },
                  "summary": {
                    "prices": 60546,
                    "platform_fee": 1514,
                    "platform_share": 757,
                    "affiliate_fee": 757,
                    "affiliate_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                    "affiliate_status": "applied",
                    "affiliate_reason": null,
                    "affiliate_share_bps": 5000,
                    "network_fee": 2652,
                    "purchase_network_fee": 2652,
                    "setup_network_fee": 0,
                    "total": 64712,
                    "vsize": 663,
                    "setup_vsize": 0,
                    "fee_rate": 4,
                    "change": 84088,
                    "padding_value": 600,
                    "items": [
                      {
                        "id": "1031931af1592e1c",
                        "outpoint": "2fb6fb60ece3672924a373d7479d144d9ce4d3591185bfb5a00e62aedd53d3a9:0",
                        "value": 546,
                        "price": 60546,
                        "unit_price": 60000,
                        "row": "black_rare",
                        "count": 1
                      }
                    ]
                  },
                  "expires_at": 1790953585
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_active": {
                    "summary": "Sold meanwhile",
                    "value": {
                      "error": "listing 1031931af1592e1c is pending",
                      "code": "not_active",
                      "id": "1031931af1592e1c",
                      "status": "pending"
                    }
                  },
                  "insufficient_funds": {
                    "summary": "Not enough funds",
                    "value": {
                      "error": "The payment address's 2 spendable UTXOs (9000 sats) cannot pay 60546 sats plus a 1514-sat platform fee, 2 padding outputs and the network fee",
                      "code": "insufficient_funds",
                      "available": 9000,
                      "prices": 60546,
                      "platform_fee": 1514
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "A backend is unavailable, or too many purchases are being prepared.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "bad_ids",
          "bad_buyer",
          "bad_address",
          "legacy_address",
          "unsupported_address",
          "key_mismatch",
          "bad_fee_rate",
          "fee_rate_too_low",
          "not_found",
          "not_active",
          "spent",
          "busy",
          "insufficient_funds",
          "fee_too_high",
          "dust_output",
          "too_many_items",
          "bad_structure",
          "bad_public_key",
          "pubkey_mismatch",
          "unsupported_script",
          "market_unavailable",
          "engine_unavailable",
          "bitcoind_unavailable",
          "fork_unavailable",
          "oracle_unavailable"
        ]
      }
    },
    "/api/market/purchase/submit": {
      "post": {
        "operationId": "submitPurchase",
        "tags": [
          "Trading"
        ],
        "summary": "Submit a signed purchase",
        "description": "Step 3 of buying: the PSBTs from prepare, your inputs signed. The server checks they are exactly the prepared transactions, verifies your signatures, adds the sellers' signatures, rechecks every rule, then `testmempoolaccept` and broadcasts (setup first). The listings become `pending`. Resubmitting the same purchase is idempotent: use it to settle `broadcast_unknown`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitPurchaseRequest"
              },
              "example": {
                "id": "5c9e5c410688cd85",
                "purchase_psbt": "cHNidP8BAP3lAQIAAAAEV/MhdPD/0sIHo8hX35p9GQud7geCW9jXa3hoAejEjgoAAAAAAP3///+3Sw6TNUSithUu7/zVH0UQDemfGc8HWcjxkuB/9nd1LAAAAAAA/f///6nTU92uYg6gtb+FEVnT5JxNFJ1H13OjJCln4+xg+7YvAAAAAAD9////VHDf42dMx3y1IrYZcBnC/YiD1iNsIqK5yRDtpRMrGUYAAAAAAP3///8JsAQAAAAAAAAXqRQ/tulYEuV7tGkfmkpiiGKmGk92m4ciAgAAAAAAACJRIKYIafDbzx3GWcnOy6+AUBNeqejNxIcFPx3GiAlJ3GhMguwAAAAAAAAWABTAzrzWw9PKjHXcXsYuvlUzDvkQ4vUCAAAAAAAAIlEgrfKcXTOb9Ymo27aSDRsOplytPApoV4riNE46JGW7F/D1AgAAAAAAACJRIKgvKZRNZbhq5rXlzHXilOrWxZORoe3F4BbjSYxn/Hu7WAIAAAAAAAAXqRQ/tulYEuV7tGkfmkpiiGKmGk92m4dYAgAAAAAAABepFD+26VgS5Xu0aR+aSmKIYqYaT3abh3hIAQAAAAAAF6kUP7bpWBLle7RpH5pKYohiphpPdpuHAAAAAAAAAAAOagxyYXJlc2F0cy5uZXQAAAAAAAEBIFgCAAAAAAAAF6kUP7bpWBLle7RpH5pKYohiphpPdpuHIgIDmztpS4/FteB/sGnHg8rHVPXTjD4IvtGWDjH9sd2jXCRIMEUCIQDqT5JFB8nk2LvYxjpKXk87G12Tn0Jt7fslQf2gSIvJjwIgbg+BAy20UrXd2niDIeZbPLkgyz+NcnSSkChVICw0gV4BAQQWABT5kGeayv4lwnYVNztAvyJEbST/RAABASBYAgAAAAAAABepFD+26VgS5Xu0aR+aSmKIYqYaT3abhyICA5s7aUuPxbXgf7Bpx4PKx1T104w+CL7Rlg4x/bHdo1wkRzBEAiAbu6SfmqbPok5pJyyLQoLTWtu6xHYFUxdkVqMdge1hPwIgXVp1PF1DvIaRLu2QeT0Qv9t+5Dfe2BUaY/Y2QBv58+ABAQQWABT5kGeayv4lwnYVNztAvyJEbST/RAABAR8iAgAAAAAAABYAFMDOvNbD08qMddxexi6+VTMO+RDiAAEBIPBJAgAAAAAAF6kUP7bpWBLle7RpH5pKYohiphpPdpuHIgIDmztpS4/FteB/sGnHg8rHVPXTjD4IvtGWDjH9sd2jXCRHMEQCIC8ykJLr2bz7gpup8hfRujOnTV4UdPVuIsfzFgJGmMuCAiARSDj1rK63S1wPEKMrRPqnZ7u+rJDysVPRn7ym3iNFpQEBBBYAFPmQZ5rK/iXCdhU3O0C/IkRtJP9EAAAAAAAAAAAAAA=="
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmitPurchaseResponse"
                },
                "example": {
                  "txid": "6897451c42f02de2594abfdd6a5d4fcf4794a62cbbd9fbec1ec983893ddc5df4"
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "expired": {
                    "summary": "Plan expired",
                    "value": {
                      "error": "the prepared purchase expired: prepare it again",
                      "code": "expired"
                    }
                  },
                  "config_changed": {
                    "summary": "Settings changed",
                    "value": {
                      "error": "The marketplace settings changed since this purchase was prepared (fee_bps): prepare it again",
                      "code": "config_changed"
                    }
                  },
                  "conflict": {
                    "summary": "Lost a race",
                    "value": {
                      "error": "a listing (or one of your UTXOs) was spent in the meantime",
                      "code": "conflict",
                      "reason": "bad-txns-inputs-missingorspent"
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "Unavailable, or `broadcast_unknown`: the outcome is not known yet; submit again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "broadcast_unknown": {
                    "summary": "Outcome unknown",
                    "value": {
                      "error": "bitcoind did not answer the broadcast: the purchase may have gone through; submit again to check",
                      "code": "broadcast_unknown",
                      "txid": "6897451c42f02de2594abfdd6a5d4fcf4794a62cbbd9fbec1ec983893ddc5df4"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "bad_id",
          "bad_psbt",
          "unknown_purchase",
          "expired",
          "not_active",
          "spent",
          "config_changed",
          "psbt_mismatch",
          "listing_changed",
          "bad_signature",
          "bad_sighash",
          "missing_signature",
          "conflict",
          "rejected",
          "broadcast_unknown",
          "market_unavailable",
          "engine_unavailable",
          "bitcoind_unavailable",
          "fork_unavailable",
          "oracle_unavailable"
        ]
      }
    },
    "/api/market/offers": {
      "get": {
        "operationId": "getOffers",
        "tags": [
          "Offers"
        ],
        "summary": "List offers",
        "description": "Offers filtered by UTXO, seller, bidder, row and status, sorted by price, unit price, age or expiry, paged. Without `status`, only active offers. A wallet's \"offers made\" are `bidder=<address>`, its \"offers received\" `seller=<address>`.",
        "parameters": [
          {
            "name": "outpoint",
            "in": "query",
            "required": false,
            "description": "Only offers on this UTXO (`txid:vout`).",
            "schema": {
              "type": "string"
            },
            "example": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0"
          },
          {
            "name": "seller",
            "in": "query",
            "required": false,
            "description": "Only offers to this address (that held the UTXO when the offer was made).",
            "schema": {
              "type": "string"
            },
            "example": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr"
          },
          {
            "name": "bidder",
            "in": "query",
            "required": false,
            "description": "Only offers made by this address (the bidder's payment or ordinals address).",
            "schema": {
              "type": "string"
            },
            "example": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh"
          },
          {
            "name": "row",
            "in": "query",
            "required": false,
            "description": "Only offers whose own row is this one (as always); with `sub=1` also those on UTXOs the row holds whole (marked `sub`), and with `contains` those on bundles holding some of its sats, apart.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_]{1,64}$"
            },
            "example": "decasat_alpha"
          },
          {
            "name": "sub",
            "in": "query",
            "required": false,
            "description": "With `row`: `1` also answers the offers on UTXOs the row holds whole, as a rarer sub-category or a label (marked `sub`).",
            "schema": {
              "type": "string",
              "enum": ["0", "1"],
              "default": "0"
            }
          },
          {
            "name": "contains",
            "in": "query",
            "required": false,
            "description": "With `row`: `1` also answers, apart, the offers on UTXOs holding only some sats of the row among others (in bundle) as `contains` (the first `limit`) and `contains_total`, each marked `in_bundle` with `contains_count`; `only` answers those alone as `offers`/`total`. Their unit price is their own row's, so `sort=unit` orders them by price.",
            "schema": {
              "type": "string",
              "enum": ["0", "1", "only"],
              "default": "0"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "`all`, or a comma-separated list of `active`, `pending`, `accepted`, `cancelled`, `expired`, `invalid`.",
            "schema": {
              "type": "string",
              "default": "active"
            },
            "example": "active,pending"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "`price` (the default), `unit` (unit price), `new` (creation time) or `expiry` (offers with no expiry last).",
            "schema": {
              "type": "string",
              "enum": [
                "price",
                "unit",
                "new",
                "expiry"
              ],
              "default": "price"
            }
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "description": "`desc` (the default; `asc` for `expiry`) or `asc`.",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Offers per page, 1-200.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "example": 20
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Offers to skip.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OfferPage"
                },
                "example": {
                  "offers": [
                    {
                      "id": "dbf866a1e7e209e7",
                      "kind": "item",
                      "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0",
                      "value": 10000,
                      "seller_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                      "price": 110000,
                      "platform_fee": 2750,
                      "fee_rate": 3,
                      "network_fee": 963,
                      "total": 113713,
                      "vsize": 321,
                      "unit_price": 100000,
                      "row": "decasat_alpha",
                      "count": 1,
                      "rows": {
                        "uncommon": 1,
                        "alpha_uncommon": 1,
                        "decasat_alpha": 1
                      },
                      "types": [
                        {
                          "types": [
                            "uncommon",
                            "decasat_alpha",
                            "alpha"
                          ],
                          "count": 1,
                          "sats": [
                            441000000000000
                          ]
                        }
                      ],
                      "sats": 1,
                      "ranges": [
                        [
                          441000000000000,
                          441000000000000
                        ]
                      ],
                      "years": {
                        "2010": 1
                      },
                      "bidder_payment_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "bidder_ordinals_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "status": "active",
                      "created_at": 1790967012,
                      "updated_at": 1790967012,
                      "expires_at": 1791571812,
                      "reason": null,
                      "txid": null,
                      "listing_id": "5e1cb930f43354c3",
                      "acceptance_public": false
                    },
                    {
                      "id": "9ab58f471cc625be",
                      "kind": "item",
                      "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0",
                      "value": 10000,
                      "seller_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                      "price": 100000,
                      "platform_fee": 2500,
                      "fee_rate": 3,
                      "network_fee": 921,
                      "total": 103421,
                      "vsize": 307,
                      "unit_price": 90000,
                      "row": "decasat_alpha",
                      "count": 1,
                      "rows": {
                        "uncommon": 1,
                        "alpha_uncommon": 1,
                        "decasat_alpha": 1
                      },
                      "types": [
                        {
                          "types": [
                            "uncommon",
                            "decasat_alpha",
                            "alpha"
                          ],
                          "count": 1,
                          "sats": [
                            441000000000000
                          ]
                        }
                      ],
                      "sats": 1,
                      "ranges": [
                        [
                          441000000000000,
                          441000000000000
                        ]
                      ],
                      "years": {
                        "2010": 1
                      },
                      "bidder_payment_address": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu",
                      "bidder_ordinals_address": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu",
                      "status": "active",
                      "created_at": 1790967012,
                      "updated_at": 1790967012,
                      "expires_at": null,
                      "reason": null,
                      "txid": null,
                      "listing_id": "5e1cb930f43354c3",
                      "acceptance_public": false
                    }
                  ],
                  "total": 2
                }
              }
            }
          },
          "400": {
            "description": "A malformed query.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_status": {
                    "summary": "Unknown status",
                    "value": {
                      "error": "status must be all, or a comma-separated list of active, pending, accepted, cancelled, expired, invalid",
                      "code": "bad_status"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`retired_row`: a retired row (`uncommon_2009`, `rare_2009`), whose listings are its parent row's; `retired` names the row and years.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "retired_row": {
                    "summary": "A retired row",
                    "value": {
                      "error": "row uncommon_2009 is retired: ask for row uncommon with years 2009",
                      "code": "retired_row",
                      "retired": {
                        "row": "uncommon_2009",
                        "successor": {
                          "row": "uncommon",
                          "years": [
                            2009
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "bad_row",
          "retired_row",
          "bad_sort",
          "bad_order",
          "bad_paging",
          "bad_status",
          "bad_address",
          "bad_outpoint"
        ]
      },
      "post": {
        "operationId": "submitOffer",
        "tags": [
          "Offers"
        ],
        "summary": "Submit an offer",
        "description": "Step 2 of making an offer: the PSBT from prepare with your inputs signed. The server checks it is exactly the prepared transaction, verifies your signatures (SIGHASH_DEFAULT or ALL), checks the UTXO and your funding are unspent, and stores the offer, `active`. Your signatures stay on the server: no API ever returns them. Resubmitting answers the stored offer.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitOfferRequest"
              },
              "example": {
                "id": "dbf866a1e7e209e7",
                "psbt": "cHNidP8BAP0fAQIAAAACfxBUfmD8FgvLWC+rhhI7HaW1ncmmlqpbSg8h3N/usyQAAAAAAP3///9Bihr4H2G1iZuygx3BHzwLSWfyqpoJAv/W0tpPJYLJAQAAAAAA/f///wUQJwAAAAAAACJRIKgvKZRNZbhq5rXlzHXilOrWxZORoe3F4BbjSYxn/Hu7sK0BAAAAAAAiUSCmCGnw288dxlnJzsuvgFATXqnozcSHBT8dxogJSdxoTL4KAAAAAAAAIlEgrfKcXTOb9Ymo27aSDRsOplytPApoV4riNE46JGW7F/AvJxUAAAAAACJRIKgvKZRNZbhq5rXlzHXilOrWxZORoe3F4BbjSYxn/Hu7AAAAAAAAAAAOagxyYXJlc2F0cy5uZXQAAAAAAAEBKxAnAAAAAAAAIlEgpghp8NvPHcZZyc7Lr4BQE16p6M3EhwU/HcaICUncaEwAAQErYOMWAAAAAAAiUSCoLymUTWW4aua15cx14pTq1sWTkaHtxeAW40mMZ/x7uwETQJva/GuDEmjt90kgar0keIovQZv62QXPHzpZgAH+Fjr29SIhlsTWs98306xkWYcBMCulKINXRtRZ1fPDLp3C5ScBFyCD3+haMVHSUXKQ2kYf4oFVke9p8rGKLOY/AWl6izExRQAAAAAAAA=="
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmitOfferResponse"
                },
                "example": {
                  "offer": {
                    "id": "dbf866a1e7e209e7",
                    "kind": "item",
                    "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0",
                    "value": 10000,
                    "seller_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                    "price": 110000,
                    "platform_fee": 2750,
                    "fee_rate": 3,
                    "network_fee": 963,
                    "total": 113713,
                    "vsize": 321,
                    "unit_price": 100000,
                    "row": "decasat_alpha",
                    "count": 1,
                    "rows": {
                      "uncommon": 1,
                      "alpha_uncommon": 1,
                      "decasat_alpha": 1
                    },
                    "types": [
                      {
                        "types": [
                          "uncommon",
                          "decasat_alpha",
                          "alpha"
                        ],
                        "count": 1,
                        "sats": [
                          441000000000000
                        ]
                      }
                    ],
                    "sats": 1,
                    "ranges": [
                      [
                        441000000000000,
                        441000000000000
                      ]
                    ],
                    "years": {
                      "2010": 1
                    },
                    "bidder_payment_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                    "bidder_ordinals_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                    "status": "active",
                    "created_at": 1790967012,
                    "updated_at": 1790967012,
                    "expires_at": 1791571812,
                    "reason": null,
                    "txid": null,
                    "listing_id": "5e1cb930f43354c3",
                    "acceptance_public": false
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unknown_offer": {
                    "summary": "Unknown or expired",
                    "value": {
                      "error": "no such prepared offer",
                      "code": "unknown_offer"
                    }
                  },
                  "funding_spent": {
                    "summary": "Funds spent",
                    "value": {
                      "error": "your UTXO 24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0 was spent meanwhile: prepare the offer again",
                      "code": "funding_spent",
                      "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0"
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "Unavailable (bitcoind, the rare-sat index or the ord indexer).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "market_unavailable": {
                    "summary": "Not ready",
                    "value": {
                      "error": "the marketplace is not available right now",
                      "code": "market_unavailable"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "bad_id",
          "bad_psbt",
          "unknown_offer",
          "expired",
          "spent",
          "changed",
          "funding_spent",
          "pending",
          "psbt_mismatch",
          "bad_signature",
          "bad_sighash",
          "missing_signature",
          "unsupported_script",
          "invariant_violated",
          "market_unavailable",
          "engine_unavailable",
          "bitcoind_unavailable",
          "fork_unavailable",
          "oracle_unavailable"
        ]
      }
    },
    "/api/market/offers/prepare": {
      "post": {
        "operationId": "prepareOffer",
        "tags": [
          "Offers"
        ],
        "summary": "Prepare an offer",
        "description": "Step 1 of making an offer on a UTXO, listed or not: checks the UTXO (tracked sats, no inscription or rune, unspent and confirmed, not yours), picks plain cardinal UTXOs of your payment address and returns the offer transaction to sign: the seller's UTXO at input 0 (unsigned), your funding after it; the UTXO's sats to your ordinals address (output 0), `price` to the address that holds it (output 1), the platform fee (output 2), your change, the marker. The plan is held 10 minutes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrepareOfferRequest"
              },
              "example": {
                "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0",
                "price": 110000,
                "bidder": {
                  "payment_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                  "payment_public_key": "0283dfe85a3151d2517290da461fe2815591ef69f2b18a2ce63f01697a8b313145",
                  "ordinals_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                  "ordinals_public_key": "0283dfe85a3151d2517290da461fe2815591ef69f2b18a2ce63f01697a8b313145"
                },
                "fee_rate": 3,
                "expires_in": 604800
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrepareOfferResponse"
                },
                "example": {
                  "id": "dbf866a1e7e209e7",
                  "psbt": "cHNidP8BAP0fAQIAAAACfxBUfmD8FgvLWC+rhhI7HaW1ncmmlqpbSg8h3N/usyQAAAAAAP3///9Bihr4H2G1iZuygx3BHzwLSWfyqpoJAv/W0tpPJYLJAQAAAAAA/f///wUQJwAAAAAAACJRIKgvKZRNZbhq5rXlzHXilOrWxZORoe3F4BbjSYxn/Hu7sK0BAAAAAAAiUSCmCGnw288dxlnJzsuvgFATXqnozcSHBT8dxogJSdxoTL4KAAAAAAAAIlEgrfKcXTOb9Ymo27aSDRsOplytPApoV4riNE46JGW7F/AvJxUAAAAAACJRIKgvKZRNZbhq5rXlzHXilOrWxZORoe3F4BbjSYxn/Hu7AAAAAAAAAAAOagxyYXJlc2F0cy5uZXQAAAAAAAEBKxAnAAAAAAAAIlEgpghp8NvPHcZZyc7Lr4BQE16p6M3EhwU/HcaICUncaEwAAQErYOMWAAAAAAAiUSCoLymUTWW4aua15cx14pTq1sWTkaHtxeAW40mMZ/x7uwEXIIPf6FoxUdJRcpDaRh/igVWR72nysYos5j8BaXqLMTFFAAAAAAAA",
                  "sign": [
                    {
                      "index": 1,
                      "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh"
                    }
                  ],
                  "summary": {
                    "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0",
                    "value": 10000,
                    "price": 110000,
                    "platform_fee": 2750,
                    "network_fee": 963,
                    "total": 113713,
                    "vsize": 321,
                    "fee_rate": 3,
                    "change": 1386287,
                    "unit_price": 100000,
                    "row": "decasat_alpha",
                    "count": 1
                  },
                  "expires_at": 1791571812,
                  "submit_by": 1790967612
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "own_utxo": {
                    "summary": "Your own UTXO",
                    "value": {
                      "error": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0 is held by your own address: make offers on other people's UTXOs",
                      "code": "own_utxo",
                      "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0"
                    }
                  },
                  "bad_expiry": {
                    "summary": "Bad expiry",
                    "value": {
                      "error": "expires_in must be 86400, 259200, 604800, 2592000 (seconds), or null / \"never\" for no expiry",
                      "code": "bad_expiry"
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "Unavailable (bitcoind, the rare-sat index or the ord indexer).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "market_unavailable": {
                    "summary": "Not ready",
                    "value": {
                      "error": "the marketplace is not available right now",
                      "code": "market_unavailable"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "bad_outpoint",
          "bad_price",
          "bad_bidder",
          "bad_address",
          "legacy_address",
          "unsupported_address",
          "key_mismatch",
          "bad_fee_rate",
          "bad_expiry",
          "fee_rate_too_low",
          "spent",
          "unconfirmed",
          "untracked",
          "unindexed",
          "inscribed",
          "runes",
          "no_row",
          "price_too_low",
          "price_too_high",
          "own_utxo",
          "pending",
          "busy",
          "insufficient_funds",
          "fee_too_high",
          "dust_output",
          "bad_structure",
          "bad_public_key",
          "pubkey_mismatch",
          "unsupported_script",
          "invariant_violated",
          "fork_behind",
          "indexer_behind",
          "market_unavailable",
          "engine_unavailable",
          "bitcoind_unavailable",
          "fork_unavailable",
          "oracle_unavailable"
        ]
      }
    },
    "/api/market/offers/cancel": {
      "post": {
        "operationId": "cancelOffers",
        "tags": [
          "Offers"
        ],
        "summary": "Cancel offers",
        "description": "Withdraws active offers with a BIP-322 signature of `raresats.net cancel-offer <id,id,…> <unix seconds>` by the bidder's payment or ordinals address, at most 10 minutes old, accepted once. The server deletes your signatures. The signed transaction itself has no expiry: to be certain, spend the funding UTXO(s).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CancelOffersRequest"
              },
              "example": {
                "ids": [
                  "f035c509de153a30"
                ],
                "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                "message": "raresats.net cancel-offer f035c509de153a30 1790967012",
                "signature": "AUAbWZZUOrgfeSJtVYKiSdx9j70KWLVcI8nznx1U8hP+zet/ojilZjtbfyFlZc/VGHpLrTT4dDfzEKaf/9dcnn3i"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelOffersResponse"
                },
                "example": {
                  "offers": [
                    {
                      "id": "f035c509de153a30",
                      "kind": "item",
                      "outpoint": "d184375c0e70392605961f20ae083a53cdac71fc923a9df49a4daf5bbc511b4a:0",
                      "value": 2000,
                      "seller_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                      "price": 52000,
                      "platform_fee": 1300,
                      "fee_rate": 3,
                      "network_fee": 963,
                      "total": 54263,
                      "vsize": 321,
                      "unit_price": 50000,
                      "row": "uncommon",
                      "count": 1,
                      "rows": {
                        "uncommon": 1
                      },
                      "types": [
                        {
                          "types": [
                            "uncommon"
                          ],
                          "count": 1,
                          "sats": [
                            1925389375000000
                          ]
                        }
                      ],
                      "sats": 1,
                      "ranges": [
                        [
                          1925389375000000,
                          1925389375000000
                        ]
                      ],
                      "years": {
                        "2023": 1
                      },
                      "bidder_payment_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "bidder_ordinals_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "status": "cancelled",
                      "created_at": 1790967012,
                      "updated_at": 1790967012,
                      "expires_at": 1791053412,
                      "reason": null,
                      "txid": null,
                      "listing_id": null,
                      "acceptance_public": false
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "replayed": {
                    "summary": "Used already",
                    "value": {
                      "error": "that cancel message was used already",
                      "code": "replayed"
                    }
                  },
                  "not_bidder": {
                    "summary": "Not yours",
                    "value": {
                      "error": "offer f035c509de153a30 was not made by bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                      "code": "not_bidder"
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "The engine is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "engine_unavailable": {
                    "summary": "Unavailable",
                    "value": {
                      "error": "the trade engine is not available",
                      "code": "engine_unavailable"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "bad_ids",
          "bad_address",
          "bad_message",
          "bad_signature",
          "stale_message",
          "future_message",
          "not_found",
          "not_bidder",
          "replayed",
          "not_active",
          "engine_unavailable"
        ]
      }
    },
    "/api/market/offers/best": {
      "get": {
        "operationId": "getBestOffers",
        "tags": [
          "Offers"
        ],
        "summary": "Get the best offers of UTXOs",
        "description": "The best active offer (the highest price, the oldest first) of up to 100 outpoints, keyed by outpoint. Outpoints without one are absent. A listing carries its own as `best_offer`.",
        "parameters": [
          {
            "name": "outpoints",
            "in": "query",
            "required": true,
            "description": "1-100 outpoints (`txid:vout`), comma-separated.",
            "schema": {
              "type": "string"
            },
            "example": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BestOffers"
                },
                "example": {
                  "offers": {
                    "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0": {
                      "id": "dbf866a1e7e209e7",
                      "kind": "item",
                      "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0",
                      "value": 10000,
                      "seller_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                      "price": 110000,
                      "platform_fee": 2750,
                      "fee_rate": 3,
                      "network_fee": 963,
                      "total": 113713,
                      "vsize": 321,
                      "unit_price": 100000,
                      "row": "decasat_alpha",
                      "count": 1,
                      "rows": {
                        "uncommon": 1,
                        "alpha_uncommon": 1,
                        "decasat_alpha": 1
                      },
                      "types": [
                        {
                          "types": [
                            "uncommon",
                            "decasat_alpha",
                            "alpha"
                          ],
                          "count": 1,
                          "sats": [
                            441000000000000
                          ]
                        }
                      ],
                      "sats": 1,
                      "ranges": [
                        [
                          441000000000000,
                          441000000000000
                        ]
                      ],
                      "years": {
                        "2010": 1
                      },
                      "bidder_payment_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "bidder_ordinals_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "status": "active",
                      "created_at": 1790967012,
                      "updated_at": 1790967012,
                      "expires_at": 1791571812,
                      "reason": null,
                      "txid": null,
                      "listing_id": "5e1cb930f43354c3",
                      "acceptance_public": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing, too many or malformed outpoints.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_outpoints": {
                    "summary": "None given",
                    "value": {
                      "error": "outpoints must list 1-100 outpoints",
                      "code": "bad_outpoints"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "bad_outpoints",
          "bad_outpoint"
        ]
      }
    },
    "/api/market/offers/{id}": {
      "get": {
        "operationId": "getOffer",
        "tags": [
          "Offers"
        ],
        "summary": "Get an offer",
        "description": "One offer by id, whatever its status.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The offer id (16 hex characters).",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{16}$"
            },
            "example": "dbf866a1e7e209e7"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Offer"
                },
                "example": {
                  "id": "dbf866a1e7e209e7",
                  "kind": "item",
                  "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0",
                  "value": 10000,
                  "seller_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                  "price": 110000,
                  "platform_fee": 2750,
                  "fee_rate": 3,
                  "network_fee": 963,
                  "total": 113713,
                  "vsize": 321,
                  "unit_price": 100000,
                  "row": "decasat_alpha",
                  "count": 1,
                  "rows": {
                    "uncommon": 1,
                    "alpha_uncommon": 1,
                    "decasat_alpha": 1
                  },
                  "types": [
                    {
                      "types": [
                        "uncommon",
                        "decasat_alpha",
                        "alpha"
                      ],
                      "count": 1,
                      "sats": [
                        441000000000000
                      ]
                    }
                  ],
                  "sats": 1,
                  "ranges": [
                    [
                      441000000000000,
                      441000000000000
                    ]
                  ],
                  "years": {
                    "2010": 1
                  },
                  "bidder_payment_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                  "bidder_ordinals_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                  "status": "pending",
                  "created_at": 1790967012,
                  "updated_at": 1790967012,
                  "expires_at": 1791571812,
                  "reason": null,
                  "txid": "332f8cf83155e2532101454afe84ed45aedf9b2f98f8593b82ff38687cfee3be",
                  "listing_id": "5e1cb930f43354c3",
                  "acceptance_public": false
                }
              }
            }
          },
          "404": {
            "description": "No such offer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Unknown id",
                    "value": {
                      "error": "no such offer",
                      "code": "not_found"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "not_found",
          "bad_path"
        ]
      }
    },
    "/api/market/offers/{id}/accept/prepare": {
      "post": {
        "operationId": "prepareAcceptOffer",
        "tags": [
          "Offers"
        ],
        "summary": "Prepare to accept an offer",
        "description": "Step 1 of accepting, for the UTXO's current holder only: checks the offer is active and the UTXO unspent at the same address and value, and returns the offer transaction with input 0 (your UTXO) ready for your wallet. It carries no bidder signature.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The offer id (16 hex characters).",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{16}$"
            },
            "example": "dbf866a1e7e209e7"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcceptOfferPrepareRequest"
              },
              "example": {
                "seller_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                "seller_public_key": "03cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcceptOfferPrepareResponse"
                },
                "example": {
                  "psbt": "cHNidP8BAP0fAQIAAAACfxBUfmD8FgvLWC+rhhI7HaW1ncmmlqpbSg8h3N/usyQAAAAAAP3///9Bihr4H2G1iZuygx3BHzwLSWfyqpoJAv/W0tpPJYLJAQAAAAAA/f///wUQJwAAAAAAACJRIKgvKZRNZbhq5rXlzHXilOrWxZORoe3F4BbjSYxn/Hu7sK0BAAAAAAAiUSCmCGnw288dxlnJzsuvgFATXqnozcSHBT8dxogJSdxoTL4KAAAAAAAAIlEgrfKcXTOb9Ymo27aSDRsOplytPApoV4riNE46JGW7F/AvJxUAAAAAACJRIKgvKZRNZbhq5rXlzHXilOrWxZORoe3F4BbjSYxn/Hu7AAAAAAAAAAAOagxyYXJlc2F0cy5uZXQAAAAAAAEBKxAnAAAAAAAAIlEgpghp8NvPHcZZyc7Lr4BQE16p6M3EhwU/HcaICUncaEwBFyDMikvGTYl73cX7wvZw96i6CzhneRBs8SI8b8XXzW/BFQABAStg4xYAAAAAACJRIKgvKZRNZbhq5rXlzHXilOrWxZORoe3F4BbjSYxn/Hu7AAAAAAAA",
                  "sign": [
                    {
                      "index": 0,
                      "address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr"
                    }
                  ],
                  "summary": {
                    "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0",
                    "value": 10000,
                    "price": 110000,
                    "platform_fee": 2750,
                    "network_fee": 963,
                    "total": 113713,
                    "vsize": 321,
                    "fee_rate": 3,
                    "unit_price": 100000,
                    "row": "decasat_alpha",
                    "count": 1,
                    "bidder_ordinals_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                    "listing_id": "5e1cb930f43354c3"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_owner": {
                    "summary": "Not the holder",
                    "value": {
                      "error": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0 is not held by bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh: only its holder can accept",
                      "code": "not_owner",
                      "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0"
                    }
                  },
                  "not_active": {
                    "summary": "Not active",
                    "value": {
                      "error": "offer dbf866a1e7e209e7 is cancelled",
                      "code": "not_active",
                      "id": "dbf866a1e7e209e7",
                      "status": "cancelled"
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "Unavailable (bitcoind, the rare-sat index or the ord indexer).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "market_unavailable": {
                    "summary": "Not ready",
                    "value": {
                      "error": "the marketplace is not available right now",
                      "code": "market_unavailable"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "not_found",
          "expired",
          "not_active",
          "config_changed",
          "bad_address",
          "legacy_address",
          "unsupported_address",
          "not_owner",
          "key_mismatch",
          "spent",
          "changed",
          "bad_public_key",
          "pubkey_mismatch",
          "unsupported_script",
          "internal",
          "market_unavailable",
          "engine_unavailable",
          "bitcoind_unavailable",
          "fork_unavailable",
          "oracle_unavailable"
        ]
      }
    },
    "/api/market/offers/{id}/accept": {
      "post": {
        "operationId": "acceptOffer",
        "tags": [
          "Offers"
        ],
        "summary": "Accept an offer",
        "description": "Step 2 of accepting: the PSBT from accept/prepare with input 0 signed. The server rechecks everything (the UTXO unspent at the same address and value, the bidder's funding unspent and plain cardinal), verifies your signature (SIGHASH_DEFAULT or ALL), adds the bidder's, finalizes, rechecks every rule, then `testmempoolaccept` and broadcasts. The offer becomes `pending` (and your listing of the UTXO, if any), `accepted` once confirmed; other offers on the UTXO become `invalid`. Resubmitting is idempotent: use it to settle `broadcast_unknown`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The offer id (16 hex characters).",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{16}$"
            },
            "example": "dbf866a1e7e209e7"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcceptOfferRequest"
              },
              "example": {
                "psbt": "cHNidP8BAP0fAQIAAAACfxBUfmD8FgvLWC+rhhI7HaW1ncmmlqpbSg8h3N/usyQAAAAAAP3///9Bihr4H2G1iZuygx3BHzwLSWfyqpoJAv/W0tpPJYLJAQAAAAAA/f///wUQJwAAAAAAACJRIKgvKZRNZbhq5rXlzHXilOrWxZORoe3F4BbjSYxn/Hu7sK0BAAAAAAAiUSCmCGnw288dxlnJzsuvgFATXqnozcSHBT8dxogJSdxoTL4KAAAAAAAAIlEgrfKcXTOb9Ymo27aSDRsOplytPApoV4riNE46JGW7F/AvJxUAAAAAACJRIKgvKZRNZbhq5rXlzHXilOrWxZORoe3F4BbjSYxn/Hu7AAAAAAAAAAAOagxyYXJlc2F0cy5uZXQAAAAAAAEBKxAnAAAAAAAAIlEgpghp8NvPHcZZyc7Lr4BQE16p6M3EhwU/HcaICUncaEwBE0AH22HiJwQjhGYmUScuZwJAaaRczyxViuzB4L48meWqATwLvJ3xPAgrv7MqmcxjqeR+Oe+frCEqFAKj0AZy4BF1ARcgzIpLxk2Je93F+8L2cPeougs4Z3kQbPEiPG/F181vwRUAAQErYOMWAAAAAAAiUSCoLymUTWW4aua15cx14pTq1sWTkaHtxeAW40mMZ/x7uwAAAAAAAA=="
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcceptOfferResponse"
                },
                "example": {
                  "txid": "332f8cf83155e2532101454afe84ed45aedf9b2f98f8593b82ff38687cfee3be"
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "funding_spent": {
                    "summary": "Bidder's funds gone",
                    "value": {
                      "error": "the bidder's UTXO 24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0 is no longer usable (spent (in the mempool or a block)): the offer is no longer valid",
                      "code": "funding_spent",
                      "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0"
                    }
                  },
                  "conflict": {
                    "summary": "Lost a race",
                    "value": {
                      "error": "a listing (or one of your UTXOs) was spent in the meantime",
                      "code": "conflict",
                      "reason": "bad-txns-inputs-missingorspent"
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "Unavailable, or `broadcast_unknown`: the outcome is not known yet; submit again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "broadcast_unknown": {
                    "summary": "Outcome unknown",
                    "value": {
                      "error": "bitcoind did not answer the broadcast: the acceptance may have gone through; submit again to check",
                      "code": "broadcast_unknown",
                      "txid": "332f8cf83155e2532101454afe84ed45aedf9b2f98f8593b82ff38687cfee3be"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "bad_psbt",
          "not_found",
          "expired",
          "not_active",
          "spent",
          "changed",
          "funding_spent",
          "pending",
          "config_changed",
          "psbt_mismatch",
          "bad_signature",
          "bad_sighash",
          "missing_signature",
          "offer_changed",
          "unsupported_script",
          "invariant_violated",
          "conflict",
          "rejected",
          "broadcast_unknown",
          "internal",
          "market_unavailable",
          "engine_unavailable",
          "bitcoind_unavailable",
          "fork_unavailable",
          "oracle_unavailable"
        ]
      }
    },
    "/api/market/transfer/prepare": {
      "post": {
        "operationId": "prepareTransfer",
        "tags": [
          "Wallet tools"
        ],
        "summary": "Prepare a transfer",
        "description": "Step 1 of every wallet tool: extract rare sats, send UTXOs or only their rare sats, send N sats of a type, chop ranges, consolidate plain bitcoin, pay many recipients, or speed up or cancel a pending transfer built here. The server checks every UTXO (yours, unspent, confirmed; its tracked sats, inscriptions and runes from the rare-sat index and the ord indexer), lays out the outputs, funds the network fee and the flat tools fee only from plain bitcoin of your payment address, checks the unsigned transaction against its invariants (no tracked, inscribed or rune sat is paid as fee, every tracked sat lands in its planned output, …) and returns it to sign with a summary. Nothing is reserved; the plan is held 10 minutes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PrepareTransferRequest"
              },
              "example": {
                "owner": {
                  "payment_address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                  "payment_public_key": "039b3b694b8fc5b5e07fb069c783cac754f5d38c3e08bed1960e31fdb1dda35c24",
                  "ordinals_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                  "ordinals_public_key": "03cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115"
                },
                "kind": "extract",
                "items": [
                  {
                    "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0"
                  }
                ],
                "fee_rate": 3
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PrepareTransferResponse"
                },
                "example": {
                  "id": "6baec47455bf8df8",
                  "psbt": "cHNidP8BAP0dAQIAAAACfxBUfmD8FgvLWC+rhhI7HaW1ncmmlqpbSg8h3N/usyQAAAAAAP3///9AKU7jykAIeJ8gRh6iFq7aPfAmRiqhMPIbX7W1YPtYHgAAAAAA/f///wWEAQAAAAAAACJRIKYIafDbzx3GWcnOy6+AUBNeqejNxIcFPx3GiAlJ3GhMSgEAAAAAAAAiUSCmCGnw288dxlnJzsuvgFATXqnozcSHBT8dxogJSdxoTEIkAAAAAAAAF6kUP7bpWBLle7RpH5pKYohiphpPdpuH6AMAAAAAAAAiUSCt8pxdM5v1iajbtpINGw6mXK08CmhXiuI0TjokZbsX8J1ZAAAAAAAAF6kUP7bpWBLle7RpH5pKYohiphpPdpuHAAAAAAABASsQJwAAAAAAACJRIKYIafDbzx3GWcnOy6+AUBNeqejNxIcFPx3GiAlJ3GhMARcgzIpLxk2Je93F+8L2cPeougs4Z3kQbPEiPG/F181vwRUAAQEgqGEAAAAAAAAXqRQ/tulYEuV7tGkfmkpiiGKmGk92m4cBBBYAFPmQZ5rK/iXCdhU3O0C/IkRtJP9EAAAAAAAA",
                  "sign": [
                    {
                      "index": 0,
                      "address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr"
                    },
                    {
                      "index": 1,
                      "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf"
                    }
                  ],
                  "summary": {
                    "kind": "extract",
                    "network_fee": 1059,
                    "tools_fee": 1000,
                    "fee_rate": 3,
                    "vsize": 353,
                    "change": 22941,
                    "total_cost": 2059,
                    "leaves_wallet": 0,
                    "destination": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                    "external": false,
                    "inputs": [
                      {
                        "index": 0,
                        "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0",
                        "value": 10000,
                        "role": "source",
                        "address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                        "owner_role": "ordinals",
                        "items": [
                          {
                            "sat": 441000000000000,
                            "len": 1,
                            "offset": 388,
                            "types": [
                              "uncommon",
                              "alpha",
                              "decasat_alpha"
                            ],
                            "selected": true
                          }
                        ],
                        "inscriptions": 0,
                        "runes": false
                      },
                      {
                        "index": 1,
                        "outpoint": "1e58fb60b5b55f1bf230a12a4626f03ddaae16a21e46209f780840cae34e2940:0",
                        "value": 25000,
                        "role": "funding",
                        "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                        "owner_role": "payment",
                        "items": [],
                        "inscriptions": 0,
                        "runes": false
                      }
                    ],
                    "outputs": [
                      {
                        "index": 0,
                        "value": 388,
                        "address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                        "role": "return",
                        "to": "source",
                        "parts": [
                          {
                            "input": 0,
                            "from": 0,
                            "to": 388,
                            "at": 0
                          }
                        ],
                        "items": [],
                        "rides_along": [],
                        "padding": 0,
                        "extracted": null
                      },
                      {
                        "index": 1,
                        "value": 330,
                        "address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                        "role": "dest",
                        "to": "ordinals",
                        "parts": [
                          {
                            "input": 0,
                            "from": 388,
                            "to": 718,
                            "at": 0
                          }
                        ],
                        "items": [
                          {
                            "sat": 441000000000000,
                            "len": 1,
                            "types": [
                              "uncommon",
                              "alpha",
                              "decasat_alpha"
                            ],
                            "input": 0,
                            "offset": 388,
                            "at": 0
                          }
                        ],
                        "rides_along": [],
                        "padding": 329,
                        "extracted": true
                      },
                      {
                        "index": 2,
                        "value": 9282,
                        "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                        "role": "plain_return",
                        "to": "payment",
                        "parts": [
                          {
                            "input": 0,
                            "from": 718,
                            "to": 10000,
                            "at": 0
                          }
                        ],
                        "items": [],
                        "rides_along": [],
                        "padding": 0,
                        "extracted": null
                      },
                      {
                        "index": 3,
                        "value": 1000,
                        "address": "bc1p4hefchfnn06cn2xmk6fq6xcw5ew260q2dptc4c35fcazgedmzlcqkxf057",
                        "role": "tools_fee",
                        "to": "fee",
                        "parts": [
                          {
                            "input": 1,
                            "from": 0,
                            "to": 1000,
                            "at": 0
                          }
                        ],
                        "items": [],
                        "rides_along": [],
                        "padding": 0,
                        "extracted": null
                      },
                      {
                        "index": 4,
                        "value": 22941,
                        "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                        "role": "change",
                        "to": "payment",
                        "parts": [
                          {
                            "input": 1,
                            "from": 1000,
                            "to": 23941,
                            "at": 0
                          }
                        ],
                        "items": [],
                        "rides_along": [],
                        "padding": 0,
                        "extracted": null
                      }
                    ],
                    "checks": [
                      {
                        "rule": "fifo",
                        "ok": true,
                        "label": "The fee is paid only from your plain bitcoin"
                      },
                      {
                        "rule": "fifo",
                        "ok": true,
                        "label": "No rare sat is paid as fee"
                      },
                      {
                        "rule": "fifo",
                        "ok": true,
                        "label": "Every rare sat lands in its planned output"
                      },
                      {
                        "rule": "fifo",
                        "ok": true,
                        "label": "No inscription or rune leaves its UTXO"
                      },
                      {
                        "rule": "owner_inputs",
                        "ok": true,
                        "label": "Every input is yours"
                      },
                      {
                        "rule": "no_op_return",
                        "ok": true,
                        "label": "No OP_RETURN output"
                      },
                      {
                        "rule": "dust",
                        "ok": true,
                        "label": "Every output is above the dust limit"
                      },
                      {
                        "rule": "tools_fee",
                        "ok": true,
                        "label": "One flat raresats.net fee output"
                      },
                      {
                        "rule": "change",
                        "ok": true,
                        "label": "Your change returns to your payment address"
                      },
                      {
                        "rule": "network_fee",
                        "ok": true,
                        "label": "The network fee matches the fee rate"
                      },
                      {
                        "rule": "standard",
                        "ok": true,
                        "label": "A standard, replaceable transaction"
                      }
                    ],
                    "warnings": [],
                    "skipped": [],
                    "replaces": null,
                    "min_fee_rate": null,
                    "layout": [
                      {
                        "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0",
                        "input": 0,
                        "separated": true,
                        "borrow": 0,
                        "merged": [],
                        "rides_along": 0
                      }
                    ]
                  },
                  "expires_at": 1791428836
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "nothing_to_separate": {
                    "summary": "Nothing to separate",
                    "value": {
                      "error": "c3f31009cbbbced4b1a0acb30d924e3e025b10647c43092b68262f4e83125bf6:0 would stay one output: its rare sats are already apart, or too close to its ends",
                      "code": "nothing_to_separate"
                    }
                  },
                  "bad_kind": {
                    "summary": "Unknown kind",
                    "value": {
                      "error": "kind must be one of extract, send, send_n, chop, consolidate, multisend, speedup, cancel",
                      "code": "bad_kind"
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "Unavailable (bitcoind, the rare-sat index or the ord indexer), or busy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "busy": {
                    "summary": "Busy",
                    "value": {
                      "error": "too many transfers are being prepared; try again in a minute",
                      "code": "busy"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "bad_kind",
          "bad_owner",
          "bad_address",
          "legacy_address",
          "unsupported_address",
          "key_mismatch",
          "bad_fee_rate",
          "fee_rate_too_low",
          "bad_items",
          "bad_outpoint",
          "duplicate_outpoint",
          "bad_destination",
          "bad_type",
          "bad_count",
          "bad_chop_size",
          "bad_split",
          "bad_sends",
          "payment_destination",
          "address_too_large",
          "spent",
          "not_owner",
          "unconfirmed",
          "pending",
          "untracked",
          "unindexed",
          "inscribed",
          "runes",
          "not_plain",
          "already_extracted",
          "split_chunk",
          "nothing_to_separate",
          "nothing_to_do",
          "keep_in_destination",
          "range_too_small",
          "not_enough_sats",
          "listed_public_alone",
          "inscribed_consolidate",
          "runes_multi",
          "dust_destination",
          "too_many_outputs",
          "tx_too_large",
          "insufficient_funds",
          "fee_too_high",
          "unknown_transfer",
          "not_pending",
          "has_descendants",
          "too_many_items",
          "nothing_to_cancel",
          "conflict",
          "replacement_fee_too_low",
          "busy",
          "invariant_violated",
          "fork_behind",
          "indexer_behind",
          "market_unavailable",
          "engine_unavailable",
          "bitcoind_unavailable",
          "fork_unavailable",
          "oracle_unavailable"
        ]
      }
    },
    "/api/market/transfer/submit": {
      "post": {
        "operationId": "submitTransfer",
        "tags": [
          "Wallet tools"
        ],
        "summary": "Submit a transfer",
        "description": "Step 2: the PSBT from prepare with every input signed. The server checks that it is exactly the prepared transaction, verifies every signature, rechecks every UTXO against bitcoind, the rare-sat index and the ord indexer (`changed`, `spent`), runs the invariants with the real size and `testmempoolaccept`, cancels the active listings of the moved UTXOs (their signatures are deleted, so they can never sell) and broadcasts. Idempotent: the same body again answers the same `txid`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitTransferRequest"
              },
              "example": {
                "id": "6baec47455bf8df8",
                "psbt": "<the PSBT from prepare, every input signed, base64>"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Broadcast.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmitTransferResponse"
                },
                "example": {
                  "txid": "a1edadb9e3b45097d272621ea8adcbee697281bd4d611462db134292d4e1cf9c",
                  "transfer": {
                    "id": "6baec47455bf8df8",
                    "txid": "a1edadb9e3b45097d272621ea8adcbee697281bd4d611462db134292d4e1cf9c",
                    "kind": "extract",
                    "status": "pending",
                    "created_at": 1791428236,
                    "updated_at": 1791428236,
                    "owner": {
                      "payment_address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                      "ordinals_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr"
                    },
                    "destination": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                    "fee_rate": 3,
                    "network_fee": 1059,
                    "tools_fee": 1000,
                    "vsize": 352,
                    "replaces": null,
                    "replaced_by": null,
                    "block_height": null,
                    "outputs": [
                      {
                        "index": 0,
                        "address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                        "value": 388,
                        "role": "return"
                      },
                      {
                        "index": 1,
                        "address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                        "value": 330,
                        "role": "dest"
                      },
                      {
                        "index": 2,
                        "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                        "value": 9282,
                        "role": "plain_return"
                      },
                      {
                        "index": 3,
                        "address": "bc1p4hefchfnn06cn2xmk6fq6xcw5ew260q2dptc4c35fcazgedmzlcqkxf057",
                        "value": 1000,
                        "role": "tools_fee"
                      },
                      {
                        "index": 4,
                        "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                        "value": 22941,
                        "role": "change"
                      }
                    ],
                    "actions": {
                      "speedup": true,
                      "cancel": false
                    }
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unknown_transfer": {
                    "summary": "Unknown id",
                    "value": {
                      "error": "no such transfer",
                      "code": "unknown_transfer"
                    }
                  },
                  "expired": {
                    "summary": "Expired",
                    "value": {
                      "error": "the prepared transfer expired: prepare it again",
                      "code": "expired"
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "The broadcast's outcome is unknown (submit the same body again), or a service is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "broadcast_unknown": {
                    "summary": "Outcome unknown",
                    "value": {
                      "error": "the transfer was sent but bitcoind has not confirmed it yet: submit the same body again to check",
                      "code": "broadcast_unknown",
                      "txid": "a1edadb9e3b45097d272621ea8adcbee697281bd4d611462db134292d4e1cf9c"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "bad_id",
          "bad_psbt",
          "unknown_transfer",
          "expired",
          "config_changed",
          "psbt_mismatch",
          "bad_signature",
          "missing_signature",
          "unsupported_script",
          "spent",
          "changed",
          "pending",
          "not_pending",
          "has_descendants",
          "offer_overlap",
          "conflict",
          "rejected",
          "fee_rate_too_low",
          "replacement_fee_too_low",
          "fee_too_high",
          "invariant_violated",
          "broadcast_unknown",
          "fork_behind",
          "internal",
          "market_unavailable",
          "engine_unavailable",
          "bitcoind_unavailable",
          "fork_unavailable",
          "oracle_unavailable"
        ]
      }
    },
    "/api/market/transfers": {
      "get": {
        "operationId": "getWalletTransfers",
        "tags": [
          "Wallet tools"
        ],
        "summary": "List an address's wallet transfers",
        "description": "The transfers built with the wallet tools that an address took part in (as payment or ordinals address), newest first. Each names only that address's part (`owner_role`).",
        "parameters": [
          {
            "name": "address",
            "in": "query",
            "required": true,
            "description": "A payment or ordinals address.",
            "schema": {
              "type": "string"
            },
            "example": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "`pending` (what you still have to watch: in the mempool, not yet known, or dropped in a chain of replacements that pays someone else, which a cancel voids) or `all` (default).",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "all"
              ]
            },
            "example": "all"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1-100, default 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "example": 5
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransferList"
                },
                "example": {
                  "transfers": [
                    {
                      "id": "6baec47455bf8df8",
                      "txid": "a1edadb9e3b45097d272621ea8adcbee697281bd4d611462db134292d4e1cf9c",
                      "kind": "extract",
                      "status": "pending",
                      "created_at": 1791428236,
                      "updated_at": 1791428236,
                      "owner_role": "ordinals",
                      "destination": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                      "fee_rate": 3,
                      "network_fee": 1059,
                      "tools_fee": 1000,
                      "vsize": 352,
                      "replaces": null,
                      "replaced_by": null,
                      "block_height": null,
                      "outputs": [
                        {
                          "index": 0,
                          "address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                          "value": 388,
                          "role": "return"
                        },
                        {
                          "index": 1,
                          "address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                          "value": 330,
                          "role": "dest"
                        },
                        {
                          "index": 2,
                          "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                          "value": 9282,
                          "role": "plain_return"
                        },
                        {
                          "index": 3,
                          "address": "bc1p4hefchfnn06cn2xmk6fq6xcw5ew260q2dptc4c35fcazgedmzlcqkxf057",
                          "value": 1000,
                          "role": "tools_fee"
                        },
                        {
                          "index": 4,
                          "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                          "value": 22941,
                          "role": "change"
                        }
                      ],
                      "actions": {
                        "speedup": true,
                        "cancel": false
                      }
                    }
                  ],
                  "total": 1
                }
              }
            }
          },
          "400": {
            "description": "Bad query.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_address": {
                    "summary": "Not an address",
                    "value": {
                      "error": "address must be an address",
                      "code": "bad_address"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "bad_address",
          "legacy_address",
          "unsupported_address",
          "bad_status",
          "bad_paging",
          "market_unavailable"
        ]
      }
    },
    "/api/market/transfers/{txid}": {
      "get": {
        "operationId": "getWalletTransfer",
        "tags": [
          "Wallet tools"
        ],
        "summary": "Get a wallet transfer",
        "description": "One transfer built with the wallet tools, by its transaction id, whatever its status, with both owner addresses and whether it can be sped up or cancelled.",
        "parameters": [
          {
            "name": "txid",
            "in": "path",
            "required": true,
            "description": "The transfer's transaction id.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{64}$"
            },
            "example": "a1edadb9e3b45097d272621ea8adcbee697281bd4d611462db134292d4e1cf9c"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransferRecord"
                },
                "example": {
                  "id": "6baec47455bf8df8",
                  "txid": "a1edadb9e3b45097d272621ea8adcbee697281bd4d611462db134292d4e1cf9c",
                  "kind": "extract",
                  "status": "pending",
                  "created_at": 1791428236,
                  "updated_at": 1791428236,
                  "owner": {
                    "payment_address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                    "ordinals_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr"
                  },
                  "destination": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                  "fee_rate": 3,
                  "network_fee": 1059,
                  "tools_fee": 1000,
                  "vsize": 352,
                  "replaces": null,
                  "replaced_by": null,
                  "block_height": null,
                  "outputs": [
                    {
                      "index": 0,
                      "address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                      "value": 388,
                      "role": "return"
                    },
                    {
                      "index": 1,
                      "address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
                      "value": 330,
                      "role": "dest"
                    },
                    {
                      "index": 2,
                      "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                      "value": 9282,
                      "role": "plain_return"
                    },
                    {
                      "index": 3,
                      "address": "bc1p4hefchfnn06cn2xmk6fq6xcw5ew260q2dptc4c35fcazgedmzlcqkxf057",
                      "value": 1000,
                      "role": "tools_fee"
                    },
                    {
                      "index": 4,
                      "address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                      "value": 22941,
                      "role": "change"
                    }
                  ],
                  "actions": {
                    "speedup": true,
                    "cancel": false
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not a wallet transfer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unknown_transfer": {
                    "summary": "Unknown txid",
                    "value": {
                      "error": "no such transfer",
                      "code": "unknown_transfer"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "unknown_transfer",
          "market_unavailable"
        ]
      }
    },
    "/api/market": {
      "get": {
        "operationId": "getMarketOverview",
        "tags": [
          "Market data"
        ],
        "summary": "Get the market overview",
        "description": "The homepage's market over a window: totals against the window before, rows by volume, the dearest and the latest sales (each with seller and buyer). Covers sales on every marketplace the index knows. Cacheable 30 s. `pending` lists the latest sales still in the mempool, in no total.",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "required": false,
            "description": "The window.",
            "schema": {
              "type": "string",
              "enum": [
                "24h",
                "7d",
                "30d",
                "90d",
                "1y",
                "all"
              ],
              "default": "30d"
            },
            "example": "30d"
          },
          {
            "name": "inscribed",
            "in": "query",
            "required": false,
            "description": "`1` counts inscribed sales too.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "0"
            }
          },
          {
            "name": "outliers",
            "in": "query",
            "required": false,
            "description": "`1` counts statistical outliers too.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "0"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MarketOverview"
                }
              }
            }
          },
          "400": {
            "description": "An unknown window, or a flag that is not 0 or 1.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/sales": {
      "get": {
        "operationId": "getSales",
        "tags": [
          "Market data"
        ],
        "summary": "Get sales (compact columns)",
        "description": "Every sale of tracked sats the index found, on every marketplace, oldest first, as compact columns (gzip when accepted). Follow new sales with `after=<seq>`. Addresses are left out: ask `/api/sales/parties`. Cacheable 30 s. With `years`, `month` or `luck`, only the sales that pass (the filter echoed as `filter`); 501 on a server without the filters, 503 (`retry: true`) while the mint days or the luck are still being read, 429 (`retry: true`, with `Retry-After`) past your network's budget of new filtered answers (a cached one is always served). Sales still in the mempool come apart, in `pending` (newest first, marked `pending: true` with `first_seen` and `fee_rate`); they never enter the columns, stats or markets.",
        "parameters": [
          {
            "name": "row",
            "in": "query",
            "required": false,
            "description": "Only sales of this row.",
            "schema": {
              "type": "string"
            },
            "example": "uncommon"
          },
          {
            "name": "group",
            "in": "query",
            "required": false,
            "description": "Only sales of this group's rows (e.g. `rarity`). Ignored with `row`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "after",
            "in": "query",
            "required": false,
            "description": "Only sales after this sequence number (an answer's `seq`). A cursor at most 5,000 sales behind the newest is answered as asked; one further back is answered whole (`after: 0` in the answer: replace what you hold rather than append), and one past the newest as the newest.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "sub",
            "in": "query",
            "required": false,
            "description": "With `row`: `1` adds its rarer sub-categories' sales, flagged 4.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "0"
            }
          },
          {
            "name": "led",
            "in": "query",
            "required": false,
            "description": "With `row` or `group`: `1` adds the sales led by another row that sold sats of these rows (their secondary rows), flagged 8, outside every market and median.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "0"
            }
          },
          {
            "name": "years",
            "in": "query",
            "required": false,
            "description": "Only the sales of the row's sats mined in these years (comma-separated YYYY; `year` too): a sale passes when a sat of the row (of any row, without `row`) it sold was mined in one of them, as `/api/sales/query` and the collection's Activity match it. The Statistics' and a row detail's sales under a year filter. Years 2009 to this one (400 otherwise).",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}(,\\d{4})*$"
            },
            "example": "2009"
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "Only the sales of each row's sats mined in this month (UTC, `YYYY-MM`, by each block's own time), matched on the dashboard: any rare-sat index.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
            },
            "example": "2017-12"
          },
          {
            "name": "blocks",
            "in": "query",
            "required": false,
            "description": "Only the sales of each row's sats mined in these blocks: heights `from-to`, inclusive (`1000-5000`), or one block (`9`), up to the tip (400 past it or for a malformed or reversed range), matched on the dashboard: any rare-sat index.",
            "schema": {
              "type": "string",
              "pattern": "^(0|[1-9]\\d{0,6})(-(0|[1-9]\\d{0,6}))?$"
            },
            "example": "1000-5000"
          },
          {
            "name": "luck",
            "in": "query",
            "required": false,
            "description": "Only the sales of the row's sats mined in blocks of these lucks: `N` (N or more) or `N-M`, matched as `years` is. With `years`, both.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{1,3}(-\\d{1,3})?$"
            },
            "example": "10"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalesColumns"
                }
              }
            }
          },
          "400": {
            "description": "A malformed `after`, `sub`, `years` or `luck`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "404": {
            "description": "An unknown row or group. A retired row (`uncommon_2009`, `rare_2009`) answers 404 too, its `retired` field naming the row and years to ask for instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                },
                "examples": {
                  "retired": {
                    "summary": "A retired row",
                    "value": {
                      "error": "row uncommon_2009 is retired: ask for row uncommon with years 2009",
                      "retired": {
                        "row": "uncommon_2009",
                        "successor": {
                          "row": "uncommon",
                          "years": [
                            2009
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "501": {
            "description": "`years` or `luck` asked of a server without the sat filters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "429": {
            "description": "Too many new filtered answers (each a pass over every sale) from your network (an IPv4 address or IPv6 /64), or from everyone at once: `retry: true`; try again after `Retry-After` seconds. Answers already built are served all the same.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until a new one is taken.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "503": {
            "description": "The mint days or the block luck are still being read (`retry: true`), or the luck is not available.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/sales/parties": {
      "get": {
        "operationId": "getSaleParties",
        "tags": [
          "Market data"
        ],
        "summary": "Get the seller and buyer of sales",
        "description": "The seller's and buyer's addresses of up to 500 sales by sequence number (`null`: a script with no address). Cacheable 30 s.",
        "parameters": [
          {
            "name": "seqs",
            "in": "query",
            "required": true,
            "description": "1-500 sequence numbers, comma-separated.",
            "schema": {
              "type": "string"
            },
            "example": "1,2"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SaleParties"
                },
                "example": {
                  "generation": 1,
                  "parties": {
                    "1": {
                      "seller": "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu",
                      "buyer": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr"
                    },
                    "2": {
                      "seller": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "buyer": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing, too many or malformed sequence numbers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/sales/stats": {
      "get": {
        "operationId": "getSalesStats",
        "tags": [
          "Market data"
        ],
        "summary": "Get every row's market stats",
        "description": "Per row: the last unit price, the 30-day median unit price, volume and sales, and all-time sales. With `years`, `month` or `luck`, every row's market over only the sales of its sats of those years, that month or those lucks (matched as `/api/sales` matches them; the sales' outlier verdicts are their row's), and `filter` echoed: the Statistics' sales columns under a year, month or luck filter, and a collection's head under its Activity filter. Confirmed sales only: pending (mempool) sales never count.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalesStats"
                }
              }
            }
          },
          "400": {
            "description": "A malformed `years`, `month` or `luck`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "501": {
            "description": "`years` or `luck` asked of a server without the sat filters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "429": {
            "description": "Too many new filtered answers (each a pass over every sale) from your network (an IPv4 address or IPv6 /64), or from everyone at once: `retry: true`; try again after `Retry-After` seconds. Answers already built are served all the same.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until a new one is taken.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "503": {
            "description": "The mint days or the block luck are still being read (`retry: true`), or the luck is not available.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "years",
            "in": "query",
            "required": false,
            "description": "Only the sales of each row's sats mined in these years (comma-separated YYYY, 2009 to this year; `year` too).",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}(,\\d{4})*$"
            },
            "example": "2009"
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "Only the sales of each row's sats mined in this month (UTC, `YYYY-MM`, by each block's own time), matched on the dashboard: any rare-sat index.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
            },
            "example": "2017-12"
          },
          {
            "name": "blocks",
            "in": "query",
            "required": false,
            "description": "Only the sales of each row's sats mined in these blocks: heights `from-to`, inclusive (`1000-5000`), or one block (`9`), up to the tip (400 past it or for a malformed or reversed range), matched on the dashboard: any rare-sat index.",
            "schema": {
              "type": "string",
              "pattern": "^(0|[1-9]\\d{0,6})(-(0|[1-9]\\d{0,6}))?$"
            },
            "example": "1000-5000"
          },
          {
            "name": "luck",
            "in": "query",
            "required": false,
            "description": "Only the sales of each row's sats mined in blocks of these lucks: `N` (N or more) or `N-M`.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{1,3}(-\\d{1,3})?$"
            },
            "example": "10"
          }
        ]
      }
    },
    "/api/sales/{seq}/tx": {
      "get": {
        "operationId": "getSaleTransaction",
        "tags": [
          "Market data"
        ],
        "summary": "A sale's transaction",
        "description": "A 302 redirect to the sale's transaction page, `/tx/{txid}` (the compact sales carry only part of the txid). With `accept: application/json`, `{txid, href}` instead.",
        "parameters": [
          {
            "name": "seq",
            "in": "path",
            "required": true,
            "description": "The sale's sequence number.",
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "With `accept: application/json`: the sale's transaction.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "txid": {
                      "type": "string"
                    },
                    "href": {
                      "type": "string",
                      "description": "`/tx/{txid}`."
                    }
                  },
                  "required": [
                    "txid",
                    "href"
                  ]
                },
                "example": {
                  "txid": "d78f3f29369db39032219ae561732dda47b54b6f6d4d93d72a22c257c3946ac2",
                  "href": "/tx/d78f3f29369db39032219ae561732dda47b54b6f6d4d93d72a22c257c3946ac2"
                }
              }
            }
          },
          "302": {
            "description": "Redirect; `location` is `/tx/{txid}`."
          },
          "404": {
            "description": "No such sale.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/sat/{n}": {
      "get": {
        "operationId": "getSat",
        "tags": [
          "Market data"
        ],
        "summary": "Get a sat",
        "description": "One sat: the block that mined it, its types and rows, inscriptions, where it is now, every sale of it (newest first) and the marketplace's live listing of its UTXO. Cacheable 15 s. `pending` says where a transaction still in the mempool takes it; its pending sales lead `sales`, marked `pending`.",
        "parameters": [
          {
            "name": "n",
            "in": "path",
            "required": true,
            "description": "The sat number, a decimal integer below 2,099,999,997,690,000.",
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "example": 45100023043
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SatPage"
                }
              }
            }
          },
          "400": {
            "description": "Not a sat number.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "503": {
            "description": "The index is unavailable or busy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/utxo/{outpoint}": {
      "get": {
        "operationId": "getUtxo",
        "tags": [
          "Market data"
        ],
        "summary": "Get a UTXO",
        "description": "One output and every rare sat in it: the sats raresats.net tracks, each with its offset in the output; the rare and exotic sats it does not track, found in the output's sat ranges; inscriptions and runes; for a spent output, where it was spent and where its tracked sats are now; its sales and the marketplace's live listing of it. Cacheable 15 s. A spend still in the mempool is one `spent_in` with `pending: true` (the index's word preferred to bitcoind's); an output a pending transaction makes has `pending`.",
        "parameters": [
          {
            "name": "outpoint",
            "in": "path",
            "required": true,
            "description": "The output as `txid:vout`.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-fA-F]{64}:[0-9]{1,10}$"
            },
            "example": "f1c500f81c331d31415902755278e2a599311d8121ac9582bc63ad981efa48fb:1"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UtxoPage"
                }
              }
            }
          },
          "400": {
            "description": "Not an outpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "404": {
            "description": "No such output: its transaction is unknown, or has no output of that index.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "503": {
            "description": "The index is unavailable or busy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/tx/{txid}": {
      "get": {
        "operationId": "getTx",
        "tags": [
          "Market data"
        ],
        "summary": "Get a transaction",
        "description": "One transaction, confirmed or in the mempool, as the site's transaction page shows it: status (block, time, confirmations; or first seen and fee rate), fee, sizes, every input and output (address, value, the tracked rare sats each held), the flow of every tracked rare sat from the input that carried it to the output (or fee) it landed in, its sales and the Transfers and Extractions feeds' notable verdicts. A transaction confirmed before the index's moves retention shows only the tracked sats still in its outputs (`sat_flow: outputs`). Cacheable 15 s (a minute once 6 blocks deep).",
        "parameters": [
          {
            "name": "txid",
            "in": "path",
            "required": true,
            "description": "The transaction id, 64 hex digits.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-fA-F]{64}$"
            },
            "example": "d78f3f29369db39032219ae561732dda47b54b6f6d4d93d72a22c257c3946ac2"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TxPage"
                },
                "example": {
                  "txid": "d78f3f29369db39032219ae561732dda47b54b6f6d4d93d72a22c257c3946ac2",
                  "status": "confirmed",
                  "height": 969717,
                  "hash": "00000000000000000001ffc80f14c6109df0c60ae45957f0f22e736914cfb276",
                  "time": 1791024538,
                  "confirmations": 11,
                  "tx_index": 1408,
                  "indexed": true,
                  "first_seen": null,
                  "removed": null,
                  "version": 2,
                  "locktime": 969671,
                  "size": 11675,
                  "vsize": 11675,
                  "weight": 46700,
                  "coinbase": false,
                  "input_value": 3649149319,
                  "output_value": 3649128183,
                  "fee": 21136,
                  "fee_rate": 1.8,
                  "sat_flow": "complete",
                  "tracked": true,
                  "marker": false,
                  "raresats": null,
                  "kinds": [
                    "transfer"
                  ],
                  "inputs": [
                    {
                      "vin": 0,
                      "outpoint": "00d22e4e66b6e4de2e3f0fb3cb146df30c8d9b40845b103d5574741c1c7c778a:0",
                      "value": 50000000,
                      "address": "12DeZJEgWyd2ffYU6KekZdevGLqnkpnUU9",
                      "script_pubkey": "76a9140d5c77dc25efd254a51e23ba422c4e6e8e2d25f588ac",
                      "sequence": 4294967293,
                      "created_height": 302976,
                      "sighash": 1,
                      "inscriptions": 0,
                      "tracked": false,
                      "extracted": false,
                      "pieces": [],
                      "inscribed_sats": []
                    },
                    {
                      "vin": 2,
                      "outpoint": "14833143ef7ebe658760f03f7533b50b9ebaa1ad87d85c597aaaa6ffe4b0b767:0",
                      "value": 210587000,
                      "address": "15vSCMDKkR3s7rDLNMnTrL7ivg8bqyRTSs",
                      "script_pubkey": "76a91435fb94d60678093dce315bbd73dd4084582c93cb88ac",
                      "sequence": 4294967293,
                      "created_height": 709400,
                      "sighash": 1,
                      "inscriptions": 0,
                      "tracked": true,
                      "extracted": false,
                      "pieces": [
                        {
                          "offset": 97510060,
                          "start": 1282092500000000,
                          "len": 1,
                          "types": [
                            "uncommon",
                            "alpha"
                          ],
                          "height": 302837,
                          "date": "2014-05-27",
                          "luck": 1
                        }
                      ],
                      "inscribed_sats": []
                    }
                  ],
                  "outputs": [
                    {
                      "vout": 0,
                      "value": 3649128183,
                      "address": "3EBzpPwBe8TBeuVzTGmKuJADQUniLKHSwy",
                      "script_pubkey": "a914891ca628ea69a42f89db374f34c7ff4eff6fce9487",
                      "kind": "spendable",
                      "tracked": true,
                      "extracted": false,
                      "pieces": [
                        {
                          "offset": 159380060,
                          "start": 1282092500000000,
                          "len": 1,
                          "types": [
                            "uncommon",
                            "alpha"
                          ],
                          "height": 302837,
                          "date": "2014-05-27",
                          "luck": 1
                        }
                      ],
                      "inscribed_sats": [],
                      "marker": false,
                      "runestone": false
                    }
                  ],
                  "flow": [
                    {
                      "source": "input",
                      "vin": 2,
                      "input_offset": 97510060,
                      "dest": "output",
                      "vout": 0,
                      "offset": 159380060,
                      "start": 1282092500000000,
                      "len": 1,
                      "types": [
                        "uncommon",
                        "alpha"
                      ],
                      "height": 302837,
                      "date": "2014-05-27",
                      "luck": 1
                    }
                  ],
                  "fee_pieces": [],
                  "mined_pieces": [],
                  "lost_pieces": [],
                  "rows": {
                    "uncommon": 8,
                    "black": 3,
                    "alpha_uncommon": 8,
                    "black_omega": 3
                  },
                  "sales": [],
                  "transfer": {
                    "id": "transfer:969717:d78f3f29369db39032219ae561732dda47b54b6f6d4d93d72a22c257c3946ac2",
                    "kind": "transfer",
                    "height": 969717,
                    "time": 1791024538,
                    "block_hash": "00000000000000000001ffc80f14c6109df0c60ae45957f0f22e736914cfb276",
                    "txid": "d78f3f29369db39032219ae561732dda47b54b6f6d4d93d72a22c257c3946ac2",
                    "tx_index": 1408,
                    "rows": {
                      "uncommon": 8,
                      "black": 3,
                      "alpha_uncommon": 8,
                      "black_omega": 3
                    },
                    "moved": [
                      {
                        "row": "uncommon",
                        "label": "Uncommon",
                        "count": 8
                      },
                      {
                        "row": "black",
                        "label": "Black",
                        "count": 3
                      },
                      {
                        "row": "alpha_uncommon",
                        "label": "Alpha uncommon",
                        "count": 8
                      },
                      {
                        "row": "black_omega",
                        "label": "Black omega",
                        "count": 3
                      }
                    ],
                    "from": [
                      {
                        "outpoint": "14833143ef7ebe658760f03f7533b50b9ebaa1ad87d85c597aaaa6ffe4b0b767:0",
                        "address": "15vSCMDKkR3s7rDLNMnTrL7ivg8bqyRTSs",
                        "label": "15vSCMDKkR3s7rDLNMnTrL7ivg8bqyRTSs",
                        "value": 210587000,
                        "sats": 1,
                        "created_height": 709400,
                        "created_time": 1636736136,
                        "extracted": false
                      }
                    ],
                    "from_count": 8,
                    "to": [
                      {
                        "vout": 0,
                        "address": "3EBzpPwBe8TBeuVzTGmKuJADQUniLKHSwy",
                        "label": "3EBzpPwBe8TBeuVzTGmKuJADQUniLKHSwy",
                        "value": 3649128183,
                        "sats": 11,
                        "kind": "spendable",
                        "extracted": false
                      }
                    ],
                    "to_count": 1,
                    "fee_sats": 0,
                    "dormancy": {
                      "seconds": 301043862,
                      "outpoint": "f836de28ecaed8eea81acee25931c47e8dc136d2969d21f2ec81ac32375cdd04:1",
                      "created_height": 458063,
                      "created_time": 1489980676
                    },
                    "sats": [
                      {
                        "sat": 472424999999999,
                        "height": 94484
                      }
                    ],
                    "sats_total": 11,
                    "reasons": [
                      {
                        "code": "dormant",
                        "category": "dormant",
                        "seconds": 301043862,
                        "label": "Dormant 9.5 years"
                      }
                    ]
                  },
                  "extractions": [],
                  "entries": [
                    {
                      "txid": "d78f3f29369db39032219ae561732dda47b54b6f6d4d93d72a22c257c3946ac2",
                      "height": 969717,
                      "time": 1791024538,
                      "tx_index": 1408,
                      "direction": "out",
                      "kind": "transfer",
                      "rows_in": {},
                      "rows_out": {
                        "uncommon": 1,
                        "alpha_uncommon": 1
                      },
                      "sats_in": 0,
                      "sats_out": 1,
                      "value_in": 0,
                      "value_out": 61700000,
                      "outputs_in": 0,
                      "inputs_out": 1,
                      "extracted_in": false,
                      "extracted_out": false,
                      "extracted_sats": 0,
                      "isolated": 0,
                      "burned": 0,
                      "roles": [],
                      "counterparty": "3EBzpPwBe8TBeuVzTGmKuJADQUniLKHSwy",
                      "counterparty_script_pubkey": "a914891ca628ea69a42f89db374f34c7ff4eff6fce9487",
                      "counterparties": 1,
                      "lead_sat": {
                        "sat": 1739532500000000,
                        "types": [
                          "uncommon",
                          "alpha"
                        ]
                      },
                      "sales": [],
                      "address": "1Hjv1dXPWvcZ2E7un5wv5tkCJ2oa9r4rj",
                      "script_pubkey": "76a914032a7a69b345c6770a95be057d54af7c384c34b288ac"
                    }
                  ],
                  "depends": [],
                  "moves_from": 965696,
                  "as_of": {
                    "height": 969727,
                    "time": 1791028507
                  },
                  "explorer": "https://mempool.space"
                }
              }
            }
          },
          "400": {
            "description": "Not a transaction id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "404": {
            "description": "No such transaction: neither the blockchain nor the mempool holds it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "503": {
            "description": "The index is unavailable, busy, or does not serve transactions yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/address/{address}": {
      "get": {
        "operationId": "getAddress",
        "tags": [
          "Market data"
        ],
        "summary": "Get an address's rare sats",
        "description": "An address's UTXOs that hold tracked sats, as its address page lists them: totals, the types it holds, and one page of UTXOs. Cacheable 30 s. A UTXO a pending transaction spends carries `spent_by_pending`; `pending_outputs` lists the outputs pending transactions send it.",
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "description": "A mainnet address.",
            "schema": {
              "type": "string"
            },
            "example": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "UTXOs to skip.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, at most 5,000.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 5000,
              "default": 500
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "A column, `-` first for descending: `rare`, `range`, `year`, `quantity`, `utxo`, `size`, `received`.",
            "schema": {
              "type": "string",
              "default": "range"
            }
          },
          {
            "name": "types",
            "in": "query",
            "required": false,
            "description": "Comma-separated sat types; a UTXO must hold every one.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddressPage"
                }
              }
            }
          },
          "400": {
            "description": "Not an address, or a malformed parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "503": {
            "description": "The index is unavailable or busy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/address/{address}/activity": {
      "get": {
        "operationId": "getAddressActivity",
        "tags": [
          "Market data"
        ],
        "summary": "Get an address's activity",
        "description": "What an address bought and sold (every marketplace), listed and cancelled on raresats.net, extracted, mined and moved, newest first, with filter facets and totals. Transfers and extractions come from the index's per-address history (from the ordinals era) where it has one, read as far as the pages asked for need it; else from the moves it keeps (about 4 weeks); before either, the address's held UTXOs. `coverage` says which and how far; `summary.partial` says when the totals cover only the history read so far. Pages follow `next` (pass it as `before`), which does not drift when newer activity arrives. Cacheable 15 s. The first page (no `before`, no `to`) leads with the address's pending items (`pending: true`, `source: mempool`), outside `limit`, `total` and the facets; `pending=0` leaves them out. A sale here the index shows pending is listed once, as the index's.",
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "description": "A mainnet address.",
            "schema": {
              "type": "string"
            },
            "example": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr"
          },
          {
            "name": "types",
            "in": "query",
            "required": false,
            "description": "Comma-separated activity types: `bought`, `sold`, `listed`, `cancelled`, `extraction`, `mined`, `transfer_in`, `transfer_out`, `consolidation`.",
            "schema": {
              "type": "string"
            },
            "example": "bought,sold"
          },
          {
            "name": "row",
            "in": "query",
            "required": false,
            "description": "Only activity of this row (collection) id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "marketplace",
            "in": "query",
            "required": false,
            "description": "Only sales and listings of this marketplace id (`magisat`, `magic_eden`, `raresats`, …).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Only activity of this UTC year.",
            "schema": {
              "type": "integer",
              "minimum": 2009
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Only activity on or after this UTC day, `YYYY-MM-DD`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Only activity on or before this UTC day, `YYYY-MM-DD`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, at most 200.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "description": "The previous page's `next`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pending",
            "in": "query",
            "required": false,
            "description": "`0` leaves the pending (mempool) items out.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "1"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddressActivity"
                }
              }
            }
          },
          "400": {
            "description": "Not an address, or a malformed parameter or cursor.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "404": {
            "description": "A retired row (`uncommon_2009`, `rare_2009`): its `retired` field names the row and years to ask for instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                },
                "examples": {
                  "retired": {
                    "summary": "A retired row",
                    "value": {
                      "error": "row uncommon_2009 is retired: ask for row uncommon with years 2009",
                      "retired": {
                        "row": "uncommon_2009",
                        "successor": {
                          "row": "uncommon",
                          "years": [
                            2009
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Too many lookups at once.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/rows/{id}": {
      "get": {
        "operationId": "getRow",
        "tags": [
          "Site feeds"
        ],
        "summary": "Get a row's supply, holders and history",
        "description": "One row: `row` (its supply stats, extracted and non-extracted top holders, label, group and definition) and `history` (extracted and located counts over time). With `years`, over the sats mined in those years (`years` echoed): one year lists its own top holders (at most 100 per list), a set of years none (`null`), and the history's holder counts are `null` for a set. With `luck`, over the sats mined in blocks of those lucks (`luck` echoed): no top holders (`null`), and the history's holder counts are `null` but for a single luck or every luck. With `month`, over the sats mined in that month (`month` echoed): its own top holders (at most 100 per list) and holder counts in its history.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The row id.",
            "schema": {
              "type": "string"
            },
            "example": "uncommon"
          },
          {
            "name": "range",
            "in": "query",
            "required": false,
            "description": "History range.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "4y",
                "1y",
                "90d",
                "30d"
              ],
              "default": "all"
            }
          },
          {
            "name": "top",
            "in": "query",
            "required": false,
            "description": "Holders per list, 1-1000.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100
            }
          },
          {
            "name": "years",
            "in": "query",
            "required": false,
            "description": "Only the sats mined in these years: comma-separated years (YYYY) blocks were mined in, at most 64 (`year` is accepted too). Counters are the years' sums, `total` and `mined` their sats mined so far, `holders` and `extracted_holders` the addresses holding sats of any of them (exact). Needs a rare-sat index with a year breakdown (`fork.status.year_stats` in `/api/status`), else 501.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}(,\\d{4})*$"
            },
            "example": "2009"
          },
          {
            "name": "luck",
            "in": "query",
            "required": false,
            "description": "Only the sats mined in blocks of these lucks: `N` (luck N or more) or `N-M`, from 0 to the index's highest luck (31, which also counts any luckier block). A block's luck is the leading zero bits of its hash beyond its target's. Counters are the lucks' sums, `holders` and `extracted_holders` the addresses holding sats of any of them (exact). Not with `years` (400): the supply is broken down by one or the other. Needs a rare-sat index with a luck breakdown (`fork.status.luck_stats` in `/api/status`), else 501.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{1,3}(-\\d{1,3})?$"
            },
            "example": "10"
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "Only the sats mined in this month (UTC, `YYYY-MM`), one a block was mined in. Not with `years` or `luck` (400). Needs a rare-sat index with a month breakdown (`fork.status.month_stats`), else 501.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
            },
            "example": "2017-12"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A JSON object; see the description for its main fields.",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "A malformed parameter, or both years and a luck, a malformed month or one no block was mined in, or more than one of years, a luck and a month.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "404": {
            "description": "No such row. A retired row (`uncommon_2009`, `rare_2009`) answers 404 too, its `retired` field naming the row and years to ask for instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                },
                "examples": {
                  "retired": {
                    "summary": "A retired row",
                    "value": {
                      "error": "row uncommon_2009 is retired: ask for row uncommon with years 2009",
                      "retired": {
                        "row": "uncommon_2009",
                        "successor": {
                          "row": "uncommon",
                          "years": [
                            2009
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The index is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "501": {
            "description": "The rare-sat index has no year (luck, month) breakdown.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/supply": {
      "get": {
        "operationId": "getSupply",
        "tags": [
          "Site feeds"
        ],
        "summary": "Get the circulating supply",
        "description": "The latest supply of every row (`supply`: `{height, hash, time, rows}`, each row with `total`, `stats` and `active_non_extracted`), the row definitions (`rows`) and their groups (`groups`). A row the site shows as a sub-category of another although its types do not say so names that row in `sub_of`: the milestone alphas (`kilosat_alpha`, `decasat_alpha`, `centasat_alpha`, `megasat_alpha`), labelled Kilosat, Decasat, Centasat and Megasat uncommon, are sub-categories of `uncommon`, and the milestone omegas (`kilosat_omega`, `decasat_omega`, `centasat_omega`, `megasat_omega`), labelled Kilosat, Decasat, Centasat and Megasat black, of `black`. With `years`, every row's supply over the sats mined in those years (rows with none have zeros), and `years` echoed; with `luck`, over the sats mined in blocks of those lucks, and `luck` echoed (`{min, max}`, `max` null for \"or more\"); with `month`, over the sats mined in that month, and `month` echoed.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A JSON object; see the description for its main fields.",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Malformed years, a year no block was mined in, a malformed luck or one past the index's highest, a malformed month or one no block was mined in, or more than one of years, a luck and a month.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "501": {
            "description": "The rare-sat index has no year (luck, month) breakdown (`years`, `luck` or `month` asked of an older index).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "502": {
            "description": "The index answered with an error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "503": {
            "description": "The index is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "years",
            "in": "query",
            "required": false,
            "description": "Only the sats mined in these years: comma-separated years (YYYY) blocks were mined in, at most 64 (`year` is accepted too). Counters are the years' sums, `total` and `mined` their sats mined so far, `holders` and `extracted_holders` the addresses holding sats of any of them (exact). Needs a rare-sat index with a year breakdown (`fork.status.year_stats` in `/api/status`), else 501.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}(,\\d{4})*$"
            },
            "example": "2009,2010"
          },
          {
            "name": "luck",
            "in": "query",
            "required": false,
            "description": "Only the sats mined in blocks of these lucks: `N` (luck N or more) or `N-M`, from 0 to the index's highest luck (31, which also counts any luckier block). A block's luck is the leading zero bits of its hash beyond its target's. Counters are the lucks' sums, `holders` and `extracted_holders` the addresses holding sats of any of them (exact). Not with `years` (400): the supply is broken down by one or the other. Needs a rare-sat index with a luck breakdown (`fork.status.luck_stats` in `/api/status`), else 501.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{1,3}(-\\d{1,3})?$"
            },
            "example": "10"
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "Only the sats mined in this month (UTC, `YYYY-MM`), one a block was mined in (`months` is accepted too). Counters, `holders` and `extracted_holders` are the month's own (exact). Not with `years` or `luck` (400): the supply is broken down by one of them. Needs a rare-sat index with a month breakdown (`fork.status.month_stats` in `/api/status`, index schema 7), else 501.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
            },
            "example": "2017-12"
          }
        ]
      }
    },
    "/api/supply/years": {
      "get": {
        "operationId": "getSupplyYears",
        "tags": [
          "Site feeds"
        ],
        "summary": "Get every row's supply by mint year",
        "description": "Every row's supply split by the year its sats were mined: `{height, hash, time, years: [{year, from_height, to_height}], rows: [{id, years: {\"2009\": {total, stats, active_non_extracted}}}]}`, a row listing only the years it has sats of. What the year chips count; cached per block. Needs a rare-sat index with a year breakdown (`fork.status.year_stats` in `/api/status`), else 501.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A JSON object; see the description for its main fields.",
                  "additionalProperties": true
                }
              }
            }
          },
          "501": {
            "description": "The rare-sat index has no year breakdown.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "502": {
            "description": "The index answered with an error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "503": {
            "description": "The index is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/supply/lucks": {
      "get": {
        "operationId": "getSupplyLucks",
        "tags": [
          "Site feeds"
        ],
        "summary": "Get every row's supply by block luck",
        "description": "Every row's supply split by the luck of the blocks its sats were mined in: `{height, hash, time, lucks: [{luck, blocks}], rows: [{id, lucks: {\"12\": {total, stats, active_non_extracted}}}]}`, a row listing only the lucks it has sats of (`lucks`: the blocks of each luck). What the luck selects count; cached per block. Needs a rare-sat index with a luck breakdown (`fork.status.luck_stats` in `/api/status`), else 501.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A JSON object; see the description for its main fields.",
                  "additionalProperties": true
                }
              }
            }
          },
          "501": {
            "description": "The rare-sat index has no luck breakdown.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "502": {
            "description": "The index answered with an error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "503": {
            "description": "The index is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/supply/months": {
      "get": {
        "operationId": "getSupplyMonths",
        "tags": [
          "Site feeds"
        ],
        "summary": "Get every row's supply by mint month",
        "description": "Every row's supply split by the month (UTC) its sats were mined in, compactly: `{height, hash, time, months: [{month, from_height, to_height}], fields: [\"mined\", \"located\", \"burned\", \"lost\", \"overwritten\", \"extracted\", \"holders\", \"extracted_holders\", \"inscribed\"], rows: [{id, months: {\"2017-12\": [counts in the order of fields]}}]}`, a row listing only the months it has sats of. What a collection's month select counts; cached per block. Needs a rare-sat index with a month breakdown (`fork.status.month_stats` in `/api/status`), else 501.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A JSON object; see the description for its main fields.",
                  "additionalProperties": true
                }
              }
            }
          },
          "501": {
            "description": "The rare-sat index has no month breakdown.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "502": {
            "description": "The index answered with an error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "503": {
            "description": "The index is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/state": {
      "get": {
        "operationId": "getState",
        "tags": [
          "Site feeds"
        ],
        "summary": "Get the dashboard state",
        "description": "Everything the site shows at once: `thresholds`, `limits`, `fork`, `feed`, `rows`, `groups`, `supply`, `sales`, and the newest `transfers` and `extractions`. `pending` is everything pending in the mempool (`/api/pending`).",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Events per list, 1-1000.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 500
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A JSON object; see the description for its main fields.",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "A malformed limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/status": {
      "get": {
        "operationId": "getStatus",
        "tags": [
          "Site feeds"
        ],
        "summary": "Get the index status",
        "description": "The rare-sat index's reachability, mode and progress (`fork`) and the dashboard's tip (`feed`).",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A JSON object; see the description for its main fields.",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/api/transfers": {
      "get": {
        "operationId": "getTransfers",
        "tags": [
          "Site feeds"
        ],
        "summary": "Get notable transfers",
        "description": "Notable transfers of rare sats, newest first: `{total, offset, items}`. Page with `before` (an event id) or `offset`. The first page (no `before`, `offset` 0) also has `pending`: the notable transfers of transactions still in the mempool, newest first, outside `total`.",
        "parameters": [
          {
            "name": "before",
            "in": "query",
            "required": false,
            "description": "An event id: the events after it.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Events to skip.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Events, 1-1000.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A JSON object; see the description for its main fields.",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "A malformed parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "404": {
            "description": "`before` is no longer held: reload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/extractions": {
      "get": {
        "operationId": "getExtractions",
        "tags": [
          "Site feeds"
        ],
        "summary": "Get notable extractions",
        "description": "Notable extractions (rare sats newly isolated), newest first, paged like transfers. The first page also has `pending`, as transfers.",
        "parameters": [
          {
            "name": "before",
            "in": "query",
            "required": false,
            "description": "An event id: the events after it.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Events to skip.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Events, 1-1000.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A JSON object; see the description for its main fields.",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "A malformed parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "404": {
            "description": "`before` is no longer held: reload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/events": {
      "get": {
        "operationId": "getEvents",
        "tags": [
          "Site feeds"
        ],
        "summary": "Stream live events (SSE)",
        "description": "Server-Sent Events: a `snapshot` (the state) on connect, then `status`, `backfill`, `block`, `supply`, `reorg`, `snapshot` and `sales` events, `mempool` (an invalidation whenever what is pending changes: `{version, keys: {sales, transfers, extractions, rows, addresses, outpoints}, counts: {sales, transfers, extractions}}`; read `/api/pending`, or the answer you show, again when a key you care about is set), the chat's `chat` (`{type: \"message\", topic, message, thread?}`, a reply with its root's new counts in `thread`, `{type: \"delete\", ids, threads, topics}`, `threads` the roots whose replies went, or `{type: \"topic\", topic, archived}`) and `profile` (`{address, display_name}`) events while chat is on, the marketplace's `listing`, `offer`, `market`, `activity`, `affiliate` and `transfer` (a wallet transfer broadcast here changed status: `{version, count, keys: {addresses}, changes}`) events while it is on, and a `ping` every 15 s. Limited to 2,048 open streams, 8 from one IPv4 address or IPv6 /64 and 32 from one IPv6 /48. When every place is taken, a newcomer takes the place of the oldest stream of the network holding the most (at least two more than the newcomer's): that stream gets `retry: 60000` and an `evicted` event (`{reason, retry_ms}`), then ends; reconnect after `retry_ms` with `last_event_id`.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Events per list in the snapshot, 1-1000.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 500
            }
          },
          {
            "name": "last_event_id",
            "in": "query",
            "required": false,
            "description": "Resume after this event id (what `Last-Event-ID` says; for a client that reopens the stream itself). Unknown or too old: a `snapshot` instead.",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "name": "Last-Event-ID",
            "in": "header",
            "required": false,
            "description": "Resume after this event id: the events after it are replayed while the server holds them (the last 2,000 or 4 MiB), else a `snapshot` is sent.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "An event stream.",
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "503": {
            "description": "Too many open streams from your network (8 from an IPv4 address or IPv6 /64, 32 from an IPv6 /48), or every place taken and no network holding more than yours.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/market/affiliates/{address}": {
      "get": {
        "operationId": "getAffiliate",
        "tags": [
          "Listings"
        ],
        "summary": "Get an affiliate's referred purchases",
        "description": "Any address of the network is an affiliate (no registration). Its totals and its newest referred purchases: purchases broadcast here whose referral applied. `registered` is informational, kept for compatibility.",
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "description": "The affiliate's mainnet address.",
            "schema": {
              "type": "string"
            },
            "example": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffiliateStats"
                },
                "example": {
                  "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                  "registered": false,
                  "registered_at": null,
                  "share_bps": 5000,
                  "totals": {
                    "purchases": 1,
                    "confirmed": 1,
                    "pending": 0,
                    "earned": 757,
                    "pending_earned": 0,
                    "volume": 60546
                  },
                  "purchases": [
                    {
                      "txid": "6897451c42f02de2594abfdd6a5d4fcf4794a62cbbd9fbec1ec983893ddc5df4",
                      "items": 1,
                      "prices": 60546,
                      "platform_fee": 1514,
                      "affiliate_fee": 757,
                      "status": "confirmed",
                      "time": 1790952985
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Not an address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_address": {
                    "summary": "Not an address",
                    "value": {
                      "error": "not a mainnet address",
                      "code": "bad_address"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "bad_address",
          "bad_path"
        ]
      }
    },
    "/api/market/affiliates/register": {
      "post": {
        "operationId": "registerAffiliate",
        "tags": [
          "Trading"
        ],
        "summary": "Register an affiliate (optional)",
        "description": "Optional, kept for compatibility: any address is an affiliate and is paid without registering. It still verifies as before: a BIP-322 signature by the payout address of `raresats.net affiliate <address> <unix seconds>`, at most 10 minutes old, used once. The registering wallet's addresses are kept with it and only ever narrow what the affiliate is paid: a purchase by any of them is a self-referral (`affiliate_wallet`). Registering again adds the new wallet's addresses.",
        "deprecated": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AffiliateRegisterRequest"
              },
              "example": {
                "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                "message": "raresats.net affiliate bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh 1790949000",
                "signature": "AUBGQvdc2H+7HTo1njZ1vlDxoX6ncoehAGbaHcAY1FtfSNg7lmo8Ih3WGInhAH/snOUIb8DkwRSQxc2dOu911Z9E",
                "wallet_addresses": [
                  "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffiliateRegisterResponse"
                },
                "example": {
                  "affiliate": {
                    "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                    "registered_at": 1790949000,
                    "wallet_addresses": [
                      "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
                      "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh"
                    ]
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_signature": {
                    "summary": "Not signed by the address",
                    "value": {
                      "error": "the signature does not verify for that address and message",
                      "code": "bad_signature"
                    }
                  },
                  "stale_message": {
                    "summary": "Old message",
                    "value": {
                      "error": "the registration message is more than 10 minutes old: sign a new one",
                      "code": "stale_message"
                    }
                  },
                  "replayed": {
                    "summary": "Used already",
                    "value": {
                      "error": "that registration message was used already",
                      "code": "replayed"
                    }
                  }
                }
              }
            }
          },
          "5XX": {
            "description": "The trade engine is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "bad_request",
          "method_not_allowed",
          "bad_address",
          "legacy_address",
          "unsupported_address",
          "bad_message",
          "bad_signature",
          "bad_wallet_addresses",
          "stale_message",
          "future_message",
          "replayed",
          "engine_unavailable"
        ]
      }
    },
    "/api/prices": {
      "get": {
        "operationId": "getPrices",
        "tags": [
          "Market data"
        ],
        "summary": "Get BTC/USD prices",
        "description": "The current BTC/USD price and one price per UTC day since 2010-07-19, for converting sats to dollars at the time of a sale. Cacheable 5 minutes (1 minute while nothing is available). Never an error: unavailable parts are `null`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Prices"
                },
                "example": {
                  "current": {
                    "usd": 86772,
                    "time": 1790945710
                  },
                  "history": {
                    "start": 1279497600,
                    "step": 86400,
                    "usd": [
                      0.0858,
                      0.0808,
                      0.0747
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/sales/query": {
      "get": {
        "operationId": "querySales",
        "tags": [
          "Market data"
        ],
        "summary": "Query sales by row, sub-category and mint date",
        "description": "Sales on every marketplace, newest first, filtered by row, rarer sub-category, mint years, a mint month, a mint day or a month-day (birthday sats), and sat luck; with facets. Page with `before` = the previous answer's `next`. Cacheable 30 s.",
        "parameters": [
          {
            "name": "row",
            "in": "query",
            "required": false,
            "description": "Only this row (collection). None: every row.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_]{1,64}$"
            },
            "example": "uncommon"
          },
          {
            "name": "sub",
            "in": "query",
            "required": false,
            "description": "A rarer sub-category of `row` (e.g. `pizza_uncommon` under `uncommon`): only items holding sats of it. Implies `subs=1`.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_]{1,64}$"
            }
          },
          {
            "name": "subs",
            "in": "query",
            "required": false,
            "description": "`1` includes the row's sub-category items (sold or listed under their own rows).",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "0"
            }
          },
          {
            "name": "led",
            "in": "query",
            "required": false,
            "description": "With `row`: `1` adds the sales led by another row that sold sats of it (every other row a sale sold sats of is one of its secondary rows), each with `led: true`. A collection's Activity asks `subs=1&led=1`: every sale that sold a sat of the row.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "0"
            }
          },
          {
            "name": "years",
            "in": "query",
            "required": false,
            "description": "Mint years, comma-separated (`2009,2010`; up to 40): items holding a sat mined in one of them. Each must be a year sats were mined in, 2009 to this one (400 otherwise); repeats and order do not matter. `year` is accepted too.",
            "schema": {
              "type": "string"
            },
            "example": "2009"
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "A mint month, `YYYY-MM` (UTC, by each block's own time): items holding a sat mined that month. Combines with the other filters.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
            },
            "example": "2017-12"
          },
          {
            "name": "blocks",
            "in": "query",
            "required": false,
            "description": "A block range: heights `from-to`, inclusive (`1000-5000`), or one block (`9`): items holding a sat mined in those blocks. Up to the tip (400 past it or for a malformed or reversed range). Combines with the other filters.",
            "schema": {
              "type": "string",
              "pattern": "^(0|[1-9]\\d{0,6})(-(0|[1-9]\\d{0,6}))?$"
            },
            "example": "1000-5000"
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "A mint day, `YYYY-MM-DD` (UTC), 2009 to this year: items holding a sat mined that day. Exclusive with `md`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "md",
            "in": "query",
            "required": false,
            "description": "A month-day, `MM-DD`: items holding a sat mined that day of any year (with `years`, of those years). Birthday sats.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "luck",
            "in": "query",
            "required": false,
            "description": "Sat luck, a minimum (`8`: luck 8 or more) or an inclusive range (`8-12`), 0 to 254: items holding a sat of that luck. A sat's luck is its block's: the leading zero bits of the block hash less those of the block's target. Combines with the other filters (the matched sat passes them all). 503 for the few seconds after a first start while the luck of every block is read.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{1,3}(-\\d{1,3})?$"
            },
            "example": "8"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1-200.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            },
            "example": 2
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "description": "A sequence number: only older sales (the previous page's `next`).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalesQuery"
                }
              }
            }
          },
          "400": {
            "description": "A malformed parameter (e.g. a `date` that is no date, `date` with `md`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "404": {
            "description": "An unknown `row` or `sub`. A retired row (`uncommon_2009`, `rare_2009`) answers 404 too, its `retired` field naming the row and years to ask for instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                },
                "examples": {
                  "retired": {
                    "summary": "A retired row",
                    "value": {
                      "error": "row uncommon_2009 is retired: ask for row uncommon with years 2009",
                      "retired": {
                        "row": "uncommon_2009",
                        "successor": {
                          "row": "uncommon",
                          "years": [
                            2009
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many new filtered answers (each a pass over every sale) from your network (an IPv4 address or IPv6 /64), or from everyone at once: `retry: true`; try again after `Retry-After` seconds. Answers already built are served all the same.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until a new one is taken.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "503": {
            "description": "Mint dates or sat luck are still being read (`retry: true`): try again in a few seconds. Without `retry`: this server has no sat luck for its chain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/listings/query": {
      "get": {
        "operationId": "queryListings",
        "tags": [
          "Listings"
        ],
        "summary": "Query listings by row, sub-category and mint date",
        "description": "Active marketplace listings filtered like `/api/sales/query`, sorted like `/api/market/listings`, with facets. Not cached. 404 `{enabled: false}` while the marketplace is off.",
        "parameters": [
          {
            "name": "row",
            "in": "query",
            "required": false,
            "description": "Only this row (collection). None: every row.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_]{1,64}$"
            },
            "example": "uncommon"
          },
          {
            "name": "sub",
            "in": "query",
            "required": false,
            "description": "A rarer sub-category of `row` (e.g. `pizza_uncommon` under `uncommon`): only items holding sats of it. Implies `subs=1`.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_]{1,64}$"
            }
          },
          {
            "name": "subs",
            "in": "query",
            "required": false,
            "description": "`1` includes the row's sub-category items (sold or listed under their own rows).",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ],
              "default": "0"
            }
          },
          {
            "name": "contains",
            "in": "query",
            "required": false,
            "description": "With `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.",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1",
                "only"
              ],
              "default": "0"
            }
          },
          {
            "name": "years",
            "in": "query",
            "required": false,
            "description": "Mint years, comma-separated (`2009,2010`; up to 40): items holding a sat mined in one of them. Each must be a year sats were mined in, 2009 to this one (400 otherwise); repeats and order do not matter. `year` is accepted too.",
            "schema": {
              "type": "string"
            },
            "example": "2009"
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "A mint month, `YYYY-MM` (UTC, by each block's own time): items holding a sat mined that month. Combines with the other filters.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
            },
            "example": "2017-12"
          },
          {
            "name": "blocks",
            "in": "query",
            "required": false,
            "description": "A block range: heights `from-to`, inclusive (`1000-5000`), or one block (`9`): items holding a sat mined in those blocks. Up to the tip (400 past it or for a malformed or reversed range). Combines with the other filters.",
            "schema": {
              "type": "string",
              "pattern": "^(0|[1-9]\\d{0,6})(-(0|[1-9]\\d{0,6}))?$"
            },
            "example": "1000-5000"
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "A mint day, `YYYY-MM-DD` (UTC), 2009 to this year: items holding a sat mined that day. Exclusive with `md`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "md",
            "in": "query",
            "required": false,
            "description": "A month-day, `MM-DD`: items holding a sat mined that day of any year (with `years`, of those years). Birthday sats.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "luck",
            "in": "query",
            "required": false,
            "description": "Sat luck, a minimum (`8`: luck 8 or more) or an inclusive range (`8-12`), 0 to 254: items holding a sat of that luck. A sat's luck is its block's: the leading zero bits of the block hash less those of the block's target. Combines with the other filters (the matched sat passes them all). 503 for the few seconds after a first start while the luck of every block is read.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{1,3}(-\\d{1,3})?$"
            },
            "example": "8"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "`unit`, `price` or `new`.",
            "schema": {
              "type": "string",
              "enum": [
                "unit",
                "price",
                "new"
              ],
              "default": "unit"
            }
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "description": "`asc` or `desc`. Default: `asc`, except `desc` for `sort=new`.",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1-200.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Listings to skip, 0-100,000.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100000,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListingsQuery"
                }
              }
            }
          },
          "400": {
            "description": "A malformed parameter (e.g. a `date` that is no date, `date` with `md`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "404": {
            "description": "An unknown `row` or `sub`, or the marketplace is off (`enabled: false`). A retired row (`uncommon_2009`, `rare_2009`) answers 404 too, its `retired` field naming the row and years to ask for instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                },
                "examples": {
                  "retired": {
                    "summary": "A retired row",
                    "value": {
                      "error": "row uncommon_2009 is retired: ask for row uncommon with years 2009",
                      "retired": {
                        "row": "uncommon_2009",
                        "successor": {
                          "row": "uncommon",
                          "years": [
                            2009
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Mint dates or sat luck are still being read (`retry: true`): try again in a few seconds. Without `retry`: this server has no sat luck for its chain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/listings/events": {
      "get": {
        "operationId": "queryListingEvents",
        "tags": [
          "Listings"
        ],
        "summary": "Query marketplace activity by row and mint date",
        "description": "The marketplace's listed, cancelled and sold events of listings that pass the filter, newest first (the newest 2,000 events searched). Not cached. 404 while the marketplace is off.",
        "parameters": [
          {
            "name": "row",
            "in": "query",
            "required": false,
            "description": "Only this row (collection). None: every row. Events of every listing under the row, any kind (marked `sub` or `in_bundle` when its own row is another).",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_]{1,64}$"
            },
            "example": "uncommon"
          },
          {
            "name": "sub",
            "in": "query",
            "required": false,
            "description": "A rarer sub-category of `row` (e.g. `pizza_uncommon` under `uncommon`): only items holding sats of it. Implies `subs=1`.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_]{1,64}$"
            }
          },
          {
            "name": "years",
            "in": "query",
            "required": false,
            "description": "Mint years, comma-separated (`2009,2010`; up to 40): items holding a sat mined in one of them. Each must be a year sats were mined in, 2009 to this one (400 otherwise); repeats and order do not matter. `year` is accepted too.",
            "schema": {
              "type": "string"
            },
            "example": "2009"
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "A mint month, `YYYY-MM` (UTC, by each block's own time): items holding a sat mined that month. Combines with the other filters.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
            },
            "example": "2017-12"
          },
          {
            "name": "blocks",
            "in": "query",
            "required": false,
            "description": "A block range: heights `from-to`, inclusive (`1000-5000`), or one block (`9`): items holding a sat mined in those blocks. Up to the tip (400 past it or for a malformed or reversed range). Combines with the other filters.",
            "schema": {
              "type": "string",
              "pattern": "^(0|[1-9]\\d{0,6})(-(0|[1-9]\\d{0,6}))?$"
            },
            "example": "1000-5000"
          },
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "A mint day, `YYYY-MM-DD` (UTC), 2009 to this year: items holding a sat mined that day. Exclusive with `md`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "md",
            "in": "query",
            "required": false,
            "description": "A month-day, `MM-DD`: items holding a sat mined that day of any year (with `years`, of those years). Birthday sats.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "luck",
            "in": "query",
            "required": false,
            "description": "Sat luck, a minimum (`8`: luck 8 or more) or an inclusive range (`8-12`), 0 to 254: items holding a sat of that luck. A sat's luck is its block's: the leading zero bits of the block hash less those of the block's target. Combines with the other filters (the matched sat passes them all). 503 for the few seconds after a first start while the luck of every block is read.",
            "schema": {
              "type": "string",
              "pattern": "^\\d{1,3}(-\\d{1,3})?$"
            },
            "example": "8"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Events, 1-200.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 60
            },
            "example": 5
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListingEvents"
                }
              }
            }
          },
          "400": {
            "description": "A malformed parameter (e.g. a `date` that is no date, `date` with `md`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "404": {
            "description": "An unknown `row` or `sub`, or the marketplace is off (`enabled: false`). A retired row (`uncommon_2009`, `rare_2009`) answers 404 too, its `retired` field naming the row and years to ask for instead.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                },
                "examples": {
                  "retired": {
                    "summary": "A retired row",
                    "value": {
                      "error": "row uncommon_2009 is retired: ask for row uncommon with years 2009",
                      "retired": {
                        "row": "uncommon_2009",
                        "successor": {
                          "row": "uncommon",
                          "years": [
                            2009
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Mint dates or sat luck are still being read (`retry: true`): try again in a few seconds. Without `retry`: this server has no sat luck for its chain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/birthday/counts": {
      "get": {
        "operationId": "getBirthdayCounts",
        "tags": [
          "Market data"
        ],
        "summary": "Count the sats mined on a day",
        "description": "Per row, how many tracked sats were mined on a UTC day (`date`), or on that month-day of every year (`md`, optionally only `years`), that the index locates. Cacheable 30 s; a cold day can take a few seconds.",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "A day, `YYYY-MM-DD`. One of `date` and `md` is required.",
            "schema": {
              "type": "string"
            },
            "example": "2009-01-09"
          },
          {
            "name": "md",
            "in": "query",
            "required": false,
            "description": "A month-day, `MM-DD`: that day of every year.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "years",
            "in": "query",
            "required": false,
            "description": "With `md`: only these years, comma-separated.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BirthdayCounts"
                },
                "example": {
                  "filter": {
                    "years": [],
                    "date": "2009-01-09",
                    "md": null,
                    "luck": null,
                    "sub": null
                  },
                  "days": [
                    {
                      "date": "2009-01-09",
                      "from": 470,
                      "to": 559,
                      "rows": {
                        "vintage_alpha": 3,
                        "vintage_omega": 1
                      }
                    }
                  ],
                  "rows": {
                    "vintage_alpha": 3,
                    "vintage_omega": 1
                  },
                  "ms": 749
                }
              }
            }
          },
          "400": {
            "description": "Neither `date` nor `md`, or a malformed one.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          },
          "503": {
            "description": "Mint dates are still being read (`retry: true`), or the index is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    },
    "/api/days": {
      "get": {
        "operationId": "getDays",
        "tags": [
          "Market data"
        ],
        "summary": "Get the mint-day table",
        "description": "Which UTC day mined each block, compactly: what the site uses to date sats in the browser. A sat's mint day is the day of its block. Cacheable 30 s.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Days"
                }
              }
            }
          }
        }
      }
    },
    "/healthz": {
      "get": {
        "operationId": "getHealth",
        "tags": [
          "Site feeds"
        ],
        "summary": "Health probe",
        "description": "`{ok, fork, mode, height, tip}`: `fork` is `up`, `stale` or `down`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "Always true when the dashboard answers."
                    },
                    "fork": {
                      "type": "string",
                      "description": "The index.",
                      "enum": [
                        "up",
                        "stale",
                        "down"
                      ]
                    },
                    "mode": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The index's mode."
                    },
                    "height": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "The index's height."
                    },
                    "tip": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "The dashboard's tip."
                    }
                  },
                  "required": [
                    "ok",
                    "fork",
                    "mode",
                    "height",
                    "tip"
                  ]
                },
                "example": {
                  "ok": true,
                  "fork": "up",
                  "mode": "live",
                  "height": 969001,
                  "tip": 969001
                }
              }
            }
          }
        }
      }
    },
    "/api/session": {
      "get": {
        "operationId": "getSession",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Get the chat session",
        "description": "The session of the request's `__Host-rs_chat` cookie: the signed-in address, its name and whether it is an admin or banned; `address` null when signed out. A browser's page uses it to know whether chat is on (off: 404 `chat_disabled`).",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatSession"
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "chat_disabled",
          "method_not_allowed"
        ]
      },
      "post": {
        "operationId": "signIn",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Sign in to chat",
        "description": "Opens a chat session from a BIP-322 signature of `raresats.net login <address> <nonce> <unix seconds>`, the nonce from [Get a login nonce](/docs/chat-sessions#get-a-login-nonce). Sets the session cookie `__Host-rs_chat` (HttpOnly, Secure, SameSite=Lax, Path=/, 30 days). The nonce and the message are each usable once; the message at most 10 minutes old. At most 20 sign-ins an hour per IPv4 address or IPv6 /64.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              },
              "example": {
                "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                "message": "raresats.net login bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh 9f2c41d07a5be3816c0d4f27e9a1b358 1790949400",
                "signature": "AUBGQvdc2H+7HTo1njZ1vlDxoX6ncoehAGbaHcAY1FtfSNg7lmo8Ih3WGInhAH/snOUIb8DkwRSQxc2dOu911Z9E"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatSession"
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "bad_nonce": {
                    "summary": "Nonce used or expired",
                    "value": {
                      "error": "that nonce was not handed out for this address, has expired or was used: ask for a new one",
                      "code": "bad_nonce"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "method_not_allowed",
          "chat_disabled",
          "bad_request",
          "bad_address",
          "bad_message",
          "bad_signature",
          "stale_message",
          "future_message",
          "bad_nonce",
          "replayed"
        ]
      },
      "delete": {
        "operationId": "signOut",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Sign out of chat",
        "description": "Ends the cookie's session and clears the cookie. Answers the signed-out session.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatSession"
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "method_not_allowed",
          "chat_disabled"
        ]
      }
    },
    "/api/session/nonce": {
      "get": {
        "operationId": "getLoginNonce",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Get a login nonce",
        "description": "A nonce for an address to sign in with: usable once, for 10 minutes, by that address only. Same-origin, and limited to 20 a minute per IPv4 address or IPv6 /64.",
        "parameters": [
          {
            "name": "address",
            "in": "query",
            "required": true,
            "description": "The address that will sign.",
            "schema": {
              "type": "string"
            },
            "example": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoginNonce"
                },
                "example": {
                  "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                  "nonce": "9f2c41d07a5be3816c0d4f27e9a1b358",
                  "expires_at": 1790950000,
                  "message": "raresats.net login bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh 9f2c41d07a5be3816c0d4f27e9a1b358 <unix seconds>"
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "bad_address",
          "method_not_allowed",
          "chat_disabled"
        ]
      }
    },
    "/api/profile": {
      "post": {
        "operationId": "setProfile",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Set a display name",
        "description": "Sets (or, with an empty name, clears) an address's display name. **Every change needs its own BIP-322 signature** by the address of `raresats.net profile <address> display_name=<name> <unix seconds>`, at most 10 minutes old and usable once; a chat session is not enough. 3-24 characters of letters, digits, spaces and `_ . -`; unique; no address-like or reserved names; at most one change in 24 hours. A banned address may not set one; the hourly cap is 10 changes per IPv4 address or IPv6 /64. Where the AI moderation is on, a new name is checked last, before it is taken (names show site-wide): refused, 422 `moderated`; not checked, 503 `moderation_unavailable` (the signed message is not used up: send it again).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProfileRequest"
              },
              "example": {
                "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                "display_name": "Rare Hunter",
                "message": "raresats.net profile bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh display_name=Rare Hunter 1790949400",
                "signature": "AUBGQvdc2H+7HTo1njZ1vlDxoX6ncoehAGbaHcAY1FtfSNg7lmo8Ih3WGInhAH/snOUIb8DkwRSQxc2dOu911Z9E"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "profile": {
                      "$ref": "#/components/schemas/Profile"
                    }
                  },
                  "required": [
                    "profile"
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "name_taken": {
                    "summary": "Taken",
                    "value": {
                      "error": "that display name is taken",
                      "code": "name_taken"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The AI moderation could not check the text: nothing was done. Try again in a moment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "moderation_unavailable": {
                    "summary": "Not checked",
                    "value": {
                      "error": "Couldn't check your display name right now: try again in a moment",
                      "code": "moderation_unavailable"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "method_not_allowed",
          "chat_disabled",
          "bad_request",
          "bad_address",
          "bad_message",
          "bad_signature",
          "stale_message",
          "future_message",
          "replayed",
          "name_length",
          "name_chars",
          "name_address",
          "name_reserved",
          "name_taken",
          "name_change_too_soon",
          "unchanged",
          "banned",
          "muted",
          "moderated",
          "moderation_unavailable",
          "chat_busy"
        ]
      }
    },
    "/api/profile/{address}": {
      "get": {
        "operationId": "getProfile",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Get a profile",
        "description": "An address's display name (null when it has none), whether it is a chat admin, and when its name may change next.",
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "description": "A mainnet address.",
            "schema": {
              "type": "string"
            },
            "example": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Profile"
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "bad_address",
          "bad_path",
          "method_not_allowed",
          "chat_disabled"
        ]
      },
      "delete": {
        "operationId": "clearProfile",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Remove a display name (admin)",
        "description": "An admin session removes an address's display name. The name is never given out again, to anyone. Pages are told with a `profile` event. Logged.",
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "description": "A mainnet address.",
            "schema": {
              "type": "string"
            },
            "example": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "profile": {
                      "$ref": "#/components/schemas/Profile"
                    },
                    "removed": {
                      "type": "string",
                      "description": "The name removed."
                    }
                  },
                  "required": [
                    "profile",
                    "removed"
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "method_not_allowed",
          "chat_disabled",
          "no_session",
          "not_admin",
          "bad_address",
          "not_found",
          "bad_path"
        ]
      }
    },
    "/api/profiles": {
      "get": {
        "operationId": "getProfiles",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Get display names",
        "description": "The display names of up to 200 addresses at once; addresses without one (or that are no address) are left out. Cached 15 s.",
        "parameters": [
          {
            "name": "addresses",
            "in": "query",
            "required": true,
            "description": "Comma-separated addresses, at most 200.",
            "schema": {
              "type": "string"
            },
            "example": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh,bc1qm34lsc65zpw79lxes69zkqmk6ee3ewf0j77s3h"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Profiles"
                },
                "example": {
                  "profiles": {
                    "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh": "Rare Hunter"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "bad_addresses",
          "method_not_allowed",
          "chat_disabled"
        ]
      }
    },
    "/api/chat/topics": {
      "get": {
        "operationId": "getChatTopics",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "List chat topics",
        "description": "The live topics, in their order, each with its newest message's id and time: a page keeps the last id it read per topic and shows the others as unread. New and archived topics come as `chat` events `{type: \"topic\", topic, archived}`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "topics": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ChatTopic"
                      }
                    }
                  },
                  "required": [
                    "topics"
                  ]
                },
                "example": {
                  "topics": [
                    {
                      "id": "general",
                      "name": "General",
                      "description": "Anything rare-sat: say gm, ask, share a find.",
                      "position": 0,
                      "created_at": 1790900000,
                      "last_message_id": 1044,
                      "last_activity_at": 1790949460
                    },
                    {
                      "id": "market",
                      "name": "Market & prices",
                      "description": "Listings, offers, floors and what things sell for.",
                      "position": 1,
                      "created_at": 1790900000,
                      "last_message_id": 1042,
                      "last_activity_at": 1790949400
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "method_not_allowed",
          "chat_disabled"
        ]
      },
      "post": {
        "operationId": "createChatTopic",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Create a chat topic (admin)",
        "description": "An admin session creates a topic, last in the list. Only admins may: topic names are not run through the AI moderation (an admin's text never is), but follow a message's text rules (NFC, no control, zero-width or bidi characters) and its link rule. An id is never reused, an archived topic's included, except a retired one's (a topic the defaults once seeded and no longer name): it comes back as the new topic, its messages with it. At most 50 topics. Pages are told with a `chat` event `{type: \"topic\", topic, archived: false}`. Logged.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "1-32 of a-z, 0-9 and inner hyphens; not `main`."
                  },
                  "name": {
                    "type": "string",
                    "description": "1-40 characters."
                  },
                  "description": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "At most 140 characters."
                  }
                },
                "required": [
                  "id",
                  "name"
                ]
              },
              "example": {
                "id": "runes",
                "name": "Runes",
                "description": "Runes on rare sats, and what they do to a sat's value."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "topic": {
                      "$ref": "#/components/schemas/ChatTopic"
                    }
                  },
                  "required": [
                    "topic"
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "method_not_allowed",
          "chat_disabled",
          "bad_request",
          "no_session",
          "not_admin",
          "bad_topic",
          "bad_topic_text",
          "suspicious_link",
          "too_many_topics",
          "topic_exists"
        ]
      }
    },
    "/api/chat/topics/{id}": {
      "delete": {
        "operationId": "archiveChatTopic",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Archive a chat topic (admin)",
        "description": "An admin session archives a topic: it leaves the list and takes no new messages or replies (404 `unknown_topic`); its messages stay in the store. General cannot be archived. Pages are told with a `chat` event `{type: \"topic\", topic, archived: true}`. Logged.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The topic's id.",
            "schema": {
              "type": "string"
            },
            "example": "off-topic"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "topic": {
                      "$ref": "#/components/schemas/ChatTopic"
                    },
                    "archived": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "topic",
                    "archived"
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "method_not_allowed",
          "chat_disabled",
          "no_session",
          "not_admin",
          "bad_topic",
          "unknown_topic",
          "not_archivable",
          "bad_path"
        ]
      }
    },
    "/api/chat/messages": {
      "get": {
        "operationId": "getChatMessages",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "List chat messages",
        "description": "A topic's messages (the threads' roots), newest first, with each author's current display name and each thread's reply count and last reply time. Without `topic`, General's (`main`, the one room before topics, names General too). Replies are on their thread: [List a thread](/docs/chat-messages#list-a-thread). Page back with `before`. Messages are kept 30 days, at most 10,000 a topic.",
        "parameters": [
          {
            "name": "topic",
            "in": "query",
            "required": false,
            "description": "A topic id ([List topics](/docs/chat-messages#list-topics)); default `general`.",
            "schema": {
              "type": "string",
              "default": "general"
            },
            "example": "market"
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "description": "A message id: only older ones (the previous page's `next`).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Messages per page, 1-100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatPage"
                },
                "example": {
                  "topic": "market",
                  "room": "market",
                  "messages": [
                    {
                      "id": 1042,
                      "topic": "market",
                      "room": "market",
                      "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                      "display_name": "Rare Hunter",
                      "admin": false,
                      "text": "gm, any block 9 for sale?",
                      "created_at": 1790949400,
                      "reply_to": null,
                      "reply_count": 2,
                      "last_reply_at": 1790949460,
                      "quote": null
                    }
                  ],
                  "next": 1042
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "bad_paging",
          "method_not_allowed",
          "chat_disabled",
          "bad_topic",
          "unknown_topic"
        ]
      },
      "post": {
        "operationId": "postChatMessage",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Post a chat message",
        "description": "Posts as the session's address (the `__Host-rs_chat` cookie of [Sign in](/docs/chat-sessions#sign-in-to-chat)), in a topic (`topic`, default `general`) or, with `reply_to`, as a reply in its root's topic: one level of threads, so a reply to a reply joins its root's thread (and quotes the reply it answered). Plain text: normalized to NFC, control, zero-width and bidi characters dropped, line breaks made spaces; 1-500 characters. One message every 3 s and 20 a minute per address; the same text twice within 2 minutes is refused; the whole chat takes at most 5 messages a second (429 `room_busy`). A link must name a plain ASCII host (422 `suspicious_link`). Then, where the AI moderation is on (the session's `moderated`), the text is checked before it is posted: refused, 422 `moderated` with its `category`; when it cannot be checked, 503 `moderation_unavailable` and nothing is posted (try again); 3 refusals in 10 minutes mute the address for an hour, and 6 from one IPv4 address or IPv6 /48 within an hour pause that network (403 `muted`); at most 6 texts a minute are checked per address and per network (429 `rate_limited`). Delivered live as a `chat` event on `/api/events`, which names the topic; a reply's answer and event carry its root's new `thread` counts.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "description": "The message."
                  },
                  "topic": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The topic's id; absent or null: `general`. With `reply_to` it may be left out; given, it must be the root's topic."
                  },
                  "reply_to": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "Reply to this message (a root, or a reply: the reply joins its root's thread, in its topic). Absent or null: a new message in the topic."
                  }
                },
                "required": [
                  "text"
                ]
              },
              "example": {
                "text": "I have two, 0.0021 each",
                "topic": "market",
                "reply_to": 1042
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "$ref": "#/components/schemas/ChatMessage"
                    },
                    "thread": {
                      "$ref": "#/components/schemas/ChatThreadSummary",
                      "description": "On a reply: its root's thread now."
                    }
                  },
                  "required": [
                    "message"
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "moderated": {
                    "summary": "Refused by the AI moderation",
                    "value": {
                      "error": "Your message was not posted: it looks like a scam or phishing.",
                      "code": "moderated",
                      "category": "scam"
                    }
                  },
                  "muted": {
                    "summary": "Muted",
                    "value": {
                      "error": "this address is muted and may not post in chat until 2026-10-02T13:00:00Z",
                      "code": "muted",
                      "until": 1790946000
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The AI moderation could not check the text: nothing was done. Try again in a moment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "moderation_unavailable": {
                    "summary": "Not checked",
                    "value": {
                      "error": "Couldn't check your message right now: try again in a moment",
                      "code": "moderation_unavailable"
                    }
                  }
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "method_not_allowed",
          "chat_disabled",
          "bad_request",
          "no_session",
          "banned",
          "empty_text",
          "text_too_long",
          "duplicate",
          "room_busy",
          "not_found",
          "muted",
          "moderated",
          "moderation_unavailable",
          "chat_busy",
          "suspicious_link",
          "bad_topic",
          "unknown_topic"
        ]
      }
    },
    "/api/chat/messages/{id}": {
      "delete": {
        "operationId": "deleteChatMessage",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Delete a chat message (admin)",
        "description": "An admin session deletes a message. Deleting a thread's root deletes its replies too (`deleted` lists them all). Pages are told with a `chat` event `{type: \"delete\", ids, threads, topics}`. Logged.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The message id.",
            "schema": {
              "type": "integer"
            },
            "example": 1042
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      }
                    }
                  },
                  "required": [
                    "deleted"
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "method_not_allowed",
          "chat_disabled",
          "no_session",
          "not_admin",
          "not_found",
          "bad_path"
        ]
      }
    },
    "/api/chat/messages/{id}/replies": {
      "get": {
        "operationId": "getChatReplies",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "List a thread",
        "description": "A thread: its root (with its reply count) and its replies, newest first, each with its author's current display name and the message it answered (`quote`). Page back with `before`. The id of a reply names its thread too. The answer names the thread's `topic`: a link to a message (`/chat/<topic>?m=<id>`) finds its page and thread from it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The thread's root (or one of its replies).",
            "schema": {
              "type": "integer"
            },
            "example": 1042
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "description": "A reply id: only older ones (the previous page's `next`).",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Replies per page, 1-100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "example": 50
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatThread"
                },
                "example": {
                  "topic": "market",
                  "room": "market",
                  "root": {
                    "id": 1042,
                    "topic": "market",
                    "room": "market",
                    "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                    "display_name": "Rare Hunter",
                    "admin": false,
                    "text": "gm, any block 9 for sale?",
                    "created_at": 1790949400,
                    "reply_to": null,
                    "reply_count": 2,
                    "last_reply_at": 1790949460,
                    "quote": null
                  },
                  "messages": [
                    {
                      "id": 1044,
                      "topic": "market",
                      "room": "market",
                      "address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
                      "display_name": null,
                      "admin": false,
                      "text": "I have two, 0.0021 each",
                      "created_at": 1790949460,
                      "reply_to": 1042,
                      "reply_count": 0,
                      "last_reply_at": null,
                      "quote": {
                        "id": 1042,
                        "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
                        "display_name": "Rare Hunter",
                        "text": "gm, any block 9 for sale?"
                      }
                    }
                  ],
                  "next": null
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "bad_paging",
          "not_found",
          "bad_path",
          "method_not_allowed",
          "chat_disabled"
        ]
      }
    },
    "/api/chat/bans": {
      "get": {
        "operationId": "getChatBans",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "List chat bans (admin)",
        "description": "The banned addresses, newest first. An admin session only.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "bans": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ChatBan"
                      }
                    }
                  },
                  "required": [
                    "bans"
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "method_not_allowed",
          "chat_disabled",
          "no_session",
          "not_admin"
        ]
      },
      "post": {
        "operationId": "setChatBan",
        "tags": [
          "Chat & profiles"
        ],
        "summary": "Ban or unban an address (admin)",
        "description": "An admin session bans (`banned: true`) or unbans an address. A banned address cannot post or set a display name, and a ban removes its display name for good. `delete_recent` also deletes its messages of the last 24 hours. Logged.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "address": {
                    "type": "string"
                  },
                  "banned": {
                    "type": "boolean"
                  },
                  "reason": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "At most 200 characters."
                  },
                  "delete_recent": {
                    "type": "boolean",
                    "description": "Also delete its messages of the last 24 hours."
                  }
                },
                "required": [
                  "address",
                  "banned"
                ]
              },
              "example": {
                "address": "bc1qm34lsc65zpw79lxes69zkqmk6ee3ewf0j77s3h",
                "banned": true,
                "reason": "spam",
                "delete_recent": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "address": {
                      "type": "string"
                    },
                    "banned": {
                      "type": "boolean"
                    },
                    "ban": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/ChatBan"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "deleted": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      },
                      "description": "The messages deleted with it."
                    }
                  },
                  "required": [
                    "address",
                    "banned",
                    "ban",
                    "deleted"
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "Refused; see `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-error-codes": [
          "rate_limited",
          "cross_origin",
          "not_json",
          "too_large",
          "bad_json",
          "method_not_allowed",
          "chat_disabled",
          "bad_request",
          "bad_address",
          "no_session",
          "not_admin",
          "not_bannable"
        ]
      }
    },
    "/api/pending": {
      "get": {
        "operationId": "getPending",
        "tags": [
          "Site feeds"
        ],
        "summary": "Get what is pending in the mempool",
        "description": "Every pending sale, notable transfer and extraction of transactions still in the mempool, the live listings being spent, and the transactions that left the mempool lately, from the index's mempool overlay (polled every 5 s). Pending items are marked `pending: true` with `first_seen` and `fee_rate`, and count in no stat. A pending sale is `txid:vin`, a move its `txid`: the confirmed record with the same key replaces it. The SSE `mempool` event says when to read it again. `available` is false against an index without the overlay.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pending"
                }
              }
            }
          }
        }
      }
    },
    "/api/types": {
      "get": {
        "operationId": "getTypes",
        "tags": [
          "Site feeds"
        ],
        "summary": "List the sat type explainers",
        "description": "Every explainer page of `/types` (one per sat type, category and concept), by section: `sections` (`[{id, label, pages: [{slug, title, summary, href}]}]`), and which page explains each row (`rows`: `{rowId: slug}`) and each sat type (`badges`: `{type: slug}`). The text comes from the site's own pages; the page is `/types/{slug}`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A JSON object; see the description for its main fields.",
                  "additionalProperties": true
                },
                "example": {
                  "sections": [
                    {
                      "id": "rarity",
                      "label": "Rarity tiers",
                      "pages": [
                        {
                          "slug": "uncommon",
                          "title": "Uncommon",
                          "summary": "The first sat of a block: the lowest rarity tier above common in ordinal theory, one per block bar the few whose first sat ranks higher.",
                          "href": "/types/uncommon"
                        }
                      ]
                    }
                  ],
                  "rows": {
                    "uncommon": "uncommon"
                  },
                  "badges": {
                    "uncommon": "uncommon"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/types/{slug}": {
      "get": {
        "operationId": "getType",
        "tags": [
          "Site feeds"
        ],
        "summary": "Get one sat type explainer",
        "description": "One explainer: `slug`, `title`, `summary`, `kind` and `kind_label` (its section), `badges` (the sat types it explains), `body` (its text as a tree of blocks: `{t: 'h3'|'h4', id, c}`, `{t: 'p', c}`, `{t: 'ul'|'ol', items: [c]}`, where `c` lists inlines: a string, `{t: 'a', href, c, ext?}`, `{t: 'b'|'i', c}`, `{t: 'code', text}` or `{t: 'n', row, field}`, a live number found in `numbers[row][field]`), `rows` (the categories it explains, each with `total`, `mined`, `extracted`, `holders`, `inscribed` and `market`: `last_unit_price`, `median_30d`, `sales`, and while the marketplace is on `floor_unit` and `listed`), `also_in` (other categories holding its types), `related` pages and `as_of` (the block the numbers are of).",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "The page's slug, as `/api/types` lists them.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
            },
            "example": "uncommon"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A JSON object; see the description for its main fields.",
                  "additionalProperties": true
                }
              }
            }
          },
          "404": {
            "description": "No such page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "description": "The error object of every `/api/market/*` route. Some codes carry extra fields.",
        "properties": {
          "error": {
            "type": "string",
            "description": "A human-readable message. Show it; do not parse it."
          },
          "code": {
            "type": "string",
            "description": "A stable machine-readable reason (see the error code table)."
          },
          "outpoint": {
            "type": "string",
            "description": "The outpoint the error is about, when there is one."
          },
          "id": {
            "type": "string",
            "description": "The listing the error is about, when there is one."
          },
          "status": {
            "type": "string",
            "description": "That listing's status (`not_active`)."
          },
          "txid": {
            "type": "string",
            "description": "The purchase transaction (`broadcast_unknown`)."
          },
          "setup_txid": {
            "type": "string",
            "description": "The setup transaction, when it was already broadcast (`conflict`, `rejected`)."
          },
          "reason": {
            "type": "string",
            "description": "bitcoind's rejection reason (`conflict`, `rejected`)."
          },
          "available": {
            "type": "integer",
            "description": "Sats the payment address can spend (`insufficient_funds`)."
          },
          "prices": {
            "type": "integer",
            "description": "Sum of the listing prices (`insufficient_funds`)."
          },
          "platform_fee": {
            "type": "integer",
            "description": "The platform fee (`insufficient_funds`)."
          },
          "violations": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "rule": {
                  "type": "string",
                  "description": "The rule broken"
                },
                "message": {
                  "type": "string",
                  "description": "What is wrong"
                }
              },
              "required": [
                "rule",
                "message"
              ]
            },
            "description": "Broken purchase invariants (`invariant_violated`)."
          },
          "next_change_at": {
            "type": "integer",
            "description": "When the address may change its display name again, unix seconds (`name_change_too_soon`)."
          },
          "retired": {
            "$ref": "#/components/schemas/RetiredRow",
            "description": "On a 404 for a retired row (`retired_row`): the row and where its sats are now."
          },
          "category": {
            "type": "string",
            "description": "Why the AI moderation refused the text (`moderated`): harassment, hate, sexual, violence, doxxing, scam, spam, malware, illegal, impersonation, manipulation or other."
          },
          "until": {
            "type": "integer",
            "description": "When the mute ends, unix seconds (`muted`; on `moderated` when that refusal muted the address)."
          }
        },
        "required": [
          "error",
          "code"
        ]
      },
      "PlainError": {
        "type": "object",
        "description": "The error object of the data routes (everything outside `/api/market/*`): a message, no code.",
        "properties": {
          "error": {
            "type": "string",
            "description": "A human-readable message."
          },
          "retired": {
            "$ref": "#/components/schemas/RetiredRow",
            "description": "On a 404 for a retired row: the row and where its sats are now."
          }
        },
        "required": [
          "error"
        ]
      },
      "TypeGroup": {
        "type": "object",
        "description": "A UTXO's (or a sale's) tracked sats grouped by exact type combination, rarest first (what the site's badges draw).",
        "properties": {
          "types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The exact combination of sat types these sats share (e.g. `[\"block9\", \"nakamoto\", \"vintage\"]`)."
          },
          "count": {
            "type": "integer",
            "description": "How many of the UTXO's (the sale's) tracked sats have exactly these types."
          },
          "sats": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Sample sat numbers of the group, ascending: its first 3 (an address's or a UTXO's page). A listing or an offer names up to 100: its first 3, then the first sat of each further run, so every special sat of a group of up to 100 (a whole range's run adds only its first sat).",
            "maxItems": 100
          },
          "inscribed": {
            "type": "integer",
            "description": "How many of them carry an inscription (absent when none)."
          }
        },
        "required": [
          "types",
          "count",
          "sats"
        ],
        "additionalProperties": false
      },
      "AsOf": {
        "type": [
          "object",
          "null"
        ],
        "description": "When the marketplace last checked every live listing against the chain: the block height and unix seconds. `null` until the first check.",
        "properties": {
          "height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Block height"
          },
          "checked_at": {
            "type": "integer",
            "description": "Unix seconds"
          }
        },
        "required": [
          "height",
          "checked_at"
        ],
        "additionalProperties": false
      },
      "Listing": {
        "type": "object",
        "description": "A listing: one UTXO for sale at a fixed price. The seller's signature is never part of it.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The listing id: 16 lowercase hex characters.",
            "pattern": "^[0-9a-f]{16}$"
          },
          "outpoint": {
            "type": "string",
            "description": "The listed UTXO, `txid:vout`.",
            "pattern": "^[0-9a-f]{64}:\\d+$"
          },
          "value": {
            "type": "integer",
            "description": "The UTXO's own value in sats (it moves to the buyer whole)."
          },
          "price": {
            "type": "integer",
            "description": "The listing price in sats: exactly what the seller receives. The buyer pays this plus the platform fee and the network fee."
          },
          "unit_price": {
            "type": "number",
            "description": "Price per sat of the listing's own row: `(price - value) / count`, to the hundredth of a sat. Floors and the `unit` sort use it."
          },
          "row": {
            "type": "string",
            "description": "The listing's own row (collection): the rarest market row holding every tracked sat of the UTXO, else the rarest market row present. Never a label row."
          },
          "count": {
            "type": "integer",
            "description": "How many sats of `row` the UTXO holds (the \"×N\" of a bulk listing)."
          },
          "rows": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Every row the UTXO's tracked sats count toward, with their counts (label rows included)."
          },
          "types": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/TypeGroup"
            },
            "description": "The UTXO's sats grouped by exact type combination, rarest first."
          },
          "sats": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Tracked sats in the UTXO (all rows)."
          },
          "ranges": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "array",
              "items": {
                "type": "integer"
              },
              "minItems": 2,
              "maxItems": 2
            },
            "description": "The tracked sats as inclusive `[first, last]` ranges, ascending."
          },
          "years": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Tracked sats per mint year (UTC year of the block that mined them)."
          },
          "seller_address": {
            "type": "string",
            "description": "The address that holds the UTXO and signed the listing."
          },
          "payout_address": {
            "type": "string",
            "description": "Where the price is paid (the seller's payment output)."
          },
          "status": {
            "type": "string",
            "description": "`active` (for sale), `pending` (a purchase is in the mempool), `sold`, `cancelled` (or replaced by a newer listing of the same UTXO), `moved` (spent elsewhere). A listing whose UTXO was sold through an accepted offer ends `sold` with `sold_via: \"offer\"`.",
            "enum": [
              "active",
              "pending",
              "sold",
              "cancelled",
              "moved"
            ]
          },
          "created_at": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "updated_at": {
            "type": "integer",
            "description": "Unix seconds of the last status change."
          },
          "txid": {
            "type": [
              "string",
              "null"
            ],
            "description": "The purchase transaction, while `pending` and once `sold`; otherwise `null`."
          },
          "signature_public": {
            "type": "boolean",
            "description": "`true` once a broadcast purchase put the seller's signature on the network: the listing can then be bought at this price anywhere until the UTXO moves, even after a cancel here."
          },
          "sold_via": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "offer",
              null
            ],
            "description": "`offer` when the listing ended `sold` through an accepted offer of its UTXO: `price` and `unit_price` are then the offer's (what was paid), `offer_id` names it. `null` otherwise."
          },
          "offer_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The accepted offer it was sold through (`sold_via: \"offer\"`), else `null`."
          },
          "best_offer": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/BestOffer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The best active offer on the UTXO, or `null`."
          },
          "spent_by_pending": {
            "$ref": "#/components/schemas/PendingSpend"
          },
          "in_bundle": {
            "type": "boolean",
            "description": "Only on a listing read for a row it holds some sats of among others (in bundle: `contains=1`'s `contains`, or a row's activity): `true`. Its `price` is the whole UTXO's and its `unit_price` its own row's, never the row asked for."
          },
          "contains_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "With `in_bundle`: how many sats of the row asked for it holds."
          }
        },
        "required": [
          "id",
          "outpoint",
          "value",
          "price",
          "unit_price",
          "row",
          "count",
          "rows",
          "types",
          "sats",
          "ranges",
          "years",
          "seller_address",
          "payout_address",
          "status",
          "created_at",
          "updated_at",
          "txid",
          "signature_public",
          "sold_via",
          "offer_id",
          "best_offer"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "id": "3324d08569806818",
            "outpoint": "8b09d6914ae17431940ce8b6cadae378a5d9b3c90c73c3a5b0b8c8e7edc9e86a:0",
            "value": 6280,
            "price": 94200,
            "unit_price": 14,
            "row": "block9",
            "count": 6280,
            "rows": {
              "block9": 6280,
              "block9_1st_tx": 6280
            },
            "types": [
              {
                "types": [
                  "block9",
                  "nakamoto",
                  "vintage"
                ],
                "count": 6280,
                "sats": [
                  45100023043,
                  45100023044,
                  45100023045
                ]
              }
            ],
            "sats": 6280,
            "ranges": [
              [
                45100023043,
                45100029322
              ]
            ],
            "years": {
              "2009": 6280
            },
            "seller_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
            "payout_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
            "status": "active",
            "created_at": 1790952985,
            "updated_at": 1790952985,
            "txid": null,
            "signature_public": false,
            "sold_via": null,
            "offer_id": null,
            "best_offer": {
              "id": "dbf866a1e7e209e7",
              "price": 100000,
              "unit_price": 15.92,
              "bidder_payment_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
              "bidder_ordinals_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
              "created_at": 1790953585,
              "expires_at": 1791558385
            }
          }
        ]
      },
      "ListingPage": {
        "type": "object",
        "properties": {
          "listings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Listing"
            },
            "description": "One page of active listings, in the requested order."
          },
          "total": {
            "type": "integer",
            "description": "Active listings matching the filters (all pages)."
          },
          "as_of": {
            "$ref": "#/components/schemas/AsOf",
            "description": "When every live listing was last checked against the chain (`{height, checked_at}`), or `null`."
          },
          "contains": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Listing"
            },
            "description": "Only 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_total": {
            "type": "integer",
            "description": "Only with `contains=1`: how many such listings there are (all pages; `contains=only` pages them)."
          }
        },
        "required": [
          "listings",
          "total",
          "as_of"
        ],
        "additionalProperties": false
      },
      "ListingsByOutpoint": {
        "type": "object",
        "properties": {
          "listings": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/Listing"
            },
            "description": "The live (active or pending) listing of each outpoint asked for, keyed by outpoint. Outpoints with none are absent."
          },
          "as_of": {
            "$ref": "#/components/schemas/AsOf"
          }
        },
        "required": [
          "listings",
          "as_of"
        ],
        "additionalProperties": false
      },
      "MarketConfig": {
        "description": "The marketplace's settings. `{\"enabled\": false}` alone when the marketplace is off.",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "enabled": {
                "const": true,
                "description": "The marketplace is on."
              },
              "network": {
                "type": "string",
                "description": "The one network it trades on (`mainnet` in production)."
              },
              "fee_bps": {
                "type": "integer",
                "description": "Buyer fee in basis points of the summed prices (250 = 2.5%)."
              },
              "min_fee": {
                "type": "integer",
                "description": "The platform fee's floor in sats (546)."
              },
              "fee_address": {
                "type": "string",
                "description": "The address of the platform fee output."
              },
              "op_return": {
                "type": "string",
                "description": "The OP_RETURN marker payload every purchase carries (`raresats.net`)."
              },
              "max_bulk": {
                "type": "integer",
                "description": "Most listings one purchase may buy (20)."
              },
              "padding_value": {
                "type": "integer",
                "description": "Value of each padding output in sats (600)."
              },
              "max_listing_items": {
                "type": "integer",
                "description": "Most UTXOs one listing PSBT may list (50)."
              },
              "cancel_prefix": {
                "type": "string",
                "description": "The start of a cancel message: `raresats.net cancel`."
              },
              "affiliate_share_bps": {
                "type": "integer",
                "description": "A referring affiliate's part of the platform fee, in basis points (5000 = half)."
              },
              "affiliate_prefix": {
                "type": "string",
                "description": "The start of an affiliate's registration message: `raresats.net affiliate <address> <unix seconds>`."
              },
              "affiliate_cookie_seconds": {
                "type": "integer",
                "description": "How long a referral link counts: the `rs_ref` cookie's lifetime (86400 = 24 hours)."
              },
              "offer_cancel_prefix": {
                "type": "string",
                "description": "The start of an offer's cancel message: `raresats.net cancel-offer`."
              },
              "offer_expiries": {
                "type": "array",
                "items": {
                  "type": "integer"
                },
                "description": "The offer lifetimes a bidder may choose, in seconds (1, 3, 7 and 30 days); an offer may also have none."
              },
              "offer_default_expiry": {
                "type": "integer",
                "description": "An offer's lifetime when `expires_in` is absent, in seconds (7 days)."
              },
              "tools": {
                "type": "object",
                "description": "The wallet tools ([Extract rare sats](/docs/guide-extract)).",
                "properties": {
                  "fee_sats": {
                    "type": "integer",
                    "description": "The flat tools fee per transfer, in sats (0 = none)."
                  },
                  "max_items": {
                    "type": "integer",
                    "description": "Most UTXOs one transfer moves (50)."
                  },
                  "max_outputs": {
                    "type": "integer",
                    "description": "Most outputs of one transfer (100)."
                  },
                  "max_sends": {
                    "type": "integer",
                    "description": "Most recipients of a multisend (50)."
                  },
                  "kinds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "The kinds prepare takes."
                  },
                  "pad": {
                    "type": "object",
                    "description": "Sats per extracted output: `default` (330), `legacy` (546, P2SH and P2PKH destinations).",
                    "properties": {
                      "default": {
                        "type": "integer"
                      },
                      "legacy": {
                        "type": "integer"
                      }
                    },
                    "required": [
                      "default",
                      "legacy"
                    ],
                    "additionalProperties": false
                  }
                },
                "required": [
                  "fee_sats",
                  "max_items",
                  "max_outputs",
                  "max_sends",
                  "kinds",
                  "pad"
                ],
                "additionalProperties": false
              },
              "ready": {
                "type": "boolean",
                "description": "Whether bitcoind, the rare-sat index and the ord indexer all follow `network` right now. While `false`, trading answers 503 `market_unavailable`."
              }
            },
            "required": [
              "enabled",
              "network",
              "fee_bps",
              "min_fee",
              "fee_address",
              "op_return",
              "max_bulk",
              "padding_value",
              "max_listing_items",
              "cancel_prefix",
              "affiliate_share_bps",
              "affiliate_prefix",
              "affiliate_cookie_seconds",
              "offer_cancel_prefix",
              "offer_expiries",
              "offer_default_expiry",
              "tools",
              "ready"
            ],
            "additionalProperties": false,
            "title": "When the marketplace is on"
          },
          {
            "type": "object",
            "properties": {
              "enabled": {
                "const": false,
                "description": "The marketplace is off."
              }
            },
            "required": [
              "enabled"
            ],
            "additionalProperties": false,
            "title": "When it is off"
          }
        ]
      },
      "Fees": {
        "type": "object",
        "description": "Fee-rate choices in sat/vB, rising from slow to fast, none below `minimum`.",
        "properties": {
          "slow": {
            "type": "number",
            "description": "About 6 blocks, sat/vB."
          },
          "normal": {
            "type": "number",
            "description": "About 3 blocks, sat/vB."
          },
          "fast": {
            "type": "number",
            "description": "Next block, sat/vB."
          },
          "minimum": {
            "type": "number",
            "description": "The lowest rate a purchase may use, sat/vB (never below 1)."
          },
          "source": {
            "type": "string",
            "description": "Where the estimates came from.",
            "enum": [
              "bitcoind",
              "mempool.space"
            ]
          }
        },
        "required": [
          "slow",
          "normal",
          "fast",
          "minimum",
          "source"
        ],
        "additionalProperties": false
      },
      "Floors": {
        "type": "object",
        "properties": {
          "rows": {
            "type": "object",
            "description": "Each row with at least one active listing, priced in it or holding some of its sats in a bundle.",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "floor_unit": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "The lowest `unit_price` among the row's active listings (its own and its sub-categories'); `null` when only listings in bundle hold its sats."
                },
                "listed": {
                  "type": "integer",
                  "description": "Active listings of the row (own and sub-categories'; never those in bundle)."
                },
                "listed_sats": {
                  "type": "integer",
                  "description": "Sats of the row those listings hold (sum of `count`)."
                },
                "contains": {
                  "type": "integer",
                  "description": "Only when above 0: active listings of other rows holding some sats of this one among others (in bundle). Never in `floor_unit`, `listed` or `listed_sats`."
                },
                "contains_min_price": {
                  "type": "integer",
                  "description": "With `contains`: the lowest total price among them (a bundle's unit price is another row's)."
                }
              },
              "required": [
                "floor_unit",
                "listed",
                "listed_sats"
              ],
              "additionalProperties": false
            }
          },
          "as_of": {
            "$ref": "#/components/schemas/AsOf"
          }
        },
        "required": [
          "rows",
          "as_of"
        ],
        "additionalProperties": false
      },
      "ActivityEvent": {
        "type": "object",
        "properties": {
          "seq": {
            "type": "integer",
            "description": "Event sequence number (rising)."
          },
          "type": {
            "type": "string",
            "description": "What happened: a listing's `listed`, `cancelled`, `sold`; an offer's `offer_made`, `offer_cancelled`, `offer_accepted` (only when asked for with `types`).",
            "enum": [
              "listed",
              "cancelled",
              "sold",
              "offer_made",
              "offer_cancelled",
              "offer_accepted"
            ]
          },
          "listing_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The listing; on an offer event, the UTXO's live listing then, or `null`."
          },
          "outpoint": {
            "type": "string",
            "description": "The listed UTXO."
          },
          "row": {
            "type": "string",
            "description": "The listing's own row."
          },
          "count": {
            "type": "integer",
            "description": "Sats of that row."
          },
          "price": {
            "type": "integer",
            "description": "The listing price in sats (an offer's price on an offer event)."
          },
          "unit_price": {
            "type": "number",
            "description": "The listing's unit price."
          },
          "seller_address": {
            "type": "string",
            "description": "The seller (same as `seller`)."
          },
          "txid": {
            "type": [
              "string",
              "null"
            ],
            "description": "The purchase (or accepting) transaction of a `sold` or `offer_accepted` event; `null` otherwise."
          },
          "time": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "seller": {
            "type": [
              "string",
              "null"
            ],
            "description": "The seller's address."
          },
          "buyer": {
            "type": [
              "string",
              "null"
            ],
            "description": "A sale's buyer (or an accepted offer's bidder): the address the sats went to. `null` for other events, or when unknown."
          },
          "affiliate": {
            "type": [
              "string",
              "null"
            ],
            "description": "A sale bought here with an applied referral: the affiliate it paid. `null` otherwise."
          },
          "offer_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The offer, on an offer event; `null` otherwise."
          },
          "bidder": {
            "type": [
              "string",
              "null"
            ],
            "description": "The bidder's payment address, on an offer event; `null` otherwise."
          },
          "sub": {
            "type": "boolean",
            "description": "Only on an event read for a row (`row=`) that is not its own row but holds every tracked sat of the item (a sub-category or a label row): `true`."
          },
          "in_bundle": {
            "type": "boolean",
            "description": "Only on an event read for a row (`row=`) whose listing or offer holds some sats of that row among others (in bundle, e.g. a Block 9 chunk under `block9_palindrome`): `true`. Its price and unit price are those of its own `row`."
          },
          "contains_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "With `in_bundle`: how many sats of the row asked for the item holds."
          }
        },
        "required": [
          "seq",
          "type",
          "listing_id",
          "outpoint",
          "row",
          "count",
          "price",
          "unit_price",
          "seller_address",
          "txid",
          "time",
          "seller",
          "buyer",
          "affiliate",
          "offer_id",
          "bidder"
        ],
        "additionalProperties": false
      },
      "SignInput": {
        "type": "object",
        "description": "One input your wallet must sign.",
        "properties": {
          "index": {
            "type": "integer",
            "description": "The input to sign."
          },
          "address": {
            "type": "string",
            "description": "The address whose key signs it."
          },
          "sighash": {
            "type": "integer",
            "description": "The sighash type to sign with, when it is not the default: 131 (`0x83`, SIGHASH_SINGLE|ANYONECANPAY) for listings. Absent on purchase inputs: sign with the default (SIGHASH_DEFAULT for Taproot, SIGHASH_ALL for SegWit v0)."
          }
        },
        "required": [
          "index",
          "address"
        ],
        "additionalProperties": false
      },
      "PrepareListingRequest": {
        "type": "object",
        "properties": {
          "seller_address": {
            "type": "string",
            "description": "The address holding the UTXOs: Taproot (`bc1p…`), native SegWit (`bc1q…`) or nested SegWit (`3…`, P2SH-P2WPKH). Legacy `1…` is refused."
          },
          "seller_public_key": {
            "type": "string",
            "description": "The public key of `seller_address`, hex: for Taproot the internal (untweaked) key, 32-byte x-only or 33-byte compressed; for SegWit the 33-byte compressed key.",
            "pattern": "^([0-9a-fA-F]{64}|[0-9a-fA-F]{66})$"
          },
          "payout_address": {
            "type": "string",
            "description": "Where the price is paid. Optional: defaults to `seller_address`. Any standard mainnet address."
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "outpoint": {
                  "type": "string",
                  "description": "The UTXO to list, `txid:vout`."
                },
                "price": {
                  "type": "integer",
                  "description": "Its price in sats: what you receive. Above the UTXO's own value, at least 546 and at least the payout output's dust limit."
                }
              },
              "required": [
                "outpoint",
                "price"
              ],
              "additionalProperties": false
            },
            "description": "1 to 50 UTXOs, each listed at its own price. One PSBT, one wallet prompt.",
            "minItems": 1,
            "maxItems": 50
          }
        },
        "required": [
          "seller_address",
          "seller_public_key",
          "items"
        ],
        "additionalProperties": false
      },
      "PreparedListingItem": {
        "type": "object",
        "properties": {
          "outpoint": {
            "type": "string",
            "description": "The UTXO."
          },
          "value": {
            "type": "integer",
            "description": "Its value in sats."
          },
          "price": {
            "type": "integer",
            "description": "Its listing price in sats."
          },
          "unit_price": {
            "type": "number",
            "description": "`(price - value) / count`."
          },
          "row": {
            "type": "string",
            "description": "Its own row."
          },
          "count": {
            "type": "integer",
            "description": "Sats of that row it holds."
          }
        },
        "required": [
          "outpoint",
          "value",
          "price",
          "unit_price",
          "row",
          "count"
        ],
        "additionalProperties": false
      },
      "PrepareListingResponse": {
        "type": "object",
        "properties": {
          "psbt": {
            "type": "string",
            "description": "The unsigned listing PSBT, base64: input i is UTXO i (with `witnessUtxo`, `sighashType` 0x83, `tapInternalKey` or `redeemScript`), output i pays its price to the payout address; version 2, locktime 0, sequence 0xfffffffd."
          },
          "sign": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SignInput"
            },
            "description": "The inputs to sign: every input, with `sighash: 131`."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PreparedListingItem"
            },
            "description": "What each listed UTXO will show."
          }
        },
        "required": [
          "psbt",
          "sign",
          "items"
        ],
        "additionalProperties": false
      },
      "SubmitListingRequest": {
        "type": "object",
        "properties": {
          "psbt": {
            "type": "string",
            "description": "The listing PSBT, every input signed with SIGHASH_SINGLE|ANYONECANPAY (0x83). Base64. Partially signed or finalized inputs are both accepted."
          }
        },
        "required": [
          "psbt"
        ],
        "additionalProperties": false
      },
      "SubmitListingResponse": {
        "type": "object",
        "properties": {
          "listings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Listing"
            },
            "description": "The new listings, `active`, in input order."
          },
          "warning": {
            "type": "string",
            "description": "Present when a listing replaced here had a public signature (see `exposed`)."
          },
          "exposed": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ids of replaced listings whose signature a broadcast purchase made public: their old price can still be taken until the UTXO moves."
          }
        },
        "required": [
          "listings"
        ],
        "additionalProperties": false
      },
      "CancelRequest": {
        "type": "object",
        "properties": {
          "ids": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "A listing id."
            },
            "description": "1 to 100 listing ids, all listed by `address`.",
            "minItems": 1,
            "maxItems": 100
          },
          "address": {
            "type": "string",
            "description": "The seller address that listed them."
          },
          "message": {
            "type": "string",
            "description": "Exactly `raresats.net cancel <id,id,…> <unix seconds>`: the ids comma-separated in the same order as `ids`, and the current time. At most 10 minutes old, at most 2 minutes ahead."
          },
          "signature": {
            "type": "string",
            "description": "A BIP-322 signature of `message` by `address`, base64 (what wallets' \"sign message\" with BIP-322 returns)."
          }
        },
        "required": [
          "ids",
          "address",
          "message",
          "signature"
        ],
        "additionalProperties": false
      },
      "CancelResponse": {
        "type": "object",
        "properties": {
          "listings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Listing"
            },
            "description": "The cancelled listings (`status: \"cancelled\"`)."
          },
          "warning": {
            "type": "string",
            "description": "Present when some of them have a public signature (see `exposed`)."
          },
          "exposed": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ids of cancelled listings whose signature a broadcast purchase made public: off sale here, but only moving the UTXO makes the cancel certain."
          }
        },
        "required": [
          "listings"
        ],
        "additionalProperties": false
      },
      "Buyer": {
        "type": "object",
        "description": "The buyer's wallet: Xverse-style wallets have two addresses, UniSat-style one (use it for both).",
        "properties": {
          "payment_address": {
            "type": "string",
            "description": "Pays: padding, funding and change. Taproot, native SegWit or nested SegWit."
          },
          "payment_public_key": {
            "type": "string",
            "description": "Its public key, hex (Taproot: the internal key, x-only or compressed; SegWit: compressed)."
          },
          "ordinals_address": {
            "type": "string",
            "description": "Receives the bought UTXOs. Taproot, native SegWit or nested SegWit. May equal `payment_address`."
          },
          "ordinals_public_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its public key, hex. Optional; checked when given."
          }
        },
        "required": [
          "payment_address",
          "payment_public_key",
          "ordinals_address"
        ],
        "additionalProperties": false
      },
      "PreparePurchaseRequest": {
        "type": "object",
        "properties": {
          "listing_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "A listing id."
            },
            "description": "1 to 20 (`max_bulk`) active listings, each once.",
            "minItems": 1,
            "maxItems": 20
          },
          "buyer": {
            "$ref": "#/components/schemas/Buyer",
            "description": "The buyer's wallet: Xverse-style wallets have two addresses, UniSat-style one (use it for both)."
          },
          "fee_rate": {
            "type": "number",
            "description": "Network fee rate in sat/vB: at least `minimum` from `GET /api/market/fees` (and at least 1), at most 5000.",
            "exclusiveMinimum": 0,
            "maximum": 5000
          },
          "affiliate": {
            "type": [
              "string",
              "null"
            ],
            "description": "Optional: the referring affiliate's address. It wins over the `rs_ref` cookie the site sets from a referral link. Any address of the network is an affiliate, with no registration; an unusable one (another network's, or the fee address) is ignored (`invalid`), never refused."
          }
        },
        "required": [
          "listing_ids",
          "buyer",
          "fee_rate"
        ],
        "additionalProperties": false
      },
      "PsbtToSign": {
        "type": "object",
        "properties": {
          "psbt": {
            "type": "string",
            "description": "The unsigned PSBT, base64. The sellers' inputs carry no signature (the server adds them at submit)."
          },
          "sign": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SignInput"
            },
            "description": "Your inputs: sign exactly these, with your wallet's default sighash."
          }
        },
        "required": [
          "psbt",
          "sign"
        ],
        "additionalProperties": false
      },
      "PurchaseItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The listing."
          },
          "outpoint": {
            "type": "string",
            "description": "Its UTXO."
          },
          "value": {
            "type": "integer",
            "description": "The UTXO's value (it lands whole in your ordinals address)."
          },
          "price": {
            "type": "integer",
            "description": "The listing price."
          },
          "unit_price": {
            "type": "number",
            "description": "The listing's unit price."
          },
          "row": {
            "type": "string",
            "description": "Its own row."
          },
          "count": {
            "type": "integer",
            "description": "Sats of that row."
          }
        },
        "required": [
          "id",
          "outpoint",
          "value",
          "price",
          "unit_price",
          "row",
          "count"
        ],
        "additionalProperties": false
      },
      "PurchaseSummary": {
        "type": "object",
        "properties": {
          "prices": {
            "type": "integer",
            "description": "Sum of the listing prices."
          },
          "platform_fee": {
            "type": "integer",
            "description": "The platform fee the buyer pays: `max(ceil(prices × fee_bps / 10000), min_fee)` (2.5%, at least 546 sats), the same with or without a referrer. Split between `platform_share` and `affiliate_fee`."
          },
          "platform_share": {
            "type": "integer",
            "description": "The part of `platform_fee` paid to the fee address (all of it without an applied referral)."
          },
          "affiliate_fee": {
            "type": "integer",
            "description": "The part paid to the affiliate, in its own output right after the platform's (0 unless `affiliate_status` is `applied`)."
          },
          "affiliate_address": {
            "type": [
              "string",
              "null"
            ],
            "description": "The referrer (normalized), or `null` when none was given or it was not a usable address."
          },
          "affiliate_status": {
            "type": "string",
            "description": "`none` (no referrer), `invalid` (not a usable address of the network, or the fee address), `ignored_self` (a self-referral; see `affiliate_reason`), `applied` (paid), `below_minimum` (a share would be under 546 sats: the platform keeps the fee).",
            "enum": [
              "none",
              "invalid",
              "ignored_self",
              "applied",
              "below_minimum"
            ]
          },
          "affiliate_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why an `ignored_self` referral was not paid: `same_address` (the referrer is the buyer's payment or ordinals address), `affiliate_wallet` (the buyer's address belongs to the wallet that registered the affiliate, when it used the optional registration), `linked_funds` (the buyer's coins came from the affiliate's addresses, or the affiliate's from the buyer's), `unchecked` (the funds could not be checked in time: no split), `seller` (the referrer is a seller's address or payout). `null` otherwise.",
            "enum": [
              "same_address",
              "affiliate_wallet",
              "linked_funds",
              "unchecked",
              "seller",
              null
            ]
          },
          "affiliate_share_bps": {
            "type": "integer",
            "description": "The affiliate's share of the fee in force, basis points."
          },
          "network_fee": {
            "type": "integer",
            "description": "Network fee of the purchase plus the setup transaction."
          },
          "purchase_network_fee": {
            "type": "integer",
            "description": "Network fee of the purchase transaction."
          },
          "setup_network_fee": {
            "type": "integer",
            "description": "Network fee of the setup transaction (0 without one)."
          },
          "total": {
            "type": "integer",
            "description": "What the purchase costs you: `prices + platform_fee + network_fee`. The padding you spend comes back to you."
          },
          "vsize": {
            "type": "integer",
            "description": "Virtual size of the purchase transaction, vB."
          },
          "setup_vsize": {
            "type": "integer",
            "description": "Virtual size of the setup transaction, vB (0 without one)."
          },
          "fee_rate": {
            "type": "number",
            "description": "The fee rate asked for, sat/vB."
          },
          "change": {
            "type": "integer",
            "description": "Change back to your payment address (0: none; a remainder below dust goes to the network fee)."
          },
          "padding_value": {
            "type": "integer",
            "description": "Value of each new padding output (600)."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PurchaseItem"
            },
            "description": "The listings bought, in purchase order."
          }
        },
        "required": [
          "prices",
          "platform_fee",
          "platform_share",
          "affiliate_fee",
          "affiliate_address",
          "affiliate_status",
          "affiliate_reason",
          "affiliate_share_bps",
          "network_fee",
          "purchase_network_fee",
          "setup_network_fee",
          "total",
          "vsize",
          "setup_vsize",
          "fee_rate",
          "change",
          "padding_value",
          "items"
        ],
        "additionalProperties": false
      },
      "PreparePurchaseResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The prepared purchase: submit it with this id."
          },
          "setup": {
            "$ref": "#/components/schemas/PsbtToSign",
            "description": "Present only when your payment address lacks padding: a setup transaction that makes it, to sign and submit too (broadcast first)."
          },
          "purchase": {
            "$ref": "#/components/schemas/PsbtToSign",
            "description": "The purchase transaction to sign."
          },
          "summary": {
            "$ref": "#/components/schemas/PurchaseSummary",
            "description": "The fee breakdown and what you buy."
          },
          "expires_at": {
            "type": "integer",
            "description": "Unix seconds: the plan is held 10 minutes. Submit before then, or prepare again."
          }
        },
        "required": [
          "id",
          "purchase",
          "summary",
          "expires_at"
        ],
        "additionalProperties": false
      },
      "SubmitPurchaseRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The prepared purchase id."
          },
          "setup_psbt": {
            "type": [
              "string",
              "null"
            ],
            "description": "The signed setup PSBT, base64: required when prepare returned `setup`, absent otherwise."
          },
          "purchase_psbt": {
            "type": "string",
            "description": "The signed purchase PSBT, base64. Not finalized is fine; the transaction must be exactly the prepared one."
          }
        },
        "required": [
          "id",
          "purchase_psbt"
        ],
        "additionalProperties": false
      },
      "SubmitPurchaseResponse": {
        "type": "object",
        "properties": {
          "txid": {
            "type": "string",
            "description": "The purchase transaction, accepted by bitcoind and broadcast."
          },
          "setup_txid": {
            "type": "string",
            "description": "The setup transaction (broadcast first), when there was one."
          }
        },
        "required": [
          "txid"
        ],
        "additionalProperties": false
      },
      "Party": {
        "type": [
          "string",
          "null"
        ],
        "description": "An address, or `null` (a script with no address)."
      },
      "SecondaryRows": {
        "type": "object",
        "description": "A sale's secondary rows: the market rows of the other sats it sold (not its own row, a row it is a sub-category of, or a label row), each with its sats, primary-first: `{\"black_omega\": 1}` for a black omega sold with an alpha uncommon; `{}` for none. A sale never counts in its secondary rows' markets (the primary-sat rule, in Concepts).",
        "additionalProperties": {
          "type": "integer"
        },
        "example": {
          "black_omega": 1
        }
      },
      "MarketSale": {
        "type": "object",
        "description": "A sale as the homepage lists it, priced per sat of its own row.",
        "properties": {
          "seq": {
            "type": "integer",
            "description": "The sale's sequence number (for `/api/sales/parties` and `/api/sales/{seq}/tx`)."
          },
          "t": {
            "type": "integer",
            "description": "Sale time, unix seconds."
          },
          "h": {
            "type": "integer",
            "description": "Block height."
          },
          "row": {
            "type": "string",
            "description": "The sale's own row."
          },
          "u": {
            "type": [
              "number",
              "null"
            ],
            "description": "Unit price: premium per sat of the row."
          },
          "c": {
            "type": "integer",
            "description": "Sats of the row sold."
          },
          "p": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Price in sats."
          },
          "n": {
            "type": "integer",
            "description": "Tracked sats the sale sold."
          },
          "s": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The first special sat sold."
          },
          "sh": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The block that mined it."
          },
          "sd": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The day it was mined (UTC days since 1970)."
          },
          "m": {
            "type": "string",
            "description": "Marketplace id (`magisat`, `magic_eden`, `unknown`, …)."
          },
          "x": {
            "type": [
              "string",
              "null"
            ],
            "description": "The txid's first 8 and last 4 hex digits."
          },
          "ins": {
            "type": "boolean",
            "description": "An inscription was on a sold sat."
          },
          "out": {
            "type": "boolean",
            "description": "A statistical outlier."
          },
          "secondary": {
            "$ref": "#/components/schemas/SecondaryRows"
          },
          "seller": {
            "type": [
              "string",
              "null"
            ],
            "description": "The seller's address."
          },
          "buyer": {
            "type": [
              "string",
              "null"
            ],
            "description": "The buyer's address."
          }
        },
        "required": [
          "seq",
          "t",
          "row",
          "p",
          "m",
          "seller",
          "buyer",
          "secondary"
        ]
      },
      "MarketOverview": {
        "type": "object",
        "description": "The homepage's market over a window: totals, rows by volume, the dearest and the latest sales. Each sale counts once, as its own row.",
        "properties": {
          "available": {
            "type": "boolean",
            "description": "Whether the sales index is available."
          },
          "generation": {
            "type": "integer",
            "description": "Sales generation (changes on a reorg)."
          },
          "seq": {
            "type": "integer",
            "description": "The newest sale's sequence number."
          },
          "as_of": {
            "type": [
              "object",
              "null"
            ],
            "description": "The block the sales are as of: `{height, time}`."
          },
          "window": {
            "type": "string",
            "description": "The window.",
            "enum": [
              "24h",
              "7d",
              "30d",
              "90d",
              "1y",
              "all"
            ]
          },
          "inscribed": {
            "type": "boolean",
            "description": "Inscribed sales counted."
          },
          "outliers": {
            "type": "boolean",
            "description": "Outliers counted."
          },
          "since": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Window start, unix seconds (`null` for `all`)."
          },
          "until": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Window end, unix seconds."
          },
          "totals": {
            "type": "object",
            "description": "The window's totals.",
            "properties": {
              "volume": {
                "type": "integer",
                "description": "Sats traded."
              },
              "sales": {
                "type": "integer",
                "description": "Sales."
              },
              "sats": {
                "type": "integer",
                "description": "Sats sold."
              }
            },
            "required": [
              "volume",
              "sales",
              "sats"
            ]
          },
          "previous": {
            "type": [
              "object",
              "null"
            ],
            "description": "The window before's totals (`null` for `all`)."
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "row": {
                  "type": "string",
                  "description": "Row id."
                },
                "volume": {
                  "type": "integer",
                  "description": "Sats traded."
                },
                "sales": {
                  "type": "integer",
                  "description": "Sales."
                },
                "sats": {
                  "type": "integer",
                  "description": "Sats sold."
                },
                "median_unit": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Median unit price."
                },
                "last_time": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Last sale, unix seconds."
                },
                "last_unit": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Last unit price."
                },
                "last_price": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Last price."
                },
                "prev_volume": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Volume in the window before."
                },
                "prev_sales": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Sales in the window before."
                }
              },
              "required": [
                "row",
                "volume",
                "sales"
              ]
            },
            "description": "Rows by volume, largest first."
          },
          "top": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MarketSale"
            },
            "description": "The window's dearest sales (up to 24)."
          },
          "latest": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MarketSale"
            },
            "description": "The latest sales (up to 10)."
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "The sales index's last error, if any."
          },
          "pending": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PendingSale"
            },
            "description": "The latest sales still in the mempool (at most 10), newest first: beside `latest`, in no total, row or top."
          }
        },
        "required": [
          "available",
          "window",
          "totals",
          "rows",
          "top",
          "latest"
        ]
      },
      "SalesColumns": {
        "type": "object",
        "description": "Sales as compact columns, oldest first: every column has one entry per sale.",
        "properties": {
          "available": {
            "type": "boolean",
            "description": "Whether the sales index is available."
          },
          "generation": {
            "type": "integer",
            "description": "Sales generation: a reorg starts a new one; reload from `after=0`."
          },
          "seq": {
            "type": "integer",
            "description": "The newest sale's sequence number: pass it as `after` to get only newer sales."
          },
          "after": {
            "type": "integer",
            "description": "The `after` asked for."
          },
          "count": {
            "type": "integer",
            "description": "Sales in this answer (the length of every column)."
          },
          "as_of": {
            "type": [
              "object",
              "null"
            ],
            "description": "`{height, time}` of the sales."
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Row ids, indexed by `r`, `o` and `w`."
          },
          "markets": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Marketplace ids, indexed by `m`."
          },
          "sub_count": {
            "type": "integer",
            "description": "With one market row: sales of its rarer sub-categories."
          },
          "sub_rows": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Those sales by their own row."
          },
          "led_count": {
            "type": "integer",
            "description": "With one market row: sales led by another row that sold sats of it (it is one of their secondary rows)."
          },
          "led_rows": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Those sales by their own row."
          },
          "t": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Sale time, unix seconds, as deltas: the first from 0, each next from the one before."
          },
          "q": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Sequence number, as deltas: the first from `after`."
          },
          "u": {
            "type": "array",
            "items": {
              "type": [
                "number",
                "null"
              ]
            },
            "description": "Unit price under the row shown."
          },
          "p": {
            "type": "array",
            "items": {
              "type": [
                "integer",
                "null"
              ]
            },
            "description": "Price in sats."
          },
          "c": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Sats of the row sold."
          },
          "r": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Index into `rows`: the row the sale is shown as."
          },
          "m": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Index into `markets`."
          },
          "f": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Flags: 1 inscribed, 2 outlier, 4 a rarer sub-category's sale (with `sub=1`), 8 a sale led by another row, shown under one of its secondary rows (with `led=1`), 16 the sale has secondary rows (an item in `w`)."
          },
          "md": {
            "type": "array",
            "items": {
              "type": [
                "number",
                "null"
              ]
            },
            "description": "The row's rolling median unit price at the sale (4 significant digits)."
          },
          "o": {
            "type": "array",
            "items": {
              "type": [
                "integer",
                "null"
              ]
            },
            "description": "With `sub=1` or `led=1`: index into `rows` of a sub-category's or a led sale's own row, else `null`."
          },
          "s": {
            "type": "array",
            "items": {
              "type": [
                "integer",
                "null"
              ]
            },
            "description": "The first special sat sold."
          },
          "sh": {
            "type": "array",
            "items": {
              "type": [
                "integer",
                "null"
              ]
            },
            "description": "The block that mined it."
          },
          "sd": {
            "type": "array",
            "items": {
              "type": [
                "integer",
                "null"
              ]
            },
            "description": "The day it was mined (UTC days since 1970)."
          },
          "n": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Tracked sats sold."
          },
          "x": {
            "type": "array",
            "items": {
              "type": [
                "string",
                "null"
              ]
            },
            "description": "The txid's first 8 and last 4 hex digits (`/api/sales/{seq}/tx` redirects to the full one)."
          },
          "w": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "integer"
              }
            },
            "description": "One item per sale flagged 16, in their order: its secondary rows, primary-first, as `[row index, sats, row index, sats, …]` (indexes into `rows`)."
          },
          "k": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "The exact types each sale sold: an index into `kinds`."
          },
          "kinds": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "integer"
              }
            },
            "description": "The kinds of sale `k` names, each `[type set index, sats, type set index, sats, …]` (indexes into `type_sets`): the sats it sold grouped by exact type combination, its own row's combination first, then rarest first. A piece longer than one sat (a block 9 chunk) counts under its first sat's types. `[]` when the fork typed none."
          },
          "type_sets": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "The exact type combinations `kinds` names, each in the badges' order (`[\"uncommon\", \"alpha\"]`)."
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "The sales index's last error, if any."
          },
          "pending": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PendingSale"
            },
            "description": "The selection's sales still in the mempool, newest first (the same `row`, `group`, `sub` and `led` rules). Never in the columns, `count`, `seq` or any market: they confirm as new sales."
          }
        },
        "required": [
          "available",
          "generation",
          "seq",
          "count",
          "rows",
          "markets",
          "t",
          "q",
          "u",
          "p",
          "c",
          "r",
          "m",
          "f",
          "md",
          "s",
          "sh",
          "sd",
          "n",
          "x",
          "w",
          "k",
          "kinds",
          "type_sets"
        ]
      },
      "SaleParties": {
        "type": "object",
        "properties": {
          "generation": {
            "type": "integer",
            "description": "Sales generation the sequence numbers belong to."
          },
          "parties": {
            "type": "object",
            "description": "Keyed by sequence number. Unknown sequence numbers are absent.",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "seller": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "An address, or `null` (a script with no address)."
                },
                "buyer": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "An address, or `null` (a script with no address)."
                }
              },
              "required": [
                "seller",
                "buyer"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "generation",
          "parties"
        ],
        "additionalProperties": false
      },
      "SalesStats": {
        "type": "object",
        "description": "Every row's market: last unit price, 30-day median, volume and sales.",
        "properties": {
          "available": {
            "type": "boolean",
            "description": "Whether the sales index is available."
          },
          "generation": {
            "type": "integer",
            "description": "Sales generation."
          },
          "seq": {
            "type": "integer",
            "description": "The newest sale's sequence number."
          },
          "count": {
            "type": "integer",
            "description": "Sales held."
          },
          "as_of": {
            "type": [
              "object",
              "null"
            ],
            "description": "`{height, time}`."
          },
          "first_time": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The first sale, unix seconds."
          },
          "stats": {
            "type": "object",
            "description": "Per row.",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "last_unit_price": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "The last sale's unit price (outliers excluded)."
                },
                "last_time": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Its time."
                },
                "median_30d": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "30-day median unit price."
                },
                "volume_30d": {
                  "type": "integer",
                  "description": "30-day volume in sats."
                },
                "volume_all": {
                  "type": "integer",
                  "description": "All-time volume in sats (inscribed sales aside)."
                },
                "sales_30d": {
                  "type": "integer",
                  "description": "30-day sales."
                },
                "sales": {
                  "type": "integer",
                  "description": "Sales in all."
                }
              },
              "required": [
                "last_unit_price",
                "median_30d",
                "volume_30d",
                "volume_all",
                "sales"
              ]
            }
          }
        },
        "required": [
          "available",
          "stats"
        ]
      },
      "SatSale": {
        "type": "object",
        "description": "One sale of the sat, newest first.",
        "properties": {
          "seq": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The sales store's sequence number, else `null`."
          },
          "txid": {
            "type": "string",
            "description": "The sale transaction."
          },
          "vin": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The seller input."
          },
          "height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Block height (null while pending)."
          },
          "time": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "marketplace": {
            "type": "string",
            "description": "Marketplace id."
          },
          "price": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Price in sats."
          },
          "row": {
            "type": [
              "string",
              "null"
            ],
            "description": "The sale's own row."
          },
          "unit_price": {
            "type": [
              "number",
              "null"
            ],
            "description": "Unit price per sat of that row."
          },
          "count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Sats of that row sold."
          },
          "sats_sold": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Tracked sats the sale sold."
          },
          "seller": {
            "type": [
              "object",
              "null"
            ],
            "description": "`{address, outpoint}`."
          },
          "buyer": {
            "type": [
              "object",
              "null"
            ],
            "description": "`{address, outpoint}`."
          },
          "inscribed": {
            "type": "boolean",
            "description": "An inscription was on a sold sat."
          },
          "outlier": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "A statistical outlier (`null` when unknown)."
          },
          "secondary": {
            "$ref": "#/components/schemas/SecondaryRows"
          },
          "as": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The sat's rows (`rows`, in its order) the sale sold sats of: why a sale another row led is listed on this sat (a Block 9 chunk on its palindrome's page names `block9`, `block9_palindrome`, `nakamoto_palindrome`)."
          },
          "pending": {
            "type": "boolean",
            "description": "Still in the mempool: listed first, with `first_seen` and `fee_rate`; `time` is `first_seen`."
          },
          "first_seen": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When the transaction was first seen in the mempool (bitcoind's entry time), unix seconds."
          },
          "fee_rate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Its fee rate, sat/vB (one decimal)."
          }
        },
        "required": [
          "txid",
          "height",
          "time",
          "marketplace",
          "price"
        ]
      },
      "SatPage": {
        "type": "object",
        "description": "One sat: what it is, where it is, every sale of it, and its listing.",
        "properties": {
          "sat": {
            "type": "integer",
            "description": "The sat number."
          },
          "as_of": {
            "type": [
              "object",
              "null"
            ],
            "description": "`{height, time}` of the index."
          },
          "explorer": {
            "type": [
              "string",
              "null"
            ],
            "description": "Block explorer base URL (`https://mempool.space`)."
          },
          "height": {
            "type": "integer",
            "description": "The block that mined it."
          },
          "block_time": {
            "type": [
              "integer",
              "null"
            ],
            "description": "That block's time, unix seconds."
          },
          "luck": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its luck, its block's: how many more leading zero bits the block hash has than its difficulty target required (every sat of a block shares it). `null` while the luck table is being read."
          },
          "tracked": {
            "type": "boolean",
            "description": "Whether the rare-sat index tracks it (location and sales are known only then)."
          },
          "types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Its sat types."
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Its rows."
          },
          "inscribed": {
            "type": "boolean",
            "description": "Whether it carries inscriptions."
          },
          "inscriptions": {
            "type": "integer",
            "description": "How many."
          },
          "location": {
            "type": [
              "object",
              "null"
            ],
            "description": "Where it is now: `{kind: unspent|burned|lost|overwritten, satpoint, outpoint, offset, output}`. `output` is the UTXO holding it (`outpoint`, `value`, `address`, `quantity`, `groups`, `ranges`, `rows` (the fork's sats per row), …), `null` for a lost sat. Its `output` carries `spent_by_pending` (a `PendingSpend`) while a pending transaction spends it."
          },
          "sales": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SatSale"
            },
            "description": "Every sale of it, newest first."
          },
          "listing": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Listing"
              },
              {
                "type": "null"
              }
            ],
            "description": "The marketplace's live (active or pending) listing of its UTXO, else `null`."
          },
          "pending": {
            "type": [
              "object",
              "null"
            ],
            "description": "Where transactions still in the mempool take it (the end of a chain of them), else null: `{txid, first_seen, fee_rate, kind: unspent|burned|fee, satpoint, outpoint, offset, output, url}`; `output` is the pending output (a `PendingOutput`), null when it goes to fees. `location` stays the confirmed one, its output carrying `spent_by_pending`. Present only while the index serves its mempool overlay."
          }
        },
        "required": [
          "sat",
          "height",
          "tracked",
          "types",
          "rows",
          "location",
          "sales",
          "listing"
        ]
      },
      "UtxoSat": {
        "type": "object",
        "description": "A sat, or a run of sats sharing their types, at its place in the output.",
        "properties": {
          "sat": {
            "type": "integer",
            "description": "The (first) sat number."
          },
          "len": {
            "type": "integer",
            "description": "How many sats from `sat` on: 1 for a single sat, more for a run of an exotic range (block 9, vintage, pizza, …)."
          },
          "offset": {
            "type": "integer",
            "description": "The sat's offset in the output (0 is its first sat)."
          },
          "types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Its sat types, rarest first."
          },
          "year": {
            "type": "integer",
            "description": "The UTC year of the block that mined it."
          },
          "luck": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its block's luck (the hash's leading zero bits less the target's); `null` for a run over several blocks, or while the luck table is being read."
          },
          "inscribed": {
            "type": "integer",
            "description": "Tracked sats only: how many of the run carry an inscription."
          }
        },
        "required": [
          "sat",
          "len",
          "offset",
          "types"
        ]
      },
      "UtxoTracked": {
        "type": "object",
        "description": "The output's tracked sats: grouped as the address page groups them, and run by run with their offsets.",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "fork",
              "moves"
            ],
            "description": "`fork`: the index's view of the unspent output; `moves`: recovered from the block moves the index keeps, as the output held them."
          },
          "quantity": {
            "type": "integer",
            "description": "Tracked sats in all."
          },
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TypeGroup"
            },
            "description": "By exact type combination, rarest first."
          },
          "ranges": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "integer"
              }
            },
            "description": "Contiguous `[first, last]` sat ranges (inclusive), at most 200."
          },
          "ranges_total": {
            "type": "integer",
            "description": "How many ranges in all."
          },
          "years": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Sats per mint year."
          },
          "year": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The year holding the most sats."
          },
          "rows": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Sats per row (the index's counts)."
          },
          "inscribed_sats": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Tracked sats carrying an inscription."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UtxoSat"
            },
            "description": "Each sat or run, lowest offset first, at most 2,000."
          },
          "items_total": {
            "type": "integer",
            "description": "How many sats or runs in all."
          }
        },
        "required": [
          "source",
          "quantity",
          "groups",
          "items",
          "items_total"
        ]
      },
      "UtxoOther": {
        "type": "object",
        "description": "The rare and exotic sats in the output that raresats.net does not track (vintage, pizza, Nakamoto, block 78/286/666, jpeg, hitman, Silk Road, plain alphas and omegas, palindromes, …), typed from the output's sat ranges.",
        "properties": {
          "quantity": {
            "type": "integer",
            "description": "Such sats in all (a lower bound when `truncated`)."
          },
          "groups": {
            "type": "array",
            "description": "By exact type combination, rarest first.",
            "items": {
              "type": "object",
              "properties": {
                "types": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "count": {
                  "type": "integer"
                },
                "samples": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  },
                  "description": "Up to 5 single sats: `{sat, offset, year, luck}`."
                },
                "runs": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  },
                  "description": "Up to 5 runs of an exotic range: `{sat, len, offset, year}`."
                }
              },
              "required": [
                "types",
                "count",
                "samples",
                "runs"
              ]
            }
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UtxoSat"
            },
            "description": "Each sat or run, lowest offset first, at most 2,000."
          },
          "items_total": {
            "type": "integer"
          },
          "truncated": {
            "type": "boolean",
            "description": "A huge output: only its first `scanned` untracked sats were scanned for special sats."
          },
          "scanned": {
            "type": "integer",
            "description": "Untracked sats scanned."
          },
          "total": {
            "type": "integer",
            "description": "Untracked sats in the output."
          }
        },
        "required": [
          "quantity",
          "groups",
          "items",
          "truncated"
        ]
      },
      "UtxoPage": {
        "type": "object",
        "description": "One output: what it holds, whether and where it was spent, and its market.",
        "properties": {
          "outpoint": {
            "type": "string",
            "description": "`txid:vout`."
          },
          "txid": {
            "type": "string"
          },
          "vout": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "unspent",
              "spent",
              "unknown"
            ],
            "description": "`unknown` when this server has no way to tell (no bitcoind or ord index configured, or both unreachable)."
          },
          "spent": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether it is spent (a spend in the mempool counts), `null` when unknown."
          },
          "value": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its value in sats."
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its address (`null` for a script without one)."
          },
          "script": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its scriptPubKey, hex."
          },
          "kind": {
            "type": [
              "string",
              "null"
            ],
            "description": "`spendable` or `unspendable`."
          },
          "created_height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The block that created it."
          },
          "created_time": {
            "type": [
              "integer",
              "null"
            ],
            "description": "That block's time, unix seconds."
          },
          "confirmations": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Confirmations of the transaction that created it."
          },
          "extracted": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "The index's extracted verdict (rare sats isolated in a small UTXO), when it tracks the output."
          },
          "as_of": {
            "type": [
              "object",
              "null"
            ],
            "description": "`{height, time}` of the index."
          },
          "chain": {
            "type": [
              "string",
              "null"
            ],
            "description": "The chain (`mainnet`)."
          },
          "explorer": {
            "type": [
              "string",
              "null"
            ],
            "description": "Block explorer base URL."
          },
          "sources": {
            "type": "object",
            "description": "`{fork, oracle, bitcoind, history}`, each `ok`, `off` (not configured) or `unavailable`: what this answer could ask."
          },
          "contents": {
            "type": "string",
            "enum": [
              "complete",
              "tracked",
              "recovered",
              "unknown"
            ],
            "description": "`complete`: every sat range was typed; `tracked`: the tracked sats only; `recovered`: a spent output's tracked sats, from the moves the index keeps; `unknown`: nothing could be recovered."
          },
          "tracked": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/UtxoTracked"
              },
              {
                "type": "null"
              }
            ]
          },
          "other": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/UtxoOther"
              },
              {
                "type": "null"
              }
            ],
            "description": "`null` without the ord index, or for a spent output."
          },
          "inscriptions": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object"
            },
            "description": "`{id, sat, offset}`, `sat` and `offset` where known (`id` null when only the tracked sat is known to be inscribed)."
          },
          "inscriptions_total": {
            "type": "integer"
          },
          "runes": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object"
            },
            "description": "`{name, amount, divisibility, symbol}`; `amount` a decimal string."
          },
          "spent_in": {
            "type": [
              "object",
              "null"
            ],
            "description": "`{txid, height, time, pending, source}`: the spending transaction (`pending` while in the mempool, then with `first_seen`, `fee_rate`, `vin`, `sale`); `source` says how it was found: `fork_mempool` (the index's mempool overlay, preferred), `mempool` (bitcoind's), `sale`, `moves` or `history`. One spender, whichever said so."
          },
          "now": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object"
            },
            "description": "A spent output: where its tracked sats are now, up to 12: `{sat, len, types, kind, outpoint, offset, address, created_height, created_time}`."
          },
          "now_total": {
            "type": "integer"
          },
          "sales": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SatSale"
            },
            "description": "Sales out of the output (`direction: sold`) and into it (`bought`), newest first."
          },
          "notes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What could not be shown, and why."
          },
          "listing": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Listing"
              },
              {
                "type": "null"
              }
            ],
            "description": "The marketplace's live listing of the output, else `null`."
          },
          "pending": {
            "type": [
              "object",
              "null"
            ],
            "description": "An output a transaction still in the mempool makes: `{txid, first_seen, fee_rate}`. Absent otherwise."
          }
        },
        "required": [
          "outpoint",
          "txid",
          "vout",
          "status",
          "spent",
          "value",
          "sources",
          "contents",
          "tracked",
          "other",
          "spent_in",
          "sales",
          "notes",
          "listing"
        ]
      },
      "AddressOutput": {
        "type": "object",
        "description": "One UTXO with tracked sats.",
        "properties": {
          "outpoint": {
            "type": "string",
            "description": "`txid:vout`."
          },
          "txid": {
            "type": "string",
            "description": "Transaction."
          },
          "vout": {
            "type": "integer",
            "description": "Output index."
          },
          "value": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Value in sats."
          },
          "kind": {
            "type": "string",
            "description": "`spendable` and so on."
          },
          "created_height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The block that created it."
          },
          "created_time": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its time."
          },
          "extracted": {
            "type": "boolean",
            "description": "Extracted (isolated rare sats)."
          },
          "inscribed_sats": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Inscribed tracked sats."
          },
          "quantity": {
            "type": "integer",
            "description": "Tracked sats."
          },
          "first": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Lowest tracked sat."
          },
          "last": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Highest tracked sat."
          },
          "ranges": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "integer"
              }
            },
            "description": "Inclusive ranges."
          },
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TypeGroup"
            },
            "description": "Sats by exact type combination, rarest first."
          },
          "years": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Sats per mint year."
          },
          "year": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The year holding the most sats."
          },
          "rows": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Row counts."
          },
          "spent_by_pending": {
            "$ref": "#/components/schemas/PendingSpend"
          },
          "split_counts": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "The sats an extract's `split` may cut, per exact type combination (types sorted, joined with `+`): the row's sats as `groups` counts them, without the tracked pieces that touch block 9 or 450x (a split leaves those whole)."
          }
        },
        "required": [
          "outpoint",
          "value",
          "quantity",
          "ranges",
          "groups"
        ]
      },
      "AddressPage": {
        "type": "object",
        "description": "An address's UTXOs that hold tracked sats.",
        "properties": {
          "address": {
            "type": "string",
            "description": "The address."
          },
          "script_pubkey": {
            "type": "string",
            "description": "Its script, hex."
          },
          "chain": {
            "type": "string",
            "description": "Network."
          },
          "explorer": {
            "type": [
              "string",
              "null"
            ],
            "description": "Block explorer base URL."
          },
          "as_of": {
            "type": [
              "object",
              "null"
            ],
            "description": "`{height, hash, time}` of the index."
          },
          "totals": {
            "type": "object",
            "properties": {
              "utxos": {
                "type": "integer",
                "description": "UTXOs with tracked sats."
              },
              "sats": {
                "type": "integer",
                "description": "Tracked sats."
              },
              "value": {
                "type": "integer",
                "description": "Their value in sats."
              }
            },
            "required": [
              "utxos",
              "sats",
              "value"
            ]
          },
          "rows": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Row counts over every UTXO."
          },
          "types": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "description": "Sat type."
                },
                "utxos": {
                  "type": "integer",
                  "description": "UTXOs holding it."
                },
                "ranges": {
                  "type": "integer",
                  "description": "Contiguous runs."
                },
                "sats": {
                  "type": "integer",
                  "description": "Sats."
                }
              },
              "required": [
                "type",
                "utxos",
                "sats"
              ]
            },
            "description": "Every type the address holds."
          },
          "page": {
            "type": "object",
            "properties": {
              "offset": {
                "type": "integer",
                "description": "Offset."
              },
              "limit": {
                "type": "integer",
                "description": "Limit."
              },
              "total": {
                "type": "integer",
                "description": "UTXOs matching `types`."
              },
              "sort": {
                "type": "string",
                "description": "Sort."
              },
              "types": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Type filter."
              }
            },
            "required": [
              "offset",
              "limit",
              "total"
            ]
          },
          "outputs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AddressOutput"
            },
            "description": "One page of UTXOs."
          },
          "pending_outputs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PendingOutput"
            },
            "description": "Outputs pending transactions send it, newest first (rare sats being received); only while the index serves its mempool overlay. A UTXO being sent away carries `spent_by_pending`. `totals`, `rows` and `types` stay confirmed-only."
          }
        },
        "required": [
          "address",
          "totals",
          "page",
          "outputs"
        ]
      },
      "ActivityItem": {
        "type": "object",
        "description": "One event of an address's activity.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable id (the cursor names it)."
          },
          "type": {
            "type": "string",
            "enum": [
              "bought",
              "sold",
              "listed",
              "cancelled",
              "extraction",
              "mined",
              "transfer_in",
              "transfer_out",
              "consolidation"
            ],
            "description": "What happened, from the address's side."
          },
          "time": {
            "type": "integer",
            "description": "Unix seconds: the block's time, or the marketplace event's."
          },
          "height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Block height; null for an event off the chain (a listing)."
          },
          "tx_index": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Place in the block (null while pending)."
          },
          "txid": {
            "type": [
              "string",
              "null"
            ],
            "description": "Transaction id; null for a listing."
          },
          "tx_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "The transaction on the block explorer."
          },
          "sat": {
            "type": [
              "object",
              "null"
            ],
            "description": "The lead sat (the rarest moved, the first sold).",
            "properties": {
              "sat": {
                "type": "integer"
              },
              "types": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "sat",
              "types"
            ]
          },
          "count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Tracked sats involved."
          },
          "row": {
            "type": [
              "string",
              "null"
            ],
            "description": "The main row id (its rarest)."
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Every row id the event counts toward (the category filter)."
          },
          "price": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Sale or listing price, sats."
          },
          "unit_price": {
            "type": [
              "number",
              "null"
            ],
            "description": "Price per sat of `row`, over the sold output's own value."
          },
          "marketplace": {
            "type": [
              "string",
              "null"
            ],
            "description": "Marketplace id, for sales and listings."
          },
          "inscribed": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "A sale of an inscribed sat."
          },
          "outlier": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "A sale far from its row's median."
          },
          "secondary": {
            "$ref": "#/components/schemas/SecondaryRows"
          },
          "value": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Sats in the UTXOs received or sent, for a transfer."
          },
          "extracted": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "The rare sats arrived in (or left) an extracted UTXO."
          },
          "counterparty": {
            "type": [
              "string",
              "null"
            ],
            "description": "The other side's main address: the seller of a purchase, the buyer of a sale, the sender or recipient of a transfer."
          },
          "counterparties": {
            "type": [
              "integer",
              "null"
            ],
            "description": "How many addresses were on the other side."
          },
          "source": {
            "type": "string",
            "enum": [
              "sales",
              "market",
              "history",
              "moves",
              "holdings",
              "mempool"
            ],
            "description": "Where it comes from: the sales index, the marketplace, the per-address history, the retained moves, a held UTXO's creation, or the index's mempool overlay (pending)."
          },
          "seq": {
            "type": "integer",
            "description": "The sale's sequence number (sales only)."
          },
          "outpoint": {
            "type": [
              "string",
              "null"
            ],
            "description": "The listed UTXO (listings only)."
          },
          "burn": {
            "type": "boolean",
            "description": "A `transfer_out` to an unspendable output."
          },
          "pending": {
            "type": "boolean",
            "description": "Not yet in a block: a pending transaction (`source: mempool`, with `first_seen` and `fee_rate`, no `height`), or a sale bought or sold on raresats.net the index has not read yet (`source: market`). Only the first page lists the former, first."
          },
          "first_seen": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When the transaction was first seen in the mempool (bitcoind's entry time), unix seconds."
          },
          "fee_rate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Its fee rate, sat/vB (one decimal)."
          }
        },
        "required": [
          "id",
          "type",
          "time",
          "height",
          "txid",
          "rows",
          "source"
        ]
      },
      "AddressActivity": {
        "type": "object",
        "description": "A page of an address's activity, with facets and totals.",
        "properties": {
          "address": {
            "type": "string",
            "description": "The address."
          },
          "as_of": {
            "type": [
              "object",
              "null"
            ],
            "description": "`{height, time}` of the index."
          },
          "explorer": {
            "type": [
              "string",
              "null"
            ],
            "description": "Block explorer base URL."
          },
          "coverage": {
            "type": "object",
            "description": "How complete each source is.",
            "properties": {
              "sales": {
                "type": "string",
                "enum": [
                  "complete",
                  "loading",
                  "unavailable"
                ],
                "description": "Sales: every one, from the sales index."
              },
              "transfers": {
                "type": "string",
                "description": "`since block N`: transfers and extractions from block N on (the history's start, or the retained moves'), and before it only the held UTXOs; `complete` (a history from genesis, read whole); `holdings` (only the held UTXOs); or `unavailable`."
              },
              "transfers_since": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "N of `since block N`; null when `complete`."
              },
              "source": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "fork_history",
                  "moves_window",
                  "holdings",
                  null
                ],
                "description": "Where transfers come from."
              },
              "history_from": {
                "type": "object",
                "description": "Where the per-address history begins (the ordinals era, the fork's `address_history_from_height`): `{height, time}`.",
                "properties": {
                  "height": {
                    "type": "integer"
                  },
                  "time": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  }
                },
                "required": [
                  "height"
                ]
              },
              "history_complete": {
                "type": "boolean",
                "description": "Whether the whole history has been read (the fork has no more pages). Until then the totals and facets cover the history read so far, and pages read further as they go."
              },
              "loaded_since": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "While the history is read in part: the oldest block read so far."
              },
              "loaded_since_time": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Its time, unix seconds."
              },
              "market": {
                "type": "string",
                "enum": [
                  "complete",
                  "off",
                  "unavailable"
                ],
                "description": "raresats.net listings."
              },
              "error": {
                "type": "string",
                "description": "Set when the index could not be read: transfers may be missing."
              }
            },
            "required": [
              "sales",
              "transfers",
              "source",
              "market"
            ]
          },
          "summary": {
            "type": "object",
            "description": "Totals over all of the address's activity known (no filter): sales and listings whole, the history as far as read.",
            "properties": {
              "bought": {
                "type": "object",
                "properties": {
                  "count": {
                    "type": "integer"
                  },
                  "volume": {
                    "type": "integer",
                    "description": "Sats."
                  }
                },
                "required": [
                  "count",
                  "volume"
                ]
              },
              "sold": {
                "type": "object",
                "properties": {
                  "count": {
                    "type": "integer"
                  },
                  "volume": {
                    "type": "integer",
                    "description": "Sats."
                  }
                },
                "required": [
                  "count",
                  "volume"
                ]
              },
              "extractions": {
                "type": "integer"
              },
              "listed": {
                "type": "integer"
              },
              "transfers": {
                "type": "integer",
                "description": "Transfers, consolidations and mined."
              },
              "first_time": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Unix seconds of the first activity shown."
              },
              "last_time": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Unix seconds of the last."
              },
              "partial": {
                "type": "boolean",
                "description": "True while the history is read in part: the extraction and transfer counts and the first activity cover the history read so far."
              }
            },
            "required": [
              "bought",
              "sold",
              "extractions",
              "first_time",
              "last_time",
              "partial"
            ]
          },
          "facets": {
            "type": "object",
            "description": "Counts for the filters, each under every other filter set, over the activity known (the history as far as read).",
            "properties": {
              "types": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                },
                "description": "By type."
              },
              "rows": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                },
                "description": "By row id."
              },
              "years": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                },
                "description": "By UTC year."
              },
              "marketplaces": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                },
                "description": "By marketplace id."
              }
            },
            "required": [
              "types",
              "rows",
              "years",
              "marketplaces"
            ]
          },
          "rows": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "label": {
                  "type": "string"
                },
                "all_of": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              },
              "required": [
                "label",
                "all_of"
              ]
            },
            "description": "The rows named on the page and in the facets: label and types."
          },
          "query": {
            "type": "object",
            "description": "The filters applied."
          },
          "total": {
            "type": "integer",
            "description": "Events matching the filters among those known (the history as far as read; see `summary.partial`)."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ActivityItem"
            },
            "description": "One page, newest first."
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "description": "The cursor of the next page (pass as `before`), or null at the end. While the history is read in part, a page may hold fewer events than `limit`, even none, with a `next` that reads further."
          },
          "pending_total": {
            "type": "integer",
            "description": "Pending items leading `items` (first page only; outside `total`, the facets and the summary)."
          }
        },
        "required": [
          "address",
          "coverage",
          "summary",
          "facets",
          "rows",
          "total",
          "items",
          "next"
        ]
      },
      "Feed": {
        "type": "object",
        "description": "A JSON object; see the description for its main fields.",
        "additionalProperties": true
      },
      "AffiliateStats": {
        "type": "object",
        "description": "What an affiliate earned: only purchases whose referral applied (an affiliate output is in the transaction).",
        "properties": {
          "address": {
            "type": "string",
            "description": "The affiliate's address, normalized."
          },
          "registered": {
            "type": "boolean",
            "description": "Informational, kept for compatibility: whether the address used the optional registration. Not needed to be paid: any address is an affiliate."
          },
          "registered_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When it used the optional registration (unix seconds), or `null`."
          },
          "share_bps": {
            "type": "integer",
            "description": "The affiliate's share of the platform fee in force, basis points."
          },
          "totals": {
            "type": "object",
            "properties": {
              "purchases": {
                "type": "integer",
                "description": "Referred purchases broadcast through the marketplace (pending or confirmed)."
              },
              "confirmed": {
                "type": "integer",
                "description": "Of those, confirmed."
              },
              "pending": {
                "type": "integer",
                "description": "Of those, in the mempool."
              },
              "earned": {
                "type": "integer",
                "description": "Sats paid to the affiliate in confirmed purchases."
              },
              "pending_earned": {
                "type": "integer",
                "description": "Sats in purchases still in the mempool."
              },
              "volume": {
                "type": "integer",
                "description": "Summed listing prices of the referred purchases."
              }
            },
            "required": [
              "purchases",
              "confirmed",
              "pending",
              "earned",
              "pending_earned",
              "volume"
            ],
            "additionalProperties": false
          },
          "purchases": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "txid": {
                  "type": "string",
                  "description": "The purchase transaction."
                },
                "items": {
                  "type": "integer",
                  "description": "Listings bought."
                },
                "prices": {
                  "type": "integer",
                  "description": "Their summed prices."
                },
                "platform_fee": {
                  "type": "integer",
                  "description": "The platform fee the buyer paid."
                },
                "affiliate_fee": {
                  "type": "integer",
                  "description": "The affiliate's output."
                },
                "status": {
                  "type": "string",
                  "description": "`pending` or `confirmed`.",
                  "enum": [
                    "pending",
                    "confirmed"
                  ]
                },
                "time": {
                  "type": "integer",
                  "description": "Unix seconds."
                }
              },
              "required": [
                "txid",
                "items",
                "prices",
                "platform_fee",
                "affiliate_fee",
                "status",
                "time"
              ],
              "additionalProperties": false
            },
            "description": "The 25 newest referred purchases, newest first."
          }
        },
        "required": [
          "address",
          "registered",
          "registered_at",
          "share_bps",
          "totals",
          "purchases"
        ],
        "additionalProperties": false
      },
      "Prices": {
        "type": "object",
        "description": "BTC/USD, from mempool.space, as the site's USD tooltips use it.",
        "properties": {
          "current": {
            "type": [
              "object",
              "null"
            ],
            "description": "The BTC price now: `usd` (dollars) and `time` (unix seconds of the quote). `null` while the source is down (after an hour of last good values).",
            "properties": {
              "usd": {
                "type": "number",
                "description": "Dollars per bitcoin."
              },
              "time": {
                "type": "integer",
                "description": "Unix seconds."
              }
            },
            "required": [
              "usd",
              "time"
            ],
            "additionalProperties": false
          },
          "history": {
            "type": [
              "object",
              "null"
            ],
            "description": "One price a UTC day: `usd[i]` is the day starting `start + i × step`. `null` while unavailable.",
            "properties": {
              "start": {
                "type": "integer",
                "description": "Unix seconds of the first day (2010-07-19)."
              },
              "step": {
                "const": 86400,
                "description": "Seconds per entry: one day."
              },
              "usd": {
                "type": "array",
                "items": {
                  "type": "number"
                },
                "description": "Daily dollars per bitcoin (the mean of the day's quotes; 4 significant digits under $100, whole dollars above)."
              }
            },
            "required": [
              "start",
              "step",
              "usd"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "current",
          "history"
        ],
        "additionalProperties": false
      },
      "Filter": {
        "type": "object",
        "description": "The filter as the server understood it.",
        "properties": {
          "years": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "The years asked for (ascending), `[]` for none."
          },
          "month": {
            "type": [
              "string",
              "null"
            ],
            "description": "The month asked for (`YYYY-MM`), `null` for none."
          },
          "date": {
            "type": [
              "string",
              "null"
            ],
            "description": "The day asked for."
          },
          "md": {
            "type": [
              "string",
              "null"
            ],
            "description": "The month-day asked for."
          },
          "blocks": {
            "type": [
              "object",
              "null"
            ],
            "description": "The blocks asked for: `{from, to}`, heights inclusive (one block: `from` = `to`), `null` for none.",
            "properties": {
              "from": {
                "type": "integer"
              },
              "to": {
                "type": "integer"
              }
            },
            "required": [
              "from",
              "to"
            ],
            "additionalProperties": false
          },
          "luck": {
            "type": [
              "object",
              "null"
            ],
            "description": "The luck asked for: `{min, max}` (`max` `null` for a minimum alone), `null` for none.",
            "properties": {
              "min": {
                "type": "integer"
              },
              "max": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            },
            "required": [
              "min",
              "max"
            ],
            "additionalProperties": false
          },
          "sub": {
            "type": [
              "string",
              "null"
            ],
            "description": "The sub-category asked for."
          },
          "subs": {
            "type": "boolean",
            "description": "Whether sub-category items are included (absent on events and counts)."
          },
          "led": {
            "type": "boolean",
            "description": "Whether sales led by another row are included (`led=1`; sales only)."
          }
        },
        "required": [
          "years",
          "date",
          "md",
          "sub"
        ],
        "additionalProperties": false
      },
      "Match": {
        "type": [
          "object",
          "null"
        ],
        "description": "The sat that made the item pass a date or luck filter: its number, block, mint day (UTC) and luck. `null` without such a filter.",
        "properties": {
          "sat": {
            "type": "integer",
            "description": "The sat."
          },
          "height": {
            "type": "integer",
            "description": "The block that mined it."
          },
          "date": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its mint day, YYYY-MM-DD."
          },
          "luck": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its luck (its block's: the leading zero bits of the block hash less the target's); `null` while the luck table is being read."
          }
        },
        "required": [
          "sat",
          "height",
          "date"
        ],
        "additionalProperties": false
      },
      "LeadSat": {
        "type": [
          "object",
          "null"
        ],
        "description": "The listing's lead sat: the sat that matched a date or luck filter, else the first sat of its rarest combination of types; its number, block, mint day (UTC) and luck (the grid's Luck column). `null` when the listing names no sat.",
        "properties": {
          "sat": {
            "type": "integer",
            "description": "The sat."
          },
          "height": {
            "type": "integer",
            "description": "The block that mined it."
          },
          "date": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its mint day, YYYY-MM-DD (UTC); `null` while the day table is being read."
          },
          "luck": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its luck (its block's: the leading zero bits of the block hash less the target's); `null` while the luck table is being read."
          }
        },
        "required": [
          "sat",
          "height",
          "date"
        ],
        "additionalProperties": false
      },
      "UtxoBlock": {
        "type": [
          "object",
          "null"
        ],
        "description": "The block that created the listed UTXO and that block's day (UTC), as the marketplace's last check of its listings saw it. `null` before the first check after the listing, or while the UTXO is unconfirmed.",
        "properties": {
          "height": {
            "type": "integer",
            "description": "The block height."
          },
          "date": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its day, YYYY-MM-DD (UTC); `null` while the day table is being read."
          }
        },
        "required": [
          "height",
          "date"
        ],
        "additionalProperties": false
      },
      "Facets": {
        "type": "object",
        "description": "Counts for refining the filter.",
        "properties": {
          "years": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Matching items per mint year (each item counted once per year it holds)."
          },
          "luck": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Luck minimums: `{N: items holding a sat of luck N or more}` from N = 1 up to the highest, counting the filter but its `luck` (what `luck=N` would match). `{}` while the luck table is being read."
          },
          "subs": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "row": {
                  "type": "string",
                  "description": "A sub-category row."
                },
                "count": {
                  "type": "integer",
                  "description": "Matching items holding it."
                }
              },
              "required": [
                "row",
                "count"
              ],
              "additionalProperties": false
            },
            "description": "The row's sub-categories, in the index's order (`[]` without a row)."
          },
          "rows": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Without `row`: matching items per own row."
          },
          "types": {
            "$ref": "#/components/schemas/SaleTypeBreakdown"
          }
        },
        "required": [
          "years",
          "subs"
        ]
      },
      "SaleTypeBreakdown": {
        "type": "object",
        "description": "`/api/sales/query` with a `row` only: the row's sales that pass the filter (its sub-categories' sales too, whatever `subs` says; never those another row led) by kind, the set of exact type combinations each sold. A plain uncommon, an alpha uncommon and an alpha uncommon sold with a black omega are three kinds: the rarer ones show what skews the row's prices.",
        "properties": {
          "kinds": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "types": {
                  "type": "array",
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "description": "The type combinations its sales sold, each in the badges' order, the lead row's first (`[[\"uncommon\", \"alpha\"], [\"black\", \"omega\"]]`). `[]` for sales the fork typed none of."
                },
                "row": {
                  "type": "string",
                  "description": "The own row of its first sale counted: a sub-category of `row` (the `sub` that filters to it) or `row` itself."
                },
                "count": {
                  "type": "integer",
                  "description": "Its sales."
                },
                "priced": {
                  "type": "integer",
                  "description": "Those the median is of: inscribed, outlier and free sales aside."
                },
                "median": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Their median unit price per sat of `row`, to the hundredth of a sat; `null` with none priced."
                }
              },
              "required": [
                "types",
                "row",
                "count",
                "priced",
                "median"
              ],
              "additionalProperties": false
            },
            "description": "The 12 commonest kinds, by sales, most first."
          },
          "other": {
            "type": "object",
            "properties": {
              "kinds": {
                "type": "integer",
                "description": "Kinds not listed."
              },
              "count": {
                "type": "integer",
                "description": "Their sales."
              }
            },
            "required": [
              "kinds",
              "count"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "kinds",
          "other"
        ],
        "additionalProperties": false
      },
      "FilteredSale": {
        "type": "object",
        "properties": {
          "seq": {
            "type": "integer",
            "description": "The sale's sequence number."
          },
          "time": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "height": {
            "type": "integer",
            "description": "Block height."
          },
          "row": {
            "type": "string",
            "description": "The row it is shown as (its own, or one it is a sub-category of or a secondary row of)."
          },
          "own": {
            "type": "string",
            "description": "Its own row."
          },
          "sub": {
            "type": "boolean",
            "description": "A sub-category sale shown under `row`."
          },
          "led": {
            "type": "boolean",
            "description": "A sale led by another row, shown under `row`, one of its secondary rows (with `led=1`)."
          },
          "secondary": {
            "$ref": "#/components/schemas/SecondaryRows"
          },
          "types": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TypeGroup"
            },
            "description": "The sats it sold grouped by exact type combination: the group of its own row's sat first, then rarest first (an alpha uncommon sold with a black omega: `uncommon, alpha` then `black, omega`). A piece longer than one sat (a block 9 chunk) counts under its first sat's types. `[]` when the fork typed none."
          },
          "unit": {
            "type": [
              "number",
              "null"
            ],
            "description": "Unit price per sat of `row`."
          },
          "count": {
            "type": "integer",
            "description": "Sats of `row` sold."
          },
          "price": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Price in sats."
          },
          "sats": {
            "type": "integer",
            "description": "Tracked sats sold."
          },
          "sat": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The first special sat sold."
          },
          "sat_height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The block that mined it."
          },
          "mined": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its mint day, YYYY-MM-DD."
          },
          "match": {
            "$ref": "#/components/schemas/Match"
          },
          "market": {
            "type": "string",
            "description": "Marketplace id."
          },
          "tx": {
            "type": [
              "string",
              "null"
            ],
            "description": "The txid's first 8 and last 4 hex digits (`/api/sales/{seq}/tx` redirects)."
          },
          "inscribed": {
            "type": "boolean",
            "description": "An inscription was on a sold sat."
          },
          "outlier": {
            "type": "boolean",
            "description": "A statistical outlier."
          },
          "seller": {
            "type": [
              "string",
              "null"
            ],
            "description": "The seller's address."
          },
          "buyer": {
            "type": [
              "string",
              "null"
            ],
            "description": "The buyer's address."
          }
        },
        "required": [
          "seq",
          "time",
          "height",
          "row",
          "own",
          "sub",
          "led",
          "secondary",
          "types",
          "unit",
          "count",
          "price",
          "sats",
          "sat",
          "sat_height",
          "mined",
          "match",
          "market",
          "tx",
          "inscribed",
          "outlier",
          "seller",
          "buyer"
        ],
        "additionalProperties": false
      },
      "SalesQuery": {
        "type": "object",
        "properties": {
          "available": {
            "type": "boolean",
            "description": "Whether the sales index is available."
          },
          "generation": {
            "type": "integer",
            "description": "Sales generation (a reorg starts a new one)."
          },
          "seq": {
            "type": "integer",
            "description": "The newest sale's sequence number."
          },
          "as_of": {
            "type": [
              "object",
              "null"
            ],
            "description": "`{height, time}` of the sales."
          },
          "row": {
            "type": [
              "string",
              "null"
            ],
            "description": "The row asked for."
          },
          "filter": {
            "$ref": "#/components/schemas/Filter"
          },
          "total": {
            "type": "integer",
            "description": "Matching sales (all pages)."
          },
          "kinds": {
            "type": "object",
            "description": "Of `total`, how the sales are under `row`: `own` (its own sales, the only ones in its stats and line), `sub` (a rarer sub-category's, with `subs=1`) and `led` (led by another row, with `led=1`). Without `row`, every sale is `own`.",
            "properties": {
              "own": {
                "type": "integer"
              },
              "sub": {
                "type": "integer"
              },
              "led": {
                "type": "integer"
              }
            },
            "required": [
              "own",
              "sub",
              "led"
            ],
            "additionalProperties": false
          },
          "facets": {
            "$ref": "#/components/schemas/Facets"
          },
          "sales": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FilteredSale"
            },
            "description": "One page, newest first."
          },
          "next": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Pass as `before` for the next page; `null` on the last."
          },
          "ms": {
            "type": "integer",
            "description": "Server time spent, ms."
          }
        },
        "required": [
          "available",
          "generation",
          "seq",
          "as_of",
          "row",
          "filter",
          "total",
          "kinds",
          "facets",
          "sales",
          "next",
          "ms"
        ],
        "additionalProperties": false
      },
      "FilteredListing": {
        "type": "object",
        "description": "A [Listing](/docs/listing-object) plus `match`, `lead` and `utxo`.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The listing id: 16 lowercase hex characters.",
            "pattern": "^[0-9a-f]{16}$"
          },
          "outpoint": {
            "type": "string",
            "description": "The listed UTXO, `txid:vout`.",
            "pattern": "^[0-9a-f]{64}:\\d+$"
          },
          "value": {
            "type": "integer",
            "description": "The UTXO's own value in sats (it moves to the buyer whole)."
          },
          "price": {
            "type": "integer",
            "description": "The listing price in sats: exactly what the seller receives. The buyer pays this plus the platform fee and the network fee."
          },
          "unit_price": {
            "type": "number",
            "description": "Price per sat of the listing's own row: `(price - value) / count`, to the hundredth of a sat. Floors and the `unit` sort use it."
          },
          "row": {
            "type": "string",
            "description": "The listing's own row (collection): the rarest market row holding every tracked sat of the UTXO, else the rarest market row present. Never a label row."
          },
          "count": {
            "type": "integer",
            "description": "How many sats of `row` the UTXO holds (the \"×N\" of a bulk listing)."
          },
          "rows": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Every row the UTXO's tracked sats count toward, with their counts (label rows included)."
          },
          "types": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/TypeGroup"
            },
            "description": "The UTXO's sats grouped by exact type combination, rarest first."
          },
          "sats": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Tracked sats in the UTXO (all rows)."
          },
          "ranges": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "array",
              "items": {
                "type": "integer"
              },
              "minItems": 2,
              "maxItems": 2
            },
            "description": "The tracked sats as inclusive `[first, last]` ranges, ascending."
          },
          "years": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Tracked sats per mint year (UTC year of the block that mined them)."
          },
          "seller_address": {
            "type": "string",
            "description": "The address that holds the UTXO and signed the listing."
          },
          "payout_address": {
            "type": "string",
            "description": "Where the price is paid (the seller's payment output)."
          },
          "status": {
            "type": "string",
            "description": "`active` (for sale), `pending` (a purchase is in the mempool), `sold`, `cancelled` (or replaced by a newer listing of the same UTXO), `moved` (spent elsewhere).",
            "enum": [
              "active",
              "pending",
              "sold",
              "cancelled",
              "moved"
            ]
          },
          "created_at": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "updated_at": {
            "type": "integer",
            "description": "Unix seconds of the last status change."
          },
          "txid": {
            "type": [
              "string",
              "null"
            ],
            "description": "The purchase transaction, while `pending` and once `sold`; otherwise `null`."
          },
          "signature_public": {
            "type": "boolean",
            "description": "`true` once a broadcast purchase put the seller's signature on the network: the listing can then be bought at this price anywhere until the UTXO moves, even after a cancel here."
          },
          "sold_via": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "offer",
              null
            ],
            "description": "`offer` when the listing ended `sold` through an accepted offer of its UTXO: `price` and `unit_price` are then the offer's (what was paid), `offer_id` names it. `null` otherwise."
          },
          "offer_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The accepted offer it was sold through (`sold_via: \"offer\"`), else `null`."
          },
          "match": {
            "$ref": "#/components/schemas/Match"
          },
          "best_offer": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/BestOffer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The best active offer on the UTXO, or `null`."
          },
          "lead": {
            "$ref": "#/components/schemas/LeadSat"
          },
          "utxo": {
            "$ref": "#/components/schemas/UtxoBlock"
          },
          "in_bundle": {
            "type": "boolean",
            "description": "Only on a listing read for a row it holds some sats of among others (in bundle: `contains=1`'s `contains`, or a row's activity): `true`. Its `price` is the whole UTXO's and its `unit_price` its own row's, never the row asked for."
          },
          "contains_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "With `in_bundle`: how many sats of the row asked for it holds."
          }
        },
        "required": [
          "id",
          "outpoint",
          "value",
          "price",
          "unit_price",
          "row",
          "count",
          "rows",
          "types",
          "sats",
          "ranges",
          "years",
          "seller_address",
          "payout_address",
          "status",
          "created_at",
          "updated_at",
          "txid",
          "signature_public",
          "sold_via",
          "offer_id",
          "best_offer",
          "match",
          "lead",
          "utxo"
        ],
        "additionalProperties": false
      },
      "ListingsQuery": {
        "type": "object",
        "properties": {
          "row": {
            "type": [
              "string",
              "null"
            ],
            "description": "The row asked for."
          },
          "filter": {
            "$ref": "#/components/schemas/Filter"
          },
          "total": {
            "type": "integer",
            "description": "Matching active listings."
          },
          "facets": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Facets"
              },
              {
                "type": "null"
              }
            ],
            "description": "Counts for refining the filter; `null` with `contains=only`."
          },
          "listings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FilteredListing"
            },
            "description": "One page, in the requested order."
          },
          "as_of": {
            "$ref": "#/components/schemas/AsOf"
          },
          "ms": {
            "type": "integer",
            "description": "Server time spent, ms."
          },
          "contains": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FilteredListing"
            },
            "description": "Only with `contains=1`: the first `limit` listings passing the filter that hold some sats of the row among others (in bundle, each `in_bundle: true`, its `lead` its first sat of the row), by total price, the cheapest first. Never in `listings`, `total` or `facets`."
          },
          "contains_total": {
            "type": "integer",
            "description": "Only with `contains=1`: how many such listings pass (all pages; `contains=only` pages them)."
          }
        },
        "required": [
          "row",
          "filter",
          "total",
          "listings",
          "as_of",
          "ms"
        ],
        "additionalProperties": false
      },
      "FilteredEvent": {
        "type": "object",
        "description": "An [activity event](/docs/get-activity) plus the sat that matched.",
        "properties": {
          "seq": {
            "type": "integer",
            "description": "Event sequence number (rising)."
          },
          "type": {
            "type": "string",
            "description": "What happened.",
            "enum": [
              "listed",
              "cancelled",
              "sold"
            ]
          },
          "listing_id": {
            "type": "string",
            "description": "The listing."
          },
          "outpoint": {
            "type": "string",
            "description": "The listed UTXO."
          },
          "row": {
            "type": "string",
            "description": "The listing's own row."
          },
          "count": {
            "type": "integer",
            "description": "Sats of that row."
          },
          "price": {
            "type": "integer",
            "description": "The listing price in sats."
          },
          "unit_price": {
            "type": "number",
            "description": "The listing's unit price."
          },
          "seller_address": {
            "type": "string",
            "description": "The seller (same as `seller`)."
          },
          "txid": {
            "type": [
              "string",
              "null"
            ],
            "description": "The purchase transaction of a `sold` event; `null` otherwise."
          },
          "time": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "seller": {
            "type": [
              "string",
              "null"
            ],
            "description": "The seller's address."
          },
          "buyer": {
            "type": [
              "string",
              "null"
            ],
            "description": "A sale's buyer: the address the sats went to. `null` for other events, or when unknown."
          },
          "affiliate": {
            "type": [
              "string",
              "null"
            ],
            "description": "A sale bought here with an applied referral: the affiliate it paid. `null` otherwise."
          },
          "sat": {
            "type": "integer",
            "description": "The sat that matched (absent without one)."
          },
          "match": {
            "$ref": "#/components/schemas/Match"
          },
          "offer_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The offer, on an offer event; `null` otherwise."
          },
          "bidder": {
            "type": [
              "string",
              "null"
            ],
            "description": "The bidder's payment address, on an offer event; `null` otherwise."
          },
          "sub": {
            "type": "boolean",
            "description": "Only on an event read for a row (`row=`) that is not its own row but holds every tracked sat of the item (a sub-category or a label row): `true`."
          },
          "in_bundle": {
            "type": "boolean",
            "description": "Only on an event read for a row (`row=`) whose listing or offer holds some sats of that row among others (in bundle, e.g. a Block 9 chunk under `block9_palindrome`): `true`. Its price and unit price are those of its own `row`."
          },
          "contains_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "With `in_bundle`: how many sats of the row asked for the item holds."
          }
        },
        "required": [
          "seq",
          "type",
          "listing_id",
          "outpoint",
          "row",
          "count",
          "price",
          "unit_price",
          "seller_address",
          "txid",
          "time",
          "seller",
          "buyer",
          "affiliate",
          "offer_id",
          "bidder",
          "match"
        ],
        "additionalProperties": false
      },
      "ListingEvents": {
        "type": "object",
        "properties": {
          "row": {
            "type": [
              "string",
              "null"
            ],
            "description": "The row asked for."
          },
          "filter": {
            "$ref": "#/components/schemas/Filter"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FilteredEvent"
            },
            "description": "Newest first."
          }
        },
        "required": [
          "row",
          "filter",
          "events"
        ],
        "additionalProperties": false
      },
      "BirthdayCounts": {
        "type": "object",
        "properties": {
          "filter": {
            "$ref": "#/components/schemas/Filter"
          },
          "days": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string",
                  "description": "The day, YYYY-MM-DD."
                },
                "from": {
                  "type": "integer",
                  "description": "Its first block."
                },
                "to": {
                  "type": "integer",
                  "description": "Its last block."
                },
                "rows": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "integer"
                  },
                  "description": "Tracked sats mined that day the index locates, per row (rows with none absent)."
                }
              },
              "required": [
                "date",
                "from",
                "to",
                "rows"
              ],
              "additionalProperties": false
            },
            "description": "Each day counted (one for `date`; that day of every year for `md`)."
          },
          "rows": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "The days' counts summed per row."
          },
          "ms": {
            "type": "integer",
            "description": "Server time spent, ms."
          }
        },
        "required": [
          "filter",
          "days",
          "rows",
          "ms"
        ],
        "additionalProperties": false
      },
      "Days": {
        "type": "object",
        "description": "The mint-day table: which UTC day mined each block. A sat's mint day is its block's.",
        "properties": {
          "ready": {
            "type": "boolean",
            "description": "Whether the table is read (date filters answer 503 until then)."
          },
          "version": {
            "type": "integer",
            "description": "Format version."
          },
          "genesis": {
            "type": [
              "string",
              "null"
            ],
            "description": "The genesis block hash."
          },
          "first_day": {
            "type": "integer",
            "description": "The first UTC day (days since 1970) of the table."
          },
          "height": {
            "type": "integer",
            "description": "The last height covered."
          },
          "hash": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its hash."
          },
          "starts": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Each day's first height, as deltas: `starts[0]` is the first day's, then each the difference from the day before."
          },
          "exceptions": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Blocks whose time is out of order, as flat pairs `[height, day, …]`: the day each belongs to."
          },
          "tail": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Recent, not yet final headers as flat pairs `[height, time, …]`."
          },
          "build_ms": {
            "type": [
              "integer",
              "null"
            ],
            "description": "How long the last build took."
          }
        },
        "required": [
          "ready",
          "first_day",
          "height",
          "starts",
          "exceptions",
          "tail"
        ]
      },
      "AffiliateRegisterRequest": {
        "type": "object",
        "description": "A payout address's registration: its BIP-322 signature of the message.",
        "properties": {
          "address": {
            "type": "string",
            "description": "The payout address: Taproot, native SegWit or nested SegWit (it must sign BIP-322)."
          },
          "message": {
            "type": "string",
            "description": "`raresats.net affiliate <address> <unix seconds>`, at most 10 minutes old (2 minutes ahead at most), usable once."
          },
          "signature": {
            "type": "string",
            "description": "The BIP-322 signature of `message` by `address` (base64), as wallets' signMessage makes it."
          },
          "wallet_addresses": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 4,
            "description": "Optional: the registering wallet's other addresses (payment and ordinals). A purchase by any of them never pays this affiliate."
          }
        },
        "required": [
          "address",
          "message",
          "signature"
        ],
        "additionalProperties": false
      },
      "AffiliateRegisterResponse": {
        "type": "object",
        "properties": {
          "affiliate": {
            "type": "object",
            "properties": {
              "address": {
                "type": "string",
                "description": "The registered payout address, normalized."
              },
              "registered_at": {
                "type": "integer",
                "description": "When it first registered (unix seconds)."
              },
              "wallet_addresses": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Every address recorded for it: the payout and the registering wallets' addresses."
              }
            },
            "required": [
              "address",
              "registered_at",
              "wallet_addresses"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "affiliate"
        ],
        "additionalProperties": false
      },
      "BestOffer": {
        "type": "object",
        "description": "The best active offer on a UTXO, as a listing shows it: the highest price, the oldest first.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The offer id.",
            "pattern": "^[0-9a-f]{16}$"
          },
          "price": {
            "type": "integer",
            "description": "What the seller would receive, in sats."
          },
          "unit_price": {
            "type": "number",
            "description": "`(price - value) / count` of the UTXO's own row, to the hundredth of a sat."
          },
          "bidder_payment_address": {
            "type": "string",
            "description": "The bidder's payment address."
          },
          "bidder_ordinals_address": {
            "type": "string",
            "description": "Where the bidder receives the UTXO."
          },
          "created_at": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "expires_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Unix seconds; `null`: no expiry."
          }
        },
        "required": [
          "id",
          "price",
          "unit_price",
          "bidder_payment_address",
          "bidder_ordinals_address",
          "created_at",
          "expires_at"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "id": "dbf866a1e7e209e7",
            "price": 100000,
            "unit_price": 15.92,
            "bidder_payment_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
            "bidder_ordinals_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
            "created_at": 1790953585,
            "expires_at": 1791558385
          }
        ]
      },
      "Offer": {
        "type": "object",
        "description": "An offer (bid) on one UTXO. The bidder's signatures are never part of it.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The offer id: 16 lowercase hex characters.",
            "pattern": "^[0-9a-f]{16}$"
          },
          "kind": {
            "type": "string",
            "enum": [
              "item"
            ],
            "description": "What the offer is on: `item`, one UTXO (the only kind so far)."
          },
          "outpoint": {
            "type": "string",
            "description": "The UTXO bid on, `txid:vout`.",
            "pattern": "^[0-9a-f]{64}:\\d+$"
          },
          "value": {
            "type": "integer",
            "description": "The UTXO's own value in sats (it moves to the bidder whole)."
          },
          "seller_address": {
            "type": "string",
            "description": "The address that held the UTXO when the offer was made: it receives `price`, and only it can accept."
          },
          "price": {
            "type": "integer",
            "description": "The offer price in sats: exactly what the seller receives (output 1)."
          },
          "platform_fee": {
            "type": "integer",
            "description": "The bidder's platform fee: 2.5% of `price`, at least 546 sats."
          },
          "fee_rate": {
            "type": "number",
            "description": "The network fee rate in sat/vB, fixed by the bidder's signature."
          },
          "network_fee": {
            "type": "integer",
            "description": "The network fee in sats."
          },
          "total": {
            "type": "integer",
            "description": "What the bidder pays: `price + platform_fee + network_fee`."
          },
          "vsize": {
            "type": "integer",
            "description": "The transaction's estimated virtual size."
          },
          "unit_price": {
            "type": "number",
            "description": "`(price - value) / count`, to the hundredth of a sat, as listings."
          },
          "row": {
            "type": "string",
            "description": "The listing's own row (collection): the rarest market row holding every tracked sat of the UTXO, else the rarest market row present. Never a label row."
          },
          "count": {
            "type": "integer",
            "description": "How many sats of `row` the UTXO holds (the \"×N\" of a bulk listing)."
          },
          "rows": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Every row the UTXO's tracked sats count toward, with their counts (label rows included)."
          },
          "types": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "$ref": "#/components/schemas/TypeGroup"
            },
            "description": "The UTXO's sats grouped by exact type combination, rarest first."
          },
          "sats": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Tracked sats in the UTXO (all rows)."
          },
          "ranges": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "array",
              "items": {
                "type": "integer"
              },
              "minItems": 2,
              "maxItems": 2
            },
            "description": "The tracked sats as inclusive `[first, last]` ranges, ascending."
          },
          "years": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Tracked sats per mint year (UTC year of the block that mined them)."
          },
          "bidder_payment_address": {
            "type": "string",
            "description": "The bidder's payment address: it funds the offer and gets the change."
          },
          "bidder_ordinals_address": {
            "type": "string",
            "description": "Where the bidder receives the UTXO (output 0)."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "pending",
              "accepted",
              "cancelled",
              "expired",
              "invalid"
            ],
            "description": "`active` (can be accepted), `pending` (accepted, in the mempool), `accepted` (confirmed), `cancelled` (by the bidder), `expired`, `invalid` (the UTXO moved or the bidder's funds were spent)."
          },
          "created_at": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "updated_at": {
            "type": "integer",
            "description": "Unix seconds of the last status change."
          },
          "expires_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Unix seconds after which it can no longer be accepted; `null`: no expiry (until cancelled, accepted or invalid)."
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "utxo_spent",
              "utxo_moved",
              "funding_spent",
              "config_changed",
              null
            ],
            "description": "Why an `invalid` offer is: `utxo_spent` (the UTXO was sold here otherwise: its listing bought, or another offer accepted), `utxo_moved` (spent elsewhere), `funding_spent` (a UTXO funding it was spent), `config_changed` (the marketplace's fee settings changed since it was made). `null` in every other status."
          },
          "txid": {
            "type": [
              "string",
              "null"
            ],
            "description": "The accepting transaction, while `pending` and once `accepted`; otherwise `null`."
          },
          "listing_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The UTXO's live listing, if it is listed."
          },
          "acceptance_public": {
            "type": "boolean",
            "description": "`true` once an acceptance the server broadcast left the mempool unconfirmed: that fully signed transaction is public and can still confirm, even after a cancel or expiry here (the offer then ends `accepted`), until the bidder spends a funding UTXO or the UTXO moves. Back to `false` once it no longer can."
          },
          "sub": {
            "type": "boolean",
            "description": "Only on an offer read for a row (`row=`) that is not its own row but holds every tracked sat of the item (a sub-category or a label row): `true`."
          },
          "in_bundle": {
            "type": "boolean",
            "description": "Only on an offer read for a row (`row=`) whose UTXO holds some sats of that row among others (in bundle): `true`. Its unit price is its own `row`'s."
          },
          "contains_count": {
            "type": [
              "integer",
              "null"
            ],
            "description": "With `in_bundle`: how many sats of the row asked for the item holds."
          }
        },
        "additionalProperties": false,
        "examples": [
          {
            "id": "dbf866a1e7e209e7",
            "kind": "item",
            "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0",
            "value": 10000,
            "seller_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
            "price": 110000,
            "platform_fee": 2750,
            "fee_rate": 3,
            "network_fee": 963,
            "total": 113713,
            "vsize": 321,
            "unit_price": 100000,
            "row": "decasat_alpha",
            "count": 1,
            "rows": {
              "uncommon": 1,
              "alpha_uncommon": 1,
              "decasat_alpha": 1
            },
            "types": [
              {
                "types": [
                  "uncommon",
                  "decasat_alpha",
                  "alpha"
                ],
                "count": 1,
                "sats": [
                  441000000000000
                ]
              }
            ],
            "sats": 1,
            "ranges": [
              [
                441000000000000,
                441000000000000
              ]
            ],
            "years": {
              "2010": 1
            },
            "bidder_payment_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
            "bidder_ordinals_address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
            "status": "active",
            "created_at": 1790967012,
            "updated_at": 1790967012,
            "expires_at": 1791571812,
            "reason": null,
            "txid": null,
            "listing_id": "5e1cb930f43354c3",
            "acceptance_public": false
          }
        ],
        "required": [
          "id",
          "kind",
          "outpoint",
          "value",
          "seller_address",
          "price",
          "platform_fee",
          "fee_rate",
          "network_fee",
          "total",
          "vsize",
          "unit_price",
          "row",
          "count",
          "rows",
          "types",
          "sats",
          "ranges",
          "years",
          "bidder_payment_address",
          "bidder_ordinals_address",
          "status",
          "created_at",
          "updated_at",
          "expires_at",
          "reason",
          "txid",
          "listing_id",
          "acceptance_public"
        ]
      },
      "OfferPage": {
        "type": "object",
        "properties": {
          "offers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Offer"
            },
            "description": "One page of offers."
          },
          "total": {
            "type": "integer",
            "description": "All offers matching the query."
          }
        },
        "required": [
          "offers",
          "total"
        ],
        "additionalProperties": false
      },
      "BestOffers": {
        "type": "object",
        "properties": {
          "offers": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/Offer"
            },
            "description": "The best active offer of each outpoint asked for that has one, keyed by outpoint."
          }
        },
        "required": [
          "offers"
        ],
        "additionalProperties": false
      },
      "Bidder": {
        "type": "object",
        "description": "The bidder's wallet: Xverse-style wallets have two addresses, UniSat-style one (use it for both).",
        "properties": {
          "payment_address": {
            "type": "string",
            "description": "Funds the offer and gets the change. Taproot, native SegWit or nested SegWit."
          },
          "payment_public_key": {
            "type": "string",
            "description": "Its public key, hex (Taproot: the internal key, x-only or compressed; SegWit: compressed)."
          },
          "ordinals_address": {
            "type": "string",
            "description": "Receives the UTXO. Taproot, native SegWit or nested SegWit. May equal `payment_address`."
          },
          "ordinals_public_key": {
            "type": "string",
            "description": "Its public key, hex (Taproot: the internal key, x-only or compressed; SegWit: compressed). Required: the ordinals address can cancel the offer and lists it as made."
          }
        },
        "required": [
          "payment_address",
          "payment_public_key",
          "ordinals_address",
          "ordinals_public_key"
        ],
        "additionalProperties": false
      },
      "PrepareOfferRequest": {
        "type": "object",
        "properties": {
          "outpoint": {
            "type": "string",
            "description": "The UTXO to bid on, `txid:vout`: any UTXO holding tracked sats, unspent and confirmed, with no inscription or rune, not your own. Listed or not."
          },
          "price": {
            "type": "integer",
            "description": "What the seller receives, in sats: above the UTXO's value, at least 546. You pay it plus the platform fee and the network fee."
          },
          "bidder": {
            "$ref": "#/components/schemas/Bidder"
          },
          "fee_rate": {
            "type": "number",
            "description": "The network fee rate in sat/vB (see `GET /api/market/fees`), fixed when you sign.",
            "exclusiveMinimum": 0,
            "maximum": 5000
          },
          "expires_in": {
            "description": "How long it can be accepted, in seconds: 86400 (1 day), 259200 (3 days), 604800 (7 days, the default when absent) or 2592000 (30 days); `null` or `\"never\"` for no expiry.",
            "oneOf": [
              {
                "type": "integer",
                "enum": [
                  86400,
                  259200,
                  604800,
                  2592000
                ]
              },
              {
                "const": "never"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "outpoint",
          "price",
          "bidder",
          "fee_rate"
        ],
        "additionalProperties": false
      },
      "OfferSummary": {
        "type": "object",
        "description": "What the offer costs and pays.",
        "properties": {
          "outpoint": {
            "type": "string",
            "description": "The UTXO bid on."
          },
          "value": {
            "type": "integer",
            "description": "Its value in sats."
          },
          "price": {
            "type": "integer",
            "description": "What the seller receives."
          },
          "platform_fee": {
            "type": "integer",
            "description": "2.5% of `price`, at least 546 sats."
          },
          "network_fee": {
            "type": "integer",
            "description": "The network fee in sats."
          },
          "total": {
            "type": "integer",
            "description": "What you pay: `price + platform_fee + network_fee`."
          },
          "vsize": {
            "type": "integer",
            "description": "Estimated virtual size."
          },
          "fee_rate": {
            "type": "number",
            "description": "sat/vB."
          },
          "change": {
            "type": "integer",
            "description": "Your change output in sats, 0 when none."
          },
          "unit_price": {
            "type": "number",
            "description": "`(price - value) / count`."
          },
          "row": {
            "type": "string",
            "description": "The UTXO's own row."
          },
          "count": {
            "type": "integer",
            "description": "Sats of `row` in the UTXO."
          }
        },
        "required": [
          "outpoint",
          "value",
          "price",
          "platform_fee",
          "network_fee",
          "total",
          "vsize",
          "fee_rate",
          "change",
          "unit_price",
          "row",
          "count"
        ],
        "additionalProperties": false
      },
      "PrepareOfferResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The prepared offer's id: submit with it."
          },
          "psbt": {
            "type": "string",
            "description": "The whole offer transaction, base64. Input 0 is the seller's UTXO, unsigned (the seller signs it to accept)."
          },
          "sign": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SignInput"
            },
            "description": "Your inputs (1 and up): sign exactly these, with your wallet's default sighash."
          },
          "summary": {
            "$ref": "#/components/schemas/OfferSummary"
          },
          "expires_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When the offer will expire, unix seconds; `null`: no expiry."
          },
          "submit_by": {
            "type": "integer",
            "description": "Submit before this (unix seconds, 10 minutes from now), or prepare again."
          }
        },
        "required": [
          "id",
          "psbt",
          "sign",
          "summary",
          "expires_at",
          "submit_by"
        ],
        "additionalProperties": false
      },
      "SubmitOfferRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The id from prepare."
          },
          "psbt": {
            "type": "string",
            "description": "The PSBT from prepare with your inputs signed (not finalized), base64."
          }
        },
        "required": [
          "id",
          "psbt"
        ],
        "additionalProperties": false
      },
      "SubmitOfferResponse": {
        "type": "object",
        "properties": {
          "offer": {
            "$ref": "#/components/schemas/Offer"
          }
        },
        "required": [
          "offer"
        ],
        "additionalProperties": false
      },
      "CancelOffersRequest": {
        "type": "object",
        "properties": {
          "ids": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "An offer id."
            },
            "description": "1 to 100 offer ids, all made by `address`.",
            "minItems": 1,
            "maxItems": 100
          },
          "address": {
            "type": "string",
            "description": "The bidder's payment or ordinals address."
          },
          "message": {
            "type": "string",
            "description": "Exactly `raresats.net cancel-offer <id,id,…> <unix seconds>`: the ids comma-separated in the same order as `ids`, and the current time. At most 10 minutes old, at most 2 minutes ahead."
          },
          "signature": {
            "type": "string",
            "description": "A BIP-322 signature of `message` by `address`, base64."
          }
        },
        "required": [
          "ids",
          "address",
          "message",
          "signature"
        ],
        "additionalProperties": false
      },
      "CancelOffersResponse": {
        "type": "object",
        "properties": {
          "offers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Offer"
            },
            "description": "The offers, now `cancelled`."
          },
          "warning": {
            "type": "string",
            "description": "Present when some of them have a public acceptance (see `exposed`)."
          },
          "exposed": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ids of cancelled offers whose acceptance was broadcast and dropped (`acceptance_public`): that transaction can still confirm until you spend a funding UTXO."
          }
        },
        "required": [
          "offers"
        ],
        "additionalProperties": false
      },
      "AcceptOfferPrepareRequest": {
        "type": "object",
        "properties": {
          "seller_address": {
            "type": "string",
            "description": "The address that holds the UTXO (the offer's `seller_address`)."
          },
          "seller_public_key": {
            "type": "string",
            "description": "Its public key, hex (Taproot: the internal key, x-only or compressed; SegWit: compressed)."
          }
        },
        "required": [
          "seller_address",
          "seller_public_key"
        ],
        "additionalProperties": false
      },
      "AcceptOfferSummary": {
        "type": "object",
        "description": "The trade you accept.",
        "properties": {
          "outpoint": {
            "type": "string",
            "description": "Your UTXO."
          },
          "value": {
            "type": "integer",
            "description": "Its value in sats (it goes to the bidder)."
          },
          "price": {
            "type": "integer",
            "description": "What you receive, in sats (output 1, to your address)."
          },
          "platform_fee": {
            "type": "integer",
            "description": "The bidder's platform fee."
          },
          "network_fee": {
            "type": "integer",
            "description": "The network fee, paid by the bidder."
          },
          "total": {
            "type": "integer",
            "description": "What the bidder pays."
          },
          "vsize": {
            "type": "integer",
            "description": "Estimated virtual size."
          },
          "fee_rate": {
            "type": "number",
            "description": "sat/vB, fixed by the bidder. If it confirms slowly, you can speed it up by spending output 1 (CPFP)."
          },
          "unit_price": {
            "type": "number",
            "description": "`(price - value) / count`."
          },
          "row": {
            "type": "string",
            "description": "The UTXO's own row."
          },
          "count": {
            "type": "integer",
            "description": "Sats of `row` in the UTXO."
          },
          "bidder_ordinals_address": {
            "type": "string",
            "description": "Where the UTXO goes."
          },
          "listing_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Your live listing of the UTXO, if any: accepting sells it (`sold` once confirmed)."
          }
        },
        "required": [
          "outpoint",
          "value",
          "price",
          "platform_fee",
          "network_fee",
          "total",
          "vsize",
          "fee_rate",
          "unit_price",
          "row",
          "count",
          "bidder_ordinals_address",
          "listing_id"
        ],
        "additionalProperties": false
      },
      "AcceptOfferPrepareResponse": {
        "type": "object",
        "properties": {
          "psbt": {
            "type": "string",
            "description": "The offer transaction, base64, with input 0 ready for your wallet. It carries no bidder signature (the server adds them)."
          },
          "sign": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SignInput"
            },
            "description": "Input 0, your UTXO: sign it with your wallet's default sighash."
          },
          "summary": {
            "$ref": "#/components/schemas/AcceptOfferSummary"
          }
        },
        "required": [
          "psbt",
          "sign",
          "summary"
        ],
        "additionalProperties": false
      },
      "AcceptOfferRequest": {
        "type": "object",
        "properties": {
          "psbt": {
            "type": "string",
            "description": "The PSBT from accept/prepare with input 0 signed (not finalized), base64."
          }
        },
        "required": [
          "psbt"
        ],
        "additionalProperties": false
      },
      "AcceptOfferResponse": {
        "type": "object",
        "properties": {
          "txid": {
            "type": "string",
            "description": "The broadcast transaction."
          }
        },
        "required": [
          "txid"
        ],
        "additionalProperties": false
      },
      "ChatSession": {
        "type": "object",
        "description": "The session of the request's cookie: `address` null when signed out.",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "Chat and display names are on (always true: off, the route is a 404)."
          },
          "max_length": {
            "type": "integer",
            "description": "The longest message, in characters."
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "The signed-in address."
          },
          "admin": {
            "type": "boolean",
            "description": "The address is a chat admin."
          },
          "display_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its display name."
          },
          "expires_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When the session ends, unix seconds."
          },
          "banned": {
            "type": "boolean",
            "description": "The address may not post: banned, or muted until `banned_until`."
          },
          "server_time": {
            "type": "integer",
            "description": "The server's clock, unix seconds: date signed messages by it."
          },
          "banned_until": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When a mute ends, unix seconds (the AI moderation mutes an address for an hour after 3 refusals in 10 minutes); null when not muted or banned for good."
          },
          "moderated": {
            "type": "boolean",
            "description": "Messages and display names are checked by the AI moderation before they are posted."
          }
        },
        "required": [
          "enabled",
          "max_length",
          "address",
          "admin",
          "display_name",
          "expires_at",
          "banned",
          "server_time",
          "banned_until",
          "moderated"
        ],
        "examples": [
          {
            "enabled": true,
            "max_length": 500,
            "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
            "admin": false,
            "display_name": "Rare Hunter",
            "expires_at": 1793541400,
            "banned": false,
            "server_time": 1790949400,
            "banned_until": null,
            "moderated": true
          }
        ]
      },
      "LoginNonce": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "description": "The address, normalized."
          },
          "nonce": {
            "type": "string",
            "description": "32 hex characters, usable once."
          },
          "expires_at": {
            "type": "integer",
            "description": "When the nonce expires, unix seconds (10 minutes)."
          },
          "message": {
            "type": "string",
            "description": "The message to sign, with `<unix seconds>` for the current time."
          }
        },
        "required": [
          "address",
          "nonce",
          "expires_at",
          "message"
        ]
      },
      "LoginRequest": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "description": "The address signing in (ordinals or payment)."
          },
          "message": {
            "type": "string",
            "description": "`raresats.net login <address> <nonce> <unix seconds>`, at most 10 minutes old."
          },
          "signature": {
            "type": "string",
            "description": "BIP-322 signature of `message` by `address` (base64; simple or full)."
          }
        },
        "required": [
          "address",
          "message",
          "signature"
        ]
      },
      "Profile": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string"
          },
          "display_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The display name, null when it has none."
          },
          "admin": {
            "type": "boolean",
            "description": "The address is a chat admin."
          },
          "changed_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When the name last changed, unix seconds."
          },
          "next_change_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When it may change again, unix seconds."
          },
          "server_time": {
            "type": "integer",
            "description": "The server's clock, unix seconds: date the profile message by it."
          }
        },
        "required": [
          "address",
          "display_name",
          "admin",
          "changed_at",
          "next_change_at",
          "server_time"
        ],
        "examples": [
          {
            "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
            "display_name": "Rare Hunter",
            "admin": false,
            "changed_at": 1790949400,
            "next_change_at": 1791035800,
            "server_time": 1790949400
          }
        ]
      },
      "ProfileRequest": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "description": "The address whose name it is."
          },
          "display_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The new name, trimmed with spaces collapsed; empty or null clears it."
          },
          "message": {
            "type": "string",
            "description": "`raresats.net profile <address> display_name=<name> <unix seconds>`, the name exactly as set, at most 10 minutes old."
          },
          "signature": {
            "type": "string",
            "description": "BIP-322 signature of `message` by `address`."
          }
        },
        "required": [
          "address",
          "display_name",
          "message",
          "signature"
        ]
      },
      "Profiles": {
        "type": "object",
        "properties": {
          "profiles": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "address → display name, for the addresses that have one."
          }
        },
        "required": [
          "profiles"
        ]
      },
      "ChatMessage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Increasing; the paging cursor."
          },
          "topic": {
            "type": "string",
            "description": "The topic it is in (a reply: its root's)."
          },
          "room": {
            "type": "string",
            "description": "Deprecated: the same as `topic` (the one room before topics was `main`, now `general`)."
          },
          "address": {
            "type": "string",
            "description": "The author."
          },
          "display_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The author's display name now."
          },
          "admin": {
            "type": "boolean",
            "description": "The author is a chat admin."
          },
          "text": {
            "type": "string",
            "description": "Plain text (NFC, no control, zero-width or bidi characters, one line, 1-500 characters). Show it as text, never as HTML."
          },
          "created_at": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "reply_to": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The thread's root, on a reply; null on a root (a message of the topic)."
          },
          "reply_count": {
            "type": "integer",
            "description": "On a root: its live replies (0 on a reply)."
          },
          "last_reply_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "On a root: its newest reply's time, unix seconds; null without replies."
          },
          "quote": {
            "type": [
              "object",
              "null"
            ],
            "description": "On a reply: the message it answered (the root, or a reply in the thread), while it is live; text only, cut at 140 characters. Null on a root.",
            "properties": {
              "id": {
                "type": "integer"
              },
              "address": {
                "type": "string"
              },
              "display_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "text": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "address",
              "display_name",
              "text"
            ]
          }
        },
        "required": [
          "id",
          "topic",
          "room",
          "address",
          "display_name",
          "admin",
          "text",
          "created_at",
          "reply_to",
          "reply_count",
          "last_reply_at",
          "quote"
        ],
        "examples": [
          {
            "id": 1042,
            "topic": "market",
            "room": "market",
            "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
            "display_name": "Rare Hunter",
            "admin": false,
            "text": "gm, any block 9 for sale?",
            "created_at": 1790949400,
            "reply_to": null,
            "reply_count": 2,
            "last_reply_at": 1790949460,
            "quote": null
          },
          {
            "id": 1044,
            "topic": "market",
            "room": "market",
            "address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
            "display_name": null,
            "admin": false,
            "text": "I have two, 0.0021 each",
            "created_at": 1790949460,
            "reply_to": 1042,
            "reply_count": 0,
            "last_reply_at": null,
            "quote": {
              "id": 1042,
              "address": "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
              "display_name": "Rare Hunter",
              "text": "gm, any block 9 for sale?"
            }
          }
        ],
        "description": "A message, or a reply in a thread (one level: a reply to a reply joins its root's thread)."
      },
      "ChatPage": {
        "type": "object",
        "properties": {
          "topic": {
            "type": "string",
            "description": "The topic."
          },
          "room": {
            "type": "string",
            "description": "Deprecated: the same as `topic`."
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatMessage"
            },
            "description": "The topic's threads' roots, newest first (replies are on their thread)."
          },
          "next": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Pass as `before` for the older page; null at the start."
          }
        },
        "required": [
          "topic",
          "room",
          "messages",
          "next"
        ]
      },
      "ChatBan": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "banned_by": {
            "type": "string",
            "description": "The admin's address, or `moderation` for an automatic mute."
          },
          "created_at": {
            "type": "integer"
          },
          "expires_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When a mute ends, unix seconds; null: banned until unbanned."
          }
        },
        "required": [
          "address",
          "reason",
          "banned_by",
          "created_at",
          "expires_at"
        ]
      },
      "RetiredRow": {
        "type": "object",
        "description": "A row the site retired, and where its sats are now. `uncommon_2009` and `rare_2009` were Uncommon and Rare narrowed to the sats mined in 2009: ask for the parent row with the year instead (`/api/rows/uncommon?years=2009`, `/api/sales/query?row=uncommon&years=2009`). Their pages, `/collection/uncommon_2009` and `/sales/uncommon_2009`, redirect (301) to `/collection/uncommon?year=2009`.",
        "properties": {
          "row": {
            "type": "string",
            "description": "The retired row asked for."
          },
          "successor": {
            "type": [
              "object",
              "null"
            ],
            "description": "The parent row and years that hold its sats; null for a row retired outright (`alpha_jan_feb_2009`).",
            "properties": {
              "row": {
                "type": "string"
              },
              "years": {
                "type": "array",
                "items": {
                  "type": "integer"
                }
              }
            },
            "required": [
              "row",
              "years"
            ]
          }
        },
        "required": [
          "row",
          "successor"
        ]
      },
      "ChatThread": {
        "type": "object",
        "description": "A thread: its root and a page of its replies.",
        "properties": {
          "topic": {
            "type": "string",
            "description": "The thread's topic (its root's): a link to a reply finds its page."
          },
          "room": {
            "type": "string",
            "description": "Deprecated: the same as `topic`."
          },
          "root": {
            "$ref": "#/components/schemas/ChatMessage"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatMessage"
            },
            "description": "The replies, newest first."
          },
          "next": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Pass as `before` for older replies; null at the start."
          }
        },
        "required": [
          "topic",
          "room",
          "root",
          "messages",
          "next"
        ]
      },
      "ChatThreadSummary": {
        "type": "object",
        "description": "A root's thread after a change, as the `chat` events carry it.",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The root."
          },
          "reply_count": {
            "type": "integer"
          },
          "last_reply_at": {
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "reply_count",
          "last_reply_at"
        ]
      },
      "ChatTopic": {
        "type": "object",
        "description": "A chat topic (a channel). Its id is its slug: the page is `/chat/<id>`.",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z0-9](?:[a-z0-9-]{0,30}[a-z0-9])?$",
            "description": "1-32 of a-z, 0-9 and inner hyphens."
          },
          "name": {
            "type": "string",
            "description": "1-40 characters, plain text."
          },
          "description": {
            "type": "string",
            "description": "At most 140 characters, plain text; may be empty."
          },
          "position": {
            "type": "integer",
            "description": "Its place in the list."
          },
          "created_at": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "last_message_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The newest live message's id (a reply counts); null when it has none. A page that keeps the last id it read per topic shows a topic as unread when this is larger."
          },
          "last_activity_at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "That message's time, unix seconds; null when it has none."
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "position",
          "created_at",
          "last_message_id",
          "last_activity_at"
        ],
        "examples": [
          {
            "id": "market",
            "name": "Market & prices",
            "description": "Listings, offers, floors and what things sell for.",
            "position": 1,
            "created_at": 1790900000,
            "last_message_id": 1042,
            "last_activity_at": 1790949400
          }
        ]
      },
      "PendingSpend": {
        "type": "object",
        "description": "A transaction still in the mempool that spends an output (`spent_by_pending`). Absent when nothing pending spends it.",
        "properties": {
          "txid": {
            "type": "string",
            "description": "The spending transaction."
          },
          "vin": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its input that spends the output."
          },
          "first_seen": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When the transaction was first seen in the mempool (bitcoind's entry time), unix seconds."
          },
          "fee_rate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Its fee rate, sat/vB (one decimal)."
          },
          "sale": {
            "type": "boolean",
            "description": "Whether the spend sells this output (a pending sale with it as the seller's input)."
          },
          "replaceable": {
            "type": "boolean",
            "description": "Always true (full RBF): the spend may still be replaced."
          }
        },
        "required": [
          "txid",
          "first_seen",
          "fee_rate",
          "sale"
        ]
      },
      "PendingSale": {
        "type": "object",
        "description": "A sale still in the mempool, placed among the rows exactly as a confirmed one (`MarketSale`'s fields), marked `pending`. It counts in no stat, median, volume, floor or leaderboard.",
        "properties": {
          "seq": {
            "type": "null",
            "description": "No sequence number until it confirms."
          },
          "t": {
            "type": [
              "integer",
              "null"
            ],
            "description": "`first_seen`: sorted by time, it leads the confirmed sales."
          },
          "h": {
            "type": "null",
            "description": "No block yet."
          },
          "row": {
            "type": "string",
            "description": "The sale's own row."
          },
          "u": {
            "type": [
              "number",
              "null"
            ],
            "description": "Unit price: premium per sat of the row."
          },
          "c": {
            "type": "integer",
            "description": "Sats of the row sold."
          },
          "p": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Price in sats."
          },
          "n": {
            "type": "integer",
            "description": "Tracked sats the sale sold."
          },
          "s": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The first special sat sold."
          },
          "sh": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The block that mined it."
          },
          "sd": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The day it was mined (UTC days since 1970)."
          },
          "m": {
            "type": "string",
            "description": "Marketplace id (`magisat`, `magic_eden`, `unknown`, …)."
          },
          "x": {
            "type": [
              "string",
              "null"
            ],
            "description": "The txid's first 8 and last 4 hex digits."
          },
          "ins": {
            "type": "boolean",
            "description": "An inscription was on a sold sat."
          },
          "out": {
            "type": "boolean",
            "description": "Always false: a pending sale is judged by no median."
          },
          "secondary": {
            "$ref": "#/components/schemas/SecondaryRows"
          },
          "seller": {
            "type": [
              "string",
              "null"
            ],
            "description": "The seller's address."
          },
          "buyer": {
            "type": [
              "string",
              "null"
            ],
            "description": "The buyer's address."
          },
          "key": {
            "type": "string",
            "description": "`txid:vin`: its identity. The confirmed sale has the same txid and vin and replaces it."
          },
          "pending": {
            "type": "boolean",
            "const": true,
            "description": "Always true: the sale is still in the mempool."
          },
          "first_seen": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When the transaction was first seen in the mempool (bitcoind's entry time), unix seconds."
          },
          "fee_rate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Its fee rate, sat/vB (one decimal)."
          },
          "txid": {
            "type": "string",
            "description": "The sale transaction, whole."
          },
          "vin": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The seller's input."
          },
          "seller_outpoint": {
            "type": [
              "string",
              "null"
            ],
            "description": "The output it sells."
          },
          "buyer_outpoint": {
            "type": [
              "string",
              "null"
            ],
            "description": "The output the sold sats go to."
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Its own row, then the rows of which it is a rarer sub-category."
          },
          "led_rows": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The rows of its other sats (it is led by `row` there)."
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The label rows it lies in."
          },
          "kind": {
            "type": [
              "string",
              "null"
            ],
            "description": "The fork's sale kind (`listing`, `offer`, …)."
          }
        },
        "required": [
          "key",
          "pending",
          "txid",
          "vin",
          "first_seen",
          "fee_rate",
          "t",
          "row",
          "p"
        ]
      },
      "PendingEvent": {
        "type": "object",
        "description": "A notable transfer or extraction of a transaction still in the mempool: the confirmed event's shape (the same notable rules, judged as if mined in the next block at `first_seen`), with `id` `pending:<kind>:<txid>`, `pending: true`, `first_seen`, `fee_rate`, and `height`, `block_hash`, `tx_index` null.",
        "properties": {
          "id": {
            "type": "string",
            "description": "`pending:transfer:<txid>` or `pending:extraction:<txid>`."
          },
          "kind": {
            "type": "string",
            "enum": [
              "transfer",
              "extraction"
            ]
          },
          "txid": {
            "type": "string"
          },
          "pending": {
            "type": "boolean",
            "const": true
          },
          "first_seen": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When the transaction was first seen in the mempool (bitcoind's entry time), unix seconds."
          },
          "fee_rate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Its fee rate, sat/vB (one decimal)."
          },
          "height": {
            "type": "null"
          },
          "time": {
            "type": [
              "integer",
              "null"
            ],
            "description": "`first_seen`."
          },
          "reasons": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Why it is notable."
          }
        },
        "required": [
          "id",
          "kind",
          "txid",
          "pending",
          "first_seen",
          "fee_rate",
          "reasons"
        ],
        "additionalProperties": true
      },
      "PendingRemoved": {
        "type": "object",
        "description": "A transaction that left the mempool (a tombstone, kept an hour).",
        "properties": {
          "txid": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "replaced",
              "conflicted",
              "evicted"
            ],
            "description": "`confirmed`: in a block (its confirmed items replace the pending ones); `replaced` (RBF, `replaced_by` set), `conflicted` (a block spent an input otherwise) or `evicted`: its pending items are dropped."
          },
          "height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The block, when confirmed."
          },
          "replaced_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "The replacement, when replaced."
          },
          "at": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When it left, unix seconds."
          }
        },
        "required": [
          "txid",
          "status"
        ]
      },
      "Pending": {
        "type": "object",
        "description": "Everything pending: what unconfirmed transactions do to tracked sats, from the index's mempool overlay. Nothing in it counts in any stat, volume, floor, leaderboard or supply. `available` is false (and every list empty) while the index serves no mempool overlay.",
        "properties": {
          "available": {
            "type": "boolean",
            "description": "Whether the index serves the mempool overlay and it has been read."
          },
          "seq": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The overlay's change counter: it moves with every change."
          },
          "height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The index tip the overlay is consistent with; pending items are judged as of the next block."
          },
          "txs": {
            "type": "integer",
            "description": "Pending transactions that move tracked sats."
          },
          "sales": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PendingSale"
            },
            "description": "Pending sales, newest first."
          },
          "transfers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PendingEvent"
            },
            "description": "Pending notable transfers, newest first."
          },
          "extractions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PendingEvent"
            },
            "description": "Pending notable extractions, newest first."
          },
          "listings": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/PendingSpend"
            },
            "description": "Live marketplace listings whose UTXO a pending transaction spends, by outpoint: they show as pending."
          },
          "removed": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PendingRemoved"
            },
            "description": "Transactions that left the mempool lately (the live event: those since the last one)."
          }
        },
        "required": [
          "available",
          "seq",
          "sales",
          "transfers",
          "extractions",
          "listings",
          "removed"
        ]
      },
      "PendingOutput": {
        "type": "object",
        "description": "An output a transaction still in the mempool sends: described as a held UTXO, with `pending: true`, `first_seen`, `fee_rate`, no block (`created_height` and `created_time` null), and `spent_by_pending` when another pending transaction spends it on.",
        "properties": {
          "outpoint": {
            "type": "string",
            "description": "`txid:vout`."
          },
          "txid": {
            "type": "string",
            "description": "Transaction."
          },
          "vout": {
            "type": "integer",
            "description": "Output index."
          },
          "value": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Value in sats."
          },
          "kind": {
            "type": "string",
            "description": "`spendable` and so on."
          },
          "created_height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The block that created it."
          },
          "created_time": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its time."
          },
          "extracted": {
            "type": "boolean",
            "description": "Extracted (isolated rare sats)."
          },
          "inscribed_sats": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Inscribed tracked sats."
          },
          "quantity": {
            "type": "integer",
            "description": "Tracked sats."
          },
          "first": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Lowest tracked sat."
          },
          "last": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Highest tracked sat."
          },
          "ranges": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "integer"
              }
            },
            "description": "Inclusive ranges."
          },
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TypeGroup"
            },
            "description": "Sats by exact type combination, rarest first."
          },
          "years": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Sats per mint year."
          },
          "year": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The year holding the most sats."
          },
          "rows": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Row counts."
          },
          "pending": {
            "type": "boolean",
            "const": true
          },
          "first_seen": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When the transaction was first seen in the mempool (bitcoind's entry time), unix seconds."
          },
          "fee_rate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Its fee rate, sat/vB (one decimal)."
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Who receives it."
          },
          "spent_by_pending": {
            "$ref": "#/components/schemas/PendingSpend"
          },
          "split_counts": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "The sats an extract's `split` may cut, per exact type combination (types sorted, joined with `+`): the row's sats as `groups` counts them, without the tracked pieces that touch block 9 or 450x (a split leaves those whole)."
          }
        },
        "required": [
          "outpoint",
          "value",
          "quantity",
          "ranges",
          "groups"
        ]
      },
      "TxPiece": {
        "type": "object",
        "description": "A run of tracked sats: `start` (its first sat), `len`, `offset` in its holder, `types` (its first sat's), and its block's `height`, mint `date` and `luck` (`null` for a run over several blocks).",
        "properties": {
          "offset": {
            "type": "integer",
            "description": "Its offset in the output (or the fee)."
          },
          "start": {
            "type": "integer",
            "description": "Its first sat."
          },
          "len": {
            "type": "integer",
            "description": "How many sats from `start` on."
          },
          "types": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The block that mined it."
          },
          "date": {
            "type": [
              "string",
              "null"
            ],
            "description": "That block's UTC day, `YYYY-MM-DD` (its birthday page)."
          },
          "luck": {
            "type": [
              "integer",
              "null"
            ],
            "description": "That block's luck."
          }
        },
        "required": [
          "start",
          "len",
          "types"
        ]
      },
      "TxRun": {
        "type": "object",
        "description": "One run of tracked sats from where the transaction took it to where it put it, under ordinal theory's first-in-first-out rule: the TxPiece fields plus its source and destination.",
        "properties": {
          "source": {
            "type": "string",
            "enum": [
              "input",
              "subsidy",
              "fees"
            ],
            "description": "A spent UTXO (`vin`), newly mined sats (a coinbase's subsidy) or the block's fees (a coinbase)."
          },
          "vin": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The input it came from (`source: input`)."
          },
          "input_offset": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its offset in the spent output (or in the coinbase's input stream)."
          },
          "dest": {
            "type": "string",
            "enum": [
              "output",
              "fee",
              "lost"
            ],
            "description": "An output (`vout`), the fee (paid to the miner) or `lost` (a coinbase that did not claim it)."
          },
          "vout": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The output it went to (`dest: output`)."
          },
          "offset": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its offset in that output (or in the fee)."
          },
          "start": {
            "type": "integer"
          },
          "len": {
            "type": "integer"
          },
          "types": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The block that mined it."
          },
          "date": {
            "type": [
              "string",
              "null"
            ],
            "description": "That block's UTC day."
          },
          "luck": {
            "type": [
              "integer",
              "null"
            ],
            "description": "That block's luck."
          }
        },
        "required": [
          "source",
          "dest",
          "start",
          "len",
          "types"
        ]
      },
      "TxInput": {
        "type": "object",
        "description": "One input: the output it spends and the tracked sats it carried.",
        "properties": {
          "vin": {
            "type": "integer"
          },
          "outpoint": {
            "type": [
              "string",
              "null"
            ],
            "description": "The spent output, `txid:vout`; `null` for a coinbase."
          },
          "value": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The spent output's value in sats; `null` for a coinbase or when unknown."
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "script_pubkey": {
            "type": [
              "string",
              "null"
            ],
            "description": "The spent output's script, hex."
          },
          "sequence": {
            "type": "integer"
          },
          "created_height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The block that created the spent output, when known."
          },
          "sighash": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its first signature's sighash flag (131 is SINGLE|ANYONECANPAY, a listing's)."
          },
          "inscriptions": {
            "type": "integer",
            "description": "Inscription envelopes it reveals."
          },
          "tracked": {
            "type": "boolean",
            "description": "It spent a UTXO holding tracked sats."
          },
          "extracted": {
            "type": "boolean",
            "description": "That UTXO was extracted."
          },
          "pieces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TxPiece"
            }
          },
          "inscribed_sats": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          }
        },
        "required": [
          "vin",
          "outpoint",
          "value",
          "tracked",
          "pieces"
        ]
      },
      "TxOutput": {
        "type": "object",
        "description": "One output and the tracked sats it received.",
        "properties": {
          "vout": {
            "type": "integer"
          },
          "value": {
            "type": "integer",
            "description": "Sats."
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "script_pubkey": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "spendable",
              "unspendable"
            ]
          },
          "tracked": {
            "type": "boolean"
          },
          "extracted": {
            "type": "boolean"
          },
          "pieces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TxPiece"
            }
          },
          "inscribed_sats": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "marker": {
            "type": "boolean",
            "description": "The marketplace's OP_RETURN marker."
          },
          "runestone": {
            "type": "boolean",
            "description": "An OP_RETURN OP_13 runestone."
          },
          "spent_by_pending": {
            "type": "object",
            "description": "The pending transaction spending it (tracked outputs only)."
          }
        },
        "required": [
          "vout",
          "value",
          "kind",
          "tracked",
          "pieces"
        ]
      },
      "TxPage": {
        "type": "object",
        "description": "One transaction as raresats.net sees it: status, fee, every input and output, the tracked rare sats each input carried and the output (or fee) each went to, its sales and the notable verdicts of the Transfers and Extractions feeds.",
        "properties": {
          "txid": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "pending",
              "replaced",
              "conflicted",
              "evicted",
              "unknown"
            ],
            "description": "`pending`: in the mempool; `replaced`, `conflicted`, `evicted`: it left the mempool unconfirmed and bitcoind no longer knows it (nothing else is known then)."
          },
          "height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The confirming block."
          },
          "hash": {
            "type": [
              "string",
              "null"
            ]
          },
          "time": {
            "type": [
              "integer",
              "null"
            ],
            "description": "That block's time, unix seconds."
          },
          "confirmations": {
            "type": [
              "integer",
              "null"
            ],
            "description": "As of the index's tip."
          },
          "tx_index": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its position in the block."
          },
          "indexed": {
            "type": "boolean",
            "description": "The index holds its block."
          },
          "first_seen": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Pending: when bitcoind first saw it, unix seconds."
          },
          "removed": {
            "type": [
              "object",
              "null"
            ],
            "description": "The index's record of its leaving the mempool (`status`, `replaced_by`, `at`)."
          },
          "version": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its version."
          },
          "locktime": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Its locktime."
          },
          "size": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Bytes."
          },
          "vsize": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Virtual bytes."
          },
          "weight": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Weight units."
          },
          "coinbase": {
            "type": "boolean"
          },
          "input_value": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Sats; `null` for a coinbase or an input of unknown value."
          },
          "output_value": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Sats."
          },
          "fee": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Sats."
          },
          "fee_rate": {
            "type": [
              "number",
              "null"
            ],
            "description": "sat/vB, one decimal."
          },
          "sat_flow": {
            "type": "string",
            "enum": [
              "complete",
              "outputs",
              "unknown"
            ],
            "description": "`complete`: every tracked sat it moved is in `flow`; `outputs`: confirmed before the index's moves retention (`moves_from`), so only the tracked sats still in its unspent outputs are known; `unknown`: its block is not indexed yet."
          },
          "tracked": {
            "type": "boolean",
            "description": "It moved (or minted) tracked sats."
          },
          "marker": {
            "type": "boolean",
            "description": "It carries the marketplace's OP_RETURN marker."
          },
          "raresats": {
            "type": [
              "object",
              "null"
            ],
            "description": "A raresats.net sale: `{kind, count}`, `kind` `purchase` or `offer`."
          },
          "kinds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Its address-history kinds: `mined`, `sale`, `extraction`, `burn`, `consolidation`, `transfer`."
          },
          "inputs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TxInput"
            }
          },
          "outputs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TxOutput"
            }
          },
          "flow": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TxRun"
            }
          },
          "fee_pieces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TxPiece"
            }
          },
          "mined_pieces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TxPiece"
            }
          },
          "lost_pieces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TxPiece"
            }
          },
          "rows": {
            "type": "object",
            "description": "Tracked sats it moved, per row."
          },
          "sales": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SatSale"
            },
            "description": "Its sales, each with `pending`."
          },
          "transfer": {
            "type": [
              "object",
              "null"
            ],
            "description": "Its notable transfer (the Transfers feed's event, with `reasons`), else `null`."
          },
          "extractions": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Its notable extractions (the Extractions feed's events)."
          },
          "entries": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "One address-history entry per party it moved tracked sats for."
          },
          "depends": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Pending parents whose tracked outputs it spends."
          },
          "moves_from": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The lowest block whose full sat flow the index keeps."
          },
          "as_of": {
            "type": [
              "object",
              "null"
            ],
            "description": "`{height, time}` of the index."
          },
          "explorer": {
            "type": [
              "string",
              "null"
            ],
            "description": "Block explorer base URL, for a secondary link."
          }
        },
        "required": [
          "txid",
          "status",
          "sat_flow",
          "inputs",
          "outputs",
          "flow",
          "sales",
          "kinds"
        ]
      },
      "TransferOwner": {
        "type": "object",
        "description": "The connected wallet: Xverse-style wallets have two addresses, UniSat-style one (give it as both). Both keys are checked against their addresses.",
        "properties": {
          "payment_address": {
            "type": "string",
            "description": "Pays the fees and gets the change and plain slices. Taproot, native SegWit or nested SegWit."
          },
          "payment_public_key": {
            "type": "string",
            "description": "Its public key, hex (Taproot: the internal key, x-only or compressed; SegWit: compressed)."
          },
          "ordinals_address": {
            "type": "string",
            "description": "Holds the rare sats; the default destination. May equal `payment_address`."
          },
          "ordinals_public_key": {
            "type": "string",
            "description": "Its public key, hex."
          }
        },
        "required": [
          "payment_address",
          "payment_public_key",
          "ordinals_address",
          "ordinals_public_key"
        ],
        "additionalProperties": false
      },
      "TransferItem": {
        "type": "object",
        "description": "One UTXO of yours to move.",
        "properties": {
          "outpoint": {
            "type": "string",
            "description": "`txid:vout`."
          },
          "sats": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer"
            },
            "maxItems": 10000,
            "description": "`extract` only: the tracked sats (absolute sat numbers) to extract; `null` or absent: all of them. A sat inside a block 9 range picks the whole range."
          }
        },
        "required": [
          "outpoint"
        ],
        "additionalProperties": false
      },
      "PrepareTransferRequest": {
        "type": "object",
        "description": "Every kind takes `owner`, `kind` and `fee_rate`; the other fields depend on the kind (see [Prepare a transfer](/docs/prepare-transfer)). A `consolidate` without `items` merges your payment address's plain UTXOs, picked by the server: up to 50, smallest first, never a listed UTXO or your offers' funding, leaving out the largest when it is worth more than all the others together; fewer than 2 is `nothing_to_do`.",
        "properties": {
          "owner": {
            "$ref": "#/components/schemas/TransferOwner"
          },
          "kind": {
            "type": "string",
            "enum": [
              "extract",
              "send",
              "send_n",
              "chop",
              "consolidate",
              "multisend",
              "speedup",
              "cancel"
            ],
            "description": "What to do."
          },
          "fee_rate": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 5000,
            "description": "sat/vB, at least `minimum` of `GET /api/market/fees`."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransferItem"
            },
            "minItems": 1,
            "maxItems": 50,
            "description": "`extract`, `send`, `chop`; `consolidate` (2 or more plain UTXOs, or absent: the server picks); optional for `send_n` (limits its pick)."
          },
          "destination": {
            "type": "string",
            "description": "Where the moved sats go. Default: your ordinals address (your payment address for `consolidate`). P2TR, P2WPKH, P2SH, P2WSH or P2PKH; never the fee address."
          },
          "plain_to": {
            "type": "string",
            "enum": [
              "payment",
              "source"
            ],
            "description": "`extract`: where slices holding no tracked sat go (default `payment`)."
          },
          "split": {
            "type": "object",
            "description": "`extract` only: split each UTXO's sats of one type into chunks instead of separating each rare sat (see [Extract rare sats](/docs/guide-extract#split-into-chunks)). Each chunk is an output of its own to `destination` (a chunk whose sats lie on both sides of a whole range, block 9, is cut around it: the range keeps an output of its own); the other rare sats of the UTXO stay home or ride along with a chunk to your own address, never to plain change. The items take no `sats`. With several items, one that cannot make 2 chunks is skipped (`summary.skipped`); 2,000 sats of the type at most per request, and per UTXO at most 2,000 of them and its other tracked runs and exotic intervals together (`too_many_items`), and the outputs as laid out (chunks too close together share one) must fit in 100 (`too_many_outputs`).",
            "properties": {
              "type": {
                "type": "string",
                "minLength": 1,
                "maxLength": 327,
                "pattern": "^(?!(?:[a-z0-9_]+\\+)*(?:block9|450x)(?:\\+|$))[a-z0-9_]{1,40}(?:\\+[a-z0-9_]{1,40}){0,7}$",
                "description": "The exact type combination to chunk (`uncommon`, `black+uncommon`): 1 to 8 lowercase types of 1-40 letters, digits or `_`, joined with `+`, as `send_n` matches it (`uncommon` does not take a `black+uncommon` sat); repeats count once. Never a whole range (`block9`, `450x`): `chop` cuts those."
              },
              "per_output": {
                "type": "integer",
                "minimum": 1,
                "maximum": 2000,
                "description": "Sats of the type per output, in offset order; the last chunk holds the remainder. Exactly one of `per_output` and `chunks`."
              },
              "chunks": {
                "type": "integer",
                "minimum": 2,
                "maximum": 100,
                "description": "How many chunks: near-equal, the first ones one larger. Exactly one of `per_output` and `chunks`."
              },
              "trim": {
                "type": "boolean",
                "default": false,
                "description": "`true`: the plain sats between two chunks go back as plain change (to `plain_to`) when they make an output of their own; smaller gaps ride along with a chunk. `false` (default): each chunk's output runs from its first sat to the next chunk; other rare or exotic sats between two chunks ride along too when `destination` is your own address (a whole range never does: it keeps an output of its own)."
              }
            },
            "required": [
              "type"
            ],
            "additionalProperties": false,
            "oneOf": [
              {
                "title": "Sats per output",
                "required": [
                  "per_output"
                ]
              },
              {
                "title": "Number of chunks",
                "required": [
                  "chunks"
                ]
              }
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "whole",
              "rare"
            ],
            "description": "`send`: the UTXOs as they are, or only their rare sats (default `whole`)."
          },
          "consolidate": {
            "type": "boolean",
            "description": "`send` `whole`: one output for all the UTXOs instead of one each."
          },
          "type": {
            "type": "string",
            "description": "`send_n`: an exact type combination (`uncommon`, `black+uncommon`) or a range type (`block9`, `450x`)."
          },
          "count": {
            "type": "integer",
            "minimum": 1,
            "description": "`send_n`: how many sats."
          },
          "chop_size": {
            "type": "integer",
            "minimum": 330,
            "maximum": 100000000,
            "description": "`chop`: cut at sats divisible by this."
          },
          "sends": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "description": "`multisend`: the payments.",
            "items": {
              "type": "object",
              "properties": {
                "address": {
                  "type": "string"
                },
                "value": {
                  "type": "integer",
                  "description": "Sats."
                }
              },
              "required": [
                "address",
                "value"
              ],
              "additionalProperties": false
            }
          },
          "txid": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$",
            "description": "`speedup`, `cancel`: the pending wallet transfer to replace."
          },
          "confirm_payment_destination": {
            "type": "boolean",
            "description": "Allow sending rare sats, inscriptions or runes to your own payment address (otherwise `payment_destination`)."
          }
        },
        "required": [
          "owner",
          "kind",
          "fee_rate"
        ],
        "additionalProperties": false
      },
      "TransferSummary": {
        "type": "object",
        "description": "The plan as people read it: what each input holds, what each output gets and where it goes, the fees, the checks run on the unsigned transaction, and the warnings.",
        "properties": {
          "kind": {
            "type": "string",
            "description": "The kind."
          },
          "network_fee": {
            "type": "integer",
            "description": "Sats, paid from your plain bitcoin."
          },
          "tools_fee": {
            "type": "integer",
            "description": "The flat raresats.net fee (`tools.fee_sats`; 0 on a speed-up or cancel, which keep the original's fee output)."
          },
          "fee_rate": {
            "type": "number",
            "description": "sat/vB."
          },
          "vsize": {
            "type": "integer",
            "description": "Estimated vbytes (an upper bound)."
          },
          "change": {
            "type": "integer",
            "description": "Sats back to your payment address as change."
          },
          "total_cost": {
            "type": "integer",
            "description": "`network_fee + tools_fee`."
          },
          "leaves_wallet": {
            "type": "integer",
            "description": "Sats paid to addresses that are not yours, other than the fees."
          },
          "destination": {
            "type": [
              "string",
              "null"
            ],
            "description": "The destination address."
          },
          "external": {
            "type": "boolean",
            "description": "The destination is not one of your addresses."
          },
          "inputs": {
            "type": "array",
            "description": "Every input: your UTXOs to move (`source`), plain funding (`funding`), or plain UTXOs (`plain`).",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer"
                },
                "outpoint": {
                  "type": "string"
                },
                "value": {
                  "type": "integer"
                },
                "role": {
                  "type": "string",
                  "enum": [
                    "source",
                    "funding",
                    "plain"
                  ]
                },
                "address": {
                  "type": "string"
                },
                "owner_role": {
                  "type": "string",
                  "enum": [
                    "ordinals",
                    "payment"
                  ]
                },
                "items": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "sat": {
                        "type": "integer",
                        "description": "The first sat."
                      },
                      "len": {
                        "type": "integer",
                        "description": "How many sats (1, or a range)."
                      },
                      "types": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Its sat types."
                      },
                      "input": {
                        "type": "integer",
                        "description": "The input it comes from."
                      },
                      "offset": {
                        "type": "integer",
                        "description": "Its offset in that input."
                      },
                      "at": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "description": "Its offset in this output."
                      },
                      "selected": {
                        "type": "boolean",
                        "description": "Picked to move (`false`: it stays where it was)."
                      }
                    },
                    "required": [
                      "sat",
                      "len",
                      "types",
                      "offset"
                    ],
                    "additionalProperties": false
                  },
                  "description": "Its tracked sats."
                },
                "inscriptions": {
                  "type": "integer",
                  "description": "How many inscriptions it carries."
                },
                "runes": {
                  "type": "boolean"
                }
              },
              "required": [
                "index",
                "outpoint",
                "value",
                "role",
                "address",
                "owner_role",
                "items",
                "inscriptions",
                "runes"
              ],
              "additionalProperties": false
            }
          },
          "outputs": {
            "type": "array",
            "description": "Every output, in order.",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer"
                },
                "value": {
                  "type": "integer"
                },
                "address": {
                  "type": "string"
                },
                "role": {
                  "type": "string",
                  "enum": [
                    "dest",
                    "return",
                    "plain_return",
                    "tools_fee",
                    "change"
                  ],
                  "description": "`dest`: moved sats; `return`: back to a source's address; `plain_return`: a plain slice to your payment address; `tools_fee`; `change`."
                },
                "to": {
                  "type": "string",
                  "enum": [
                    "ordinals",
                    "payment",
                    "source",
                    "external",
                    "fee"
                  ],
                  "description": "Whose address it pays."
                },
                "parts": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "input": {
                        "type": "integer"
                      },
                      "from": {
                        "type": "integer"
                      },
                      "to": {
                        "type": "integer"
                      },
                      "at": {
                        "type": "integer"
                      },
                      "kind": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "input",
                      "from",
                      "to"
                    ],
                    "additionalProperties": false
                  },
                  "description": "The input sats it receives, first in first out: `[from, to)` of input `input`, at offset `at`."
                },
                "items": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "sat": {
                        "type": "integer",
                        "description": "The first sat."
                      },
                      "len": {
                        "type": "integer",
                        "description": "How many sats (1, or a range)."
                      },
                      "types": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Its sat types."
                      },
                      "input": {
                        "type": "integer",
                        "description": "The input it comes from."
                      },
                      "offset": {
                        "type": "integer",
                        "description": "Its offset in that input."
                      },
                      "at": {
                        "type": [
                          "integer",
                          "null"
                        ],
                        "description": "Its offset in this output."
                      },
                      "selected": {
                        "type": "boolean",
                        "description": "Picked to move (`false`: it stays where it was)."
                      }
                    },
                    "required": [
                      "sat",
                      "len",
                      "types",
                      "offset"
                    ],
                    "additionalProperties": false
                  },
                  "description": "The tracked sats it receives."
                },
                "rides_along": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "input": {
                        "type": "integer"
                      },
                      "from": {
                        "type": "integer"
                      },
                      "to": {
                        "type": "integer"
                      },
                      "at": {
                        "type": "integer"
                      },
                      "kind": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "input",
                      "from",
                      "to"
                    ],
                    "additionalProperties": false
                  },
                  "description": "Unpicked or exotic sats that ride along in an output to yourself."
                },
                "kept": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "input": {
                        "type": "integer"
                      },
                      "from": {
                        "type": "integer"
                      },
                      "to": {
                        "type": "integer"
                      },
                      "kind": {
                        "type": "string"
                      },
                      "types": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    },
                    "required": [
                      "input",
                      "from",
                      "to"
                    ],
                    "additionalProperties": false
                  },
                  "description": "Sats that are not plain going back home in this output: unpicked tracked sats and exotic ranges (`types`, e.g. vintage). Never shown as plain bitcoin."
                },
                "padding": {
                  "type": "integer",
                  "description": "Sats other than the picked ones in an extracted output."
                },
                "extracted": {
                  "type": [
                    "boolean",
                    "null"
                  ],
                  "description": "Whether the index will count it extracted ([Extraction](/types/extraction)); `null` when it holds no tracked sat or the rule is unknown."
                }
              },
              "required": [
                "index",
                "value",
                "address",
                "role",
                "to",
                "parts",
                "items",
                "rides_along",
                "padding",
                "extracted"
              ],
              "additionalProperties": false
            }
          },
          "checks": {
            "type": "array",
            "description": "What the server verified on the unsigned transaction (\"No rare sat is paid as fee\", …).",
            "items": {
              "type": "object",
              "properties": {
                "rule": {
                  "type": "string"
                },
                "ok": {
                  "type": "boolean"
                },
                "label": {
                  "type": "string"
                }
              },
              "required": [
                "rule",
                "ok",
                "label"
              ],
              "additionalProperties": false
            }
          },
          "warnings": {
            "type": "array",
            "description": "Things to know before signing: `listed` (carries `listing_id`, `signature_public` and, when that is true, `recommended_fee_rate`: the fast rate), `offers_received`, `spends_offer_funding`, `payment_destination`, `not_taproot`, `external`, `fee_exceeds_freed`, `merged`, `chunk_not_extracted` (a split's chunk output above the extraction budget), `chunk_cut` (a split's chunk cut around a whole range), `not_aligned`.",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                },
                "outpoint": {
                  "type": "string"
                }
              },
              "required": [
                "code",
                "message"
              ]
            }
          },
          "skipped": {
            "type": "array",
            "description": "Items left out of a multi-item extract or an automatic send N pick, with the reason (`already_extracted`, `split_chunk`, `inscribed`, `runes`, `unconfirmed`, `pending`, `untracked`, `nothing_to_separate`, `keep_in_destination`, `listed`, `offered`; for a split over several UTXOs `not_enough_sats` and `nothing_to_do`).",
            "items": {
              "type": "object",
              "properties": {
                "outpoint": {
                  "type": "string"
                },
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "outpoint",
                "code",
                "message"
              ],
              "additionalProperties": false
            }
          },
          "replaces": {
            "type": [
              "object",
              "null"
            ],
            "description": "A speed-up or cancel: the pending transaction it replaces (`fee` and `fee_rate` null for a void of one no longer in the mempool).",
            "properties": {
              "txid": {
                "type": "string"
              },
              "fee": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "fee_rate": {
                "type": [
                  "number",
                  "null"
                ]
              }
            },
            "required": [
              "txid",
              "fee",
              "fee_rate"
            ],
            "additionalProperties": false
          },
          "min_fee_rate": {
            "type": [
              "number",
              "null"
            ],
            "description": "A replacement: the lowest fee rate that replaces the pending transaction."
          },
          "layout": {
            "type": "array",
            "description": "How each source was cut (layout kinds).",
            "items": {
              "type": "object",
              "properties": {
                "outpoint": {
                  "type": "string"
                },
                "input": {
                  "type": "integer"
                },
                "separated": {
                  "type": "boolean",
                  "description": "Something was split off."
                },
                "borrow": {
                  "type": "integer",
                  "description": "Sats the last output borrowed from the funding."
                },
                "merged": {
                  "type": "array",
                  "items": {
                    "type": "object"
                  },
                  "description": "Picked sats sharing one output (too close together, or at the tail)."
                },
                "rides_along": {
                  "type": "integer"
                },
                "chunks": {
                  "type": "integer",
                  "description": "A split: the chunks planned for this source."
                },
                "chunk_outputs": {
                  "type": "integer",
                  "description": "A split: the outputs they make (fewer when chunks sit too close together to separate; a `merged` warning)."
                }
              },
              "additionalProperties": true
            }
          },
          "split": {
            "type": "object",
            "description": "An extract with `split`: the split as planned (the request's, normalized).",
            "properties": {
              "type": {
                "type": "string"
              },
              "per_output": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "chunks": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "trim": {
                "type": "boolean"
              }
            },
            "required": [
              "type",
              "per_output",
              "chunks",
              "trim"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "kind",
          "network_fee",
          "tools_fee",
          "fee_rate",
          "vsize",
          "change",
          "total_cost",
          "leaves_wallet",
          "destination",
          "external",
          "inputs",
          "outputs",
          "checks",
          "warnings",
          "skipped",
          "replaces",
          "min_fee_rate"
        ],
        "additionalProperties": false
      },
      "PrepareTransferResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The prepared transfer, for submit."
          },
          "psbt": {
            "type": "string",
            "description": "The PSBT to sign, base64. Every input carries `witnessUtxo` (and `tapInternalKey` / `redeemScript` / `nonWitnessUtxo` as its type needs); no `sighashType`."
          },
          "sign": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SignInput"
            },
            "description": "Every input, with the address whose key signs it. Sign with the default sighash."
          },
          "summary": {
            "$ref": "#/components/schemas/TransferSummary"
          },
          "expires_at": {
            "type": "integer",
            "description": "Unix seconds: submit before then (10 minutes)."
          }
        },
        "required": [
          "id",
          "psbt",
          "sign",
          "summary",
          "expires_at"
        ],
        "additionalProperties": false
      },
      "SubmitTransferRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "From prepare."
          },
          "psbt": {
            "type": "string",
            "description": "The PSBT from prepare with every input signed, base64 (finalized or not)."
          }
        },
        "required": [
          "id",
          "psbt"
        ],
        "additionalProperties": false
      },
      "TransferRecord": {
        "type": "object",
        "description": "A wallet transfer: what is on chain or was chosen by its owner.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The prepared transfer's id."
          },
          "txid": {
            "type": "string",
            "description": "Its transaction id (what `/tx/{txid}` shows)."
          },
          "kind": {
            "type": "string",
            "enum": [
              "extract",
              "send",
              "send_n",
              "chop",
              "consolidate",
              "multisend",
              "speedup",
              "cancel"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "confirmed",
              "replaced",
              "conflicted",
              "dropped",
              "unknown",
              "rejected"
            ],
            "description": "`pending` in the mempool; `confirmed` in a block; `replaced` by a speed-up or cancel built here (`replaced_by`); `conflicted`: a block spent its inputs and it was provably not mined (its own outputs never appeared within six blocks); `dropped`: in no mempool and its inputs unspent (it may still resurface until voided); `unknown`: the broadcast's outcome is not known yet; `rejected`: bitcoind refused it, so it was never sent and cannot resurface."
          },
          "created_at": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "updated_at": {
            "type": "integer",
            "description": "Unix seconds."
          },
          "owner": {
            "type": "object",
            "description": "The owner's addresses (one transfer's read).",
            "properties": {
              "payment_address": {
                "type": "string",
                "description": "Paid the fees."
              },
              "ordinals_address": {
                "type": "string",
                "description": "The ordinals address."
              }
            },
            "required": [
              "payment_address",
              "ordinals_address"
            ],
            "additionalProperties": false
          },
          "owner_role": {
            "type": "string",
            "enum": [
              "payment",
              "ordinals",
              "both"
            ],
            "description": "The queried address's part in it (a list read)."
          },
          "destination": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where the moved sats went (`null` for a multisend)."
          },
          "fee_rate": {
            "type": "number",
            "description": "sat/vB."
          },
          "network_fee": {
            "type": "integer",
            "description": "Sats."
          },
          "tools_fee": {
            "type": "integer",
            "description": "The flat raresats.net fee it paid, in sats."
          },
          "vsize": {
            "type": "integer",
            "description": "Its size in vbytes."
          },
          "replaces": {
            "type": [
              "string",
              "null"
            ],
            "description": "The transfer it replaced (speed-up, cancel)."
          },
          "replaced_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "The transaction that replaced it."
          },
          "block_height": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The block it confirmed in."
          },
          "outputs": {
            "type": "array",
            "description": "Its outputs.",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer",
                  "description": "vout."
                },
                "address": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Who it pays."
                },
                "value": {
                  "type": "integer",
                  "description": "Sats."
                },
                "role": {
                  "type": "string",
                  "description": "`dest`, `return`, `plain_return`, `tools_fee` or `change`."
                }
              },
              "required": [
                "index",
                "address",
                "value",
                "role"
              ],
              "additionalProperties": false
            }
          },
          "actions": {
            "type": "object",
            "description": "What its owner can do now.",
            "properties": {
              "speedup": {
                "type": "boolean",
                "description": "It is pending: a speed-up can replace it."
              },
              "cancel": {
                "type": "boolean",
                "description": "It could still confirm (pending, unknown, dropped) and its chain of replacements pays someone else: a cancel (or a void) sends its sources back. It never hides a cancel the prepare would allow; the prepare decides with the mempool (409 nothing_to_cancel)."
              }
            },
            "required": [
              "speedup",
              "cancel"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "id",
          "txid",
          "kind",
          "status",
          "created_at",
          "updated_at",
          "destination",
          "fee_rate",
          "network_fee",
          "tools_fee",
          "vsize",
          "replaces",
          "replaced_by",
          "block_height",
          "outputs",
          "actions"
        ],
        "additionalProperties": false
      },
      "SubmitTransferResponse": {
        "type": "object",
        "properties": {
          "txid": {
            "type": "string",
            "description": "The broadcast transaction."
          },
          "transfer": {
            "$ref": "#/components/schemas/TransferRecord"
          }
        },
        "required": [
          "txid"
        ],
        "additionalProperties": false
      },
      "TransferList": {
        "type": "object",
        "properties": {
          "transfers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TransferRecord"
            },
            "description": "Newest first."
          },
          "total": {
            "type": "integer",
            "description": "How many transfers match without `limit` (with `status=pending`: everything you still have to watch)."
          }
        },
        "required": [
          "transfers",
          "total"
        ],
        "additionalProperties": false
      }
    }
  }
}
