Build

Agent API

Two hosts matter to an integrator. The gateway at api.tagit.network publishes a public A2A agent card and agent directory, invokes agent skills behind an API key, and serves one verification call metered with x402 that returns an ECDSA-signed statement of an asset's on-chain lifecycle state. The verify service at verify.tagit.network serves the same lifecycle facts with no key at all: public JSON per token and a read-only MCP server. Everything below runs against Base Sepolia (chainId 84532) — a testnet, against contracts that have not been audited. Do not put production settlement behind it.

Scope and dates. Every status on this page was probed on 2026-10-23 without credentials. The agent card, the MCP servers, A2A dispatch and the /api/v1 agent routes went live on 2026-09-14; before that date they did not exist, and until 2026-10-23 this page still said they returned 404. What is key-gated, what is public elsewhere and what is not yet available is listed under Status of everything else, in words, so the record is explicit rather than merely absent.

The live surface

Probed 2026-10-23. "Access" is what an unauthenticated caller receives.

MethodEndpointAccessPurpose
GETapi.tagit.network/healthPublicLiveness plus a health flag per agent service. No key, no payment.
GETapi.tagit.network/.well-known/agent.jsonPublicA2A agent card: six agent services, twelve skills with input schemas.
GETapi.tagit.network/api/v1/agentsPublicAgent directory; /api/v1/agents/:agentId returns one agent.
POSTapi.tagit.network/verifyx402Asset verification. An unpaid call gets a 402 envelope with the terms; see below.
POSTapi.tagit.network/api/v1/agents/:agentId/invokeAPI keyInvoke one agent skill. 401 without a key.
POSTapi.tagit.network/mcpAPI keyMCP server, twelve tools (one per skill). 401 without a key.
POSTapi.tagit.network/a2aAPI keyA2A task dispatch. 401 without a key.
GETverify.tagit.network/api/asset/:tokenIdPublicLifecycle verdict as JSON — the same data the MCP tools return.
POSTverify.tagit.network/mcpPublicRead-only MCP server over streamable HTTP: verify_asset, get_lifecycle_history, check_flagged. Manifest at /.well-known/mcp.json.

To invoke skills you need an API key; ask through developer contact. Everything the gateway signs is also readable straight from the contracts over any public Base Sepolia RPC — see Reading the contracts without the gateway. The consumer tap flow is a separate service, described below.

The verify service is also described by an OpenAPI 3.1 document at /openapi.json. It tags each route assertion (keyless reads such as /api/asset/:tokenId), discovery (the MCP manifest) or attestation (the tap-gated /api/verify and /api/dpp routes, documented as not remotely callable), and declares security: [] on purpose: no key, no wallet, no payment.

GET /health

curl https://api.tagit.network/health

{"status":"ok","timestamp":"2026-10-23T18:31:29.397Z",
 "agents":{"count":6,"details":[{"agentId":1,"name":"Sage","healthy":true}, ...]}}

That is the whole contract of this endpoint: a status string, the server clock, and a health flag per agent service. It is not a dependency health report — a 200 here does not tell you the RPC or the oracle key is healthy.

POST /verify — x402 metered

/verify is priced per call in USDC on Base Sepolia using the x402 protocol. Call it with no payment attached and the gateway answers 402 Payment Required with a machine-readable envelope of payment terms.

A 402 here is the handshake, not an error. It is how the endpoint advertises its price, its asset, its network and its recipient to a caller that has never seen it before. An agent is expected to receive one, pay, and retry. Treating the 402 as a failure means you never get past the first request.

Step 1 — call it unpaid, read the terms

curl -X POST https://api.tagit.network/verify \
  -H "Content-Type: application/json" \
  -d '{}'

HTTP/2 402
{
  "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"
    }
  ]
}
  • scheme: "exact" — pay the stated amount, no more, no less.
  • maxAmountRequired is in the asset's base units. 10000 against a 6-decimal token is 0.01 USDC.
  • asset is the USDC contract on Base Sepolia; payTo is the address the payment settles to.
  • maxTimeoutSeconds: 30 — the window in which the paid retry is accepted.

Step 2 — pay, then retry with X-PAYMENT

curl -X POST https://api.tagit.network/verify \
  -H "Content-Type: application/json" \
  -H "X-PAYMENT: <x402 payment payload>" \
  -d '{ "assetId": "18", "chain": "base-sepolia" }'

assetId must be a numeric token id and chain must be base-sepolia; anything else is rejected with 400. The endpoint is rate limited to 10 requests per minute per IP, after which it answers 429.

Testnet honesty. On Base Sepolia today the gateway gates on the presence of the X-PAYMENT header. Verifying and settling that payload through an x402 facilitator is planned and is not yet wired up, so no funds actually move. Treat the paid path as a working protocol demonstration, not as a revenue rail.

What the paid call returns

