@endstate-sdk/web is the browser half of that flow. It captures the tap from a redirect or Web NFC, hands it to @endstate-sdk/core to open a session, and provisions the customer’s wallet. Key material never enters your page, and this version exposes no signing surface.
The whole flow is one line: tap -> verify -> read the item -> provision a wallet -> claim. In React it is one provider and three hooks; the vanilla client runs the same steps by hand. This quickstart leads with React and shows the vanilla path alongside it.
Install
@endstate-sdk/core is a peer dependency - it is the API client the tap sources and hooks plug into. react is an optional peer (^19), needed only for the React entrypoint at @endstate-sdk/web/react; the vanilla client at @endstate-sdk/web needs neither React nor any runtime dependency. Both Endstate packages are ESM-only.
Prerequisites
- A publishable key (
end_pk_...). It is safe in browser source; a secret key is not, and is rejected here by type and at runtime. Credentials covers the difference. - Your page’s origin on your organization’s allowed-origins list, for both the API and the wallet frame. Until it is listed the browser blocks the request before it reaches Endstate.
- A way to mint an identity token for your signed-in user - a fresh, single-use token your own backend signs. It is yours to build, not part of the SDK - see the identity credential and Bring your own auth.
The golden path
One provider, three hooks.<EndstateProvider> wraps your app - it builds the browser client, provisions the wallet, and verifies the landing tap on mount - and a child component reads the verified item, resolves the wallet address, and claims in a single call. The vanilla client in the second tab runs the same steps by hand.
- Wrap once with
<EndstateProvider>. It builds the browser client, provisions the wallet from yourgetIdentityTokencallback, and - becauseautoVerifyis on by default - captures the landing tap and verifies it on mount.wallet.enabledgates provisioning on whether a customer is signed in; while it isfalsethe wallet staysunconfigured. - Read the verified item with
useSession(). Itsstatusmovesidle->capturing->verifying->verified(orerror), anditemis the verified unit ({ id, external_id, name, attributes, collection }) oncestatusisverified. It is read straight off the session with no extra request. - Resolve the wallet with
useWallet().accountis aWalletAccount({ address }) once the wallet reports ready; itsstatusrunsunconfigured->idle->provisioning->ready. Customers who bring no address of their own get one this way. - Claim with
useClaim().claim()with no arguments hands the item to the wallet address, sotodefaults to the address the provider provisioned. Itsstatusdrives the button:claimingthensettling, landing onclaimed,expired, orfailed.claim()defaults to Endstate submitting the write for you; the alternateclient_broadcastexecution mode returns a payload for your own signer instead.
createEndstateClient(...) builds the client, captureTap() reads the tap inside a user gesture, client.verify(tap) opens the session, session.item is the verified unit, wallet.ready() resolves the address, and session.claims.create({ to }) claims it. verify derives its idempotency key from the tap, so a page reload replays the original response instead of spending the single-use credential.
The provider provisions the wallet as it mounts, in parallel with capturing
and verifying the tap, so the address is usually ready by the time a customer
taps Claim. Only the claim waits on the wallet; capture, verify, and read do
not touch it. In the vanilla flow this is why
createWallet runs at page load
and only wallet.ready() blocks the claim.Capturing more than the landing tap
The golden path reads the tap that opened the page. To let a customer already on your page scan another item in-page with Web NFC,useTap() exposes scan(), its status, and the Web NFC permission state; the vanilla client does the same through captureTap(). Either way, see Tap capture for the source priority model, the user-gesture rule that gates in-page scanning, and how to present each Web NFC permission state.
Next steps
Tap capture
In-page scanning, the source priority model, and Web NFC permissions.
Wallet
The createWallet lifecycle, the identity credential, and error handling.
session.claims.create
The claim request body, execution modes, and error codes.
Bring your own auth
Issue an identity token for your signed-in user from your own login.

