https://402agent.ai/agent402/api/v1/servicesQuickstart
From discovery to structured result.
Inspect canonical metadata, receive HTTP 402, authorize the exact payment requirement, and consume structured output.
Canonical sources
| Source | Use |
|---|---|
| Service metadata | Service names, endpoints, current price, input contract, output fields, and payment metadata. |
| OpenAPI | Full request/response schemas and documented HTTP behavior. |
| Pricing | Current per-request prices. |
| Health | Current service runtime state. |
Production onboarding
Start with one canonical discovery URL. The programs below select a named service from that response, preserve the exact request through the payment retry, and print structured output.
End-to-end / live metadata, no payment executed here
SEARCH: discovery to structured result
{"query":"latest public developments in battery storage"}eip155:8453 · exact requirement in PAYMENT-REQUIREDsame method + endpoint + bodysources[] · generated_atTypeScript / Node
Demo-only flow: this uses a clearly labeled local test payment with no wallet, network, or real funds.
const metadataUrl = "https://402agent.ai/agent402/api/v1/services";
const desiredService = (process.env.AGENT402_SERVICE ?? "search").toLowerCase();
const metadata = await fetch(metadataUrl).then((response) => response.json());
const target = metadata.services.find((item: { service: string }) =>
item.service === desiredService,
);
if (!target) throw new Error(`Unknown Agent402 service: ${desiredService}`);
const inputs: Record<string, Record<string, string>> = {
search: { query: "latest public developments in battery storage" },
read: { url: "https://example.com/public-source" },
verify: { claim: "The James Webb Space Telescope launched in December 2021." },
};
const body = JSON.stringify(inputs[target.service]);
const request = {
method: target.method,
headers: {
"Content-Type": "application/json",
"X-Agent402-Client": "quickstart-typescript",
},
body,
};
// Demo mode still returns HTTP 402. It then issues a clearly labeled local
// test payment; no wallet, network, or real funds are used.
const quote = await fetch(target.url, request);
if (quote.status !== 402) throw new Error(`Expected HTTP 402, got ${quote.status}`);
const requirement = await quote.json();
const testPaymentUrl = metadata.endpoints.test_payment;
if (!testPaymentUrl) throw new Error("Test payment endpoint unavailable");
const payment = await fetch(testPaymentUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ transaction_id: requirement.transaction_id }),
}).then((response) => response.json());
const response = await fetch(target.url, {
...request,
headers: {
...request.headers,
[metadata.payment.payment_header]: payment.x_payment_header,
},
});
if (!response.ok) throw new Error(`Agent402 returned HTTP ${response.status}`);
console.log(JSON.stringify(await response.json(), null, 2));
Python / httpx
Demo-only flow: it receives the mock HTTP 402, mints a local test payment, and retries the unchanged request.
# pip install httpx
import asyncio
import json
import os
import httpx
METADATA_URL = "https://402agent.ai/agent402/api/v1/services"
INPUTS = {
"search": {"query": "latest public developments in battery storage"},
"read": {"url": "https://example.com/public-source"},
"verify": {"claim": "The James Webb Space Telescope launched in December 2021."},
}
async def main():
async with httpx.AsyncClient(timeout=30) as http:
metadata = (await http.get(METADATA_URL)).json()
desired_service = os.getenv("AGENT402_SERVICE", "search").lower()
target = next(
(item for item in metadata["services"] if item["service"] == desired_service),
None,
)
if target is None or desired_service not in INPUTS:
raise ValueError(f"Unknown Agent402 service: {desired_service}")
headers = {
"Content-Type": "application/json",
"X-Agent402-Client": "quickstart-python",
}
quote = await http.request(
target["method"], target["url"], json=INPUTS[desired_service], headers=headers
)
if quote.status_code != 402:
raise RuntimeError(f"Expected HTTP 402, got {quote.status_code}")
payment_url = metadata["endpoints"]["test_payment"]
if not payment_url:
raise RuntimeError("Test payment endpoint unavailable")
payment = await http.post(
payment_url, json={"transaction_id": quote.json()["transaction_id"]}
)
payment.raise_for_status()
headers[metadata["payment"]["payment_header"]] = payment.json()["x_payment_header"]
response = await http.request(
target["method"], target["url"], json=INPUTS[desired_service], headers=headers
)
response.raise_for_status()
print(json.dumps(response.json(), indent=2))
if __name__ == "__main__":
asyncio.run(main())
Privacy-preserving usage attribution
Optional and coarse by design. The examples send one of two fixed integration categories in
X-Agent402-Client. Attribution analytics only aggregate that category with the public payment surface and service; they do not retain IP addresses, user agents, cookies, browser fingerprints, or identities.Available services
SEARCH
POST https://402agent.ai/agent402/api/v1/search
Request contract / canonical metadata
- query: string (1-2000 chars)
Response fields / canonical metadata
- results[] (title, url, snippet, source_tier)
- sources[]
- generated_at
READ
POST https://402agent.ai/agent402/api/v1/read
Request contract / canonical metadata
- url: string (http/https URL)
Response fields / canonical metadata
- title
- summary
- key_points[]
- extracted_facts[]
- source_url
VERIFY
POST https://402agent.ai/agent402/api/v1/verify
Request contract / canonical metadata
- claim: string (1-4000 chars)
Response fields / canonical metadata
- verdict (VERIFIED | NOT_VERIFIED | INSUFFICIENT_EVIDENCE | CONFLICTING_EVIDENCE)
- confidence (0-1)
- supporting_evidence[]
- contradictory_evidence[]
- sources[]
Payment flow
- Read service metadata and choose a resource.
- Send the canonical request body without the configured payment signature header.
- Use the HTTP 402 response to obtain the exact current payment requirement.
- Authorize the requirement with an x402-compatible client and retry the identical request.