This spec defines how x402scan discovers and registers resources.
If you want reliable pickup, implement discovery in this order:
- OpenAPI-first (recommended)
/.well-known/x402(compatibility)- DNS
_x402TXT pointer (compatibility)
If you cannot expose discovery yet, endpoint-only manual registration still works.
Discovery precedence used by x402scan:
- OpenAPI (
/openapi.json, then/.well-known/openapi.json) /.well-known/x402- DNS
_x402TXT pointer
Runtime 402 behavior is authoritative over static metadata.
Supported URLs:
https://yourdomain.com/openapi.jsonhttps://yourdomain.com/.well-known/openapi.json
openapi(string)info.title(string)info.version(string)paths(object)
For each paid operation:
- declare
x-payment-info - include a
402response inresponses - include
x-payment-info.protocols(for example"x402") - include valid pricing metadata:
pricingMode: "fixed"+price- or
pricingMode: "range"+minPrice+maxPrice - or
pricingMode: "quote"
Use OpenAPI security + components.securitySchemes.
Legacy x-agentcash-auth.mode is accepted as a migration fallback, but is not recommended for new integrations.
Use x-discovery:
{
"x-discovery": {
"ownershipProofs": ["0x..."],
"llmsTxtUrl": "https://yourdomain.com/llms.txt"
}
}Endpoint:
GET https://yourdomain.com/.well-known/x402
Minimal payload:
{
"version": 1,
"resources": [
"https://yourdomain.com/api/route-1",
"https://yourdomain.com/api/route-2"
]
}Optional fields:
{
"version": 1,
"resources": ["https://yourdomain.com/api/route-1"],
"ownershipProofs": ["0x..."],
"instructions": "Optional legacy guidance"
}Example TXT record:
_x402.yourdomain.com TXT "v=x4021;url=https://yourdomain.com/.well-known/x402"
Notes:
- DNS is compatibility-only; do not prefer it over OpenAPI.
- Keep payload URL stable and cache-friendly.
Use this when discovery docs are not available yet.
A route is registerable when probing returns 402 with a parseable x402 challenge.
Accepted challenge transport:
Payment-Requiredheader (x402 v2), or- JSON response body (legacy compatibility)
For payable indexing in x402scan, challenge data should include:
- non-empty
accepts - Bazaar-style input schema (
extensions.bazaar.info+ schema-derived input)
Compatibility behavior:
402+accepts: []+extensions["sign-in-with-x"]=> SIWX auth-only, markedskipped.- Missing input schema => strict non-invocable, marked
skipped.
llms.txt is optional and unstructured.
Use it for concise cross-route human/agent guidance. Keep machine-parseable contract data in OpenAPI.
Accepted locations:
- OpenAPI
x-discovery.ownershipProofs(preferred) /.well-known/x402ownershipProofs(compatibility)
When a user clicks Add Server:
- Run discovery with precedence above.
- Probe discovered URLs with method-aware fallback.
- Parse x402 challenge.
- Register valid routes.
- Mark non-conformant routes as failed/skipped with explicit reasons.
When a user clicks Register This URL Only:
- Skip fan-out.
- Register only that endpoint.
- Useful for partial rollouts and rate-limited providers.
Expected 402, got 404/405/429parseResponse: Accepts must contain at least one valid payment requirementparseResponse: Missing input schema- discovery fetch/parse failures for OpenAPI or
/.well-known/x402
429 responses are upstream provider limits, not generated by x402scan.
Full discovery audit:
npx -y @agentcash/discovery yourdomain.com -vSingle endpoint probe:
curl -i -X POST https://yourdomain.com/api/route
curl -i -X GET https://yourdomain.com/api/route- Ensure routes return valid x402 challenges (
402, parseable, non-emptyacceptsfor payable routes). - Add OpenAPI discovery +
x-payment-info+ security declarations. - Keep
/.well-known/x402+ DNS compat during migration. - Remove compat paths when your consumers no longer depend on them.