x402 Service Providers
You run an API. Agents call it. Agentlink lets you give better pricing or access to agents backed by real humans — without managing agent wallets or running a linking UI yourself.
If you also run the agent runtime, use Self-Hosted Agent Operators to link your agent, then come back here for the route integration.
Choose a mode
| Mode | Behavior | Use when |
|---|---|---|
free-trial | First N uses free per human per Biomapper generation | ✅ Best first choice — easy to prove the linked-human path |
free | Linked agents bypass payment entirely | Rewarding verified humans unconditionally |
linked-only | Reject unlinked or inactive agents | Hard gating on sensitive or abuse-prone endpoints |
observe | Verify and emit identity events, never alter access | Custom payout logic, audit trails, reward models |
discount | Linked agents pay a reduced percent | Not recommended — use a human-backed agent tier instead |
Start with free-trial on one route. It gives linked agents free access up to a limit without committing to unconditional free, and it is the fastest way to verify the end-to-end path.
Wire your route
pnpm add @techdigger/humanode-agentlinkAdd createAgentLink to your existing x402 route. The example below uses free-trial — swap mode for whichever you chose above:
import { createAgentLink } from '@techdigger/humanode-agentlink'
const link = createAgentLink({
network: 'base-sepolia',
registry: '0xYourRegistry',
mode: { type: 'free-trial', uses: 5 },
protect: {
'GET /data': {
price: '$YOUR_PRICE',
payTo: '0xYourPayoutAddress',
},
},
storage: yourPersistentStorage,
})
await link.initialize()
app.use(link)createAgentLink wraps x402 route protection, registry verification, and middleware in one call. It also embeds the agentlink extension in your 402 responses automatically — calling agents see the extension and know to include the identity header on retry.
Use the tracked registry for the profile you are integrating. See Profile Support for the current canonical addresses and lifecycle status.
Production storage
createAgentLink requires an explicit storage backend in production — it throws at startup without one. Implement AgentLinkStorage against whatever persistence layer you already run. See Package Reference for the full interface.
Nonce methods (hasUsedNonce / recordNonce) — required for all modes. Entries only need to outlive the request's expirationTime (a few minutes), so any cache, key-value store, or unique-constraint column works.
Usage methods (getUsageCount / incrementUsage) — required for free-trial only. Not needed for linked-only, free, or observe. The key is (endpoint, owner, generationPtr) — usage resets when the Biomapper generation advances. Increments must be atomic.
InMemoryAgentLinkStorage is available for local development and tests only.
Verify the 402 response
Once your route is running, confirm the agentlink extension is present in the 402 response body before testing with a real agent.
curl -s https://api.example.com/data | jq '.accepts[0].extensions.agentlink.supportedChains'Expected output:
[
{ "chainId": "eip155:84532", "type": "eip191" },
{ "chainId": "eip155:84532", "type": "eip1271" }
]If extensions.agentlink is absent, the route is not advertising Agentlink support and calling agents will not know to include the identity header.
For unit testing the decisioning path with a mocked registry, see agentlink/tests/hooks.test.ts.
Human-backed agent tier
If you want human-backed agents to pay less, set up a separate lower-priced route protected with linked-only rather than using discount mode.
discount tries to dynamically recover an underpayment at the facilitator level — it requires a facilitator hook, persistent usage storage, and the x402 payer and agentlink signer to be the same address. A dedicated tier sidesteps all of that: the gate is the pricing.
// Human tier — linked agents only, lower price
// Standard route keeps your existing x402 setup unchanged
const humanLink = createAgentLink({
network: 'base-sepolia',
registry: '0xYourRegistry',
mode: { type: 'linked-only' },
protect: {
'GET /generate/human': { price: '$YOUR_LOWER_PRICE', payTo: '0xYourPayoutAddress' },
},
storage: yourStorage,
})
await humanLink.initialize()
app.use(humanLink)Standard agents call your existing full-price route. Human-backed agents call GET /generate/human at the lower price. linked-only ensures unlinked agents cannot reach the cheaper route at all.
Storage on the human tier only needs nonce replay protection — getUsageCount and incrementUsage are not required for linked-only mode.
Custom post-payment logic (observe mode)
Use mode: { type: 'observe' } when you need agent identity but want to control what happens after payment yourself — for example, everyone pays the same price but linked agents receive a larger payout, or you want to log identity without changing access at all.
observe runs the full hook pipeline: signature verification, nonce replay protection, registry lookup, and event emission. It never returns grantAccess or abort — x402 decides access entirely, and your route handler receives the identity result via onEvent.
The pattern:
- Pass
mode: { type: 'observe' }andonEventtocreateAgentLink. WhenrequestHookfires (before payment settles), it emitsagent_verifiedoragent_not_verified. Stash that result somewhere your route handler can reach it. - Omit
protectandroutes— you wire x402 directly. RegisteragentlinkResourceServerExtensionon your x402 resource server and embedlink.declare()in each route's extensions object. This puts the agentlink block in the 402 response so calling agents know to include the identity header on retry. - Attach
link.requestHookto your x402 HTTP server'sonProtectedRequestcallback. - In your route handler, read the stashed identity and apply whatever logic you need.
Storage requirements: nonce replay protection is always required; observe mode does not require usage counting.
Tell your users
Your users link their own agents — you do not need to issue approval URLs or manage their wallets.
Point them to:
- Self-Hosted Agent Operators — full path from install to signed requests
- Link Your Agent — just the wallet approval step
Next steps
- Need webhooks or usage events in your control plane → Package Reference
- Your agent also calls x402-paid routes → Add x402 Payments to Your Agent
- Need framework adapters on top → Framework Integrations