{
  "openapi": "3.1.0",
  "info": {
    "title": "Testnet ETH Merchant",
    "version": "0.1.0",
    "description": "Buy Sepolia or Hoodi testnet ETH with Base or Solana mainnet USDC through x402. Testnet ETH has no monetary value.",
    "contact": { "url": "https://github.com/graykode/stallkeeper-testnet-eth-merchant" },
    "x-guidance": "Call a free quote route first, then call the matching buy route with an x402-capable client. The payer receives the testnet ETH unless recipient is supplied."
  },
  "servers": [
    { "url": "https://merchant-production-c224.up.railway.app" }
  ],
  "security": [],
  "paths": {
    "/v1/catalog": {
      "get": {
        "summary": "List products and limits",
        "security": [],
        "responses": { "200": { "description": "Catalog" } }
      }
    },
    "/v1/quote/{product}": {
      "get": {
        "summary": "Calculate a free quote",
        "security": [],
        "parameters": [
          { "name": "product", "in": "path", "required": true, "schema": { "type": "string", "enum": ["sepolia", "hoodi"] } },
          { "$ref": "#/components/parameters/Amount" },
          { "$ref": "#/components/parameters/Recipient" }
        ],
        "responses": {
          "200": { "description": "Quote" },
          "400": { "description": "Invalid amount or recipient" }
        }
      }
    },
    "/v1/buy/sepolia": {
      "get": {
        "summary": "Buy 1 to 100 Sepolia ETH with x402 USDC",
        "description": "Returns a Base and Solana USDC x402 challenge. Base buyers may use their payer address as the payout address; Solana buyers supply recipient.",
        "parameters": [
          { "$ref": "#/components/parameters/SepoliaAmount" },
          { "$ref": "#/components/parameters/Recipient" }
        ],
        "x-payment-info": {
          "protocols": [{ "x402": {} }],
          "price": { "mode": "dynamic", "currency": "USD", "min": "0.05", "max": "5.00" }
        },
        "responses": {
          "202": { "description": "Payment settled and order queued for payout" },
          "402": { "description": "x402 payment required" },
          "409": { "description": "Insufficient inventory" }
        }
      }
    },
    "/v1/buy/hoodi": {
      "get": {
        "summary": "Buy 2 to 400 Hoodi ETH with x402 USDC",
        "description": "Returns a Base and Solana USDC x402 challenge. Base buyers may use their payer address as the payout address; Solana buyers supply recipient.",
        "parameters": [
          { "$ref": "#/components/parameters/HoodiAmount" },
          { "$ref": "#/components/parameters/Recipient" }
        ],
        "x-payment-info": {
          "protocols": [{ "x402": {} }],
          "price": { "mode": "dynamic", "currency": "USD", "min": "0.05", "max": "10.00" }
        },
        "responses": {
          "202": { "description": "Payment settled and order queued for payout" },
          "402": { "description": "x402 payment required" },
          "409": { "description": "Insufficient inventory" }
        }
      }
    },
    "/v1/orders/{id}": {
      "get": {
        "summary": "Read order and payout status",
        "security": [],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }
        ],
        "responses": {
          "200": { "description": "Order" },
          "404": { "description": "Not found" }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "Amount": {
        "name": "amount",
        "in": "query",
        "description": "Whole testnet ETH amount. Defaults to the product minimum.",
        "schema": { "type": "string", "pattern": "^[1-9][0-9]*$" }
      },
      "SepoliaAmount": {
        "name": "amount",
        "in": "query",
        "description": "Whole Sepolia ETH amount. Defaults to 1.",
        "schema": { "type": "integer", "minimum": 1, "maximum": 100 }
      },
      "HoodiAmount": {
        "name": "amount",
        "in": "query",
        "description": "Whole Hoodi ETH amount. Defaults to 2.",
        "schema": { "type": "integer", "minimum": 2, "maximum": 400 }
      },
      "Recipient": {
        "name": "recipient",
        "in": "query",
        "description": "EVM payout address. Optional for Base payments and required for Solana payments.",
        "schema": { "type": "string", "pattern": "^0x[0-9a-fA-F]{40}$" }
      }
    }
  }
}