The gateway reads getAsset(tokenId) from TAGITCore on Base Sepolia and signs what it read. The response carries three things: the asset state, an oracle proof over that state, and the chain it was read from.

  • verified — true when the lifecycle state is between 1 (MINTED) and 4 (CLAIMED); a token that does not exist (0), or one that is FLAGGED or RECYCLED, returns false.
  • asset — tokenId, lifecycleState, stateCode, owner, timestamp, contractAddress.
  • proof — signature, messageHash, oracleAddress, timestamp.
  • chain — id and name, plus elapsedMs for the round trip.

What the oracle actually signs

messageHash = keccak256(
  abi.encodePacked(
    uint256 tokenId,        // the asset
    uint8   lifecycleState, // 0 NONE · 1 MINTED · 2 BOUND · 3 ACTIVATED
                            // 4 CLAIMED · 5 FLAGGED · 6 RECYCLED
    uint256 chainId,        // 84532
    uint256 timestamp       // unix seconds, when the read happened
  )
)
  • The signature is an EIP-191 personal-signature over those 32 bytes. On-chain recovery must re-apply the \x19Ethereum Signed Message:\n32 prefix before ecrecover, or the recovered address will not match the oracle.
  • The hash commits to the token, its state, the chain and the moment of the read. It does not commit to the NFC tag UID or to a SUN counter — earlier revisions of this page published a formula containing those fields, which does not match what the gateway signs and would fail verification.
  • Because timestamp is inside the hash, a proof is a statement about a moment, not a standing guarantee. State can change immediately after the read; re-verify before acting on a stale proof.

Reading the contracts without the gateway

The gateway is a convenience, not a gatekeeper. Every fact it signs is public on Base Sepolia and can be read straight from the contract over any public RPC, with no payment and no dependency on us being online:

import { createPublicClient, http } from "viem";
import { baseSepolia } from "viem/chains";

const client = createPublicClient({
  chain: baseSepolia,
  transport: http("https://sepolia.base.org"),
});

// TAGITCore on Base Sepolia
const [owner, timestamp, state, flags, reserved] = await client.readContract({
  address: "0x3aDc7EFDb58Ae85483eFf5D4966D916185f31d1D",
  abi: TAGIT_CORE_ABI,
  functionName: "getAsset",
  args: [18n],
});

The difference is trust placement: a direct read is trustless but tells an agent nothing it can hand to a third party, while the signed gateway proof is portable and checkable by a contract that never made the RPC call itself.

Physical tap verification is a separate service

Scanning a real NTAG 424 DNA tag does not go through this gateway. The tag itself emits a one-time picc and cmac pair, and those are consumed by the verification service at verify.tagit.network, which also serves the human-readable asset and tag pages, the public lifecycle JSON at /api/asset/:tokenId, the read-only MCP server listed above and a W3C Verifiable Credential digital product passport. The picc and cmac parameters are generated by the chip on each tap and cannot be constructed by hand, so the tap surface is not something an agent can call without the physical object in its possession; the JSON and MCP surfaces read chain state and need no tap. See NFC Hardware for the chip side of it.

Status of everything else

Listed in words, not styling, because this is the part that gets copied into other people's answers. Probed 2026-10-23.

  • Skill invocation, MCP and A2A on the gateway — live since 2026-09-14 behind an API key: POST /api/v1/agents/:agentId/invoke, POST /mcp (twelve tools, one per skill) and POST /a2a answer 401 without one. The card at GET /.well-known/agent.json and the directory at GET /api/v1/agents are public. Priced skills are registry metadata: nothing is charged today. The agents' on-chain identities are readable without any key — see Agent registry.
  • Public MCP — live at verify.tagit.network/mcp, read-only, no key, no payment: verify_asset, get_lifecycle_history, check_flagged. It cannot produce a SUN cryptogram and cannot write anything.
  • x402 settlement — the 402 handshake on POST /verify is live, but the payment payload is not verified or settled through a facilitator on the test network. No funds move.
  • Product REST API for asset management (CRUD, webhooks, dashboards) — planned, not yet available.
  • Relayer status — /relayer/status answers 401 like every unlisted path; there is no public relayer health endpoint.
  • SDK on npm — not published; build @tagitnetwork/sdk from source.

Contracts behind all of this

Deployed on Base Sepolia and readable by anyone. Verify each address on sepolia.basescan.org before you trust this page:

ContractAddress (Base Sepolia)Used by
TAGITCore0x3aDc7EFDb58Ae85483eFf5D4966D916185f31d1DRead by POST /verify
TAGITAgentIdentity0x0611FE60f6E37230bDaf04c5F2Ac2dc9012130a9Direct reads only
TAGITAgentReputation0x32be6C82A57d5bCe897538d7dA4109eA0eeB0aA1Direct reads only
TAGITAgentValidation0x34766dBa7040C2c8817f1Ee1e448209826DD607eDirect reads only
VerificationEscrow0x4c9aACfcb64169E3BC187c227c4C0e0a5CFDA1cFDeployed, but not yet wired into the live /verify path

The full deployment registry, including the core protocol contracts, lives on Contract Addresses.

Next steps