raresats.net API
Getting started View as Markdown

Errors and limits

The error object #

Every /api/market/* route answers an error with its HTTP status and:

Error
{
  "error": "the cancel message is more than 10 minutes old: sign a new one",
  "code": "stale_message"
}
  • code is stable and machine-readable: branch on it. error is for people and may change.
  • Some codes carry extra fields: outpoint, id and status (not_active), txid (broadcast_unknown), reason and setup_txid (conflict, rejected), available, prices and platform_fee (insufficient_funds).
  • The data routes (/api/market, /api/sales, /api/sat/…, /api/address/…, /api/rows/… and the feeds) answer {"error": "..."} with no code.
FieldTypeRequiredDescription
errorstringyesA human-readable message. Show it; do not parse it.
codestringyesA stable machine-readable reason (see the error code table).
outpointstringnoThe outpoint the error is about, when there is one.
idstringnoThe listing the error is about, when there is one.
statusstringnoThat listing's status (not_active).
txidstringnoThe purchase transaction (broadcast_unknown).
setup_txidstringnoThe setup transaction, when it was already broadcast (conflict, rejected).
reasonstringnobitcoind's rejection reason (conflict, rejected).
availableintegernoSats the payment address can spend (insufficient_funds).
pricesintegernoSum of the listing prices (insufficient_funds).
platform_feeintegernoThe platform fee (insufficient_funds).
violationsarray of objectnoBroken purchase invariants (invariant_violated).
violations[].rulestringyesThe rule broken
violations[].messagestringyesWhat is wrong
next_change_atintegernoWhen the address may change its display name again, unix seconds (name_change_too_soon).
retiredobjectnoOn a 404 for a retired row (retired_row): the row and where its sats are now.
retired.rowstringyesThe retired row asked for.
retired.successorobject | nullyesThe parent row and years that hold its sats; null for a row retired outright (alpha_jan_feb_2009).
retired.successor.rowstringyes
retired.successor.yearsarray of integeryes
categorystringnoWhy the AI moderation refused the text (moderated): harassment, hate, sexual, violence, doxxing, scam, spam, malware, illegal, impersonation, manipulation or other.
untilintegernoWhen the mute ends, unix seconds (muted; on moderated when that refusal muted the address).

Statuses #

StatusMeaningRetry?
400A malformed request.No: fix it.
403A cross-origin browser POST.No: call from a server.
404No such route, listing, outpoint listing or prepared purchase.No.
405Wrong method; see the allow header.No.
409A conflict with the chain or the store: spent, sold, changed, expired, a lost race.Re-read, then prepare again.
413Body over 256 KiB.No.
415A POST that is not application/json.No.
422A marketplace rule the request breaks.No: change the request.
429Rate limited.After retry-after seconds.
500A server bug.Report it.
503bitcoind, the rare-sat index or the ord indexer is unavailable or catching up; or broadcast_unknown.Yes, after a short wait (broadcast_unknown: submit the same purchase again).

Every error code #

CodeStatusMeaning
bad_address400An address is not a mainnet address (or not one at all).
bad_addresses400addresses must list 1 to 200 addresses.
bad_bidder400The offer's bidder is missing, not an object, or lacks ordinals_public_key.
bad_buyer400buyer is not an object.
bad_config500The marketplace is misconfigured.
bad_contains400contains is not 0, 1 or only, or is set without row.
bad_expiry400expires_in is not 86400, 259200, 604800 or 2592000 (seconds), null or "never".
bad_fee_rate400fee_rate is not a positive number up to 5000.
bad_id400id is not a prepared purchase or transfer id.
bad_ids400ids / listing_ids is empty, too long, malformed, or lists an id twice.
bad_items400items 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.
bad_json400The body is not valid JSON.
bad_message400The 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.
bad_nonce422The login nonce was not handed out for this address, has expired (10 minutes) or was used: ask for a new one.
bad_order400order is not asc or desc.
bad_outpoint400Not an outpoint (txid:vout).
bad_outpoints400outpoints lists none, or more than 100.
bad_paging400limit or offset out of range.
bad_path400The path is not valid percent-encoding.
bad_payout422A listed input is paired with an output that pays no address, or the payout address is the marketplace's fee address.
bad_price400A price is not a whole number of sats.
bad_psbt400Not a base64 PSBT, or one that does not parse.
bad_public_key400A public key is not hex, or not a valid secp256k1 key of the right size.
bad_request400The body is not a JSON object, or the engine refused a malformed request (e.g. a purchase submitted without its signed setup PSBT).
bad_row400row is not a row id.
bad_sequence422A listed input is not signed with sequence 0xfffffffd.
bad_sighash422A signature uses the wrong sighash type (listings: 0x83; purchases: DEFAULT or ALL).
bad_signature400, 422400: signature is missing or too long. 422: a signature does not verify (cancel or registration message, listing or purchase input).
bad_sort400sort is not unit, price or new.
bad_status400status is not all or a comma-separated list of offer statuses, or (wallet transfers) not pending or all.
bad_structure422The listing PSBT is not the expected layout (pairing, version 2, locktime 0, one seller, sequences), or a purchase would pay the fee address.
bad_sub400sub is not 0 or 1.
bad_types400types is not a comma-separated list of activity event types.
bad_wallet_addresses400wallet_addresses is not a list of at most 4 mainnet addresses.
banned403The address is banned from chat: it may not post or set a display name.
bitcoind_unavailable503bitcoind is not available.
broadcast_unknown503The broadcast's outcome is unknown: submit the same purchase or transfer again to settle it. Carries txid.
busy503Too 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.
changed409The 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.
chat_busy429Too 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.
chat_disabled404Chat and display names are off on this server.
config_changed409The 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).
conflict409A 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.
cross_origin403A 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.
duplicate409The same message (ignoring case) from the same address within 2 minutes.
duplicate_outpoint400The same UTXO twice in one listing.
dust_output422A bought UTXO is below the dust limit of your ordinals address type: use a Taproot or native SegWit ordinals address.
empty_text422Nothing is left of the message once control, zero-width and bidi characters are dropped and spaces collapsed.
engine_unavailable503The trade engine is not available.
expired409The prepared purchase, offer or transfer expired, or the offer itself has: prepare it again.
fee_rate_too_low422fee_rate is below the current minimum (GET /api/market/fees).
fee_too_high422The network fee would exceed the per-transaction cap (200,000 sats): lower the fee rate or move fewer.
fees_unavailable503No fee estimate is available.
fork_behind503The rare-sat index has not caught up with bitcoind: try again in a minute.
fork_unavailable503The rare-sat index is not available.
funding_spent409A UTXO of the bidder's that funds the offer was spent (or is no longer plain cardinal): the offer is no longer valid.
future_message422The cancel or registration message is dated more than 2 minutes ahead: check the clock.
indexer_behind503The ord indexer is catching up: try again shortly.
inscribed422The UTXO carries an inscription: only rare sats are listed; the wallet tools only send it whole.
insufficient_funds422The payment address's plain UTXOs cannot pay prices, fee, padding and network fee (or a transfer's fees). Carries available, prices, platform_fee.
internal500A server bug. Report it.
invariant_violated500A planned or finalized purchase or transfer broke an invariant (violations); nothing was broadcast.
key_mismatch422The public key does not control the address.
legacy_address422A legacy (P2PKH, 1…) address: use Taproot or SegWit.
listing_changed409A listing's stored terms no longer match the plan: prepare it again.
market_unavailable503The marketplace is closed right now (its backends disagree on the network, or are unreachable).
method_not_allowed405Wrong method for the route; the allow header lists the right ones.
missing_signature422An input that must be signed is not.
moderated422The 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).
moderation_unavailable503The AI moderation could not check the text right now (timeout or model error): nothing was posted. Try again in a moment.
muted403The 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.
name_address422A display name must not look like an address (bc1…, base58) or a hash.
name_change_too_soon429A display name changes at most once in 24 hours; next_change_at says when.
name_chars422A display name uses only letters, digits, spaces and _ . -, and starts and ends with a letter or digit.
name_length422A display name is 3 to 24 characters.
name_reserved422The display name is reserved (raresats, admin, moderator, support, official, satoshi and the like).
name_taken409Another 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.
no_endpoint404No such /api/market/* route.
no_row422The UTXO holds no sat of a market row.
no_session401No chat session: sign in (POST /api/session) and send its cookie.
not_active409A listing (or offer) is not active: being bought (or accepted), sold, cancelled, moved, expired or invalid. Carries id and status.
not_admin403Only a chat admin (SUPPLY_CHAT_ADMINS) may do that.
not_bannable422An admin cannot be banned.
not_bidder422An offer was not made by address (neither its payment nor its ordinals address).
not_found404No such listing or offer. In chat: no such message. A display name to remove that does not exist.
not_json415A POST without content-type: application/json.
not_listed404That outpoint has no live listing.
not_owner422The UTXO does not belong to the seller address, or (wallet tools) to the owner's addresses, or the transfer was made by another wallet.
not_seller422A listing was not listed by address.
offer_changed409The offer's stored signatures no longer verify: it cannot be accepted.
oracle_unavailable503The ord oracle is not available.
own_utxo422The UTXO is held by one of the bidder's own addresses.
pending409The UTXO's listing is being bought, or an offer of it accepted, right now.
price_too_high422The price is above 21,000,000 BTC.
price_too_low422The price is at most the UTXO's own value, below 546 sats, or below the payout output's dust limit.
psbt_mismatch422The signed PSBT is not the prepared transaction.
pubkey_mismatch422The trade engine found the public key is not the address's key.
rate_limited429Over 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.
rejected422bitcoind refused the transaction (reason).
replayed409That cancel or registration message was used already.
retired_row404row 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.
room_busy429Over 5 chat messages a second across the whole chat; wait retry-after seconds.
runes422The UTXO carries runes (the wallet tools only send it whole).
spent409The UTXO (or a listing's UTXO) is spent or does not exist.
stale_message422The cancel or registration message is more than 10 minutes old: sign a new one.
suspicious_link422A 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.
bad_topic400A 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.
unknown_topic404No such chat topic, or an archived one (which takes no new messages).
bad_topic_text422A topic's name must be 1-40 characters, its description at most 140.
topic_exists409A topic (or an archived one) has that id already.
too_many_topics422At most 50 chat topics: archive one first.
not_archivable422General cannot be archived.
text_too_long422A chat message is at most 500 characters.
too_large413The body is over 256 KiB.
too_many_items422Too 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.
unchanged409That is already the display name.
unconfirmed409The UTXO is not confirmed yet.
unindexed409The ord indexer does not know the UTXO yet.
unknown_offer404No such prepared offer (it expired, or the server restarted): prepare it again.
unknown_purchase404No such prepared purchase (it was dropped: your 11th prepared since, a busy server, or a restart): prepare it again.
unsupported_address422An address type the marketplace does not trade (only Taproot, native SegWit and nested SegWit).
unsupported_script422The trade engine met a script type it does not support.
untracked422The UTXO holds no rare sat the index tracks (send it whole instead).
utxo_mismatch409The PSBT's amount or script of a UTXO is not the chain's.
utxos_required500A server bug in listing verification.
bad_kind400kind is not one of the wallet tools (extract, send, send_n, chop, consolidate, multisend, speedup, cancel), or a send mode is unknown.
bad_owner400owner must give the payment and ordinals addresses and their public keys.
bad_destination422The destination (or a multisend recipient) is the marketplace's fee address, or missing.
bad_type400type (send N) is not a sat type, types joined with +, or block9 / 450x.
bad_count400count (send N) is not a whole number of sats of at least 1.
bad_chop_size400chop_size is not a whole number from 330 to 100,000,000.
bad_split400split (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).
bad_sends400sends must list 1-50 payments of {address, value}, each at least its address type's minimum (330, or 546 for P2SH and P2PKH).
payment_destination422Rare 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.
address_too_large422An owner address holds more than 5,000 outputs: the wallet tools cannot plan for it.
not_plain422A UTXO to consolidate is not plain bitcoin (it holds tracked, exotic or inscribed sats, or runes).
already_extracted422The UTXO is extracted already (its rare sats sit in an output of their own).
split_chunk422Skip 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.
not_enough_sats422Your UTXOs do not hold count sats of that type that can be sent. Carries available.
nothing_to_do422Nothing to move: every item was skipped (skipped), or a consolidation has fewer than 2 UTXOs, or a chop leaves one piece.
nothing_to_separate422Extracting would leave the UTXO one output: its rare sats are apart already, or too close to its ends.
keep_in_destination422Exotic or unpicked tracked sats sit so close to a picked one that they would have to leave with it: send the whole UTXO instead.
range_too_small422A range chunk (send N of block9 or 450x) must be at least the destination's padding: 330 sats, 546 for P2SH and P2PKH.
listed_public_alone422A UTXO whose listing signature is public must be moved on its own (and fast).
inscribed_consolidate422Inscribed UTXOs are sent whole and 1:1, never merged into one output.
runes_multi422At most one rune UTXO per transfer (except a whole send merged into one output).
dust_destination422A whole UTXO is too small for the destination's address type.
too_many_outputs422The transfer would have more than 100 outputs: move fewer UTXOs at once.
tx_too_large422The transfer would exceed 100,000 vB: move fewer UTXOs at once.
unknown_transfer404No such transfer: an unknown or forgotten prepared id, or a txid the wallet tools did not build.
not_pending409The transfer to speed up or cancel is not waiting in the mempool any more (confirmed, replaced).
has_descendants409A transaction spends the transfer's outputs already: it can no longer be replaced.
offer_overlap409Since the prepare, a planned input started funding one of your offers, or a UTXO the server picked got an offer: prepare the transfer again.
nothing_to_cancel409A 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.
replacement_fee_too_low422The replacement pays too little to replace the pending transaction (BIP 125): raise the fee rate to at least min_fee_rate.

Limits #

  • Edge rate limit: 50 requests per 10 seconds per IP on /api/* (Cloudflare). Requests over it are blocked at the edge for a short while.
  • POST rate limit: 30 POSTs a minute per client (an IPv4 address or an IPv6 /64) on /api/market/*, a fixed window: 429 rate_limited with a retry-after header in seconds.
  • Prepared purchases and offers: each client keeps its 10 latest of each; preparing an 11th drops its oldest (which then answers unknown_purchase / unknown_offer at submit).
  • Body: JSON, content-type: application/json, at most 256 KiB (413 too_large, 415 not_json, 400 bad_json).
  • Origin: a POST with an Origin header of another host, or sec-fetch-site: cross-site, is refused (403 cross_origin). No CORS headers are sent, so browsers on other sites cannot read answers either. Server-side clients (curl, Node, Python) send no Origin and are unaffected.
  • Sizes: at most 50 UTXOs per listing PSBT, 20 listings per purchase (max_bulk), 100 ids per cancel, 100 outpoints per batch lookup, 200 listings or events per page, 500 sequence numbers per /api/sales/parties.
  • Caching: marketplace answers are no-store. The data routes may be cached briefly (/api/market, /api/sales and /api/sales/parties 30 s, /api/sat/{n} 15 s, /api/address/{address} 30 s). Large answers are gzipped when you send accept-encoding: gzip.