{
  "openapi": "3.1.0",
  "info": {
    "title": "BTR Gateway API",
    "version": "1.0.0",
    "summary": "Read-only market data for the BTR AIMM (Adaptive Inventory Market Maker).",
    "description": "Public, unauthenticated, read-only HTTP API serving live state for the BTR decentralised exchange on Arc testnet: oracle marks, pool composition, swap and liquidity activity, asset metadata and technical indicators. Every figure is derived from on-chain events and pool state by the BTR indexer.\n\n**No authentication.** Writes happen on chain through the user's own wallet, never through this API, so there is no authenticated surface, no API key to obtain and nothing to store.\n\n**No rate limit.** The read endpoints are unmetered and return no RateLimit headers, because there is no limit to report. An agent does not need to self-throttle. Responses are edge-cached for a few seconds, so polling faster than the cache TTL returns the same body.\n\n**Versioning.** The major version is pinned in the path (`/v1`) and will not change meaning under you: fields are added, never removed or retyped, within a version. A breaking change ships as `/v2` alongside `/v1`. When a version is scheduled for retirement its responses carry the RFC 8594 `Deprecation` and `Sunset` headers, and the sunset date is at least 180 days out. No endpoint is currently deprecated, so no such header is emitted today.\n\n**CORS is an allowlist, not `*`.** A request from an un-allowlisted origin gets no `Access-Control-Allow-Origin` header back and a bare preflight is refused, so browser `fetch` from a third-party page will fail. Server-side calls are unaffected. Verified against the live service rather than assumed.",
    "contact": {
      "name": "BTR",
      "url": "https://btr.markets/docs",
      "email": "security@btr.markets"
    },
    "license": {
      "name": "MIT",
      "identifier": "MIT"
    }
  },
  "servers": [
    {
      "url": "https://api.btr.markets",
      "description": "Production gateway"
    }
  ],
  "externalDocs": {
    "description": "Protocol documentation",
    "url": "https://btr.markets/docs"
  },
  "paths": {
    "/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Service liveness and readiness",
        "description": "Returns the gateway's readiness. Use this to confirm the API is reachable before issuing data requests.",
        "responses": {
          "200": {
            "description": "Gateway is up.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "service": {
                      "type": "string",
                      "const": "btr-gateway"
                    },
                    "status": {
                      "type": "string",
                      "example": "ok"
                    },
                    "ready": {
                      "type": "boolean"
                    },
                    "port": {
                      "type": "integer"
                    },
                    "timestamp": {
                      "type": "integer",
                      "description": "Unix epoch milliseconds."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/md/tickers": {
      "get": {
        "operationId": "listTickers",
        "summary": "Current oracle marks for every tracked ticker",
        "description": "One entry per instrument the oracle tracks, carrying the mid, the two-sided quote, a confidence interval in pbps, the age of the signed mark, and a liveness status. A ticker whose status is `dead` has exceeded its staleness bound and must not be treated as a current price.",
        "responses": {
          "200": {
            "description": "Ticker snapshot.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Ticker"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/assets/pools": {
      "get": {
        "operationId": "listPools",
        "summary": "Deployed pools and their assets",
        "description": "Pool addresses on the configured chain, each with the assets it holds and the LP receipt token per leg. This is the entry point for discovering what can be traded and deposited.",
        "responses": {
          "200": {
            "description": "Pool composition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "chainId",
                    "pools"
                  ],
                  "properties": {
                    "chainId": {
                      "type": "integer",
                      "examples": [
                        5042002
                      ]
                    },
                    "name": {
                      "type": "string",
                      "examples": [
                        "arc"
                      ]
                    },
                    "pools": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Pool"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/activity": {
      "get": {
        "operationId": "listActivity",
        "summary": "Recent swap, deposit and withdraw events",
        "description": "Chronological protocol activity decoded from on-chain logs. Each event carries its transaction hash and log index, the pool, the payer, and the amounts in and out.",
        "responses": {
          "200": {
            "description": "Event feed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "chainId": {
                      "type": "integer"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/liquidity": {
      "get": {
        "operationId": "getLiquidity",
        "summary": "Liquidity flow bucketed over time",
        "description": "Deposits and withdrawals aggregated into time buckets, per pool and per asset leg, in both native and USD terms.",
        "parameters": [
          {
            "name": "asset",
            "in": "query",
            "required": false,
            "description": "Restrict to a single asset leg. Omit for all legs.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Bucketed flow.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "buckets"
                  ],
                  "properties": {
                    "asset": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "buckets": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LiquidityBucket"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/indicators": {
      "get": {
        "operationId": "getIndicators",
        "summary": "Technical indicators for one symbol",
        "description": "Computed indicator series for a single instrument.",
        "parameters": [
          {
            "name": "symbol",
            "in": "query",
            "required": true,
            "description": "Instrument symbol, e.g. `BTC-USDC`.",
            "schema": {
              "type": "string"
            },
            "example": "BTC-USDC"
          },
          {
            "name": "preset",
            "in": "query",
            "required": true,
            "description": "Which series to compute. The `*ma` presets return an indicator with its moving average; the `*macd` presets return the divergence between the two. An unrecognised name returns 422.",
            "schema": {
              "type": "string",
              "enum": [
                "ema-trend",
                "emacd",
                "rsima",
                "rsimacd",
                "adxma",
                "adxmacd",
                "sdevma",
                "sdevmacd"
              ]
            },
            "example": "sdevma"
          }
        ],
        "responses": {
          "200": {
            "description": "Indicator series.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/IndicatorRow"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing `symbol` or `preset`, or an unrecognised preset name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/assets": {
      "get": {
        "operationId": "getAssets",
        "summary": "Metadata for specific asset addresses",
        "description": "Token metadata for an explicit address list. Unlike the other endpoints this one has no default result set: `addresses` is required and the request is rejected without it.",
        "parameters": [
          {
            "name": "addresses",
            "in": "query",
            "required": true,
            "description": "Comma-separated EVM addresses.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Asset metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "assets"
                  ],
                  "properties": {
                    "assets": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Asset"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`addresses` not supplied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/quote": {
      "post": {
        "operationId": "postQuote",
        "summary": "Exact quote for one leg",
        "description": "Prices a single leg exactly, using the same integer arithmetic the pool executes. POST rather than GET because the caller supplies the full pool state: the service holds no chain state of its own, which is what makes the result reproducible against the contract. A GET to this path returns 404.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Computed result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuoteResponse"
                }
              }
            }
          },
          "400": {
            "description": "Malformed or incomplete body; the message names the first missing field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/route": {
      "post": {
        "operationId": "postRoute",
        "summary": "Best route across supplied pools",
        "description": "Enumerates and ranks routes across the pool states you supply, optionally splitting across several. Returns the ranked plans; the caller turns a plan into calldata. There is no on-chain router. A GET to this path returns 404.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RouteRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Computed result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RouteResponse"
                }
              }
            }
          },
          "400": {
            "description": "Malformed or incomplete body; the message names the first missing field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/depth": {
      "post": {
        "operationId": "postDepth",
        "summary": "Aggregated depth ladder",
        "description": "Aggregates a depth ladder across the supplied pool states. A GET to this path returns 404.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DepthRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Computed result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DepthBook"
                }
              }
            }
          },
          "422": {
            "description": "Malformed or incomplete body; the message names the first missing field. This endpoint answers 422 where /v1/quote and /v1/route answer 400.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Ticker": {
        "type": "object",
        "properties": {
          "ticker": {
            "type": "integer",
            "description": "Packed MITCH instrument id."
          },
          "mid": {
            "type": "number"
          },
          "bid": {
            "type": "number"
          },
          "ask": {
            "type": "number"
          },
          "ci": {
            "type": "integer",
            "description": "Confidence interval, pbps."
          },
          "confidence": {
            "type": "number"
          },
          "flags": {
            "type": "integer"
          },
          "age_ms": {
            "type": "integer",
            "description": "Milliseconds since the mark was signed."
          },
          "status": {
            "type": "string",
            "enum": [
              "live",
              "stale",
              "dead"
            ]
          }
        }
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "`<txHash>:<logIndex>`."
          },
          "kind": {
            "type": "string",
            "enum": [
              "swap",
              "deposit",
              "withdraw"
            ]
          },
          "pool": {
            "type": "string"
          },
          "payer": {
            "type": "string"
          },
          "amountIn": {
            "type": "number"
          },
          "amountOut": {
            "type": "number"
          },
          "logIndex": {
            "type": "integer"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "Pool": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "description": "Pool contract address."
          },
          "key": {
            "type": "string",
            "description": "Stable pool identifier, e.g. `cryptoPool`."
          },
          "tag": {
            "type": "string",
            "description": "Short slug used in activity and liquidity rows, e.g. `btr-crypto`."
          },
          "symbols": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Symbols of the assets this pool holds."
          },
          "spokes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Spoke asset addresses hanging off the pool's base."
          },
          "refFeeds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Oracle reference feeds the pool prices against."
          },
          "receipts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Receipt"
            },
            "description": "LP receipt token, one per asset leg."
          }
        }
      },
      "Receipt": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "decimals": {
            "type": [
              "integer",
              "null"
            ]
          },
          "pool": {
            "type": "string"
          },
          "underlying": {
            "type": "string",
            "description": "Address of the asset this receipt represents a claim on."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "Asset": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "display": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "decimals": {
            "type": [
              "integer",
              "null"
            ]
          },
          "icon": {
            "type": [
              "string",
              "null"
            ]
          },
          "pool": {
            "type": [
              "string",
              "null"
            ]
          },
          "underlying": {
            "type": [
              "string",
              "null"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "LiquidityBucket": {
        "type": "object",
        "properties": {
          "t": {
            "type": "integer",
            "description": "Bucket start, Unix epoch seconds."
          },
          "pool": {
            "type": "string"
          },
          "poolTag": {
            "type": "string"
          },
          "symbol": {
            "type": "string"
          },
          "side": {
            "type": "string",
            "enum": [
              "deposit",
              "withdraw"
            ]
          },
          "amount": {
            "type": "number",
            "description": "Native amount, base units."
          },
          "amountUsd": {
            "type": "number"
          },
          "lpAmount": {
            "type": "number"
          },
          "eventCount": {
            "type": "number"
          }
        }
      },
      "IndicatorRow": {
        "type": "object",
        "description": "One point of the requested series. Always carries `time`; the remaining keys are named by the preset (for example `sdev` and `sdevMA` for `sdevma`).",
        "properties": {
          "time": {
            "type": "number",
            "description": "Unix epoch seconds."
          }
        },
        "additionalProperties": {
          "type": "number"
        }
      },
      "CurveWire": {
        "type": "object",
        "description": "The pool's depth curve, as stored on chain: knot weights, segment count, dispersion reference and flags.",
        "additionalProperties": true
      },
      "QuoteRequest": {
        "type": "object",
        "required": [
          "curve",
          "min_dispersion_pbps",
          "vega_bps",
          "min_fee_pbps",
          "kappa_cov_bps",
          "amount_in",
          "reserves",
          "liabilities",
          "mark",
          "sigma_pbps",
          "selling",
          "confidence_bps",
          "stale_excess",
          "proto_share_pct"
        ],
        "properties": {
          "curve": {
            "$ref": "#/components/schemas/CurveWire"
          },
          "min_dispersion_pbps": {
            "type": "integer",
            "format": "int64",
            "description": "Additive dispersion floor, PBPS."
          },
          "vega_bps": {
            "type": "integer",
            "description": "Volatility sensitivity, BPS."
          },
          "min_fee_pbps": {
            "type": "integer",
            "format": "int64",
            "description": "Per-leg fee floor, PBPS."
          },
          "kappa_cov_bps": {
            "type": "integer",
            "description": "Coverage-toll coefficient, BPS. Zero disables the toll."
          },
          "amount_in": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Unsigned integer as a 0x-prefixed hex string. Sent as hex, not a JSON number: values above 2^53 lose precision and JavaScript serialises them as `1e+21`, which the server rejects."
          },
          "reserves": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Unsigned integer as a 0x-prefixed hex string. Sent as hex, not a JSON number: values above 2^53 lose precision and JavaScript serialises them as `1e+21`, which the server rejects."
          },
          "liabilities": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Unsigned integer as a 0x-prefixed hex string. Sent as hex, not a JSON number: values above 2^53 lose precision and JavaScript serialises them as `1e+21`, which the server rejects."
          },
          "mark": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Unsigned integer as a 0x-prefixed hex string. Sent as hex, not a JSON number: values above 2^53 lose precision and JavaScript serialises them as `1e+21`, which the server rejects."
          },
          "sigma_pbps": {
            "type": "integer",
            "format": "int64",
            "description": "Volatility, PBPS."
          },
          "selling": {
            "type": "boolean",
            "description": "Direction: true sells the leg into the pool."
          },
          "confidence_bps": {
            "type": "integer",
            "description": "Oracle confidence interval, BPS."
          },
          "stale_excess": {
            "type": "integer",
            "format": "int64",
            "description": "Seconds of mark age beyond the grace window."
          },
          "proto_share_pct": {
            "type": "integer",
            "description": "Protocol share of the LP fee, percent."
          }
        }
      },
      "QuoteResponse": {
        "type": "object",
        "properties": {
          "amount_out": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Unsigned integer as a 0x-prefixed hex string. Sent as hex, not a JSON number: values above 2^53 lose precision and JavaScript serialises them as `1e+21`, which the server rejects."
          },
          "gross_out": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Unsigned integer as a 0x-prefixed hex string. Sent as hex, not a JSON number: values above 2^53 lose precision and JavaScript serialises them as `1e+21`, which the server rejects."
          },
          "avg_price": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Unsigned integer as a 0x-prefixed hex string. Sent as hex, not a JSON number: values above 2^53 lose precision and JavaScript serialises them as `1e+21`, which the server rejects."
          },
          "mid_price": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Inventory-skewed mid. The gap to `mark_price` is the extractable component."
          },
          "mark_price": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Oracle mark before inventory skew."
          },
          "spread_pbps": {
            "type": "integer",
            "description": "Quoted spread, PBPS. One swap pays half of it."
          },
          "cov_toll": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Unsigned integer as a 0x-prefixed hex string. Sent as hex, not a JSON number: values above 2^53 lose precision and JavaScript serialises them as `1e+21`, which the server rejects."
          },
          "proto_fee": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Unsigned integer as a 0x-prefixed hex string. Sent as hex, not a JSON number: values above 2^53 lose precision and JavaScript serialises them as `1e+21`, which the server rejects."
          },
          "lp_fee": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Unsigned integer as a 0x-prefixed hex string. Sent as hex, not a JSON number: values above 2^53 lose precision and JavaScript serialises them as `1e+21`, which the server rejects."
          }
        }
      },
      "RouteRequest": {
        "type": "object",
        "required": [
          "pools",
          "token_in",
          "token_out",
          "amount_in"
        ],
        "properties": {
          "pools": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Candidate pool states to route across. Build from `GET /v1/assets/pools` plus on-chain reads."
          },
          "token_in": {
            "type": "string"
          },
          "token_out": {
            "type": "string"
          },
          "amount_in": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "Unsigned integer as a 0x-prefixed hex string. Sent as hex, not a JSON number: values above 2^53 lose precision and JavaScript serialises them as `1e+21`, which the server rejects."
          },
          "slices": {
            "type": "integer",
            "description": "Water-fill granularity for split routes."
          },
          "min_gain_bps": {
            "type": "integer",
            "format": "int64",
            "description": "Discard a split that improves the result by less than this."
          },
          "max_routes": {
            "type": "integer"
          }
        }
      },
      "DepthRequest": {
        "type": "object",
        "required": [
          "pools",
          "from",
          "to"
        ],
        "description": "Aggregate a depth ladder across the supplied pool states. `from`/`to` name the pair; pools that touch neither are skipped.",
        "properties": {
          "pools": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Pool states to aggregate over, same wire shape as /v1/route."
          },
          "from": {
            "type": "string",
            "description": "Symbol being sold."
          },
          "to": {
            "type": "string",
            "description": "Symbol being bought."
          },
          "samples": {
            "type": "integer",
            "default": 48,
            "minimum": 8,
            "maximum": 200,
            "description": "Sweep resolution per side per pool. Clamped to [8, 200]."
          },
          "base_reserves": {
            "type": [
              "string",
              "null"
            ],
            "description": "Legacy request-level hub-side cap, raw units of base. A per-pool `base_reserves` wins where both are given."
          }
        }
      },
      "DepthRow": {
        "type": "object",
        "description": "One rung of the ladder, in human units.",
        "properties": {
          "price": {
            "type": "number"
          },
          "size": {
            "type": "number"
          },
          "cum": {
            "type": "number",
            "description": "Cumulative size through this rung."
          }
        }
      },
      "DepthBook": {
        "type": "object",
        "properties": {
          "mark": {
            "type": "number",
            "description": "Oracle mark."
          },
          "mid": {
            "type": "number",
            "description": "Inventory-skewed mid. The gap to `mark` is the extractable component."
          },
          "bid": {
            "type": "number"
          },
          "ask": {
            "type": "number"
          },
          "step": {
            "type": "number",
            "description": "Ladder bucket width."
          },
          "bids": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DepthRow"
            }
          },
          "asks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DepthRow"
            }
          },
          "poolCount": {
            "type": "integer",
            "description": "How many supplied pools contributed."
          }
        }
      },
      "LegWire": {
        "type": "object",
        "properties": {
          "pool_tag": {
            "type": "string"
          },
          "token_in": {
            "type": "string"
          },
          "token_out": {
            "type": "string"
          },
          "amount_in": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$"
          },
          "amount_out": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$"
          }
        }
      },
      "QuoteRouteWire": {
        "type": "object",
        "properties": {
          "legs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LegWire"
            }
          },
          "amount_in": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$"
          },
          "amount_out": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$"
          }
        }
      },
      "SplitPartWire": {
        "type": "object",
        "properties": {
          "legs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LegWire"
            }
          },
          "fraction": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$",
            "description": "WAD hex of the share routed through this part."
          },
          "amount_out": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$"
          }
        }
      },
      "RouteResponse": {
        "type": "object",
        "description": "Ranked result. No minOut is computed anywhere -- derive it from amount_out and your own tolerance.",
        "properties": {
          "best_amount_out": {
            "type": "string",
            "pattern": "^0x[0-9a-fA-F]+$"
          },
          "best_is_split": {
            "type": "boolean",
            "description": "Whether the best plan splits across several routes."
          },
          "best_parts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SplitPartWire"
            }
          },
          "singles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuoteRouteWire"
            },
            "description": "Every single (non-split) route, ranked by output."
          }
        }
      }
    }
  }
}