Skip to main content
Beta — BRC wallet only. Desktop / Mobile over BRC-100, not Connect Items.

The model

A collectable is a one-satoshi ordinal output. The wallet holds it in storage basket 1sat, and your app addresses it three different ways depending on what you are doing: Your app builds the inscription script. The wallet funds the transaction, signs it, files the output, and shows the user what they are approving. Item calls always prompt — auto-pay never covers them. Prerequisites: a connected origin and, for reads, an item view grant.

Read inventory

Reads use scoped permission baskets, never the storage basket. See Permissions and scopes for the full grammar and grant behaviour.

All items

totalOutputs is what your grant exposes, not the wallet’s true holdings. A user who approved two collections sees two collections here, with HTTP 200 and no error.

One collection

One exact row, with its transaction

A specific row id resolves without a prompt, which makes it the right call for a detail screen after the user already picked an item. Tags are always returned for item reads.

Item vocabulary

Tags

An item with none of name, app, collection, content, or id is invisible to third-party apps, so always tag at least a name.

customInstructions

Send a JSON string. The wallet reads these fields:

Mint an item

An item mint is a createAction with no inputs and at least one one-satoshi output in an item basket:
The wallet stamps a row id onto the output tags so you can address this exact item later. Baskets and tags index the item; they never create the inscription, so validate the script against the 1Sat protocol before you send it. The user sees a Mint item prompt with your description and the item name from the name: tag. Refusal returns 403 ACTION_DENIED; funding problems return 400 INSUFFICIENT_FUNDS or INSUFFICIENT_OR_STALE_FUNDS.

Transfer an item

A transfer spends the held tip and creates the next one. Name the held row with a spend label so the wallet knows which item you mean:
The label grammar is exactly p 1sat input id <rowId>. Each label must resolve to exactly one held row and that row’s outpoint must appear in inputs, or the call fails with 400 INVALID_P1SAT_SPEND before the user is ever prompted. Supply inputBEEF for the tip’s source transactions. If you send unlockingScriptLength instead of a script, you get a staged transaction back and must finish that exact reference with signAction — the wallet does not hold your unlock recipe and never exposes a root private key. Covenant-locked tips cannot be spent with a plain P2PKH unlock; the wallet refuses rather than guessing. If a tip has gone missing on chain, that is a wallet-side abandon in HandCash, not something an app resolves with relinquishOutput.

Burning

There is no burn method for apps. A burn is a transfer whose output is a protocol-valid terminal spend that your app constructs. Never turn a failed item path into a plain payment.

Receive an item

protocol must be the string basket insertion, and the remittance basket is the storage basket 1sat.
Keep insertionRemittance.customInstructions small — identity fields only. The receive path caps it near 1,000 characters, so a full BRC-150 proof does not fit. The wallet rebuilds and verifies provenance locally instead.
The wallet validates the transaction before accepting it. Do not tell the sender a delivery succeeded until this call resolves. The user sees a Receive item prompt the first time; after that a stored receive grant can carry it.

Authenticity

HandCash shows an item as verified only when a complete BRC-150 v2 proof checks out. The proof is a local object in customInstructions.provenance:
What the wallet checks: the path starts at the tip and ends at the origin, every hop is an exact parent spend, one-satoshi continuity holds throughout, and the origin carries a valid ordinal envelope. Two rules matter for app authors. Provenance is local metadata — it does not ride along on a P2PKH lock, so a recipient’s wallet reconstructs it. And an oversized proof is omitted, never truncated: the wallet’s cap is 400,000 characters of BEEF, above which the item stays unproven rather than carrying a partial lineage.

Release a row

This drops the wallet’s record of the output. It is not a burn, it moves no coins, and it prompts as Release item. Use p 1sat all here: scoped forms that require a tag cannot carry one on this call.

Not available to apps

Next steps