Developers · Agent API
Wire an agent to a paid API in one request
Harpd sells AI product intelligence per call over x402. There is no signup, no API key and no dashboard: the integration is an agent wallet plus an HTTP request. This page answers every question an engineer asks before connecting one.
Endpoints
| Method | Path | Price | What it returns |
|---|
GET | /api/agent/v1/manifest | free | Capabilities, endpoints, payment rails, limits. |
GET | /api/agent/v1/pricing | free | Live price list — the same object that builds the 402. |
GET | /api/agent/v1/search?q= | free | Keyword search over the published catalog. |
GET | /api/agent/v1/rank | free | Rank board for any scope and category. |
GET | /api/agent/v1/products/{slug} | free | Single product profile. |
POST | /api/agent/v1/compare | 0.01 USDC | 2–8 products head to head. |
POST | /api/agent/v1/optimize-model | 0.05 USDC | Cheaper model that still clears the task quality floor. |
POST | /api/agent/v1/research | 0.05 USDC | Structured research answer with evidence. |
POST | /api/agent/v1/dataset/query | from 0.02 USDC | Field-selective dataset rows. |
GET | https://api.harpd.com/mcp | free | MCP tool catalog (paid tools listed with prices). |
POST | https://api.harpd.com/mcp | per tool | MCP JSON-RPC: search_products, rank_products, compare_products, research_products, optimize_model. |
Base URL for the REST API is https://api.harpd.com. The MCP server lives at the same host. Both speak the same payment flow, so one x402 client covers both transports.
The questions
What is the Harpd Agent API?
A machine-first HTTP API over Harpd's AI product intelligence: rankings, product comparison, research, model pricing and datasets. It is designed for autonomous callers, so every response is a stable `{ data, meta }` envelope, every price is machine-readable before the call, and no account, API key or human checkout exists anywhere in the flow.
What can an AI agent buy?
Four paid products and three free ones. Paid: product comparison (0.01 USDC), model cost optimisation (0.05 USDC), product research (0.05 USDC) and dataset query (from 0.02 USDC, priced in row bands). Free, permanently: product search, the Rank board and the pricing manifest.
How does payment work?
Over x402. Call a paid endpoint with no payment header and it returns HTTP 402 with the exact requirements in the `PAYMENT-REQUIRED` header. Sign the USDC payment with the agent wallet, retry with the `PAYMENT-SIGNATURE` header, and Harpd verifies and settles through a facilitator. Harpd is non-custodial and never sees a private key. A settled payment is single-use — replaying it returns HTTP 409.
What does one request cost?
A fixed price per request, published in three generated places: `/api/agent/v1/pricing`, the OpenAPI contract, and the 402 challenge itself. Free endpoints cost nothing and need no credential. There is no subscription, no minimum, no metered overage and no hidden tier. A per-request ceiling of 1 USDC and a daily ceiling of 10 USDC per payer wallet are enforced server-side.
Am I charged if my request is malformed?
No. Harpd validates every paid request against the published input schema, and resolves dataset and field names, **before** it asks for payment. A request it already knows it cannot fulfil — a missing required field, a value outside its enum, an unknown dataset field — is rejected with HTTP 400 `INVALID_INPUT`, `UNKNOWN_DATASET` or `UNKNOWN_FIELDS` and no payment is taken: no challenge is issued, nothing settles and nothing counts against your daily ceiling. An agent is never charged for a response it does not receive. The error body includes the full `input_schema` and a `validation_errors` list so the agent can correct itself and retry for free.
What data is returned?
Structured JSON only — never prose for an agent to parse. Search returns matched catalog entries with a relevance score and matched terms. Comparison returns per-product category, published rank, list pricing and a computed differences list. Model optimisation returns the task token profile, ranked cheaper alternatives with per-call and projected monthly savings, a performance trade-off, a confidence value and the evidence behind each number. Research returns products, category distribution, price bands, findings with sources and explicit caveats.
What is the schema?
Every response is `{ data, meta }`. `meta` always carries source, version, updated_at, methodology, canonical, dataset, license, citation, request_id, free and payment — `payment` is `null` on a free response and the settled receipt on a paid one, so a client never has to branch on whether the key exists. `data` is documented per operation in the OpenAPI contract, which is generated from the same product catalog the Worker enforces.
How can an agent cite Harpd?
Every response carries a ready-to-quote `meta.citation` with a text line, the canonical URL, the dataset, the methodology URL and the retrieval timestamp. Data is CC BY 4.0 with attribution, so an agent can cite it directly without asking.
How are datasets updated?
Rank-derived answers are computed at request time from the live board. Model pricing is a registry re-verified against official provider pages on a published date. Every response stamps `meta.updated_at`, so an agent can enforce its own staleness policy instead of trusting a blanket promise.
How are refunds and disputes handled?
A settled on-chain payment cannot be reversed, so Harpd corrects rather than reverses. If a paid request settles and the response is an error or empty, that request is recorded with the failure status and receipt; contact support with the `request_id` from `meta` and the receipt hash and Harpd re-serves the answer or refunds the amount to the paying wallet. A replayed payment is refused with 409 and never charged twice.
Free call — curl
Start here. No credential of any kind.
# What does Harpd sell?
curl -s https://api.harpd.com/api/agent/v1/manifest | jq .capabilities
# What does it cost, right now?
curl -s https://api.harpd.com/api/agent/v1/pricing | jq '.data.products[] | {product, price, pricing_mode}'
# Search the catalog (free)
curl -s "https://api.harpd.com/api/agent/v1/search?q=video%20generator&limit=3" | jq '.data.results[] | {name, rank, relevance_score}'Paid call — the full 402 handshake with curl
Step 1 sends no payment and gets the challenge. Step 2 is what a real agent does programmatically: sign the requirement from the PAYMENT-REQUIRED header with the wallet, then retry with PAYMENT-SIGNATURE.
# 1. Unpaid request → HTTP 402 with the exact requirements
curl -s -D- -o /dev/null -X POST https://api.harpd.com/api/agent/v1/optimize-model \
-H 'content-type: application/json' \
-d '{"task":"write a 3000-word technical article","current_model":"claude-opus-4-8","max_cost":0.5}'
# HTTP/2 402
# payment-required: eyJ4NDAyVmVyc2lvbiI6MiwicmVzb3VyY2UiOnsi...
# {"error":"PAYMENT_REQUIRED","request_id":"...","payment":{"accepts":[{"scheme":"exact",
# "network":"eip155:8453","asset":"0x8335...","amount":"50000","payTo":"0xc5eE..."}]}}
# 2. Decode the challenge to see exactly what you are being asked to sign
curl -s -D- -o /dev/null -X POST https://api.harpd.com/api/agent/v1/optimize-model \
-H 'content-type: application/json' \
-d '{"task":"...","current_model":"claude-opus-4-8"}' \
| grep -i '^payment-required:' | cut -d' ' -f2 | base64 -d | jq .accepts[0]
# 3. Sign and retry. The x402 client does this for you (see below); by hand:
curl -s -X POST https://api.harpd.com/api/agent/v1/optimize-model \
-H 'content-type: application/json' \
-H "PAYMENT-SIGNATURE: $SIGNED_X402_PAYLOAD" \
-d '{"task":"write a 3000-word technical article","current_model":"claude-opus-4-8","max_cost":0.5}' \
| jq '.data.recommended_alternative, .meta.payment, .meta.citation'An unpaid retry of a payment that already settled returns HTTP 409 PAYMENT_REPLAYED. Payments are single-use by design — store the receipt, not the signature.
x402 example — the client library does the handshake
With @x402/fetch the entire flow above is one call. This is the shape an agent runtime should use.
import { wrapFetchWithPayment } from '@x402/fetch'
import { x402Client } from '@x402/core/client'
import { ExactEvmScheme } from '@x402/evm/exact/client'
import { privateKeyToAccount } from 'viem/accounts'
// The wallet lives in the agent runtime. It is never sent to Harpd.
const account = privateKeyToAccount(process.env.AGENT_WALLET_KEY)
const client = new x402Client()
client.register('eip155:*', new ExactEvmScheme(account))
const paidFetch = wrapFetchWithPayment(fetch, client)
// 402 → sign → retry → verify → settle → 200, automatically.
const response = await paidFetch('https://api.harpd.com/api/agent/v1/optimize-model', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
task: 'write a 3000-word technical article',
current_model: 'claude-opus-4-8',
max_cost: 0.5,
}),
})
const { data, meta } = await response.json()
console.log(data.recommended_alternative.model.display_name)
console.log(data.estimated_savings.monthly_usd, 'USD/month')
console.log('cite as:', meta.citation.text)JSON example — a real response
The envelope is identical on every product. Only data changes, andmeta.payment is always present — null when nothing was charged, the settled receipt when it was. A client never has to check whether the key exists.
{
"data": {
"task": "write a 3000-word technical article",
"current_model": {
"model_id": "claude-opus-4-8",
"display_name": "Claude Opus 4.8",
"tier": "flagship",
"estimated_cost_per_call_usd": 0.0705,
"estimated_monthly_cost_usd": 70.5
},
"task_profile": {
"workload_class": "long_form_generation",
"estimated_input_tokens": 1200,
"estimated_output_tokens": 4050,
"quality_floor_tier_score": 2,
"inferred": false
},
"recommended_alternative": {
"model": { "id": "gemini-2-5-flash", "display_name": "Gemini 2.5 Flash", "tier": "mini" },
"estimated_cost_per_call_usd": 0.010485,
"estimated_savings_per_call_usd": 0.060015,
"estimated_savings_monthly_usd": 60.015,
"savings_ratio": 0.8513,
"quality_risk": "medium",
"latency_expectation": "faster"
},
"confidence": 0.7,
"confidence_basis": [
"Task stated an explicit output size, so the cost driver is known rather than assumed.",
"The recommended substitute is a lower capability tier than the current model, so quality risk is real.",
"Quality is inferred from capability tier, not measured on your task. Run your own eval before switching."
],
"synthesis_method": "deterministic_catalog_and_price_intersection"
},
"meta": {
"source": "Harpd",
"version": "1",
"updated_at": "2026-09-17T12:00:00.000Z",
"methodology": "https://harpd.com/methodology/cost-per-successful-task/",
"canonical": "https://harpd.com/llm-cost-optimization/",
"dataset": "https://harpd.com/data/llm-pricing.json",
"license": "CC BY 4.0",
"citation": {
"text": "Harpd. \"Model cost optimisation — Claude Opus 4.8 on \\\"write a 3000-word technical article\\\"\" (retrieved 2026-09-17). https://harpd.com/data/llm-pricing.json — CC BY 4.0.",
"url": "https://harpd.com/llm-cost-optimization/",
"dataset": "https://harpd.com/data/llm-pricing.json",
"methodology": "https://harpd.com/methodology/cost-per-successful-task/",
"retrieved_at": "2026-09-17T12:00:00.000Z"
},
"request_id": "4f0c1e2a-...",
"free": false,
"payment": {
"status": "settled",
"network": "eip155:8453",
"currency": "USDC",
"amount": "0.05",
"amount_atomic": "50000",
"transaction": "0xabc...",
"product": "optimize_model",
"timestamp": "2026-09-17T12:00:01.000Z",
"receipt_hash": "9d1f..."
}
}
}MCP example
Harpd exposes the same products as MCP tools, so a framework that speaks MCP needs no HTTP integration at all. Paid tools are marked as paid in their own description — an agent never discovers the price by being surprised by a 402.
# Discover the tools, their prices and the payment method (no auth)
curl -s https://api.harpd.com/mcp | jq '.tools[] | {name, pricing_mode, price_usd}'
# List tools over JSON-RPC
curl -s https://api.harpd.com/mcp -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# Call a free tool
curl -s https://api.harpd.com/mcp -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"search_products","arguments":{"q":"video generator","limit":3}}}'
# Call a paid tool with no payment → HTTP 402 with x402 requirements,
# exactly like the REST endpoint. Sign, retry with PAYMENT-SIGNATURE.
curl -s -D- -X POST https://api.harpd.com/mcp -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call",
"params":{"name":"optimize_model",
"arguments":{"task":"summarise 200 support tickets","current_model":"gpt-5"}}}'MCP tools: search_products and rank_products (free),compare_products (0.01 USDC), research_products andoptimize_model (0.05 USDC).
Testing against Base Sepolia
Every paid product has a nominal testnet price so the whole handshake can be exercised without real funds. Point the same client at the testnet host, use a throwaway wallet, and expect the identical 402 → sign → retry → 200 sequence on eip155:84532.
# Confirm which rail you are talking to before spending anything
curl -s https://api.harpd.com/v1/payments/health | jq '{ok, paymentMode, price}'
curl -s https://api.harpd.com/v1/payments/config | jq '{mode, network, chainId, treasuryAddress}'Error codes
| Status | Code | Meaning and what to do |
|---|
| 400 | INVALID_INPUT | Body does not match the published input schema. The response repeats the schema and the exact validation errors. |
| 402 | PAYMENT_REQUIRED | Sign the requirement from PAYMENT-REQUIRED and retry. |
| 402 | PAYMENT_NOT_VERIFIED | The facilitator rejected the signature. Usually a wrong amount, network or recipient — check against the challenge. |
| 402 | REQUEST_EXCEEDS_MAX | The request costs more than the configured per-request cap. |
| 403 | WALLET_NOT_ALLOWLISTED | This deployment restricts payers to an allowlist and the wallet is not on it. |
| 404 | MODEL_NOT_FOUND | Unknown model id. The response lists every known id. |
| 409 | PAYMENT_REPLAYED | This payment was already consumed. Do not retry the same signature — issue a new payment. |
| 429 | RATE_LIMITED | 120 requests/minute per caller by default. Back off. |
| 429 | DAILY_SPEND_LIMIT_REACHED | Per-wallet daily cap reached. Retry after 00:00 UTC. |
| 503 | PAYMENT_CONFIGURATION_INCOMPLETE | Fail-closed: the payment rail is not fully configured. Nothing was charged. |
| 503 | PAYMENT_FACILITATOR_UNAVAILABLE | Facilitator unreachable. Nothing was charged — safe to retry. |
Next
Worked examples for Claude, a Cloudflare Agent, an OpenAI-style client, a generic HTTP agent and an MCP agent.
Trust page for methodology, freshness, provenance and the refund policy.
Harpd for AI Agents for the product overview.