Discovery Spec

Build once, register reliably, and keep your AgentCash resources discoverable.

Why This Matters

If agents can't discover your API, they can't call it. Bulletproof discovery turns your endpoint from merely listed to reliably invocable.

When metadata and runtime 402 behavior agree, agents succeed on the first pass. You get fewer AgentCash failures, less debugging churn, and more real agent traffic.

  • Publish OpenAPI as the canonical machine-readable contract.
  • Treat runtime 402 challenge behavior as the final source of truth.

Copy for Agents

Paste this directly into your coding agent. It should handle discovery implementation and validation end-to-end.

Implement AgentCash discovery for this server and make it pass.

Discovery strategy:
Your api should expose an OpenAPI document at /openapi.json, which abides by the OpenAPI specification,
with several additional fields required for AgentCash discovery.
You can use the @agentcash/discovery package to validate your OpenAPI document.

Validation commands:
npx -y @agentcash/discovery@latest discover "$TARGET_URL"
npx -y @agentcash/discovery@latest check "$TARGET_URL"


This will yield warnings regarding the discovery document and how it can be improved.

Schema guidance (important):
- Each invocable route should expose an input schema.
- In OpenAPI, define requestBody.content["application/json"].schema.
- This is required for reliable agent invocation and robust listing behavior.
- Add high-level guidance in info.x-guidance for agent-friendly discovery. This document should explain to an agent how to use your API at a high level.

OpenAPI payable operation must include ALL:
- x-payment-info with:
  - protocols: array of protocol objects, e.g. [{ "x402": {} }, { "mpp": { "method": "", "intent": "", "currency": "" } }]
  - price object with mode, currency, and pricing fields:
    - fixed: { price: { mode: "fixed", currency: "USD", amount: "<amount>" } }
    - dynamic: { price: { mode: "dynamic", currency: "USD", min: "<min>", max: "<max>" } }
    Legacy flat format still works: { pricingMode: "fixed", price: "<amount>" }
  - IMPORTANT: for fixed pricing use "amount" in the price object (not "value")
- responses: { "402": { description: "Payment Required" } }

Identity-only (authed) endpoints:
For x402: declare a security scheme named "siwx" in components.securitySchemes and reference it on each identity-gated operation: security: [{ "siwx": [] }]. Do NOT add x-payment-info to SIWX-only routes — that classifies them as paid.
For MPP: set the price amount to "0" — the client signs the Challenge to prove key ownership without any funds transfer. See https://mpp.dev/advanced/identity for details.

Minimal valid example:
{
  "openapi": "3.1.0",
  "info": {
    "title": "My API",
    "version": "1.0.0",
    "description": "example demo server",
    "x-guidance": "Use POST /api/search for neural web search. Accepts a JSON body with a 'query' field."
  },
  "x-discovery": {
    "ownershipProofs": ["<proof-1>"]
  },
  "paths": {
    "/api/search": {
      "post": {
        "operationId": "search",
        "summary": "Search - Neural search across the web",
        "tags": ["Search"],
        "x-payment-info": {
          "price": { "mode": "fixed", "currency": "USD", "amount": "0.010000" },
          "protocols": [{ "x402": {} }, { "mpp": { "method": "", "intent": "", "currency": "" } }]
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "query": { "type": "string", "minLength": 1, "description": "The query string for the search" }
                },
                "required": ["query"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": { "type": "array", "items": { "type": "object" } }
                  },
                  "required": ["results"]
                }
              }
            }
          },
          "402": { "description": "Payment Required" }
        }
      }
    }
  }
}


Workflow:
1) Validate your OpenAPI document with the @agentcash/discovery package.
2) Fix your OpenAPI document until it passes validation.
3) Register your server on MppScan or X402Scan once it passes validation.

Discovery Strategy

OpenAPI is the canonical discovery format. Use it for the cleanest machine-readable contract and best agent compatibility.

The x-payment-info fields are a superset of the IETF API payment spec. The fields do not collide — if you already follow the IETF standard, your service is still compatible and you can define both without conflict.

OpenAPI Implementation

Use this first. It gives the cleanest machine-readable contract and best tooling compatibility.

Expected location: GET /openapi.json

  • Top-level fields: openapi, info.title, info.x-guidance, info.version, paths.
  • For paid operations: responses.402 and x-payment-info.
  • Set x-payment-info.protocols (array of protocol objects) and one pricing mode (fixed or dynamic) with currency.
  • Use OpenAPI security + components.securitySchemes for auth declaration.
  • For identity-only (authed) endpoints, use SIWX for x402 (declare a "siwx" security scheme, no x-payment-info) or zero-dollar auth for MPP (set price amount to "0"). See https://mpp.dev/advanced/identity for details.
  • Add high-level guidance in info.x-guidance for user-friendly discovery.
{
  "openapi": "3.1.0",
  "info": {
    "title": "My API",
    "version": "1.0.0",
    "description": "example demo server",
    "x-guidance": "Use POST /api/search for neural web search. Accepts a JSON body with a 'query' field."
  },
  "x-discovery": {
    "ownershipProofs": ["<proof-1>"]
  },
  "paths": {
    "/api/search": {
      "post": {
        "operationId": "search",
        "summary": "Search - Neural search across the web",
        "tags": ["Search"],
        "x-payment-info": {
          "price": { "mode": "fixed", "currency": "USD", "amount": "0.010000" },
          "protocols": [{ "x402": {} }, { "mpp": { "method": "", "intent": "", "currency": "" } }]
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "query": { "type": "string", "minLength": 1, "description": "The query string for the search" }
                },
                "required": ["query"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "results": { "type": "array", "items": { "type": "object" } }
                  },
                  "required": ["results"]
                }
              }
            }
          },
          "402": { "description": "Payment Required" }
        }
      }
    }
  }
}

SIWX (Sign-In with X) Routes

Identity-gated routes require a wallet proof but no payment. Agents with an AgentCash wallet can call these for free.

  • x402: Declare a siwx security scheme in components.securitySchemes and reference it via security: [{ "siwx": [] }]. Do not add x-payment-info — that classifies the route as paid.
  • MPP: Set the price amount to "0" — the client signs the Challenge to prove key ownership without funds transfer. See mpp.dev/advanced/identity.
// x402 example — SIWX security scheme
{
  "components": {
    "securitySchemes": {
      "siwx": { "type": "apiKey", "in": "header", "name": "SIGN-IN-WITH-X" }
    }
  },
  "paths": {
    "/api/me": {
      "get": {
        "summary": "Get current user profile",
        "security": [{ "siwx": [] }],
        "responses": { "200": { "description": "OK" } }
      }
    }
  }
}

The scheme must be named siwx — discovery resolves it by name.

Discovery Precedence

X402Scan/MPPScan uses the OpenAPI document at /openapi.json to discover your API. It will also check the runtime 402 challenge behavior to ensure it is correct.

OrderSourceExpected Location
1OpenAPI document/openapi.json
2402 API ResponseCorrect 402 header response

Common Failure Reasons

These are the most frequent errors seen during registration.

ErrorLikely CauseFix
Not FoundOpenAPI not found at {origin}/openapi.jsonAdd a OpenAPI document at {origin}/openapi.json
Input/Output Schema MissingOperation has no input or output schemaAdd an input and output schema to the operation
No Payment Modes DetectedNo payment modes detected in the responseAdd a valid payment mode to the response (x402 or MPP)