Listing quickstart

x402 service listing quickstart

Use this when you run an x402-paid endpoint and you want agents to discover it with point-in-time evidence. Ontario listings are evidence-backed (readiness reports + integrity + history), not permanent safety guarantees. Agents should still run a fresh preflight policy check before spending.

Trust boundary

This workflow never asks for private keys or seed phrases. Treat listing + readiness as public evidence; do not submit raw wallet credentials, sensitive customer data, or secrets in listing metadata.

Step 1 — Generate a public readiness report

UI: /verify. API: POST /api/verify/x402-readiness. You will use the returned report_id as your proof link while iterating.

curl -X POST https://ontarioprotocol.com/api/verify/x402-readiness \
  -H "Content-Type: application/json" \
  -d '{"target_url":"https://example.com/api/paid-endpoint"}'

Step 2 — Reach grade=ready before you expect /discover inclusion

Challenge behavior

Unpaid requests should fail closed (HTTP 402 with x402 metadata), not leak paid content.

Manifest + schema

Publish /.well-known/x402.json and an OpenAPI document agents can parse.

Stable metadata

Use a consistent endpoint URL, method, price, network, and owner fields.

Repeatability

Rerun verification after fixes to create a fresh public report ID.

Practical checklist: /proof/x402-discovery-listing-checklist.

Step 3 — Prepare listing JSON (validate locally and via API)

Ontario exposes the canonical payload contract as a strict JSON Schema: /.well-known/x402-list-service.schema.json. Use the free validator endpoint before you run the paid listing call.

{
  "name": "Example Service",
  "description": "Paid endpoint for agents",
  "category": "data",
  "endpoint": "https://example.com/api/paid",
  "method": "POST",
  "price_usdc": "0.01",
  "network": "base",
  "owner_url": "https://example.com",
  "owner_contact": "ops@example.com",
  "tags": ["x402", "ai-agent"]
}
curl -sS https://ontarioprotocol.com/api/x402/list-service/validate \
  -H "Content-Type: application/json" \
  -d '{"name":"Example Service","description":"Paid endpoint for agents","endpoint":"https://example.com/api/paid","method":"POST","price_usdc":"0.01","network":"base","owner_url":"https://example.com"}' | jq .

Step 4 — Rehearse the x402 listing flow in sandbox (no spend, no storage)

Use the sandbox rehearsal endpoint to test client behavior end-to-end. It still challenges with HTTP 402 on the first request, but settlement is simulated and the listing is not stored.

# 1) Probe: expect HTTP 402 + PAYMENT-REQUIRED (no listing stored yet)
curl -i -X POST https://ontarioprotocol.com/sandbox/api/x402/list-service \
  -H "Content-Type: application/json" \
  -d '{"name":"Example Service","description":"Paid endpoint for agents","endpoint":"https://example.com/api/paid","method":"POST","price_usdc":"0.01","network":"base","owner_url":"https://example.com"}'

The sandbox will accept any non-empty payload.signature field as “valid” to let you test client retry logic. This is not a production x402 payment signature.

# 2) Retry with a simulated sandbox PAYMENT-SIGNATURE header (no keys; sandbox-only)
SIG="$(python3 - <<'PY'
import base64, json
payload = {
  "x402Version": 1,
  "scheme": "exact",
  "network": "base-sandbox",
  "payload": {
    "signature": "sandbox-valid",
    "authorization": {"from": "0xSandboxAgent"}
  }
}
print(base64.b64encode(json.dumps(payload, separators=(",", ":"), sort_keys=True).encode("utf-8")).decode("ascii"))
PY
)"

curl -sS -X POST https://ontarioprotocol.com/sandbox/api/x402/list-service \
  -H "Content-Type: application/json" \
  -H "PAYMENT-SIGNATURE: ${SIG}" \
  -d '{"name":"Example Service","description":"Paid endpoint for agents","endpoint":"https://example.com/api/paid","method":"POST","price_usdc":"0.01","network":"base","owner_url":"https://example.com"}' | jq .

Sandbox tutorial: /docs/agent-commerce-sandbox.

SDK examples: ontario_list_service.py · ontario-list-service.ts

Step 5 — Submit the paid listing (production)

The first request should return HTTP 402 (no listing stored yet). Then pay + retry using your x402 client against POST /api/x402/list-service. If the stored readiness report grades ready, the endpoint can become eligible for /discover's default filters.

curl -i -X POST https://ontarioprotocol.com/api/x402/list-service \
  -H "Content-Type: application/json" \
  -d '{"name":"Example Service","description":"Paid endpoint for agents","endpoint":"https://example.com/api/paid","method":"POST","price_usdc":"0.01","network":"base","owner_url":"https://example.com"}'

After submission, check /listings and filter-ready discovery via /discover?grade=ready.

Next

Agents should treat the listing as a pointer to evidence, not a permission slip. Use POST /api/agent/can-pay with strict policy, explicit budget, and review rules before any wallet signs a payment payload.