{
  "openapi": "3.1.0",
  "info": {
    "title": "Robyn AnyGas API",
    "version": "3.1.0",
    "summary": "Gasless, cross-chain relay for AI agents.",
    "description": "Move value across 22 EVM chains, Stellar, Solana and native Bitcoin with one signed intent and no native gas. A relayer fronts the gas and is repaid from the token being moved. Read endpoints need no credentials; execution takes a Permit2 / EIP-712 signature. Add the header `x-anygas-sandbox: 1` to POST /api/route/execute to simulate the whole lifecycle with zero funds. Base URL is https://api.anygas.xyz/svc (the gateway strips the /svc prefix). Also available as an MCP server (npx anygas-mcp) and a hosted MCP endpoint (https://api.anygas.xyz/mcp). Client SDKs are MIT-licensed; the hosted relayer, routing service and contracts are proprietary.",
    "contact": { "name": "Robyn AnyGas", "url": "https://anygas.xyz" },
    "license": { "name": "Service terms", "url": "https://anygas.xyz/svc/api/terms" }
  },
  "servers": [{ "url": "https://api.anygas.xyz/svc", "description": "Production gateway (also https://anygas.xyz/svc)" }],
  "tags": [
    { "name": "discovery", "description": "Health, mesh and gasless config" },
    { "name": "routing", "description": "Quote and execute gasless cross-chain routes" },
    { "name": "best-execution", "description": "Multi-rail comparator and goal-based intent solver (read-only)" },
    { "name": "explorer", "description": "Anonymized recent-routes feed" },
    { "name": "primitives", "description": "Batch / schedule / conditional route primitives (gated, dry-run by default)" },
    { "name": "keys-hooks", "description": "Optional developer keys and completion webhooks" },
    { "name": "concierge", "description": "AI concierge and terms" }
  ],
  "components": {
    "parameters": {
      "SandboxHeader": {
        "name": "x-anygas-sandbox",
        "in": "header",
        "required": false,
        "description": "Set to \"1\" to simulate the full execute lifecycle with zero funds — no signature, no relayer spend, nothing on-chain. Returns an sbx_ id that progresses BRIDGING -> DONE in ~40s.",
        "schema": { "type": "string", "enum": ["1"] }
      },
      "ApiKeyHeader": {
        "name": "x-anygas-key",
        "in": "header",
        "required": false,
        "description": "Optional API key (ak_…). Never required for reads; only tags requests for usage visibility.",
        "schema": { "type": "string" }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": { "error": { "type": "string", "example": "rate limited" } }
      },
      "Status": {
        "type": "object",
        "properties": {
          "status": { "type": "string", "enum": ["operational", "degraded", "down", "unknown"], "example": "operational" },
          "ts": { "type": "integer", "example": 1784012730722 },
          "nodes": {
            "type": "object",
            "properties": {
              "up": { "type": "integer", "example": 25 },
              "total": { "type": "integer", "example": 25 },
              "evm": { "type": "array", "items": { "type": "object", "properties": { "chainId": { "type": "integer" }, "name": { "type": "string" }, "up": { "type": "boolean" } } } },
              "nonEvm": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "up": { "type": "boolean" } } } }
            }
          },
          "rails": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "up": { "type": "boolean" } } } },
          "routes": { "type": "integer", "nullable": true, "example": 500 },
          "endpoints": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "up": { "type": "boolean" } } } }
        }
      },
      "Mesh": {
        "type": "object",
        "properties": {
          "nodes": { "type": "integer", "example": 25 },
          "chains": { "type": "array", "items": { "type": "integer" }, "description": "EVM chain ids", "example": [1, 10, 56, 100, 130, 137, 146, 480, 999, 1135, 1868, 4663, 5000, 8453, 33139, 34443, 42161, 43114, 57073, 59144, 81457, 7777777] },
          "routableNonEvm": { "type": "array", "items": { "type": "string" }, "example": ["stellar", "solana", "bitcoin"] },
          "directedRoutes": { "type": "integer", "example": 500 },
          "relayer": { "type": "string", "description": "Permit2 spender the SDK signs for", "example": "0x1253D25A0B6a757CfD65CDf441E2d91DBeCeE6c5" },
          "permit2": { "type": "string", "example": "0x000000000022D473030F116dDEE9F6B43aC78BA3" },
          "engine": { "type": "string", "example": "LI.FI aggregation (Across / Gas.zip / Near / Squid / Symbiosis / Relay + ~15 bridges); Stellar + Solana via Allbridge Core; Bitcoin via Chainflip" },
          "nonEvmNodes": { "type": "object", "additionalProperties": true, "description": "Per-node metadata; quote-only nodes carry executeReady:false" },
          "comparatorQuoteOnly": { "type": "object", "additionalProperties": true, "description": "Scroll, extra Chainflip asset lanes and Sui — quotable but NOT execute-ready" }
        },
        "additionalProperties": true
      },
      "GaslessInfo": {
        "type": "object",
        "properties": {
          "service": { "type": "string", "example": "Robyn Gasless Pay" },
          "router": { "type": "string", "example": "0x8f4a466435264A2D56Bc80e6749Ea351d567D141" },
          "anyGasRouter": { "type": "string", "example": "0x298ab4Be2B3a8f1A2dB3650f578407AA1f952487" },
          "tokenPaymaster": { "type": "string", "example": "0x4afc3DD9143bC75fCfFDA52e9E5e50dA4Cb3A635" },
          "permit2": { "type": "string", "example": "0x000000000022D473030F116dDEE9F6B43aC78BA3" },
          "entryPoint": { "type": "string", "example": "0x0000000071727De22E5E9d8BAf0edAc6f37da032" },
          "chainId": { "type": "integer", "example": 4663 },
          "routes": { "type": "array", "items": { "type": "string" }, "example": ["direct", "cheapest", "fastest"] },
          "recommended": { "type": "string", "example": "direct" },
          "gaslessChains": { "type": "object", "additionalProperties": true, "description": "Per-chain deployment map keyed by chain id" },
          "acceptedTokens": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "domain": { "type": "object", "additionalProperties": true, "description": "EIP-712 domain" }
        },
        "additionalProperties": true
      },
      "RouteRequest": {
        "type": "object",
        "required": ["fromChain", "toChain", "amount"],
        "properties": {
          "fromChain": { "description": "Source node: EVM chain id or one of \"solana\"/\"stellar\"/\"bitcoin\".", "oneOf": [{ "type": "string" }, { "type": "integer" }], "example": 42161 },
          "toChain": { "description": "Destination node.", "oneOf": [{ "type": "string" }, { "type": "integer" }], "example": "bitcoin" },
          "amount": { "type": "string", "description": "Source-token smallest units.", "example": "50000000" },
          "fromToken": { "type": "string", "description": "Symbol or address; omit for native.", "example": "USDC" },
          "toToken": { "type": "string", "description": "Symbol or address; omit for native.", "example": "BTC" },
          "toAddress": { "type": "string", "description": "Recipient; defaults to fromAddress." },
          "fromAddress": { "type": "string", "description": "Quote origin; anonymous default used if omitted." },
          "slippage": { "type": "number", "description": "Fraction, e.g. 0.005." }
        }
      },
      "Quote": {
        "type": "object",
        "description": "Single-intent quote. Non-EVM legs return a dedicated shape (shown); EVM<->EVM lanes return best-of-N fields (bridge, bestOf, compared[]).",
        "properties": {
          "gasless": { "type": "boolean", "example": true },
          "from": { "type": "object", "properties": { "chain": {}, "token": { "type": "string" }, "amount": { "type": "string" } }, "example": { "chain": 42161, "token": "USDC", "amount": "50000000" } },
          "to": { "type": "object", "additionalProperties": true, "example": { "chain": "bitcoin", "token": "BTC", "estimated": "78660", "min": "76693", "recipient": "bc1q…" } },
          "bridge": { "type": "string", "example": "chainflip" },
          "via": { "type": "array", "items": { "type": "string" }, "example": ["Chainflip (REGULAR)"] },
          "bestOf": { "type": "integer", "description": "EVM<->EVM: number of aggregators compared", "example": 3 },
          "compared": { "type": "array", "items": { "type": "object", "additionalProperties": true }, "description": "EVM<->EVM: per-aggregator outputs" },
          "durationSec": { "type": "number", "example": 408 },
          "robynRouteFeeBps": { "type": "integer", "example": 25 },
          "robynRouteFee": { "type": "string", "example": "125000" },
          "note": { "type": "string" }
        },
        "additionalProperties": true
      },
      "ExecuteRequest": {
        "type": "object",
        "required": ["fromChain", "toChain", "amount"],
        "properties": {
          "fromChain": { "oneOf": [{ "type": "string" }, { "type": "integer" }], "example": 42161 },
          "toChain": { "oneOf": [{ "type": "string" }, { "type": "integer" }], "example": 8453 },
          "amount": { "type": "string", "description": "Smallest units.", "example": "5000000" },
          "fromToken": { "type": "string", "example": "USDC" },
          "toToken": { "type": "string", "example": "USDC" },
          "toAddress": { "type": "string", "example": "0x8EdE0eEb8C03a45886836A1baDec03CdB08cDFb2" },
          "mode": { "type": "string", "enum": ["self", "permit2"], "default": "self", "description": "\"permit2\" = user-signed off-chain pull; \"self\" = operator moves own funds." },
          "permit2": { "type": "object", "description": "Required when mode=permit2: { owner, permitted:{token,amount}, nonce, deadline, signature }.", "additionalProperties": true }
        }
      },
      "RouteReceipt": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "rt_1a2b3c4d5e6f" },
          "status": { "type": "string", "description": "BRIDGING | DONE | FAILED (plus FUNDS_REQUIRED / AWAITING_DEPOSIT for unfunded non-EVM lanes)", "example": "BRIDGING" },
          "gasless": { "type": "boolean", "example": true },
          "sandbox": { "type": "boolean", "example": false },
          "bridge": { "type": "string", "example": "across" },
          "aggregator": { "type": "string", "example": "lifi" },
          "robynFee": { "type": "string", "example": "12500" },
          "bridged": { "type": "string", "example": "4987500" },
          "from": { "type": "object", "additionalProperties": true },
          "to": { "type": "object", "additionalProperties": true },
          "srcTx": { "type": "string", "nullable": true },
          "destTx": { "type": "string", "nullable": true },
          "stage": { "type": "string", "example": "RECEIVING" },
          "elapsedSec": { "type": "number" },
          "track": { "type": "string", "example": "/api/route/status?id=rt_1a2b3c4d5e6f" }
        },
        "additionalProperties": true
      },
      "CompareResult": {
        "type": "object",
        "properties": {
          "lane": { "type": "object", "properties": { "fromChain": { "type": "string" }, "toChain": { "type": "string" }, "applicableRails": { "type": "array", "items": { "type": "string" } }, "estOutUnit": { "type": "string" } } },
          "quotes": { "type": "array", "items": {
            "type": "object",
            "properties": {
              "rail": { "type": "string" },
              "ok": { "type": "boolean" },
              "estOut": { "type": "string" },
              "etaSeconds": { "type": "number" },
              "best": { "type": "boolean" },
              "effectiveFeePct": { "type": "number" },
              "qualityScore": { "type": "integer" }
            },
            "additionalProperties": true
          } },
          "best": { "type": "string", "example": "allbridge" },
          "comparedRails": { "type": "integer", "example": 2 },
          "railsAttempted": { "type": "integer", "example": 2 },
          "guard": { "type": "object", "properties": { "ok": { "type": "boolean" }, "effectiveFeePct": { "type": "number" }, "thresholdPct": { "type": "number" }, "recommendedMinInput": { "type": "string" } } },
          "cached": { "type": "boolean", "example": false }
        },
        "additionalProperties": true
      },
      "IntentRequest": {
        "type": "object",
        "required": ["toChain", "toToken", "from"],
        "properties": {
          "toChain": { "oneOf": [{ "type": "string" }, { "type": "integer" }], "example": 8453 },
          "toToken": { "type": "string", "example": "USDC" },
          "from": { "type": "array", "description": "1–10 candidate sources.", "items": { "type": "object", "properties": { "chain": {}, "token": { "type": "string" }, "amount": { "type": "string" } } }, "example": [{ "chain": 42161, "token": "USDC", "amount": "5000000" }, { "chain": 10, "token": "USDC", "amount": "5000000" }] },
          "goal": { "type": "string", "enum": ["max-output", "cheapest", "fastest"], "default": "max-output" },
          "amount": { "type": "string", "description": "Shared amount if sources omit their own." },
          "toAddress": { "type": "string", "description": "Recipient, echoed into plan.execute." }
        }
      },
      "IntentPlan": {
        "type": "object",
        "properties": {
          "goal": { "type": "string", "example": "max-output" },
          "to": { "type": "object", "properties": { "chain": {}, "token": { "type": "string" } } },
          "plan": {
            "type": "object",
            "nullable": true,
            "description": "Winner (null if nothing quoted). plan.execute is ready to POST to /api/route/execute.",
            "properties": {
              "from": { "type": "object", "additionalProperties": true },
              "rail": { "type": "string" },
              "estOut": { "type": "string" },
              "qualityScore": { "type": "integer" },
              "execute": { "type": "object", "additionalProperties": true }
            },
            "additionalProperties": true
          },
          "alternatives": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "skipped": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "sourcesConsidered": { "type": "integer", "example": 2 },
          "note": { "type": "string" }
        },
        "additionalProperties": true
      },
      "RecentRoutes": {
        "type": "object",
        "properties": {
          "routes": { "type": "array", "items": {
            "type": "object",
            "properties": {
              "lane": { "type": "string", "example": "Arbitrum → Bitcoin" },
              "asset": { "type": "string", "example": "USDC → BTC" },
              "rail": { "type": "string", "example": "Chainflip" },
              "status": { "type": "string", "example": "pending" },
              "when": { "type": "string", "example": "4h ago" },
              "size": { "type": "string", "example": "small" },
              "sandbox": { "type": "boolean", "example": false }
            }
          } },
          "count": { "type": "integer", "example": 2 },
          "note": { "type": "string" }
        }
      },
      "BatchRequest": {
        "type": "object",
        "required": ["routes"],
        "properties": {
          "routes": { "type": "array", "description": "Up to 20 legs; toAddress required per leg.", "items": { "type": "object", "properties": { "fromChain": {}, "fromToken": { "type": "string" }, "toChain": {}, "toToken": { "type": "string" }, "amount": { "type": "string" }, "toAddress": { "type": "string" } } } },
          "live": { "type": "boolean", "default": false, "description": "Ignored unless the watcher runs with PRIMITIVES_LIVE=1." }
        }
      },
      "BatchResult": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "batch_086f0679dfac4a905d" },
          "status": { "type": "string", "example": "planned" },
          "live": { "type": "boolean", "example": false },
          "legs": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "warnings": { "type": "array", "items": { "type": "string" } },
          "note": { "type": "string" }
        },
        "additionalProperties": true
      },
      "ScheduleRequest": {
        "type": "object",
        "required": ["route"],
        "properties": {
          "route": { "type": "object", "additionalProperties": true, "description": "A single route object {fromChain,fromToken,toChain,toToken,amount,toAddress}." },
          "everySeconds": { "type": "integer", "minimum": 10, "description": "Omit for a one-shot." },
          "at": { "description": "Epoch or ISO time for a one-shot start.", "oneOf": [{ "type": "string" }, { "type": "integer" }] },
          "count": { "type": "integer", "minimum": 1, "maximum": 1000 },
          "live": { "type": "boolean", "default": false }
        }
      },
      "ScheduleResult": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "sched_cde9a12f1107fa3652" },
          "route": { "type": "object", "additionalProperties": true },
          "everySeconds": { "type": "integer", "example": 3600 },
          "remaining": { "type": "integer", "example": 24 },
          "count": { "type": "integer", "example": 24 },
          "live": { "type": "boolean", "example": false },
          "status": { "type": "string", "example": "active" },
          "runs": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "note": { "type": "string" }
        },
        "additionalProperties": true
      },
      "ConditionalRequest": {
        "type": "object",
        "required": ["route", "when"],
        "properties": {
          "route": { "type": "object", "additionalProperties": true },
          "when": {
            "type": "object",
            "required": ["type"],
            "properties": {
              "type": { "type": "string", "enum": ["priceAbove", "priceBelow", "timeAfter"] },
              "asset": { "type": "string", "description": "Required for price conditions, e.g. ETH/USD, BTC/USD, USDG/USD.", "example": "ETH/USD" },
              "value": { "description": "Numeric price for price conditions; epoch/ISO for timeAfter.", "oneOf": [{ "type": "number" }, { "type": "string" }], "example": 3000 }
            }
          },
          "live": { "type": "boolean", "default": false }
        }
      },
      "ConditionalResult": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "cond_3728705d2654926bc1" },
          "route": { "type": "object", "additionalProperties": true },
          "when": { "type": "object", "additionalProperties": true },
          "live": { "type": "boolean", "example": false },
          "status": { "type": "string", "example": "armed" },
          "runs": { "type": "array", "items": { "type": "object", "additionalProperties": true } },
          "note": { "type": "string" }
        },
        "additionalProperties": true
      },
      "PrimitiveCancelled": {
        "type": "object",
        "properties": { "id": { "type": "string" }, "status": { "type": "string", "example": "cancelled" } }
      },
      "KeyCreated": {
        "type": "object",
        "properties": {
          "key": { "type": "string", "example": "ak_9fa383a39ca3b33b74775e7d8f3d04c70b98057c" },
          "label": { "type": "string", "example": "docs-example" },
          "created": { "type": "integer", "example": 1784012809055 },
          "note": { "type": "string" }
        }
      },
      "KeyUsage": {
        "type": "object",
        "properties": {
          "key": { "type": "object", "properties": { "label": { "type": "string" }, "created": { "type": "integer" } } },
          "hour": { "type": "object", "properties": { "total": { "type": "integer" }, "errors": { "type": "integer" }, "topPaths": { "type": "array", "items": { "type": "object", "additionalProperties": true } } } },
          "day": { "type": "object", "properties": { "total": { "type": "integer" }, "errors": { "type": "integer" }, "topPaths": { "type": "array", "items": { "type": "object", "additionalProperties": true } } } },
          "recent": { "type": "array", "items": { "type": "object", "additionalProperties": true } }
        }
      },
      "HookRegistered": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "wh_1008e656e4d46f7aec" },
          "routeId": { "type": "string", "example": "rt_abc123" },
          "url": { "type": "string", "example": "https://example.com/webhook" },
          "status": { "type": "string", "example": "pending" },
          "note": { "type": "string" }
        }
      }
    }
  },
  "paths": {
    "/api/status": {
      "get": {
        "tags": ["discovery"],
        "summary": "Operational status",
        "description": "Sanitized public health: overall state, per-node up/down (22 EVM + Stellar/Solana/Bitcoin), bridge rails, endpoint probes and route count. Cached ~30s. Rate limit 60/min.",
        "operationId": "getStatus",
        "responses": { "200": { "description": "Status snapshot", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Status" } } } } }
      }
    },
    "/api/route/chains": {
      "get": {
        "tags": ["discovery"],
        "summary": "The gasless mesh / route graph",
        "description": "Supported chain ids, node/route counts, the Permit2 spender (relayer) your SDK signs for, the routing engine, and per-node metadata for the non-EVM legs. Source of truth for what is routable. No key required.",
        "operationId": "getMesh",
        "responses": { "200": { "description": "Mesh snapshot", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Mesh" } } } } }
      }
    },
    "/api/gasless/info": {
      "get": {
        "tags": ["discovery"],
        "summary": "Same-chain gasless config",
        "description": "Deployed router / anyGas / tokenPaymaster / Permit2 / EntryPoint addresses, the EIP-712 domain, the per-chain deployment map and accepted fee tokens. No key required.",
        "operationId": "gaslessInfo",
        "responses": { "200": { "description": "Config", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GaslessInfo" } } } } }
      }
    },
    "/api/route/quote": {
      "post": {
        "tags": ["routing"],
        "summary": "Quote a gasless route (POST only)",
        "description": "Best gasless route for a single intent. POST with a JSON body — there is NO GET form (GET returns 404). EVM<->EVM runs best-of-N over the bridge aggregators; a Stellar/Solana/Bitcoin side is dispatched to its dedicated leg. Rate limit 40/min.",
        "operationId": "quoteRoute",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RouteRequest" } } } },
        "responses": {
          "200": { "description": "Best route quote", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Quote" } } } },
          "404": { "description": "Wrong method (e.g. GET) or unroutable lane", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/api/route/execute": {
      "post": {
        "tags": ["routing"],
        "summary": "Execute a signed gasless route",
        "description": "Submit a route; the relayer fronts all gas, tries ranked routes in net-output order and fails over on error, then returns a route id to track. Use mode=permit2 for a user-signed off-chain pull. Add header x-anygas-sandbox: 1 for a zero-funds simulation. Rate limit 8/min.",
        "operationId": "executeRoute",
        "parameters": [{ "$ref": "#/components/parameters/SandboxHeader" }, { "$ref": "#/components/parameters/ApiKeyHeader" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ExecuteRequest" } } } },
        "responses": { "200": { "description": "Route accepted (or FUNDS_REQUIRED for an unfunded non-EVM lane)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RouteReceipt" } } } } }
      }
    },
    "/api/route/status": {
      "get": {
        "tags": ["routing"],
        "summary": "Track a route",
        "description": "Live ids (rt_…) are re-checked against the underlying bridge on each read; sandbox ids (sbx_…) advance on a timer. No key required.",
        "operationId": "routeStatus",
        "parameters": [{ "name": "id", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Route id from execute", "example": "sbx_611d3343c9b8a0edae" }],
        "responses": {
          "200": { "description": "Route status", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RouteReceipt" } } } },
          "404": { "description": "Unknown route id", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/api/route/compare": {
      "get": {
        "tags": ["best-execution"],
        "summary": "Compare every rail for a lane (query form)",
        "description": "Quotes every rail that can serve a lane (aggregators + Allbridge + Chainflip) in parallel, ranks by net destination output and flags the best. Read-only, nothing signed. Adds effectiveFeePct, qualityScore, guard and a 12s cached flag. Rate limit 30/min.",
        "operationId": "compareRoutesGet",
        "parameters": [
          { "name": "fromChain", "in": "query", "required": true, "schema": { "type": "string" }, "example": "42161" },
          { "name": "toChain", "in": "query", "required": true, "schema": { "type": "string" }, "example": "solana" },
          { "name": "fromToken", "in": "query", "required": false, "schema": { "type": "string" }, "example": "USDC" },
          { "name": "toToken", "in": "query", "required": false, "schema": { "type": "string" }, "example": "USDC" },
          { "name": "amount", "in": "query", "required": true, "schema": { "type": "string" }, "example": "50000000" },
          { "name": "toAddress", "in": "query", "required": false, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Ranked rails", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CompareResult" } } } } }
      },
      "post": {
        "tags": ["best-execution"],
        "summary": "Compare every rail for a lane (JSON body)",
        "description": "Same as the GET form; accepts the RouteRequest body. Read-only.",
        "operationId": "compareRoutesPost",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RouteRequest" } } } },
        "responses": { "200": { "description": "Ranked rails", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CompareResult" } } } } }
      }
    },
    "/api/intent/solve": {
      "post": {
        "tags": ["best-execution"],
        "summary": "Goal-based source picker (JSON body)",
        "description": "State a goal, a destination and 1–10 candidate funding sources; the solver reads /compare once per source and ranks them, returning a plan with ready-to-POST execute params. It NEVER executes. Rate limit 20/min.",
        "operationId": "solveIntentPost",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IntentRequest" } } } },
        "responses": { "200": { "description": "Ranked plan", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IntentPlan" } } } } }
      },
      "get": {
        "tags": ["best-execution"],
        "summary": "Goal-based source picker (query form)",
        "description": "Query-string form of intent/solve. Encode the sources as JSON in the `from` param.",
        "operationId": "solveIntentGet",
        "parameters": [
          { "name": "toChain", "in": "query", "required": true, "schema": { "type": "string" }, "example": "8453" },
          { "name": "toToken", "in": "query", "required": true, "schema": { "type": "string" }, "example": "USDC" },
          { "name": "from", "in": "query", "required": true, "schema": { "type": "string" }, "description": "JSON array of sources, url-encoded.", "example": "[{\"chain\":42161,\"token\":\"USDC\",\"amount\":\"5000000\"}]" },
          { "name": "goal", "in": "query", "required": false, "schema": { "type": "string", "enum": ["max-output", "cheapest", "fastest"] } },
          { "name": "amount", "in": "query", "required": false, "schema": { "type": "string" } },
          { "name": "toAddress", "in": "query", "required": false, "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Ranked plan", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/IntentPlan" } } } } }
      }
    },
    "/api/routes/recent": {
      "get": {
        "tags": ["explorer"],
        "summary": "Recent routes feed",
        "description": "Anonymized feed of recent real routes settled by the relayer (powers the public Explorer). No addresses, tx hashes or exact amounts. Rate limit 60/min.",
        "operationId": "recentRoutes",
        "parameters": [{ "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "default": 25, "maximum": 100 } }],
        "responses": { "200": { "description": "Recent routes", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RecentRoutes" } } } } }
      }
    },
    "/api/route/batch": {
      "post": {
        "tags": ["primitives"],
        "summary": "Plan a multi-leg payout (gated, dry-run by default)",
        "description": "Plans a multi-recipient/multi-leg payout (up to 20 legs), each via /compare. Plans & stores only — it does NOT move funds. Execution needs the watcher running with PRIMITIVES_LIVE=1 AND the record carrying live:true; the shipped default (live:false) simulates every tick. Rate limit 30/min.",
        "operationId": "routeBatch",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchRequest" } } } },
        "responses": { "200": { "description": "Planned batch record", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchResult" } } } } }
      }
    },
    "/api/route/schedule": {
      "post": {
        "tags": ["primitives"],
        "summary": "Create a scheduled / recurring transfer (gated)",
        "description": "Plans & stores a scheduled or recurring transfer. Same double gate as batch (PRIMITIVES_LIVE=1 + live:true); default live:false simulates. Rate limit 30/min.",
        "operationId": "routeSchedule",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleRequest" } } } },
        "responses": { "200": { "description": "Schedule record", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleResult" } } } } }
      }
    },
    "/api/route/schedule/{id}": {
      "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "example": "sched_cde9a12f1107fa3652" }],
      "get": {
        "tags": ["primitives"],
        "summary": "Inspect a schedule",
        "operationId": "getSchedule",
        "responses": {
          "200": { "description": "Schedule record", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ScheduleResult" } } } },
          "404": { "description": "Bad schedule path or id", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "delete": {
        "tags": ["primitives"],
        "summary": "Cancel a schedule",
        "operationId": "cancelSchedule",
        "responses": { "200": { "description": "Cancelled", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PrimitiveCancelled" } } } } }
      }
    },
    "/api/route/conditional": {
      "post": {
        "tags": ["primitives"],
        "summary": "Create a trigger-based transfer (gated)",
        "description": "Plans & stores a trigger-based transfer (priceAbove/priceBelow against on-chain feeds, or timeAfter). Same double gate as batch; default live:false simulates. Rate limit 30/min.",
        "operationId": "routeConditional",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConditionalRequest" } } } },
        "responses": { "200": { "description": "Conditional record", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConditionalResult" } } } } }
      }
    },
    "/api/route/conditional/{id}": {
      "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "example": "cond_3728705d2654926bc1" }],
      "get": {
        "tags": ["primitives"],
        "summary": "Inspect a condition",
        "operationId": "getConditional",
        "responses": {
          "200": { "description": "Conditional record", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ConditionalResult" } } } },
          "404": { "description": "Bad conditional path or id", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      },
      "delete": {
        "tags": ["primitives"],
        "summary": "Cancel a condition",
        "operationId": "cancelConditional",
        "responses": { "200": { "description": "Cancelled", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PrimitiveCancelled" } } } } }
      }
    },
    "/api/keys/create": {
      "post": {
        "tags": ["keys-hooks"],
        "summary": "Create an optional developer key",
        "description": "Self-serve key for a stable identity + usage visibility. The API stays keyless; a key just tags requests. The key is shown once. Rate limit 5/hour.",
        "operationId": "createKey",
        "requestBody": { "required": false, "content": { "application/json": { "schema": { "type": "object", "properties": { "label": { "type": "string", "example": "docs-example" } } } } } },
        "responses": { "200": { "description": "Key created (shown once)", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/KeyCreated" } } } } }
      }
    },
    "/api/keys/usage": {
      "get": {
        "tags": ["keys-hooks"],
        "summary": "Usage stats for your key",
        "description": "Hour + day aggregates and recent calls. Pass the key via the x-anygas-key header or ?key=.",
        "operationId": "keyUsage",
        "parameters": [{ "$ref": "#/components/parameters/ApiKeyHeader" }, { "name": "key", "in": "query", "required": false, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "Usage", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/KeyUsage" } } } } }
      }
    },
    "/api/hooks/register": {
      "post": {
        "tags": ["keys-hooks"],
        "summary": "Register a completion webhook",
        "description": "Get called on DONE/FAILED for a route id instead of polling. We POST {event,routeId,status,destTx,srcTx,ts}. If secret is set, deliveries carry x-anygas-signature: sha256=HMAC(secret, rawBody). Watch state at GET /api/hooks/{id}. Rate limit 120/min.",
        "operationId": "registerHook",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["routeId", "url"], "properties": { "routeId": { "type": "string", "example": "rt_abc123" }, "url": { "type": "string", "example": "https://example.com/webhook" }, "secret": { "type": "string" } } } } } },
        "responses": { "200": { "description": "Hook registered", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HookRegistered" } } } } }
      }
    },
    "/api/ask": {
      "post": {
        "tags": ["concierge"],
        "summary": "Ask the AI concierge",
        "description": "Natural-language questions about Robyn AnyGas; the concierge can call the read endpoints to answer.",
        "operationId": "ask",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["question"], "properties": { "question": { "type": "string", "example": "What chains can I move USDC between gaslessly?" } } } } } },
        "responses": { "200": { "description": "Answer", "content": { "application/json": { "schema": { "type": "object", "properties": { "answer": { "type": "string" } } } } } } }
      }
    },
    "/api/terms": {
      "get": { "tags": ["concierge"], "summary": "Terms of Service", "operationId": "terms", "responses": { "200": { "description": "HTML terms" } } }
    }
  }
}
