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
| Field | Type | Required | Description |
|---|---|---|---|
owner | object | yes | The connected wallet: Xverse-style wallets have two addresses, UniSat-style one (give it as both). Both keys are checked against their addresses. |
owner.payment_address | string | yes | Pays the fees and gets the change and plain slices. Taproot, native SegWit or nested SegWit. |
owner.payment_public_key | string | yes | Its public key, hex (Taproot: the internal key, x-only or compressed; SegWit: compressed). |
owner.ordinals_address | string | yes | Holds the rare sats; the default destination. May equal payment_address. |
owner.ordinals_public_key | string | yes | Its public key, hex. |
kind | string | yes | What to do. One of: extract, send, send_n, chop, consolidate, multisend, speedup, cancel. |
fee_rate | number | yes | sat/vB, at least minimum of GET /api/market/fees. (max 5000) |
items | array of object | no | extract, send, chop; consolidate (2 or more plain UTXOs, or absent: the server picks); optional for send_n (limits its pick). (1-50 items) |
items[].outpoint | string | yes | txid:vout. |
items[].sats | array of integer | null | no | 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. (0-10000 items) |
destination | string | no | 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 | string | no | extract: where slices holding no tracked sat go (default payment). One of: payment, source. |
split | object | object | no | extract 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.type | string | yes | 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. |
split.per_output | integer | no | Sats 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.chunks | integer | no | How many chunks: near-equal, the first ones one larger. Exactly one of per_output and chunks. (min 2, max 100) |
split.trim | boolean | no | 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). |
mode | string | no | send: the UTXOs as they are, or only their rare sats (default whole). One of: whole, rare. |
consolidate | boolean | no | send whole: one output for all the UTXOs instead of one each. |
type | string | no | send_n: an exact type combination (uncommon, black+uncommon) or a range type (block9, 450x). |
count | integer | no | send_n: how many sats. (min 1) |
chop_size | integer | no | chop: cut at sats divisible by this. (min 330, max 100000000) |
sends | array of object | no | multisend: the payments. (1-50 items) |
sends[].address | string | yes | |
sends[].value | integer | yes | Sats. |
txid | string | no | speedup, cancel: the pending wallet transfer to replace. |
confirm_payment_destination | boolean | no | Allow sending rare sats, inscriptions or runes to your own payment address (otherwise payment_destination). |
Example request #
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
}'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();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 #
| Field | Type | Description |
|---|---|---|
id | string | The prepared transfer, for submit. |
psbt | string | The PSBT to sign, base64. Every input carries witnessUtxo (and tapInternalKey / redeemScript / nonWitnessUtxo as its type needs); no sighashType. |
sign | array of object | Every input, with the address whose key signs it. Sign with the default sighash. |
sign[].index | integer | The input to sign. |
sign[].address | string | The address whose key signs it. |
sign[].sighash | integer | 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). |
summary | object | 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. |
summary.kind | string | The kind. |
summary.network_fee | integer | Sats, paid from your plain bitcoin. |
summary.tools_fee | integer | The flat raresats.net fee (tools.fee_sats; 0 on a speed-up or cancel, which keep the original's fee output). |
summary.fee_rate | number | sat/vB. |
summary.vsize | integer | Estimated vbytes (an upper bound). |
summary.change | integer | Sats back to your payment address as change. |
summary.total_cost | integer | network_fee + tools_fee. |
summary.leaves_wallet | integer | Sats paid to addresses that are not yours, other than the fees. |
summary.destination | string | null | The destination address. |
summary.external | boolean | The destination is not one of your addresses. |
summary.inputs | array of object | Every input: your UTXOs to move (source), plain funding (funding), or plain UTXOs (plain). |
summary.inputs[].index | integer | |
summary.inputs[].outpoint | string | |
summary.inputs[].value | integer | |
summary.inputs[].role | string | One of: source, funding, plain. |
summary.inputs[].address | string | |
summary.inputs[].owner_role | string | One of: ordinals, payment. |
summary.inputs[].items | array of object | Its tracked sats. |
summary.inputs[].items[].sat | integer | The first sat. |
summary.inputs[].items[].len | integer | How many sats (1, or a range). |
summary.inputs[].items[].types | array of string | Its sat types. |
summary.inputs[].items[].input | integer | The input it comes from. |
summary.inputs[].items[].offset | integer | Its offset in that input. |
summary.inputs[].items[].at | integer | null | Its offset in this output. |
summary.inputs[].items[].selected | boolean | Picked to move (false: it stays where it was). |
summary.inputs[].inscriptions | integer | How many inscriptions it carries. |
summary.inputs[].runes | boolean | |
summary.outputs | array of object | Every output, in order. |
summary.outputs[].index | integer | |
summary.outputs[].value | integer | |
summary.outputs[].address | string | |
summary.outputs[].role | string | dest: moved sats; return: back to a source's address; plain_return: a plain slice to your payment address; tools_fee; change. |
summary.outputs[].to | string | Whose address it pays. One of: ordinals, payment, source, external, fee. |
summary.outputs[].parts | array of object | The input sats it receives, first in first out: [from, to) of input input, at offset at. |
summary.outputs[].parts[].input | integer | |
summary.outputs[].parts[].from | integer | |
summary.outputs[].parts[].to | integer | |
summary.outputs[].parts[].at | integer | |
summary.outputs[].parts[].kind | string | |
summary.outputs[].items | array of object | The tracked sats it receives. |
summary.outputs[].items[].sat | integer | The first sat. |
summary.outputs[].items[].len | integer | How many sats (1, or a range). |
summary.outputs[].items[].types | array of string | Its sat types. |
summary.outputs[].items[].input | integer | The input it comes from. |
summary.outputs[].items[].offset | integer | Its offset in that input. |
summary.outputs[].items[].at | integer | null | Its offset in this output. |
summary.outputs[].items[].selected | boolean | Picked to move (false: it stays where it was). |
summary.outputs[].rides_along | array of object | Unpicked or exotic sats that ride along in an output to yourself. |
summary.outputs[].rides_along[].input | integer | |
summary.outputs[].rides_along[].from | integer | |
summary.outputs[].rides_along[].to | integer | |
summary.outputs[].rides_along[].at | integer | |
summary.outputs[].rides_along[].kind | string | |
summary.outputs[].kept | array of object | 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. |
summary.outputs[].kept[].input | integer | |
summary.outputs[].kept[].from | integer | |
summary.outputs[].kept[].to | integer | |
summary.outputs[].kept[].kind | string | |
summary.outputs[].kept[].types | array of string | |
summary.outputs[].padding | integer | Sats other than the picked ones in an extracted output. |
summary.outputs[].extracted | boolean | null | Whether the index will count it extracted (Extraction); null when it holds no tracked sat or the rule is unknown. |
summary.checks | array of object | What the server verified on the unsigned transaction ("No rare sat is paid as fee", …). |
summary.checks[].rule | string | |
summary.checks[].ok | boolean | |
summary.checks[].label | string | |
summary.warnings | array of object | 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. |
summary.warnings[].code | string | |
summary.warnings[].message | string | |
summary.warnings[].outpoint | string | |
summary.skipped | array of object | 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). |
summary.skipped[].outpoint | string | |
summary.skipped[].code | string | |
summary.skipped[].message | string | |
summary.replaces | object | null | 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). |
summary.replaces.txid | string | |
summary.replaces.fee | integer | null | |
summary.replaces.fee_rate | number | null | |
summary.min_fee_rate | number | null | A replacement: the lowest fee rate that replaces the pending transaction. |
summary.layout | array of object | How each source was cut (layout kinds). |
summary.layout[].outpoint | string | |
summary.layout[].input | integer | |
summary.layout[].separated | boolean | Something was split off. |
summary.layout[].borrow | integer | Sats the last output borrowed from the funding. |
summary.layout[].merged | array of object | Picked sats sharing one output (too close together, or at the tail). |
summary.layout[].rides_along | integer | |
summary.layout[].chunks | integer | A split: the chunks planned for this source. |
summary.layout[].chunk_outputs | integer | A split: the outputs they make (fewer when chunks sit too close together to separate; a merged warning). |
summary.split | object | An extract with split: the split as planned (the request's, normalized). |
summary.split.type | string | |
summary.split.per_output | integer | null | |
summary.split.chunks | integer | null | |
summary.split.trim | boolean | |
expires_at | integer | Unix seconds: submit before then (10 minutes). |
{
"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.
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_address | An address is not a mainnet address (or not one at all). |
| 400 | bad_chop_size | chop_size is not a whole number from 330 to 100,000,000. |
| 400 | bad_count | count (send N) is not a whole number of sats of at least 1. |
| 400 | bad_fee_rate | fee_rate is not a positive number up to 5000. |
| 400 | bad_items | 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. |
| 400 | bad_json | The body is not valid JSON. |
| 400 | bad_kind | kind is not one of the wallet tools (extract, send, send_n, chop, consolidate, multisend, speedup, cancel), or a send mode is unknown. |
| 400 | bad_outpoint | Not an outpoint (txid:vout). |
| 400 | bad_owner | owner must give the payment and ordinals addresses and their public keys. |
| 400 | bad_request | The body is not a JSON object, or the engine refused a malformed request (e.g. a purchase submitted without its signed setup PSBT). |
| 400 | bad_sends | sends must list 1-50 payments of {address, value}, each at least its address type's minimum (330, or 546 for P2SH and P2PKH). |
| 400 | bad_split | 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). |
| 400 | bad_type | type (send N) is not a sat type, types joined with +, or block9 / 450x. |
| 400 | duplicate_outpoint | The same UTXO twice in one listing. |
| 403 | cross_origin | 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. |
| 404 | unknown_transfer | No such transfer: an unknown or forgotten prepared id, or a txid the wallet tools did not build. |
| 405 | method_not_allowed | Wrong method for the route; the allow header lists the right ones. |
| 409 | conflict | 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. |
| 409 | has_descendants | A transaction spends the transfer's outputs already: it can no longer be replaced. |
| 409 | not_pending | The transfer to speed up or cancel is not waiting in the mempool any more (confirmed, replaced). |
| 409 | nothing_to_cancel | 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. |
| 409 | pending | The UTXO's listing is being bought, or an offer of it accepted, right now. |
| 409 | spent | The UTXO (or a listing's UTXO) is spent or does not exist. |
| 409 | unconfirmed | The UTXO is not confirmed yet. |
| 409 | unindexed | The ord indexer does not know the UTXO yet. |
| 413 | too_large | The body is over 256 KiB. |
| 415 | not_json | A POST without content-type: application/json. |
| 422 | address_too_large | An owner address holds more than 5,000 outputs: the wallet tools cannot plan for it. |
| 422 | already_extracted | The UTXO is extracted already (its rare sats sit in an output of their own). |
| 422 | bad_destination | The destination (or a multisend recipient) is the marketplace's fee address, or missing. |
| 422 | dust_destination | A whole UTXO is too small for the destination's address type. |
| 422 | fee_rate_too_low | fee_rate is below the current minimum (GET /api/market/fees). |
| 422 | fee_too_high | The network fee would exceed the per-transaction cap (200,000 sats): lower the fee rate or move fewer. |
| 422 | inscribed | The UTXO carries an inscription: only rare sats are listed; the wallet tools only send it whole. |
| 422 | inscribed_consolidate | Inscribed UTXOs are sent whole and 1:1, never merged into one output. |
| 422 | insufficient_funds | The payment address's plain UTXOs cannot pay prices, fee, padding and network fee (or a transfer's fees). Carries available, prices, platform_fee. |
| 422 | keep_in_destination | 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. |
| 422 | key_mismatch | The public key does not control the address. |
| 422 | legacy_address | A legacy (P2PKH, 1…) address: use Taproot or SegWit. |
| 422 | listed_public_alone | A UTXO whose listing signature is public must be moved on its own (and fast). |
| 422 | not_enough_sats | Your UTXOs do not hold count sats of that type that can be sent. Carries available. |
| 422 | not_owner | 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. |
| 422 | not_plain | A UTXO to consolidate is not plain bitcoin (it holds tracked, exotic or inscribed sats, or runes). |
| 422 | nothing_to_do | Nothing to move: every item was skipped (skipped), or a consolidation has fewer than 2 UTXOs, or a chop leaves one piece. |
| 422 | nothing_to_separate | Extracting would leave the UTXO one output: its rare sats are apart already, or too close to its ends. |
| 422 | payment_destination | 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. |
| 422 | range_too_small | A range chunk (send N of block9 or 450x) must be at least the destination's padding: 330 sats, 546 for P2SH and P2PKH. |
| 422 | replacement_fee_too_low | The replacement pays too little to replace the pending transaction (BIP 125): raise the fee rate to at least min_fee_rate. |
| 422 | runes | The UTXO carries runes (the wallet tools only send it whole). |
| 422 | runes_multi | At most one rune UTXO per transfer (except a whole send merged into one output). |
| 422 | split_chunk | 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. |
| 422 | too_many_items | 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. |
| 422 | too_many_outputs | The transfer would have more than 100 outputs: move fewer UTXOs at once. |
| 422 | tx_too_large | The transfer would exceed 100,000 vB: move fewer UTXOs at once. |
| 422 | unsupported_address | An address type the marketplace does not trade (only Taproot, native SegWit and nested SegWit). |
| 422 | untracked | The UTXO holds no rare sat the index tracks (send it whole instead). |
| 429 | rate_limited | 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. |
| 500 | invariant_violated | A planned or finalized purchase or transfer broke an invariant (violations); nothing was broadcast. |
| 503 | bitcoind_unavailable | bitcoind is not available. |
| 503 | busy | 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. |
| 503 | engine_unavailable | The trade engine is not available. |
| 503 | fork_behind | The rare-sat index has not caught up with bitcoind: try again in a minute. |
| 503 | fork_unavailable | The rare-sat index is not available. |
| 503 | indexer_behind | The ord indexer is catching up: try again shortly. |
| 503 | market_unavailable | The marketplace is closed right now (its backends disagree on the network, or are unreachable). |
| 503 | oracle_unavailable | The ord oracle is not available. |
{
"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 #
kind | Body fields | What the transaction does |
|---|---|---|
extract | items: [{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). |
send | items, 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_n | type, 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. |
chop | items, chop_size, destination? | Cuts a UTXO's whole ranges (block 9 style) into chop_size-aligned pieces. |
consolidate | items?, 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. |
multisend | sends: [{address, value}] | Plain bitcoin to 1–50 recipients, change back to you. |
speedup | txid | Replaces a pending transfer the site built with the same transaction at a higher fee rate (RBF). |
cancel | txid | Replaces (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).