Documentation

Getting started

AgentRail is a drop-in middleware plus a hosted control plane. The middleware detects AI agents, gates each request by purpose, and charges per call over HTTP 402 (x402 USDC, AP2, or Bedrock); the control plane holds your pricing, policies, payment rails, and shadow/live mode — change them without a redeploy. This guide takes you from npm install to your first paid agent request.

The path: create a project (get an API key) → install the SDK → add one line to your app → set pricing in the dashboard → test → run in shadow → flip to live.

Before you start

You'll need:

  • A web app or API you want to protect. Node.js + Express is the reference integration; framework adapters (@agentrails/nextjs, @agentrails/cloudflare, @agentrails/hono) and ports for Python, Go, PHP, Ruby, Java, .NET, Rust, and Elixir share the same control plane — see all SDKs.
  • A recent Node.js LTS for the JavaScript SDK (shipped as CommonJS).
  • An AgentRail account (sign-in is a one-time magic link — no password).
  • No crypto knowledge to start. The built-in demo payment rail needs nothing; real USDC over x402 is opt-in (step 6).

1Create a project

Sign in to the dashboard with your work email — we send a one-time magic link, no password. Then create your first project (a name, optionally your site URL). A project owns your pricing, policies, payout wallet, analytics, and API keys.

On creation you're shown an API key (agr_live_…). It is shown once — copy it now and store it as the AGENTRAIL_API_KEY environment variable. This key links your running app to your dashboard.

A project can hold many keys — issue one per deployment, site, or service, and traffic is attributed per surface in your analytics.

2Install the SDK

# npm npm install @agentrails/sdkclick to copy

Prefer another stack? The framework adapters and language ports (@agentrails/nextjs, @agentrails/cloudflare, @agentrails/hono, the Python/Go/Ruby/Java/.NET/Rust/Elixir SDKs, and @agentrails/mcp for MCP servers) all talk to the same control plane and dashboard.

Availability: the Node/Express SDK (@agentrails/sdk) is published today. The framework adapters and other-language ports are fully implemented and tested but not yet published to their registries (npm, PyPI, crates.io, …), and the MCP adapter is in preview. Check all SDKs for each one's current status.

3Add it to your app

Mount the middleware once. In hosted mode, pass only your API key — policies, pricing, payment rails, and shadow/live mode all come from the control plane.

// server.js const express = require('express'); const { agentrail } = require('@agentrails/sdk'); const app = express(); app.use(agentrail({ apiKey: process.env.AGENTRAIL_API_KEY, // hosted: policies + pricing + mode come from the dashboard })); // ...your existing routes are unchanged. app.listen(3000);click to copy

That's the whole integration. The SDK auto-refreshes config from the control plane (no redeploy when you change pricing) and streams events — visits, blocks, payments, extractions — back to your dashboard. Within a few seconds the onboarding checklist auto-ticks Install and Integrate from the SDK's heartbeat.

Mount it before your routes. agentrail() returns standard Express middleware; the returned function also exposes .controlPlane (the hosted client) so you can call .controlPlane.stop() on a clean shutdown.

4Send a test request

Hit a priced route as if you were an AI agent — declare a known crawler user-agent and a purpose:

curl -i https://your-app.com/api/products \ -H 'User-Agent: Mozilla/5.0 (compatible; GPTBot/1.1; +https://openai.com/gptbot)' \ -H 'X-Agent-Purpose: answer'click to copy

In live mode you get 402 Payment Required with price headers and an x402 payment challenge. Humans (no agent signature) pass straight through — only detected agents are gated. That first gated request — the 402 and its blocked event — auto-advances the test step on your checklist.

5Set pricing (policies)

In the dashboard, define policies — one per path pattern. A policy decides the price and which agent purposes are allowed.

