raresats.net API
Wallet tools API View as Markdown

Prepare a transfer

POST/api/market/transfer/prepare

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.

Request body #

content-type: application/json

FieldTypeRequiredDescription
ownerobjectyesThe connected wallet: Xverse-style wallets have two addresses, UniSat-style one (give it as both). Both keys are checked against their addresses.
owner.payment_addressstringyesPays the fees and gets the change and plain slices. Taproot, native SegWit or nested SegWit.
owner.payment_public_keystringyesIts public key, hex (Taproot: the internal key, x-only or compressed; SegWit: compressed).
owner.ordinals_addressstringyesHolds the rare sats; the default destination. May equal payment_address.
owner.ordinals_public_keystringyesIts public key, hex.
kindstringyesWhat to do. One of: extract, send, send_n, chop, consolidate, multisend, speedup, cancel.
fee_ratenumberyessat/vB, at least minimum of GET /api/market/fees. (max 5000)
itemsarray of objectnoextract, send, chop; consolidate (2 or more plain UTXOs, or absent: the server picks); optional for send_n (limits its pick). (1-50 items)
items[].outpointstringyestxid:vout.
items[].satsarray of integer | nullnoextract 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. (0-10000 items)
destinationstringnoWhere the moved sats go. Default: your ordinals address (your payment address for consolidate). P2TR, P2WPKH, P2SH, P2WSH or P2PKH; never the fee address.
plain_tostringnoextract: where slices holding no tracked sat go (default payment). One of: payment, source.
splitobject | objectnoextract only: split each UTXO's sats of one type into chunks instead of separating each rare sat (see Extract rare sats). 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).
split.typestringyesThe 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.
split.per_outputintegernoSats of the type per output, in offset order; the last chunk holds the remainder. Exactly one of per_output and chunks. (min 1, max 2000)
split.chunksintegernoHow many chunks: near-equal, the first ones one larger. Exactly one of per_output and chunks. (min 2, max 100)
split.trimbooleannotrue: 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).
modestringnosend: the UTXOs as they are, or only their rare sats (default whole). One of: whole, rare.
consolidatebooleannosend whole: one output for all the UTXOs instead of one each.
typestringnosend_n: an exact type combination (uncommon, black+uncommon) or a range type (block9, 450x).
countintegernosend_n: how many sats. (min 1)
chop_sizeintegernochop: cut at sats divisible by this. (min 330, max 100000000)
sendsarray of objectnomultisend: the payments. (1-50 items)
sends[].addressstringyes
sends[].valueintegeryesSats.
txidstringnospeedup, cancel: the pending wallet transfer to replace.
confirm_payment_destinationbooleannoAllow sending rare sats, inscriptions or runes to your own payment address (otherwise payment_destination).

Example request #

cURL
curl -X POST 'https://raresats.net/api/market/transfer/prepare' \
  -H 'content-type: application/json' \
  -d '{
  "owner": {
    "payment_address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
    "payment_public_key": "039b3b694b8fc5b5e07fb069c783cac754f5d38c3e08bed1960e31fdb1dda35c24",
    "ordinals_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
    "ordinals_public_key": "03cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115"
  },
  "kind": "extract",
  "items": [
    {
      "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0"
    }
  ],
  "fee_rate": 3
}'
JavaScript
const response = await fetch('https://raresats.net/api/market/transfer/prepare', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({
    "owner": {
      "payment_address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
      "payment_public_key": "039b3b694b8fc5b5e07fb069c783cac754f5d38c3e08bed1960e31fdb1dda35c24",
      "ordinals_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
      "ordinals_public_key": "03cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115"
    },
    "kind": "extract",
    "items": [
      {
        "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0"
      }
    ],
    "fee_rate": 3
  })
});
const data = await response.json();
Python
import requests

data = requests.post("https://raresats.net/api/market/transfer/prepare", json={
    "owner": {
        "payment_address": "37VucYSaXLCAsxYyAPfbSi9eh4iEcbShgf",
        "payment_public_key": "039b3b694b8fc5b5e07fb069c783cac754f5d38c3e08bed1960e31fdb1dda35c24",
        "ordinals_address": "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
        "ordinals_public_key": "03cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115"
    },
    "kind": "extract",
    "items": [{
        "outpoint": "24b3eedfdc210f4a5baa96a6c99db5a51d3b1286ab2f58cb0b16fc607e54107f:0"
    }],
    "fee_rate": 3
}).json()

Response 200 #

