{
  "openapi": "3.1.0",
  "info": {
    "title": "SwapEazi Routing API",
    "version": "1.1.0",
    "summary": "Cross-chain stablecoin routing — agent-callable, pay-per-use.",
    "description": "SwapEazi routes stablecoin swaps across 7 EVM chains + Tron / USDT-TRC20.\n\n## What makes this API different\n- Routes USDT (Tron) ↔ USDC (Base/Polygon) — the corridor Jumper Exchange and generic aggregators won't serve.\n- Single 0.5% all-in fee (gas + bridge + DEX + slippage included).\n- Pay per call via x402 ($0.02 USDC on Base) — no signup, no API key.\n- Optional HMAC API keys for higher-volume B2B integrations.\n- Wallet compliance screening on every swap.\n\n## How an AI agent uses it\n1. GET `/api/mpp/routes` — discover supported chains, tokens, corridors. Free.\n2. POST `/api/x402/quote` — get a free quote with estimated output, fees, timing.\n3. POST `/api/x402/swap` — pay $0.02 USDC via x402 `X-PAYMENT` header, receive an unsigned tx.\n4. Sign and broadcast the tx with the user's wallet.\n\nTron / USDT-TRC20 corridors require a TronLink-signed flow — direct end users to https://swapeazi.io/app for those. The agent-callable surface covers all EVM-to-EVM corridors.",
    "contact": { "name": "SwapEazi", "email": "hello@swapeazi.io", "url": "https://swapeazi.io/developers" },
    "license": { "name": "Commercial — see https://swapeazi.io/legal" },
    "x-logo": { "url": "https://swapeazi.io/logo.png", "altText": "SwapEazi" }
  },
  "servers": [{ "url": "https://swapeazi.io", "description": "Production" }],
  "externalDocs": {
    "description": "Developer portal — code examples, playground, key issuance",
    "url": "https://swapeazi.io/developers"
  },
  "tags": [
    { "name": "Discovery", "description": "Free endpoints for agents to learn what SwapEazi can route." },
    { "name": "Quote",     "description": "Free pricing — best route, output, fees, timing." },
    { "name": "Swap",      "description": "Paid — execute a routed swap. $0.02 per call via x402, or HMAC key." },
    { "name": "B2B",       "description": "Higher-volume HMAC-key routes for partners." }
  ],
  "paths": {
    "/api/mpp/routes": {
      "get": {
        "tags": ["Discovery"],
        "summary": "List supported chains, tokens, corridors, pricing",
        "operationId": "listRoutes",
        "responses": {
          "200": {
            "description": "Capability manifest",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RoutesManifest" } } }
          }
        }
      }
    },
    "/api/x402/quote": {
      "post": {
        "tags": ["Quote"],
        "summary": "Free quote — best route + estimated output",
        "operationId": "quoteX402",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteParams" } } }
        },
        "responses": {
          "200": { "description": "Quote returned",   "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteResult" } } } },
          "400": { "description": "Missing/invalid body" },
          "422": { "description": "Unsupported pair / no route" }
        }
      }
    },
    "/api/mpp/quote": {
      "post": {
        "tags": ["Quote"],
        "summary": "Alias of /api/x402/quote (MPP discovery path)",
        "operationId": "quoteMpp",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteParams" } } } },
        "responses": { "200": { "description": "Quote returned", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteResult" } } } } }
      }
    },
    "/api/x402/swap": {
      "post": {
        "tags": ["Swap"],
        "summary": "Execute a swap — paid via x402",
        "description": "Returns an unsigned transaction object the agent must sign + broadcast.\nFirst call without an `X-PAYMENT` header returns HTTP 402 with a payment challenge.\nPay $0.02 USDC on Base via x402, then retry with the signed payment payload as `X-PAYMENT`.",
        "operationId": "swapX402",
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "Base64url-encoded x402 payment payload (USDC on Base, $0.02). Omit on first call to receive the 402 challenge.",
            "schema": { "type": "string" }
          }
        ],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteParams" } } } },
        "responses": {
          "200": {
            "description": "Swap transaction returned",
            "content":     { "application/json": { "schema": { "$ref": "#/components/schemas/SwapResult" } } },
            "headers":     { "x-payment-response": { "schema": { "type": "string" }, "description": "Base64url settle receipt" } }
          },
          "402": { "description": "Payment required — body contains x402 challenge", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/X402Challenge" } } } },
          "422": { "description": "Unsupported pair / no route" }
        }
      }
    },
    "/api/mpp/swap": {
      "post": {
        "tags": ["Swap"],
        "summary": "Execute a swap — paid via x402 OR MPP/Tempo",
        "description": "Same handler as /api/x402/swap, also accepts MPP/Tempo (pathUSD) authorization headers for non-x402 agents.",
        "operationId": "swapMpp",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteParams" } } } },
        "responses": {
          "200": { "description": "Swap transaction returned", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SwapResult" } } } },
          "402": { "description": "Payment required" }
        }
      }
    },
    "/api/v1/health": {
      "get": {
        "tags": ["B2B"],
        "summary": "Health + EUR/ZAR rate",
        "operationId": "health",
        "responses": { "200": { "description": "Health payload" } }
      }
    },
    "/api/v1/corridors": {
      "get": {
        "tags": ["B2B"],
        "summary": "Live corridors with liquidity metadata",
        "operationId": "listCorridors",
        "responses": { "200": { "description": "Corridor list" } }
      }
    },
    "/api/v1/chains": {
      "get": {
        "tags": ["B2B"],
        "summary": "Supported networks + tokens",
        "operationId": "listChains",
        "responses": { "200": { "description": "Chain list" } }
      }
    },
    "/api/v1/quote": {
      "post": {
        "tags": ["B2B"],
        "summary": "Ranked quote (FASTEST/BALANCED/CHEAPEST)",
        "operationId": "quoteV1",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QuoteParams" } } } },
        "responses": { "200": { "description": "Three ranked routes returned" } }
      }
    },
    "/api/v1/swap": {
      "post": {
        "tags": ["B2B"],
        "summary": "Execute a quoted swap (HMAC key)",
        "operationId": "swapV1",
        "security": [{ "HmacApiKey": [] }],
        "responses": { "200": { "description": "Swap reference + status" }, "401": { "description": "Invalid key" } }
      }
    },
    "/api/v1/batch/disburse": {
      "post": {
        "tags": ["B2B"],
        "summary": "Batch disbursement (up to 50 recipients per call)",
        "operationId": "batchDisburse",
        "security": [{ "HmacApiKey": [] }],
        "responses": { "200": { "description": "Disbursement reference" }, "401": { "description": "Invalid key" } }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "HmacApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-swapeazi-key",
        "description": "Stateless HMAC-signed key. Issue one at https://swapeazi.io/developers (free, rate-limited)."
      },
      "X402Payment": {
        "type": "apiKey",
        "in": "header",
        "name": "X-PAYMENT",
        "description": "Base64url-encoded x402 payment payload. $0.02 USDC on Base. See https://docs.cdp.coinbase.com/x402"
      }
    },
    "schemas": {
      "QuoteParams": {
        "type": "object",
        "required": ["fromChain", "toChain", "fromToken", "toToken", "fromAmount", "fromAddress"],
        "properties": {
          "fromChain":   { "type": "string", "enum": ["ETH", "POL", "ARB", "OPT", "BAS", "BNB"], "description": "Source chain code" },
          "toChain":     { "type": "string", "enum": ["ETH", "POL", "ARB", "OPT", "BAS", "BNB"], "description": "Destination chain code" },
          "fromToken":   { "type": "string", "description": "Source token symbol (USDC, USDT, DAI, EURC, cKES, cNGN, ZARP, …)" },
          "toToken":     { "type": "string", "description": "Destination token symbol" },
          "fromAmount":  { "type": "string", "description": "Human-readable amount, e.g. \"100\"" },
          "fromAddress": { "type": "string", "description": "Sender wallet (0x…)" },
          "slippage":    { "type": "number", "default": 0.005, "description": "Max slippage tolerance (0.005 = 0.5%)" }
        }
      },
      "QuoteResult": {
        "type": "object",
        "properties": {
          "fromAmount":        { "type": "string" },
          "toAmount":          { "type": "string", "description": "Estimated output (after all fees)" },
          "toAmountMin":       { "type": "string", "description": "Minimum output after slippage" },
          "estimatedGasUSD":   { "type": "string" },
          "estimatedDuration": { "type": "number", "description": "Seconds" },
          "bridge":            { "type": "string", "description": "Bridge protocol used" },
          "tool":              { "type": "string", "description": "DEX or aggregator tool" },
          "quoteId":           { "type": "string", "description": "Use with /api/v1/swap" }
        }
      },
      "SwapResult": {
        "type": "object",
        "properties": {
          "transactionRequest": { "type": "object", "description": "Unsigned tx — sign + broadcast with the user's wallet" },
          "route":              { "type": "object", "description": "Route metadata (bridge, tool, fee breakdown)" },
          "swapEaziRef":        { "type": "string", "description": "swp_… reference for support" }
        }
      },
      "X402Challenge": {
        "type": "object",
        "properties": {
          "x402Version": { "type": "integer", "const": 1 },
          "accepts":     { "type": "array",   "items": { "$ref": "#/components/schemas/PaymentRequirement" } },
          "error":       { "type": "string" }
        }
      },
      "PaymentRequirement": {
        "type": "object",
        "properties": {
          "scheme":            { "type": "string", "const": "exact" },
          "network":           { "type": "string", "const": "base" },
          "maxAmountRequired": { "type": "string", "const": "20000", "description": "20000 atomic units = $0.02 USDC (6 decimals)" },
          "asset":             { "type": "string", "const": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "description": "USDC on Base" },
          "payTo":             { "type": "string", "description": "SwapEazi receiver wallet" },
          "resource":          { "type": "string" },
          "description":       { "type": "string" }
        }
      },
      "RoutesManifest": { "type": "object", "description": "See live response at /api/mpp/routes" }
    }
  }
}
