1
Set up and pair your items
Before any taps, each item needs a collection, its own unit, and a paired chip — a one-time setup you run during fulfillment, not at tap time. The Set up your catalog guide covers it end to end: create the collection, create a unit per item, and pair the encoded chip (which issues the unit and assigns its serial).Two things to carry into the verify flow below:
- On every tap, the chip’s tap URL carries the
chip_idand a fresh one-timee. Theeyou supplied at pairing comes from encoding and is consumed then — it is not the tape. - A chip is permanently bound to its unit. A chip can also be paired the first time it is tapped, through a hosted pairing screen — see Pairing a chip, including how to route unpaired taps to your own system.
2
The user taps
When a user taps the NFC chip on the item, the chip generates a fresh one-time The format of this URL is fixed by the chip’s encoding. Your job is to extract
e value and opens a URL. That URL carries both the chip_id and the new e as parameters — for example:chip_id and e from it (or from the query parameters your app receives when the user is redirected to your domain) and forward them to your backend immediately.The e value is a credential. Treat it accordingly:- Do not log it.
- Do not store it at rest.
- Pass it to the verify endpoint promptly — it is single-use and has a short validity window.
chip_id and e to your own server, which makes the verify call using your API key.Reading the tap in a browser is non-trivial. Endstate ships no browser NFC
SDK — the tag is standard NFC. Web NFC (
NDEFReader) works only on Android
Chrome (secure context + user gesture); desktop needs a USB/PC-SC reader
driven over WebUSB/WebHID; iOS Safari has no in-browser tap path. The
tag’s payload is just a URL — read the NDEF record, extract the URI, then pull
chip_id + e from it.A raw tap URL is often a short Endstate URL that 302-redirects to the
destination, with the params on the redirect target. If you resolve a tap URL
server-side, follow the redirect and read the params off the
Location
header — fetch(url, { redirect: "manual" }).3
Verify the tap
Your backend calls Here is what each field tells you:
POST /v1/chips/{chip_id} with the e value. This is the core verification call. A successful response is non-replayable proof that the physical chip was tapped moments ago.id — the unique scan record ID. Log it alongside the X-Request-Id response header for support requests.chip.scan_count — the total number of successful verifications for this chip, including this one. A value of 1 means this is the first successful tap. Higher values mean the item has been verified before. Your application decides what a high count means — Endstate records the count but does not set policy on it.unit — the digital record for the verified item, including any name, external_id, and attributes you set when creating it. Issuance status and serial number are nested under unit.collection.token — status: "active" and a serial value confirm the unit is fully issued. Use this data to render an item detail view.session_token — an object containing a short-lived token string (end_sess_...) that proves this specific chip was just tapped. Valid for 600 seconds by default. Pass the token string to a browser or mobile client. See the next step.redirect_url — the canonical page to send the user to after a successful tap, or null if your account has no verified domain configured. When present, you can redirect the user here directly; the URL already carries the context needed to display the correct item.4
Hand the session token to your client
The This tells the client exactly which chip was tapped, which unit it belongs to, and when the session expires. The client can use this to confirm scope without a second round-trip to your server.The default session lifetime is 600 seconds. If your user flow needs more or less time, pass
session_token from the verify response is designed to cross the server–client boundary safely. Your API key (end_sk_...) must never leave your server — but the session token can.After verifying the tap server-side, pass the token string from the session_token object to your browser or mobile client. The client can then call GET /v1/session-tokens/current using that token string as its bearer credential:ttl (integer, 60–3600) in the verify request body.See Session tokens for the full security model and use cases.Handle failures
Branch onerror.code — never on HTTP status or message. The three codes specific to chip verification are:
For the full error envelope and handling conventions, see Errors.
The session token also authorizes claiming a unit on behalf of the user
who tapped — handing it to a recipient. See Claims for the
full flow, execution modes, and status polling.
Next steps
Claim a unit
Transfer ownership of the verified unit to a recipient, authorized by the
session token.
Session tokens
Understand the credential you just received and how to use it on a client.