FieldExampleMeaning
Path pattern/api/products/:skuwhich resource this rule covers — exact, /api/reports/* prefix, or :param
Tiermeteredfree · metered · premium
Price5cents per call (0 = free but still gated by purpose & mode)
Allowed purposes["browsing","answer"]gate by why the agent is here — e.g. allow answering, block training

Policies are versioned with one-click rollback, and changes reach your live SDK within seconds — no deploy. See Policies & purposes for the full reference.

6Set your payout wallet

To take real USDC over x402 (instead of the built-in demo rail), open Payouts in your project settings:

  • Merchant wallet address — the public address USDC settles to (never a private key). Changing it later never affects past payments — each is recorded with the address it actually paid to.
  • Network — Base Sepolia (testnet, free, start here) or Base (mainnet).
  • Move funds on-chain — capture each payment on-chain (you get a tx hash) versus authorize-only (verified, funds don't move yet).

Start on Base Sepolia with the public testnet facilitator — real signed payments, no real money at risk — then switch to Base mainnet when you're ready.

7Shadow → Live

Every project starts in shadow mode. Flip to live when your pricing looks right.

Shadow

AgentRail observes and logs agent traffic and shows what it would charge. No 402s, zero risk. Run here for a day to sanity-check pricing against real traffic.

Live

Flip the toggle and agents get a 402 + payment challenge, pay, and get access. Money flows (or is authorized) per your Payouts setting.

Roll out one priced route at a time. You can also pin mode in code with the mode option (see Configuration) — otherwise it's driven by the dashboard.

Configuration

Every option accepted by agentrail(config). In hosted mode you typically pass only apiKey; the rest are for self-hosting and advanced control.

OptionTypeWhat it does
apiKeystringHosted mode. Project key (agr_live_…) — pulls policies/pricing/mode and streams events.
controlPlaneUrlstringOverride the control-plane URL. Default https://app.agentrail.com.
policiesobjectSelf-hosted. Static policy table, { "/path": { priceCents, purposeAllow, tier? } }. Merged under any hosted policies.
validatorsobjectSelf-hosted. Map of { rail: validatorFn } — see Self-hosted mode.
validatePaymentfnSingle legacy validator (use validators for multi-rail).
paymentMethodsstring[]Override the advertised X-Payment-Methods list.
onEventfnCalled for every visit / blocked / payment / extraction event.
treatPathAsAgentfnMark paths as agent-only, e.g. p => p.startsWith('/api/agent/').
headerPrefixstringPrefix for the SDK's response headers. Default X-AgentRail.
mode'shadow' | 'live'Force enforcement mode. Default: derived from the control plane.
verifierVerifier | falseAgent-identity verification (reverse-DNS + IP allowlist). Pass false to disable.

Reading detection in your handler

After the middleware runs, req.agentrail carries the detection result for the request. Read it to branch your own logic, and call recordExtraction() to log what an agent pulled.

app.get('/api/products', (req, res) => { const a = req.agentrail; // detection result for this request if (a?.isAgent) { console.log(a.identity?.operator, a.confidence, a.verified); } const products = getProducts(); a?.recordExtraction(products.map(p => p.sku)); // shows in "what AI extracted" res.json({ products }); });click to copy

req.agentrail fields:

isAgentboolean — classified as an agent (confidence ≥ 50).
confidence0–100 detection score.
identity{ operator, product, purpose, source } or null. source = how we knew (user-agent / self-declared / heuristic / endpoint-inferred).
verifiedstrength of identity proof: rdns · ip-allowlist · signed · receipt · null.
signalshuman-readable reasons that contributed to the score.
automationLikelihood0–1 "how automated does this look" score — catches stealth agents with browser-shaped UAs.
recordExtraction(facts)log what the agent extracted (array or string). No-op for humans.

Policies & purposes

Path patterns come in three shapes:

  • Exact/api/data
  • Wildcard prefix/api/reports/*
  • Parameterized/api/products/:sku

Tiers: free (no charge, still gated by purpose & mode), metered (per-call price), premium (higher-priced resources). To block an agent, restrict the allowed purposes below — a request whose purpose isn't allowed is denied and logged as a blocked event.

Purposes describe why an agent is calling. Allow or deny each per policy:

* browsing answer training search-index extraction

["*"] allows any purpose. A common setup: allow browsing and answer, charge for them, and block training.

Agent headers

How agents are recognized, and what AgentRail sends back.

Agents are detected by known user-agent fingerprints, self-declared headers, MCP protocol signals, and behavioral heuristics. Two self-declared request headers are the emerging standard:

X-Agent-Identitywho the agent is, e.g. openai/chatgpt.
X-Agent-Purposewhy it's calling — one of the purposes.

On a priced request without valid payment, AgentRail responds 402 Payment Required with price headers (the required price and accepted X-Payment-Methods) and an x402 challenge in the body. The SDK's own informational headers use the X-AgentRail prefix (configurable via headerPrefix).

How payments work

The 30-second mental model:

  1. Agent calls a priced resource → AgentRail returns 402 with a price + an x402 challenge.
  2. The agent's runtime signs a one-time, amount-capped USDC payment with its own wallet (you never see its key) and retries.
  3. AgentRail's facilitator verifies the payment (and settles on-chain if you enabled it) → the agent gets the resource, you get a transaction.

You only ever configure your receiving address. The agent brings and signs its own wallet — that separation is the point: you can monetize agents you've never met.

Supported rails: the built-in demo rail (no setup), x402 (Coinbase, on-chain USDC), AP2 (Google signed mandates), and AWS Bedrock agent payments. Hosted mode wires x402 for you; self-hosting lets you mix rails (see below).

Monetizing an MCP server

Running a Model Context Protocol server? The MCP adapter gates tool calls with the same control plane:

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { createAgentrailMcp } from '@agentrails/mcp'; const server = new McpServer({ name: 'acme-mcp', version: '1.0.0' }); const guard = createAgentrailMcp({ apiKey: process.env.AGENTRAIL_API_KEY, serverName: 'acme-mcp' }); guard.register(server, 'get_report', { inputSchema: { id: z.string() } }, async ({ id }) => ({ content: [{ type: 'text', text: await fetchReport(id) }] }));click to copy

A priced tool with no valid payment returns a structured "payment required" result carrying an x402 challenge; the agent pays in the call's _meta and retries. Works with Node and Python MCP servers.

The MCP adapter (@agentrails/mcp) is in preview and not yet published to npm — see all SDKs.

Self-hosted mode

Don't want the hosted dashboard? Skip apiKey and pass your own policy table plus payment validators. The SDK runs entirely in your infrastructure — no calls home.

const { agentrail, makeX402Validator, makeDemoValidator } = require('@agentrails/sdk'); app.use(agentrail({ mode: 'live', policies: { '/api/products': { priceCents: 1, purposeAllow: ['browsing','answer'] }, '/api/products/:sku': { priceCents: 1, purposeAllow: ['browsing','answer'] }, '/api/reports/*': { priceCents: 25, purposeAllow: ['answer'] }, }, validators: { x402: makeX402Validator({ recipientAddress: process.env.MERCHANT_WALLET, chain: 'base' }), demo: makeDemoValidator(), }, onEvent: (e) => console.log(e.type, e.resource, e.amountCents), }));click to copy

Builders for each rail: makeDemoValidator(), makeX402Validator(), makeAp2Validator(), makeBedrockValidator(). Each takes its own config (merchant address, payee id, region, keys). Provide a seenStore in production for replay protection that survives restarts.

Verify on the dashboard

Everything shows up in real time:

Analytics

Traffic & revenue over time, plus a filterable event explorer.

By surface / language

Which deployment or language each agent call came from.

Agents seen

Who's hitting you (OpenAI, Anthropic, Perplexity, …), paying vs. blocked.

What the AI extracted

The structured facts agents pulled from your priced resources.

Environment variables

VariableUsed byNotes
AGENTRAIL_API_KEYHosted modeYour project key (agr_live_…). Passed to agentrail({ apiKey }). Keep it secret.
AGENTRAIL_CONTROL_PLANE_URLOptionalPoint the SDK at a self-hosted control plane (same as the controlPlaneUrl option). Default https://app.agentrail.com.
MERCHANT_WALLETSelf-hosted x402Your own convention — the public address passed to makeX402Validator({ recipientAddress }).

FAQ

Do I have to handle crypto or keys?

No. You configure a public receiving address; the demo rail needs nothing. Real USDC is opt-in.

Will this break my human traffic?

No — only detected agents are gated; humans pass through untouched.

Change pricing without redeploying?

Yes — pricing, rails, and shadow/live live in the dashboard and propagate in seconds.

Which agents do you detect?

17 known agents by fingerprint (OpenAI, Anthropic, Google, Apple, Meta, Perplexity, …), self-declared headers, MCP signals, and behavioral heuristics.

Next steps

  • Run the shadow → live flow on a single priced route first.
  • Wire real x402 on Base Sepolia, then switch to mainnet.
  • Read the Agent API — the pricing table, payment methods, and curl examples a third-party agent uses.
  • Browse every SDK and framework adapter.

Not building yet? Join the waitlist and we'll be in touch.