Quick Start Guide
The fastest way to see TAG IT work is to read a real asset's authenticity state straight off the blockchain. It takes about a minute, runs on public infrastructure, and needs no account, no API key and no wallet. This page walks that path first, then states plainly what else is live — and what does not exist yet.
Everything on this page runs against Base Sepolia testnet (chain ID 84532), and the contracts are unaudited. Results are suitable for integration and evaluation. Do not use them as the sole basis for a custody, payment or settlement decision.
What you need
- Node.js 20 or newer — the example below was executed on Node 20.20.
- A terminal and an internet connection — reads go to a public Base Sepolia RPC endpoint.
What you explicitly do not need: a sign-up, an API key, a wallet, or any testnet funds. Reading TAG IT state is open to everyone, humans and autonomous agents alike. There is no developer dashboard and no key issuance today — see What does not exist yet.
Step 1: Read a real asset from the chain
TAG IT's source of truth is the TAGITCore contract. Its getAsset function returns an asset's owner, its lifecycle state, and when that state was last written. Create an empty project and install viem:
mkdir tagit-quickstart && cd tagit-quickstart
npm install viem
Save this as tagit-check.mjs:
import { createPublicClient, http } from 'viem';
import { baseSepolia } from 'viem/chains';
const TAGIT_CORE = '0x3aDc7EFDb58Ae85483eFf5D4966D916185f31d1D';
const getAssetAbi = [{
name: 'getAsset', type: 'function', stateMutability: 'view',
inputs: [{ name: 'tokenId', type: 'uint256' }],
outputs: [
{ name: 'assetOwner', type: 'address' },
{ name: 'timestamp', type: 'uint64' },
{ name: 'state', type: 'uint8' },
{ name: 'flags', type: 'uint8' },
{ name: 'reserved', type: 'uint16' },
],
}];
const STATES = ['NONE', 'MINTED', 'BOUND', 'ACTIVATED', 'CLAIMED', 'FLAGGED', 'RECYCLED'];
const client = createPublicClient({ chain: baseSepolia, transport: http() });
const [assetOwner, timestamp, state] = await client.readContract({
address: TAGIT_CORE,
abi: getAssetAbi,
functionName: 'getAsset',
args: [50n],
});
console.log('owner:', assetOwner);
console.log('state:', state, `(${STATES[state]})`);
console.log('since:', new Date(Number(timestamp) * 1000).toISOString());
Run it:
node tagit-check.mjs
Actual output, executed 26 July 2026 against the live deployment:
owner: 0x458B4d0c3a55006965Fd13D6af7B8509De51Cb3D
state: 4 (CLAIMED)
since: 2026-07-16T23:56:24.000Z
That is a real verdict about a real asset, produced without asking TAG IT for permission. Token 50 exists, it has completed the full manufacturing lifecycle, and it is currently claimed by an end owner.
You are not trusting a TAG IT server to tell you the truth — you are reading the same contract our own products read, over an RPC endpoint you chose. Every verdict on this page can be re-derived independently by anyone. That property is the point of the system, so we lead with it rather than with a hosted API.
Step 2: Interpret the result
getAsset returns five values:
| Field | Type | Meaning |
|---|---|---|
assetOwner | address | Current on-chain owner of the digital twin |
timestamp | uint64 | Unix seconds when the state was last written |
state | uint8 | Lifecycle state, see the table below |
flags | uint8 | Bit flags, reserved for future use |
reserved | uint16 | Reserved for future metadata |
The state integer is the whole verdict. It comes from the seven-state asset lifecycle:
| Code | State | Meaning |
|---|---|---|
0 | NONE | Token does not exist |
1 | MINTED | Digital twin created, no chip bound yet |
2 | BOUND | NFC chip cryptographically bound |
3 | ACTIVATED | QA passed, ready for distribution |
4 | CLAIMED | Owned by an end consumer |
5 | FLAGGED | Reported lost, stolen or recalled |
6 | RECYCLED | End of life, terminal |
An unknown token is not an error. Change args to [999999n] and the call still succeeds, returning the zero value — owner 0x0000000000000000000000000000000000000000, state 0 (NONE). Branch on state, never on whether the call threw.
The same read without Node
If you have Foundry installed, the entire quick start collapses to one line:
cast call 0x3aDc7EFDb58Ae85483eFf5D4966D916185f31d1D \
"getAsset(uint256)(address,uint64,uint8,uint8,uint16)" 50 \
--rpc-url https://sepolia.base.org
0x458B4d0c3a55006965Fd13D6af7B8509De51Cb3D
1784246184 [1.784e9]
4
0
0
Same contract, same answer, no dependencies beyond cast itself.
Step 3: The hosted endpoints
Two HTTP surfaces are live today. Neither is required for the read above, but both are real and callable now.
A liveness check on the gateway, no authentication:
curl https://api.tagit.network/health
{"status":"ok","timestamp":"2026-07-26T21:53:19.795Z","runtime":"vercel"}
And a signed verification, metered by the x402 micropayment protocol. Calling it without a payment proof returns 402 Payment Required along with the payment requirements — that response is the protocol handshake, not a failure:
curl -X POST "https://api.tagit.network/verify" \
-H "Content-Type: application/json" \
-d '{"assetId":"50","chain":"base-sepolia"}'
{
"x402Version": 1,
"error": "Payment required",
"accepts": [{
"scheme": "exact",
"network": "base-sepolia",
"maxAmountRequired": "10000",
"resource": "https://api.tagit.network/verify",
"description": "TAG IT Asset Verification — BOUND state proof + ECDSA signature",
"mimeType": "application/json",
"payTo": "0x458B4d0c3a55006965Fd13D6af7B8509De51Cb3D",
"maxTimeoutSeconds": 30,
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
}]
}
With a valid X-PAYMENT header the response carries the asset state plus an ECDSA signature over it, so the verdict can be checked on-chain by a third party. Full details in the REST API reference.
Verifying a physical tag
The read in Step 1 tells you what the chain says about a token. Proving that a specific physical chip is present is a separate operation, and it deliberately cannot be done from a keyboard.
TAG IT uses NXP NTAG 424 DNA chips, which emit an AES-encrypted SUN cryptogram on every tap. Those picc and cmac values come from the chip itself and cannot be constructed without physically tapping it:
curl "https://verify.tagit.network/api/verify?picc=<32-hex>&cmac=<16-hex>"
The same tap can also return a W3C Verifiable Credential Digital Product Passport:
curl "https://verify.tagit.network/api/dpp/01/<GTIN>/21/<serial>?picc=<hex>&cmac=<hex>"
For a human, the rendered pages live on verify.tagit.network: /asset/{tokenId}, /tag/{uid}, and /01/{gtin}/21/{serial}. No tap is needed to read the ledger — check an asset on-chain to see the format.
Attestation — proving a physical chip was present — requires a real tap and is intentionally unreachable without one. Assertion — reading the resulting on-chain state — is open to everyone with no credential at all. If you are building software rather than handling goods, the assertion half is the one you integrate against.
What does not exist yet
Documenting things before they ship wastes your time, so here is the honest list. None of the following exists today:
| Thing you might expect | Reality |
|---|---|
| Developer sign-up, dashboard, API keys, usage plans | Do not exist. No key is issued or required |
A versioned REST API (a /v1 base URL) | Does not exist. Only the endpoints listed above are live |
| A sandbox or staging host | Does not exist. Base Sepolia is the test environment |
| Python SDK | Does not exist |
| Swift / Kotlin packages | Do not exist as published packages |
| Product registration, verification or ownership-transfer helpers in an SDK | Do not exist. Use the contract directly |
| Webhooks, event subscriptions, GraphQL | Do not exist |
| Keyless public read of an asset by token ID over HTTP | Planned. Until then, read the contract — it is keyless already |
About the TypeScript SDK
An SDK package named @tagit/sdk exists in our source tree but is not published to npm, so npm install will not resolve it. It is TypeScript/JavaScript only.
It is also narrower than its name suggests: it is a client for agent identity, reputation and validation, plus WTag and Voucher helpers. It does not register products, verify assets or transfer ownership — the direct contract read on this page is the supported way to do those things. Its default chain is still OP Sepolia (11155420), which was deprecated on 27 June 2026 in favour of Base Sepolia (84532).
Nothing about it is usable from this quick start today. When it is published, it will be documented here with a working install command — not before.
Writing to the chain
Reads are open to everyone. Most writes are not. The seven lifecycle transitions — mint, bindTag, activate, claim, flag, resolve and recycle — each require a BIDGES capability badge held by the calling address. None of them is open to the public, and there is currently no self-service route to obtain a badge. If you need write access for a pilot, get in touch.
There is exactly one exception. transferAsset(uint256 tokenId, address to) is owner-gated, not capability-gated — if you are the current owner of an asset in state 4 (CLAIMED), you can transfer it yourself with no badge at all. It is the consumer-to-consumer resale path, and it is not one of the seven transitions above because it does not change the lifecycle state: the asset stays CLAIMED and only the owner changes. It reverts if the caller is not the current owner, if the asset is not CLAIMED, or if to is the zero address or the current owner. See the Ownership Transfer tutorial for the full walkthrough.
Next steps
- Platform Overview — how the pieces fit together
- REST API Reference — every HTTP endpoint that is live, in full
- Contract Addresses — the full Base Sepolia deployment list
- ABI Reference — the rest of the contract surface you can read
- NFC Chip Selection — the hardware behind the physical tap
Join our Discord community for real-time support. If a code sample on this page does not run exactly as written, that is a bug — please tell us.