Overview
robot-id.eth is the neutral ENS protocol layer for robots. Reads go straight to chain via viem + Alchemy; writes return unsigned transactions you sign with your own wallet or multisig. There is no free self-serve tier — a key is issued only after an active on-chain USDC subscription.
5-minute Quickstart
npm i @robot-id/sdk
import { RobotIdClient } from '@robot-id/sdk'
const client = new RobotIdClient({ apiKey: 'rid_...', network: 'mainnet' })
const robot = await client.robots.get(1n)
const caps = await client.capability.get(1n)Authentication
Subscription-gated, SIWE via Reown AppKit. Connect a wallet on /subscribe, optionally reserve your namespace, approve USDC, and call Subscription.subscribe(tier). The on-chain Subscribed event triggers API-key minting + provisioning of the namespace you reserved (or an address-derived default). Retrieve your key via a SIWE-authenticated GET /auth/keys/info. Every request re-checks isActive; expired subscriptions get 402 Payment Required.
Robot Identity
ERC-721 + ERC-5192 (per-token soulbound) + ERC-2981 royalties. Each unit’s serialHash is keccak256(normalize(serialNumber)) — privacy-preserving but verifiable, and normalized so it matches the ENS label the gateway resolves. The ENS name <serial>.<mfr>.robot-id.eth always resolves to the current NFT holder via the CCIP-Read gateway. No registration fee — minting costs gas only.
Namespaces
An OEM picks its own namespace at checkout — e.g. boston-dynamics.robot-id.eth — and every one of its units resolves beneath it: spot-0001.boston-dynamics.robot-id.eth. Names are first-come, first-served; there is no brand-reservation list. Slugs are normalized (lowercase, dash-separated, 3–63 chars) and a small set of protocol words is reserved.
Only the OEM namespace is written on-chain (one setSubnodeRecord, owned by the OEM wallet). The unit names below it are virtual — resolved by the CCIP-Read gateway with zero ENS writes — so a single subscription scales to 100,000+ identities with one namespace write and one Merkle root.
GET /auth/namespace/boston-dynamics // availability (public)
→ { slug, valid, available, name }
POST /auth/namespace/reserve // SIWE, free, at checkout
{ address, message, signature, slug:"boston-dynamics" }
→ { reserved:true, name:"boston-dynamics.robot-id.eth" }
// consumed by the Subscribed watcher → provisioned on paymentMerkle Batches (OEM)
Pre-authorize up to 100,000 serials off-chain: the API builds a Merkle tree, you commit the root via MerkleBatchOracle.submitRoot, and each unit later claims its NFT with a proof via claimWithProof(batchId, proof, …).
POST /api/v1/robots/batch/preauthorize
{ "manufacturer":"Unitree", "model":"Go2",
"serials":[{"serialNumber":"GO2-0001","owner":"0x…"}] }
→ { batchId, root, unsignedTx } // sign submitRoot, then distribute proofsCapability Registry
OEM-signed, append-only attestations of what a robot is authorized to do (max_payload_kg, operating_zone, human_interaction_certified). Off-chain cert detail is pinned to IPFS and anchored by a Merkle root; verify(robotId, capabilityKey, leaf, proof) checks a proof against the latest root.
Intent Routing
IntentRouter.submitIntent is on-chain authorization + an immutable audit log. An intent is authorized only if it passes the robot’s AgentWallet limits; otherwise it’s rejected with a reason. Per-robot rate gating prevents intent floods.
OTA Verification
OTAVerifier.verify(firmwareHash, version, signature, oemAddress) gates each update. It cross-references RobotIdentity.firmwareVersion to reject downgrades. A blob signed by the registered OEM key verifies true; any other signer or a downgrade verifies false.
Subscriptions
Three tiers in USDC (6 decimals): Small Manufacturer $5,000, OEM $7,500, Enterprise $12,500. subscribe pulls via transferFrom (approve first) and sets a 30-day expiry; renewal extends from max(now, currentExpiry).
TypeScript SDK
const batch = await client.robots.preauthorize({
manufacturer, model, capabilityClass, serials
})
const active = await client.subscription.isActive('0x…')Intent SDK (ROS2 + voice)
import { RobotIntentPlugin } from '@robot-id/intent-sdk'
const plugin = new RobotIntentPlugin({
robotId: 1n, apiKey: process.env.ROBOT_ID_KEY!,
adapter: 'ros2-bridge', // alexa | google-assistant | custom-llm
})
const ack = await plugin.handleUtterance(
"Authorize payment for charging dock B and log the task")
// → classify → check AgentWallet limits → IntentRouter.submitIntent → ackTools
Quickstart smoke script (oem-quickstart.sh), a REST .http collection, a WebSocket event server at /ws (robots · intent · capability channels), and GraphQL at /graphql. Swagger UI: https://robot-idapi-production.up.railway.app/docs.
Testing · Unit Tests
One .t.sol per contract under contracts/test/, covering every state-changing path: soulbound lock/transfer revert, batch Merkle verification, AgentWallet limit enforcement, IntentRouter accept/reject, CapabilityRegistry immutability, OTA accept/reject + downgrade reject, and Subscription subscribe/renew/expire/price-update.
forge testTesting · Integration Tests (forked mainnet)
Because we launch on mainnet with no testnet-only phase, integration coverage is mandatory. The suite runs against a forked mainnet so real contracts (USDC) are exercised, not mocks:
- Subscription lifecycle — fund a fork account with real USDC, approve, subscribe(OEM), warp 30 days, renew.
- Batch path — preauthorize → commit root → claimWithProof for a sampled unit → assert ownership.
- AgentWallet — userOps that pass and that exceed limits; assert enforcement.
- OTA — verify a correctly-signed blob; reject a wrong signer / downgrade.
- ENS end-to-end — resolve
SN-X.mfr.robot-id.eththrough the CCIP gateway.
RPC_URL=https://eth-mainnet.g.alchemy.com/v2/KEY \
FOUNDRY_PROFILE=integration forge testError Codes
401— missing/invalid API key402— subscription inactive or expired429— rate limit exceeded for tier404— robot / batch not found
Rate Limits
- Small Manufacturer — 1,000,000 req/mo · 300/min
- OEM — 5,000,000 req/mo · 1,000/min
- Enterprise — unlimited · 5,000/min
Mainnet Contracts
RobotIdentity · AgentWallet · IntentRouter · CapabilityRegistry · OTAVerifier · MerkleBatchOracle · Subscription — all source-verified. See the live table on the landing page.