Skip to content

Recovery

Stop before doing more work if the wallet rejects, the session changes, a request times out, or storage fails. Earlier successful operations stay successful. Do not throw away your log and rerun the whole plan with new identifiers.

A timeout or 5xx does not prove a write failed. Reconcile first, then act.

Interrupted operation Recovery
Listing preflight response lost Repeat the exact request with the same idempotency_key, address, asset, outpoint, and price
Listing signature submitted, response lost Read GET /v1/listing-preflights/:id. If completed, read the listing. Otherwise retry the saved signed bytes for that same preflight
Wallet rejected a listing Keep completed items. Read the saved preflight before signing unfinished work; prepare again if it expired
Change an unsigned listing draft POST /v1/listing-preflights/:id/price on the existing draft. Record the desired price first; read back the exact template before signing
Remove an unsigned listing draft POST /v1/listing-preflights/:id/discard (owner). Retry a lost response with the same id. It releases the prepared output, not an attachment or an existing listing
Reprice response lost Read managed listings. Check the current price and status before resubmitting saved bytes; do not overwrite a newer intentional reprice
Delist or cancel response lost Read your listings and offers. A missing active listing does not tell sale, expiry, and cancellation apart; reconcile fill history before acting
Checkout completion response lost Read GET /v1/fills/:id and GET /v1/address/:address/in-flight-purchases. Resubmitting the same signed PSBT is safe; it answers already_completed
Offer placement response lost Read GET /v1/address/:address/offers and match the funding slot, collection, expiry, and placement id. POST /v1/offers is not generally idempotent
Exact authorization batch response lost Repeat the same batch for the same offer id and exact target set; pending authorizations are reused
Buyer authorization signature submitted, response lost Read GET /v1/exact-offer-authorizations/:id/status. If active, settling, or completed, do not sign again. If still awaiting the buyer, resubmit the saved PSBT
Collection offer placement response lost Repeat the identical POST /v1/policy-offers with the same signed parents; a stored set answers already_placed. Check GET /v1/address/:address/policy-offers
Collection offer acceptance lost, or 202 Poll GET /v1/policy-accepts/:id. Do not sign a new child while it is signed, journaled, or broadcast
Soft cancel response lost Read GET /v1/address/:address/policy-offers; repeating the same signed cancel is harmless. To be certain on-chain, sign the cancel-transaction self-send
Self-relayed attach, relay uncertain Rebroadcast the exact saved bytes with POST /v1/transactions; check with POST /v1/transactions/status. Never re-sign
401 Get a fresh session for the same owner, then inspect state before resuming
409 Re-read that order or outpoint. Never silently switch to another asset or funding output
429 Wait retry_after_seconds (also sent as Retry-After), then reconcile before retrying a write
Anything uncertain about your own orders Read GET /v1/address/:address/events (owner session): fills, delists, expiries, accepted and cancelled offers, and confirmations in one feed. See Events

A ready preflight alone does not prove that an uncertain submission failed: the request may still be in progress. Reconcile before editing. Preflight status reads recover listing_id and listed_price_sats from an accepted listing even if completion was interrupted.

Reprice previews check the expected old price, but the API has no atomic expected-version condition for repricing. Do not run two repricing agents against the same inventory and assume the preview is a lock.

Write every preflight id, request body, and signed PSBT to disk before you submit it; that is what makes an uncertain submission recoverable. Use a durable, append-only log, and stop on an uncertain response until you reconcile its status.

That log is sensitive trade authorization, even though it is not a seed:

  • Keep it out of version control; add your local log directory to .gitignore.
  • Restrict it with filesystem permissions and never paste it into an issue.
  • Never write session tokens or private keys into it.
  • A truncated final line may mean the process stopped mid-write. Keep it and reconcile the previous request before continuing.

Delist and cancel remove the marketplace’s authority to offer an order. They do not revoke a Bitcoin signature. Spending the signed input is what invalidates it:

To make it impossible on-chain Spend
A listing The asset UTXO
An exact-target offer The funding slot (POST /v1/offer-slot-releases)
A collection offer Any funding input (POST /v1/policy-offers/:id/cancel-transaction)

A settlement already in progress may own the input; cancellation then returns a conflict instead of interrupting a signed trade. Moving asset UTXOs, detaching, and consolidating funding are separate decisions involving real Bitcoin transactions, so the examples never do them automatically.