useClaim() hook. The rest of this page leads with the hook and shows the Vanilla primitive alongside it.
The flow
In React, wrap the claim page inEndstateProvider and drive the claim from useClaim. With autoVerify on (the default) the provider captures and verifies the landing tap on mount, so useSession().item is the item the customer tapped and useWallet() provisions their address in the background. useClaim().claim() with no arguments claims into that wallet address, and because wait defaults to true it auto-settles before it resolves. status is a ClaimStatus you render the UI from.
The Vanilla path picks up from a session you captured and verified yourself - the browser quickstart golden path and Tap capture cover how you get one, and Tap sessions covers what it is - then calls session.claims.create({ to }) and settles with waitUntilSettled.
string
The recipient’s EVM wallet address (
0x followed by 40 hex characters). In
React, omit it and claim() claims into the provisioned wallet address from
useWallet(); pass one to target a specific address. Vanilla’s
session.claims.create requires it - for a customer who brings no address of
their own, this is (await wallet.ready()).address.A claim reads
unit_id from the session’s scope, so you never pass it. A
session freshly opened by verify() (including the provider’s autoVerify)
already carries that scope; one you adopted from a bare
token does not,
and the call throws EndstateSessionScopeError until you await session.refreshScope().execution defaults to endstate_relay), so a single claim() is the whole write; to broadcast it yourself from your own funded account or relayer instead, pass execution: "client_broadcast" and send the returned payload - see session.claims.create.
Settlement
A claim startsidle, and once claim() runs it moves through claiming (signed and submitted) and settling (awaiting confirmation) to one of three terminal statuses:
claimed- done. Ownership has transferred and settled.expired- the signed authorization’s window (about 30 minutes) passed before the claim settled. Create a new claim.failed- the submission did not settle. Create a new claim.
status on error and puts the Error on useClaim().error. In React you drive the whole progression off status; because wait defaults to true, claim() resolves only once the status is terminal, so you never write a poll loop.
In Vanilla, session.claims.waitUntilSettled does that waiting for you:
session.claims.get(claimId), or
endstate.claims.get(unitId, claimId) from a secret-key client on your backend.
Pass wait: false to opt out of auto-settlement and drive it yourself. On
expired or failed, create a new claim.
Idempotency
Creating a claim is a mutation, so it is safe to retry with an idempotency key. PassidempotencyKey; omit it and one is generated for you. Replaying the same
key with the same body returns the original claim rather than opening a second
one; the same key with a different body is rejected as a conflict.
Errors
Every failure carries a branchablecode. In React it surfaces on
useClaim().error with status set to error; in Vanilla
session.claims.create throws it. For how those errors behave and what retries
automatically, see Errors and retries; for the
full claim code list - unit.not_minted, claim.in_progress,
claim.already_to_recipient, session_token.wrong_chip, and the rest - see
session.claims.create and the
Claim a unit guide.
Next steps
session.claims.create
The claim request body, execution modes, and every error code.
Transfer ownership
Move an item between existing owners - the sibling action to a claim.
Wallet
Provision the recipient address the claim sends the item to.
Claim a unit
The credential-neutral walkthrough and the full error matrix.