FieldTypeDescription
idstringThe prepared transfer, for submit.
psbtstringThe PSBT to sign, base64. Every input carries witnessUtxo (and tapInternalKey / redeemScript / nonWitnessUtxo as its type needs); no sighashType.
signarray of objectEvery input, with the address whose key signs it. Sign with the default sighash.
sign[].indexintegerThe input to sign.
sign[].addressstringThe address whose key signs it.
sign[].sighashintegerThe 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).
summaryobjectThe 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.
summary.kindstringThe kind.
summary.network_feeintegerSats, paid from your plain bitcoin.
summary.tools_feeintegerThe flat raresats.net fee (tools.fee_sats; 0 on a speed-up or cancel, which keep the original's fee output).
summary.fee_ratenumbersat/vB.
summary.vsizeintegerEstimated vbytes (an upper bound).
summary.changeintegerSats back to your payment address as change.
summary.total_costintegernetwork_fee + tools_fee.
summary.leaves_walletintegerSats paid to addresses that are not yours, other than the fees.
summary.destinationstring | nullThe destination address.
summary.externalbooleanThe destination is not one of your addresses.
summary.inputsarray of objectEvery input: your UTXOs to move (source), plain funding (funding), or plain UTXOs (plain).
summary.inputs[].indexinteger
summary.inputs[].outpointstring
summary.inputs[].valueinteger
summary.inputs[].rolestringOne of: source, funding, plain.
summary.inputs[].addressstring
summary.inputs[].owner_rolestringOne of: ordinals, payment.
summary.inputs[].itemsarray of objectIts tracked sats.
summary.inputs[].items[].satintegerThe first sat.
summary.inputs[].items[].lenintegerHow many sats (1, or a range).
summary.inputs[].items[].typesarray of stringIts sat types.
summary.inputs[].items[].inputintegerThe input it comes from.
summary.inputs[].items[].offsetintegerIts offset in that input.
summary.inputs[].items[].atinteger | nullIts offset in this output.
summary.inputs[].items[].selectedbooleanPicked to move (false: it stays where it was).
summary.inputs[].inscriptionsintegerHow many inscriptions it carries.
summary.inputs[].runesboolean
summary.outputsarray of objectEvery output, in order.
summary.outputs[].indexinteger
summary.outputs[].valueinteger
summary.outputs[].addressstring
summary.outputs[].rolestringdest: moved sats; return: back to a source's address; plain_return: a plain slice to your payment address; tools_fee; change.
summary.outputs[].tostringWhose address it pays. One of: ordinals, payment, source, external, fee.
summary.outputs[].partsarray of objectThe input sats it receives, first in first out: [from, to) of input input, at offset at.
summary.outputs[].parts[].inputinteger
summary.outputs[].parts[].frominteger
summary.outputs[].parts[].tointeger
summary.outputs[].parts[].atinteger
summary.outputs[].parts[].kindstring
summary.outputs[].itemsarray of objectThe tracked sats it receives.
summary.outputs[].items[].satintegerThe first sat.
summary.outputs[].items[].lenintegerHow many sats (1, or a range).
summary.outputs[].items[].typesarray of stringIts sat types.
summary.outputs[].items[].inputintegerThe input it comes from.
summary.outputs[].items[].offsetintegerIts offset in that input.
summary.outputs[].items[].atinteger | nullIts offset in this output.
summary.outputs[].items[].selectedbooleanPicked to move (false: it stays where it was).
summary.outputs[].rides_alongarray of objectUnpicked or exotic sats that ride along in an output to yourself.
summary.outputs[].rides_along[].inputinteger
summary.outputs[].rides_along[].frominteger
summary.outputs[].rides_along[].tointeger
summary.outputs[].rides_along[].atinteger
summary.outputs[].rides_along[].kindstring
summary.outputs[].keptarray of objectSats 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.
summary.outputs[].kept[].inputinteger
summary.outputs[].kept[].frominteger
summary.outputs[].kept[].tointeger
summary.outputs[].kept[].kindstring
summary.outputs[].kept[].typesarray of string
summary.outputs[].paddingintegerSats other than the picked ones in an extracted output.
summary.outputs[].extractedboolean | nullWhether the index will count it extracted (Extraction); null when it holds no tracked sat or the rule is unknown.
summary.checksarray of objectWhat the server verified on the unsigned transaction ("No rare sat is paid as fee", …).
summary.checks[].rulestring
summary.checks[].okboolean
summary.checks[].labelstring
summary.warningsarray of objectThings 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.
summary.warnings[].codestring
summary.warnings[].messagestring
summary.warnings[].outpointstring
summary.skippedarray of objectItems 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).
summary.skipped[].outpointstring
summary.skipped[].codestring
summary.skipped[].messagestring
summary.replacesobject | nullA speed-up or cancel: the pending transaction it replaces (fee and fee_rate null for a void of one no longer in the mempool).
summary.replaces.txidstring
summary.replaces.feeinteger | null
summary.replaces.fee_ratenumber | null
summary.min_fee_ratenumber | nullA replacement: the lowest fee rate that replaces the pending transaction.
summary.layoutarray of objectHow each source was cut (layout kinds).
summary.layout[].outpointstring
summary.layout[].inputinteger
summary.layout[].separatedbooleanSomething was split off.
summary.layout[].borrowintegerSats the last output borrowed from the funding.
summary.layout[].mergedarray of objectPicked sats sharing one output (too close together, or at the tail).
summary.layout[].rides_alonginteger
summary.layout[].chunksintegerA split: the chunks planned for this source.
summary.layout[].chunk_outputsintegerA split: the outputs they make (fewer when chunks sit too close together to separate; a merged warning).
summary.splitobjectAn extract with split: the split as planned (the request's, normalized).
summary.split.typestring
summary.split.per_outputinteger | null
summary.split.chunksinteger | null
summary.split.trimboolean
expires_atintegerUnix seconds: submit before then (10 minutes).
Response
{
  "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
}

Errors #

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

StatusCodeMeaning
400bad_addressAn address is not a mainnet address (or not one at all).
400bad_chop_sizechop_size is not a whole number from 330 to 100,000,000.
400bad_countcount (send N) is not a whole number of sats of at least 1.
400bad_fee_ratefee_rate is not a positive number up to 5000.
400bad_itemsitems 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.
400bad_jsonThe body is not valid JSON.
400bad_kindkind is not one of the wallet tools (extract, send, send_n, chop, consolidate, multisend, speedup, cancel), or a send mode is unknown.
400bad_outpointNot an outpoint (txid:vout).
400bad_ownerowner must give the payment and ordinals addresses and their public keys.
400bad_requestThe body is not a JSON object, or the engine refused a malformed request (e.g. a purchase submitted without its signed setup PSBT).
400bad_sendssends must list 1-50 payments of {address, value}, each at least its address type's minimum (330, or 546 for P2SH and P2PKH).
400bad_splitsplit (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).
400bad_typetype (send N) is not a sat type, types joined with +, or block9 / 450x.
400duplicate_outpointThe same UTXO twice in one listing.
403cross_originA 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.
404unknown_transferNo such transfer: an unknown or forgotten prepared id, or a txid the wallet tools did not build.
405method_not_allowedWrong method for the route; the allow header lists the right ones.
409conflictA 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.
409has_descendantsA transaction spends the transfer's outputs already: it can no longer be replaced.
409not_pendingThe transfer to speed up or cancel is not waiting in the mempool any more (confirmed, replaced).
409nothing_to_cancelA 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.
409pendingThe UTXO's listing is being bought, or an offer of it accepted, right now.
409spentThe UTXO (or a listing's UTXO) is spent or does not exist.
409unconfirmedThe UTXO is not confirmed yet.
409unindexedThe ord indexer does not know the UTXO yet.
413too_largeThe body is over 256 KiB.
415not_jsonA POST without content-type: application/json.
422address_too_largeAn owner address holds more than 5,000 outputs: the wallet tools cannot plan for it.
422already_extractedThe UTXO is extracted already (its rare sats sit in an output of their own).
422bad_destinationThe destination (or a multisend recipient) is the marketplace's fee address, or missing.
422dust_destinationA whole UTXO is too small for the destination's address type.
422fee_rate_too_lowfee_rate is below the current minimum (GET /api/market/fees).
422fee_too_highThe network fee would exceed the per-transaction cap (200,000 sats): lower the fee rate or move fewer.
422inscribedThe UTXO carries an inscription: only rare sats are listed; the wallet tools only send it whole.
422inscribed_consolidateInscribed UTXOs are sent whole and 1:1, never merged into one output.
422insufficient_fundsThe payment address's plain UTXOs cannot pay prices, fee, padding and network fee (or a transfer's fees). Carries available, prices, platform_fee.
422keep_in_destinationExotic or unpicked tracked sats sit so close to a picked one that they would have to leave with it: send the whole UTXO instead.
422key_mismatchThe public key does not control the address.
422legacy_addressA legacy (P2PKH, 1…) address: use Taproot or SegWit.
422listed_public_aloneA UTXO whose listing signature is public must be moved on its own (and fast).
422not_enough_satsYour UTXOs do not hold count sats of that type that can be sent. Carries available.
422not_ownerThe UTXO does not belong to the seller address, or (wallet tools) to the owner's addresses, or the transfer was made by another wallet.
422not_plainA UTXO to consolidate is not plain bitcoin (it holds tracked, exotic or inscribed sats, or runes).
422nothing_to_doNothing to move: every item was skipped (skipped), or a consolidation has fewer than 2 UTXOs, or a chop leaves one piece.
422nothing_to_separateExtracting would leave the UTXO one output: its rare sats are apart already, or too close to its ends.
422payment_destinationRare 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.
422range_too_smallA range chunk (send N of block9 or 450x) must be at least the destination's padding: 330 sats, 546 for P2SH and P2PKH.
422replacement_fee_too_lowThe replacement pays too little to replace the pending transaction (BIP 125): raise the fee rate to at least min_fee_rate.
422runesThe UTXO carries runes (the wallet tools only send it whole).
422runes_multiAt most one rune UTXO per transfer (except a whole send merged into one output).
422split_chunkSkip 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.
422too_many_itemsToo 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.
422too_many_outputsThe transfer would have more than 100 outputs: move fewer UTXOs at once.
422tx_too_largeThe transfer would exceed 100,000 vB: move fewer UTXOs at once.
422unsupported_addressAn address type the marketplace does not trade (only Taproot, native SegWit and nested SegWit).
422untrackedThe UTXO holds no rare sat the index tracks (send it whole instead).
429rate_limitedOver 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.
500invariant_violatedA planned or finalized purchase or transfer broke an invariant (violations); nothing was broadcast.
503bitcoind_unavailablebitcoind is not available.
503busyToo 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.
503engine_unavailableThe trade engine is not available.
503fork_behindThe rare-sat index has not caught up with bitcoind: try again in a minute.
503fork_unavailableThe rare-sat index is not available.
503indexer_behindThe ord indexer is catching up: try again shortly.
503market_unavailableThe marketplace is closed right now (its backends disagree on the network, or are unreachable).
503oracle_unavailableThe ord oracle is not available.
Error (422)
{
  "error": "c3f31009cbbbced4b1a0acb30d924e3e025b10647c43092b68262f4e83125bf6:0 would stay one output: its rare sats are already apart, or too close to its ends",
  "code": "nothing_to_separate"
}

Then sign every input in sign (each with the key of its address; your wallet's default sighash) and submit before expires_at. Nothing is reserved meanwhile: if a UTXO moves, submit answers 409 and you prepare again.

Kinds #

kindBody fieldsWhat the transaction does
extractitems: [{outpoint, sats?}], destination?, plain_to?, split?Carves the chosen tracked sats (all of them when sats is absent) of 1–50 UTXOs into outputs of their own, to destination (default: your ordinals address). What you did not pick goes back to the address it came from. With split: {type, per_output | chunks, trim?} it cuts each UTXO's sats of one type into chunks instead, one output per chunk (Split into chunks).
senditems, destination, mode: "whole"|"rare", consolidate?whole: the UTXOs as they are, one output each (or one output for all with consolidate: true). rare: only the rare sats, laid out as an extraction; the rest comes back.
send_ntype, count, destination, items?N sats of one type: an exact type combination such as uncommon or black+uncommon, or a range type (block9, 450x) cut as an aligned sub-range.
chopitems, chop_size, destination?Cuts a UTXO's whole ranges (block 9 style) into chop_size-aligned pieces.
consolidateitems?, destination?Merges plain UTXOs into one output (default: your payment address). Without items the server picks your payment address's plain UTXOs: up to 50, smallest first, never a listed UTXO or your offers' funding, and not the largest when it is worth more than all the others together (merging into it would only cost fees). Fewer than 2 left is nothing_to_do.
multisendsends: [{address, value}]Plain bitcoin to 1–50 recipients, change back to you.
speeduptxidReplaces a pending transfer the site built with the same transaction at a higher fee rate (RBF).
canceltxidReplaces (or voids) a transfer the site built with one that sends every source UTXO back to where it came from.

Every kind also takes owner and fee_rate. The guides walk through them: Extract rare sats, Send rare sats and bitcoin, Speed up or cancel.

The summary #

summary is the plan drawn for people: each input with its tracked sats (items, selected), each output with what it holds (items, rides_along, padding) and where it goes (to: ordinals, payment, source, external or fee), the checks the server ran on the unsigned transaction, and warnings and skipped items with their reasons (for example listed, offered, inscribed, runes, already_extracted, nothing_to_separate, or spent for a UTXO send_n would have picked that is already spent in the mempool). An output that carries home sats that are not plain (unpicked rare sats, exotic ranges such as vintage) lists them in kept, with their types. A split also answers split (as planned) and, per source in layout, chunks and chunk_outputs. total_cost is the network fee plus the tools fee; leaves_wallet is what is paid to addresses that are not yours (other than the fees).