Get Paid Per Request
One HTTP status code turns any endpoint into a metered service
npm install @orches/x402 viemStart here
#introductionThe model
Orches is the coordination layer between agent intent and executable financial workflows. Providers register a capability and price it per request. Agents resolve provider selection from a machine-readable registry, settle at request level over the x402 protocol on Robinhood Chain, and take back a verifiable outcome. No key exchange, no account, no subscription.
You have an endpoint
Register any HTTPS route as a capability, price it per request, and settle to your wallet.
You have an agent
Resolve a provider, settle the 402, and act on a verifiable outcome without a human in the path.
Both sides of the exchange run on the same open packages: SDKs, an MCP server, and a registry spec, published to npm and PyPI. See what to install.
Payment is the credential
Settlement carries the authority. Rather than issuing a credential ahead of time, a provider answers with a plain HTTP 402. The agent settles in stablecoin, the transfer is verified on-chain, and the workflow continues. Nothing to provision, nothing to rotate, nobody to approve it.
The transaction hash is the authority, so the model composes across agent runtimes, MCP servers, and recursive delegation. Where software acts on its own behalf, request-level settlement is the only access control that survives the recursion.
Pick a path
| If this is you | Go here |
|---|---|
| A provider with an API to monetize | Read Selling a call |
| Building an agent that needs live data | Read Buying a call |
| Using Claude, Codex, Antigravity or Cursor | Set up the MCP server |
| Integrating the discovery registry | Read Being found |
The settlement handshake
#paymentsThe two-step exchange
Intent becomes execution in two HTTP round trips, on standard status codes:
- Agent calls
POST /api/services/[id]/callwith the request payload. - Orches returns
HTTP 402with a payment object: recipient wallet, USDG amount, network, and a 10-minute expiry. - Agent submits a USDG transfer on Robinhood Chain and captures the transaction hash.
- Agent retries with an
x-payment-proofheader containing thetxHashandpayerWallet. - Orches verifies the on-chain transfer and returns
HTTP 200with the provider response.
The request is checked against the capability's inputSchema before any challenge is issued, so a malformed body returns 400 and never costs anyone a settlement. fetchWithPayment collapses steps 2 to 5 into one call.
Challenge fields
The 402 body carries every term of the exchange. The same fields sit at the top level for x402 clients and under a payment key for everyone else.
| Field | Example | Meaning |
|---|---|---|
| type | x402_payment_required | Discriminator that marks an x402 challenge. |
| amountAtomic | 50000 | Exact USDG to transfer, in atomic units (6 decimals). Send this value. |
| amount | 0.05 | Human-readable USDG amount (display only). |
| payTo | 0x2DDa…191a | Provider wallet. The USDG recipient. |
| network | robinhood | Settlement network. robinhood = mainnet. |
| chainId | 4663 | Robinhood Chain (4663) or Robinhood Chain testnet (46630). |
| currency | USDG | Settlement token. |
| expiresAt | ISO 8601 | Challenge expiry, 10 minutes from issuance. |
amountAtomicexactly. Underpayment is rejected, and the value is already denominated in USDG's 6-decimal base units, so no conversion is required.Proving payment
Once settled, the agent replays the request carrying an x-payment-proof header. The evidence is a small JSON object:
1{
2 "txHash": "0x91c9…6055", // required. The USDG transfer hash
3 "payerWallet": "0x8A05…0C08" // recommended. The paying account
4}Orches verifies the transfer on-chain before it routes anything to the provider. It confirms that the:
- transaction succeeded and is a USDG transfer on the expected network;
- token contract matches the canonical USDG address for that network;
- recipient equals the service's
payTowallet; - amount is at least the registered price (underpayment is rejected);
txHashhas not been used for this service before (replay protection).
Single-use rules
txHash is single-use. Reusing one returns 409 Conflict. Pay a fresh transaction per call.Replay protection is the difference between a settlement and a bare transfer. Every proof is indexed, so one transaction unlocks one capability exactly once and the receipt stays auditable afterwards.
What to install
#sdksAll of it is open source and shipped. The SDK owns the handshake and the on-chain verification, so neither side of the exchange writes that code twice.
Make any REST endpoint x402-payable, and pay for x402 endpoints as an agent. Express, Next.js & FastAPI adapters.
npm install @orches/x402 viemThe Python distribution: FastAPI middleware and on-chain verification.
pip install orches-x402[fastapi]Give Claude, Codex, Antigravity, Cursor & Robinhood Chain MCP direct access to the marketplace: list, inspect, pay for, and call any service.
npx -y @orches/mcp@latestValidate an agent-services.json discovery document against the Orches spec.
npx @orches/validate-spec ./agent-services.jsonSelling a call
#providersTwo ways to put a capability up for selection. Most providers register with Orches and let the coordination layer do the work. Providers who want the gateway on their own infrastructure can run x402 themselves.
Via the registry
Ship a plain HTTPS endpointthat takes JSON and returns JSON. You write no payment code. Orches issues the challenge, verifies the transfer, enforces replay protection, then routes the request through. USDG lands in your wallet, not in an intermediary's balance.
- Stand up a reachable HTTPS route (POST, JSON in and out).
- Publish JSON Schemas for input and output. This is what an agent evaluates before it selects you.
- Connect a payout key. Provider identity and settlement destination are the same address.
- Submit on the Publish page. New services enter
pending_review; once approved they go live in the marketplace.
npx @orches/validate-spec ./agent-services.jsonOn your own server
Metering an endpoint that stays off the registry? Wrap it with @orches/x402. One wrapper installs the whole challenge, verify, respond cycle.
1import { withX402 } from "@orches/x402";
2
3app.post(
4 "/api/risk",
5 withX402(
6 async (req, res) => {
7 // payment already verified; req.x402.payerWallet is available
8 res.json(await yourBusinessLogic(req.body));
9 },
10 { price: "0.05", wallet: process.env.PROVIDER_WALLET, network: "robinhood" },
11 ),
12);1// app/api/risk/route.ts
2import { withX402Payment } from "@orches/x402";
3
4export const POST = withX402Payment(
5 async (req, { x402 }) => Response.json({ score: 0.92, paidBy: x402.payerWallet }),
6 { price: "0.05", wallet: process.env.PROVIDER_WALLET!, network: "robinhood" },
7);1from orches_x402 import X402Middleware
2
3X402Middleware(app, price="0.05", wallet=PROVIDER_WALLET, network="robinhood", protected_paths=["/api/risk"])Buying a call
#agentsThree ways to turn intent into a settled call, from most abstracted to least.
With the SDK
fetchWithPayment takes a viem wallet, settles the challenge, and replays the request. The whole exchange behind one function.
1import { fetchWithPayment } from "@orches/x402";
2import { createWalletClient, http } from "viem";
3import { privateKeyToAccount } from "viem/accounts";
4import { base } from "viem/chains";
5
6const wallet = createWalletClient({
7 account: privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`),
8 chain: base,
9 transport: http(),
10});
11
12const res = await fetchWithPayment(
13 "https://fletch402.xyz/api/services/{id}/call",
14 { method: "POST", body: JSON.stringify({ input: { address: "0x…" } }) },
15 wallet,
16);
17console.log(await res.json());Through MCP
Add @orches/mcp and the model performs provider selection itself: browse, compare price, settle, call. Tools: list_services, get_service_details, call_service, check_payment_status.
The config below is the standard MCP format. Drop it into your client's config file (claude_desktop_config.json, Codex's MCP settings, or Antigravity's mcp_config.json).
1{
2 "mcpServers": {
3 "orches": {
4 "command": "npx",
5 "args": ["-y", "@orches/mcp@latest"],
6 "env": {
7 "ORCHES_API_BASE": "https://fletch402.xyz",
8 "ORCHES_NETWORK": "robinhood",
9 "ORCHES_PRIVATE_KEY": "0xYourAgentWalletKey"
10 }
11 }
12 }
13}ORCHES_PRIVATE_KEY is required only for paid call_servicecalls; discovery works read-only without it. Use a dedicated agent wallet funded with only what you're willing to let the agent spend.
Raw HTTP
No SDK in the path? Drive the two round trips yourself:
1// 1. First call, expect 402
2const challenge = await fetch(callUrl, {
3 method: "POST",
4 headers: { "Content-Type": "application/json" },
5 body: JSON.stringify({ input }),
6});
7const { payment } = await challenge.json(); // { payTo, amountAtomic, network, ... }
8
9// 2. Transfer USDG(payment.payTo, payment.amountAtomic) on Robinhood Chain -> txHash
10
11// 3. Retry with proof
12const result = await fetch(callUrl, {
13 method: "POST",
14 headers: {
15 "Content-Type": "application/json",
16 "x-payment-proof": JSON.stringify({ txHash, payerWallet }),
17 },
18 body: JSON.stringify({ input }),
19});Being found
#discoveryRegistry routes
The registry an agent reads before it selects anything, at three canonical routes:
| Endpoint | Format | Best for |
|---|---|---|
| /api/agent/services | JSON | Programmatic discovery, pageable, CORS-open |
| /.well-known/agent-services.json | JSON | Standard well-known location |
| /llms.txt | Plain text | LLM context windows |
The record format is an open, versioned standard. Check your own against it with @orches/validate-spec.
Record shape
Every record is self-describing, so provider selection, price comparison, and invocation all resolve in a single pass. The fields that matter:
| Field | Description |
|---|---|
| id / slug | Stable identifier and human-readable handle. Either works in the call URL. |
| price | { amount, currency }. Per-call cost in USDG. |
| network | Settlement network (robinhood). |
| capabilities / tags | Keywords for capability-based routing and search. |
| inputSchema / outputSchema | JSON Schemas. Build a valid request and parse the response. |
| endpoint | The call URL to POST against. |
| reliability | { verified, successRate, averageLatencyMs, totalCalls }. Live operational stats. |
| playgroundUrl | Try the service with a simulated payment, no wallet required. |
1{
2 "id": "cmpjq32i80002qaimfb2fezm4",
3 "slug": "wallet-risk",
4 "name": "Wallet Risk Score API",
5 "capabilities": ["risk", "wallet", "security"],
6 "price": { "amount": "0.05", "currency": "USDG" },
7 "network": "robinhood",
8 "endpoint": "https://fletch402.xyz/api/services/{id}/call",
9 "inputSchema": { /* JSON Schema */ },
10 "outputSchema": { /* JSON Schema */ },
11 "reliability": {
12 "verified": true,
13 "successRate": 99.5,
14 "averageLatencyMs": 132,
15 "totalCalls": 2059
16 },
17 "playgroundUrl": "https://fletch402.xyz/playground/wallet-risk"
18}Wire reference
#referenceStatus codes
| Status | Meaning | Action |
|---|---|---|
| 400 | Input failed schema validation. | Fix the request body to match inputSchema. |
| 402 | Payment required. Includes the payment object. | Pay on Robinhood Chain, retry with x-payment-proof. |
| 403 | Service exists but is not published. | Wait for the service to go live. |
| 404 | No service matches that id or slug. | Re-check the id from the discovery registry. |
| 409 | txHash already used (replay rejected). | Submit a new on-chain transaction. |
| 429 | Rate limited (10 req / 10s / IP). | Wait for X-RateLimit-Reset, then retry. |
| 502 | Provider endpoint unreachable or timed out. | Try again later. |
| 500 | Internal Orches error. | Retry once; contact support if it persists. |
Rate limits
All call endpoints: 10 requests per 10 seconds per IP. On a 429, response headers tell you when to retry:
1X-RateLimit-Remaining: 0
2X-RateLimit-Reset: 1717056123000Source and prompts
#resourcesRepositories
| Repo | What it is |
|---|---|
| Orches/x402-sdk | @orches/x402. Provider middleware and agent client, TypeScript and Python. |
| Orches/provider-starter | Deploy-ready Express / Next.js / FastAPI paid-API templates |
| Orches/agent-services-spec | The discovery standard, plus the @orches/validate-spec CLI. |
| Orches/orches-mcp | @orches/mcp. MCP server for Claude, Codex, Antigravity, Cursor and Robinhood Chain MCP. |
| Orches/examples | Reference agents for LangChain, Claude, OpenAI and Robinhood Chain MCP. |
| Orches/awesome-orches | Curated ecosystem index |
Agent system prompt
Drop this into a system prompt and the model can transact on the coordination layer:
1You are an AI assistant that can call financial services on Orches.
21. Discover services at https://fletch402.xyz/api/agent/services.
32. Read inputSchema and build a valid request body.
43. Call the service's call endpoint. If HTTP 402, read the payment object.
54. Transfer USDG to payment.payTo on Robinhood Chain. Capture the txHash.
65. Retry with x-payment-proof: {"txHash":"0x...","payerWallet":"0x..."}.
76. Return the provider response to the user.
8
9Never expose private keys. Validate output before irreversible actions.
10Payment requirements expire after 10 min - never reuse a txHash.