Build agents that can pay for services without holding keys.
Gordon handles wallet custody, policy, payment, and audit so your agent does not have to. It acts as the control plane for agent-to-machine (A2M) and agent-to-agent (A2A) transactions with paid services.
Create an account, then an agent — each agent gets its own Base wallet and scoped API key.
Curated services come pre-enabled; set per-service spend caps, domains, and approval thresholds.
Authorize x402, confirm receipts, and audit every call.
Quickstart
Sign in at withgordon.ai, create an agent, fund its wallet, review services, then call it via the API, SDK, or MCP. See the full quickstart for a step-by-step walkthrough.
# Install the Gordon SDK
npm install @withgordon/core
# Environment — agent key + secret from the dashboard
GORDON_PLATFORM_URL=https://api.withgordon.ai
GORDON_AGENT_API_KEY=gak_pub_...
GORDON_AGENT_API_SECRET=gak_sec_...Core concepts
Agent
A scoped actor with an API key. Agents request service payments but never hold private keys.
Service
A catalog provider such as search, scrape, crawl, enrich, or infrastructure.
Operation
A callable method on a service with a method, endpoint, price, and settlement terms.
Policy
Per-agent controls: operation subset, spend caps, approval thresholds, and allowed domains.
Settlement
The x402 authorization, payment headers, provider response proof, and receipt status.
Buyer
The user or organization that owns policies, agents, wallets, and receipts.
API keys
Gordon uses agent API keys for all programmatic access. OTP email login is only for the browser dashboard — every SDK call, direct API call, and MCP tool call uses a key+secret pair scoped to a single agent.
Keys are created when you create or rotate an agent. The secret is shown once at creation time. Store it securely — if lost, rotate the key.
Authorization header format
Authorization: Bearer {API_KEY}:{API_SECRET}
# Example
Authorization: Bearer gak_pub_Smcyy7PL02LUeUlVq7WqkByA:gak_sec_qiQ7PfyipgrNNUCXOrmS7sfN...The gak_pub_ key identifies your agent and is safe to log. The gak_sec_ secret authorizes requests — never embed it in client code.
Creating an agent
An agent holds the API key pair, the on-chain USDC wallet, and the spend policy.
Option A — Dashboard
- Sign in at withgordon.ai via OTP email.
- Go to Agents → New agent and give it a name.
- Gordon provisions a CDP custody wallet on Base and pre-enables the curated catalog — copy the
gak_sec_shown once. - Open the agent and click Fund to deposit USDC on Base.
- Review the pre-enabled services — set per-call caps or disable any you don't want.
Option B — Management API
# Step 1 — request OTP
curl -X POST https://api.withgordon.ai/auth/request-otp \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com"}'
# Step 2 — verify OTP → short-lived session JWT
curl -X POST https://api.withgordon.ai/auth/verify-otp \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com", "code": "123456"}'
# → { "token": "<SESSION_JWT>", "user": { "id": "usr_..." } }
# Step 3 — mint a long-lived Personal Access Token (1 year)
curl -X POST https://api.withgordon.ai/users/{userId}/api-tokens \
-H "Authorization: Bearer <SESSION_JWT>"
# → { "token": "<PAT>", "expires_in": 31536000 }
# Step 4 — create an agent
curl -X POST https://api.withgordon.ai/users/{userId}/agents \
-H "Authorization: Bearer <PAT>" \
-H "Content-Type: application/json" \
-d '{"name": "my-prod-agent"}'
# → { "agent": { "id": "agent_...", "api_key_public": "gak_pub_..." },
# "api_secret": "gak_sec_...", ← shown ONCE — store immediately
# "wallet": { "address": "0x...", "chain": "base-mainnet" } }POST /agents/{agentId}/rotate-key.Enable a service for the agent
curl -X POST https://api.withgordon.ai/agents/{agentId}/services \
-H "Authorization: Bearer <PAT>" \
-H "Content-Type: application/json" \
-d '{
"service_id": "exa",
"max_per_call_units": 50000,
"max_per_day_units": 5000000
}'
# → { "agent_id": "...", "service_id": "...", "max_per_call_units": 50000, ... }Rotate & verify keys
# Rotate agent key — returns a fresh gak_pub + gak_sec pair
POST https://api.withgordon.ai/agents/{agentId}/rotate-key
Authorization: Bearer {USER_JWT}
# Verify your key is working (200 = valid)
curl https://api.withgordon.ai/services \
-H "Authorization: Bearer gak_pub_...:gak_sec_..."Discover services
The catalog is public — no auth required to browse. New agents are auto-enrolled into the curated catalog at permissive limits; the buyer can tighten caps or disable services per agent. Any service not in an agent's enabled set is blocked (service_not_enabled) — enforcement is fail-closed.
https://api.withgordon.ai/servicesQuery parameters
categorystringFilter by category: search, scrape, ai, data, infrastructure, finance.
trust_statusstringFilter by trust level: listed, discovered, probe_passed (verified).
limitintegerMax results. Default 50.
curl "https://api.withgordon.ai/services?category=search"
# → { "services": [{ "id": "...", "slug": "exa", "name": "Exa Search", ... }] }Service detail
https://api.withgordon.ai/services/{serviceId}serviceId accepts either a UUID or the slug (e.g. exa). Returns all callable operations with pricing and live x402 payment requirements.
{
"id": "0b3f2c1a-7e44-4a90-9b1e-2c8d5f6a1b20",
"slug": "exa",
"name": "Exa Search",
"operations": [
{
"availability": "paid_x402",
"operation_id": "search.web",
"label": "Web Search",
"method": "POST",
"endpoint": "https://api.exa.ai/search",
"estimated_price_units": 7000, // 7000 units = $0.007
"payment": {
"scheme": "exact",
"network": "base",
"token": "USDC",
"amount_units": 7000,
"pay_to": "0x6d6E695b09861467c7d462f5AAF31cF3540B9192"
}
}
]
}All prices are in Gordon micro-units: 1,000,000 units = $1.00 USD. So 7,000 units = $0.007.
x402 payment lifecycle
- 11. Call the provider — Make a normal HTTP request. If payment is required the provider returns HTTP 402 with a v1 X-Payment-Required header, a v2 payment-required header, or a v2 JSON body.
- 22. Extract payment requirement — Decode the provider requirement and pass the full object to Gordon. Gordon selects a supported Base USDC EIP-3009 payment option from v2 accepts arrays.
- 33. POST /x402/authorize — Send the requirement to Gordon. Gordon checks your agent policy, signs using the CDP wallet, and returns X-Payment headers.
- 44. Retry the provider — Replay the request with the X-Payment header. The provider verifies the USDC TransferWithAuthorization and returns the result.
- 55. POST /x402/settlements/:id/complete — Send the X-Payment-Response header back to Gordon to mark the receipt as confirmed.
Decoded provider examples
// x402 v1 — decoded X-Payment-Required header
{
"scheme": "exact",
"network": "base",
"token": "USDC",
"amount": "7000",
"payTo": "0x6d6E695b09861467c7d462f5AAF31cF3540B9192",
"nonce": "0x..."
}
// x402 v2 — payment-required header or 402 response body
{
"x402Version": 2,
"accepts": [{
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"amount": "7000",
"payTo": "0x6d6E695b09861467c7d462f5AAF31cF3540B9192",
"maxTimeoutSeconds": 60
}]
}Confirm receipt
After the provider returns 200, send its payment-response proof to Gordon. Gordon extracts the transaction hash and independently verifies the successful, exact USDC transfer on Base before marking the settlement confirmed.
https://api.withgordon.ai/x402/settlements/{settlementId}/completecurl -X POST https://api.withgordon.ai/x402/settlements/85e6f79c-.../complete \
-H "Authorization: Bearer gak_pub_...:gak_sec_..." \
-H "Content-Type: application/json" \
-d '{ "payment_response_header": { "X-Payment-Response": "eyJzZXR0bGVkIjp0cnVlLCJ..." } }'
# → { "settlement_id": "85e6f79c-...", "receipt_status": "confirmed" }Fetch receipts
https://api.withgordon.ai/x402/settlements/{settlementId}https://api.withgordon.ai/agents/{agentId}/settlements?limit=25{
"id": "85e6f79c-4e6a-4f95-b18c-1baabd45f879",
"transaction_id": "8510fc02-c699-42ea-aafc-04f0e18dd3d5",
"agent_id": "agent_yzmxwq3v48",
"receipt_status": "confirmed",
"amount_units": 7000,
"network": "eip155:8453",
"token": "USDC",
"service_id": "0b3f2c1a-7e44-4a90-9b1e-2c8d5f6a1b20",
"operation_id": "search.web",
"authorized_at": "2026-05-27T05:31:36.000Z",
"settled_at": "2026-05-27T05:31:38.000Z"
}Dashboard receipt page: withgordon.ai/account/receipts/{transactionId}
SDK
The SDK wraps the full authorize → retry → confirm flow in a single gordon.fetch() call.
import { Gordon } from "@withgordon/core";
const gordon = new Gordon({
platformUrl: "https://api.withgordon.ai",
agentApiKey: process.env.GORDON_AGENT_API_KEY!,
agentApiSecret: process.env.GORDON_AGENT_API_SECRET!,
});
// Drop-in replacement for fetch — handles 402 automatically.
// receipt is null when the provider returns 2xx without requiring payment.
const result = await gordon.fetch("https://api.exa.ai/search", {
method: "POST",
serviceId: "exa",
operationId: "search.web",
maxPaymentUnits: 10000,
body: JSON.stringify({ query: "agentic payments", numResults: 5 }),
headers: { "Content-Type": "application/json" },
});
if (result.receipt?.confirmed) {
console.log("Paid", result.receipt.amount_units / 1_000_000, "USD");
}MCP server
Gordon runs as a remote HTTP MCP server — no local install needed. See the MCP install guide for Cursor, Claude Desktop, VS Code, Codex, and Windsurf configs.
// Any MCP client — remote HTTP config
{
"mcpServers": {
"gordon": {
"url": "https://api.withgordon.ai/mcp",
"headers": { "Authorization": "Bearer gak_pub_...:gak_sec_..." }
}
}
}gordon_find_serviceNatural language search — describe what you want, get matching operation strings and pricing.gordon_requestCall a catalog service by URL with service_id + operation_id. Gordon handles 402 → authorize → retry → confirm.gordon_call_serviceCall by slug.operationId (e.g. exa.search.web). Enforces enabled-service policy automatically.gordon_list_servicesBrowse the catalog. Filter by category or trust status.gordon_get_serviceFull service record — operations, pricing, live x402 terms.gordon_list_enabled_servicesServices this agent is permitted to pay, with spend caps.gordon_get_balanceThis agent's USDC wallet balance and per-service daily spend remaining.gordon_get_receiptFetch a settlement receipt by ID.gordon_get_audit_logRecent payment receipts for this agent.gordon_call_service when you know the catalog operation string such as exa.search.web. Use gordon_request when you already have a raw provider URL and need to associate it with a service and operation.MCP quickstart
Three steps: install → review services → call it.
Step 1 — add Gordon to your client
Get your agent key from Agents → Connect. See the full MCP guide for Cursor, Claude Desktop, VS Code, Codex, and Windsurf.
Step 2 — review services (optional)
Curated services are enabled by default on new agents. To tighten, go to Agents → your agent → Services and set a per-call cap or disable services you don't want.
Step 3 — discover and call
// In any MCP client connected to Gordon:
gordon_find_service({ query: "web search" })
// → Exa, Brave, etc. with operation strings and pricing
gordon_call_service({
operation: "exa.search.web",
params: { query: "latest x402 integrations", numResults: 5 },
max_payment_units: 10000 // $0.01 cap
})settlement_status values
"confirmed"Payment made and settlement confirmed on-chain. Receipt is final."failed"Payment sent but on-chain confirmation failed — thrown as SETTLEMENT_NOT_CONFIRMED error. Check gordon_get_receipt.nullNo payment was required (provider returned 200 directly).Agent discovery (SKILL.md)
Gordon publishes a machine-readable capability file at a public URL. Agents running in Claude Code, Cursor, Codex, or any agent with a fetch tool can retrieve it to learn Gordon's full tool set, auth format, spend semantics, and failure behavior.
https://api.withgordon.ai/SKILL.mdNo auth required. Cache-Control: public, max-age=3600. The file is served by the Gordon MCP host, not this frontend. If you hit a 404, the MCP server may be restarting — retry after 30 seconds or fall back to https://www.withgordon.ai/docs.
// In Claude Code, Cursor, or any agent with web_fetch:
const skill = await web_fetch("https://api.withgordon.ai/SKILL.md");
// Gordon's full tool set, install config, spend semantics, and failure handlinghttps://api.withgordon.ai/SKILL.md before its first tool call. This ensures correct tool names, spend semantics, and graceful failure handling — even without prior training data on Gordon.Gordon also serves an llms.txt index pointing LLMs to docs, SKILL.md, and the public service catalog.
Policy controls
New agents are auto-enrolled into the curated catalog at permissive limits. Tighten caps, restrict operations, or disable services per agent. Enforcement is fail-closed: any service not in the agent's enabled set is blocked (service_not_enabled). When a service is enabled, all its operations are allowed by default — tighten with enabled_operations if needed.
POST https://api.withgordon.ai/agents/{agentId}/services
Authorization: Bearer {USER_JWT}
{
"service_id": "exa",
// Leave enabled_operations out to allow all operations (default)
// "enabled_operations": ["search.web"], // optional: restrict to specific ops
"max_per_call_units": 10000, // $0.01 per call — default $1.00
"max_per_day_units": 1000000, // $1.00 per day — default $50.00
"require_approval_above_units": 500000 // escalate above $0.50 — default $10.00
// "allowed_domains": ["example.com"] // optional: scrape/crawl domain allowlist
}Full API reference
See the API reference page for complete schemas, request/response shapes, and error codes. Quick reference:
/servicesnoneList catalog services (public)./services/:idnoneService detail with operations and live pricing./x402/authorizeagent keyAuthorize and sign x402 payment./x402/checkagent keyPolicy-only preflight; authorize still re-evaluates./x402/settlements/:id/completeagent keyConfirm provider receipt./x402/settlements/:idagent keyFetch a settlement receipt./agents/:id/settlementsagent keyList settlements for this agent./agents/:id/servicesuser JWTList enabled services./agents/:id/servicesuser JWTEnable a service with spend policy./agents/:id/services/:serviceIduser JWTDisable a service for this agent./agents/:id/services/:serviceId/policyuser JWTUpdate an enabled service policy./agents/:id/policiesuser JWTUpsert the agent spending constitution./agents/:id/rotate-keyuser JWTRotate agent key — returns new pair.Base URL: https://api.withgordon.ai · See Error codes for 4xx/5xx response shapes.
Test locally
cd /path/to/new-gordon
AUTH_SECRET=... npx vitest run --workspace gordon-core
# E2E against staging
GORDON_PLATFORM_URL=https://api.withgordon.ai \
GORDON_AGENT_API_KEY=gak_pub_... \
GORDON_AGENT_API_SECRET=gak_sec_... \
npx tsx packages/mcp/src/e2e-test.ts