{
  "openapi": "3.1.0",
  "info": {
    "title": "fynd-rpc",
    "description": "HTTP RPC server for Fynd DEX router",
    "license": {
      "name": "MIT",
      "identifier": "MIT"
    },
    "version": "0.75.1"
  },
  "paths": {
    "/v1/health": {
      "get": {
        "tags": [
          "health"
        ],
        "summary": "GET /v1/health - Health check endpoint.",
        "description": "Returns the current health status of the service.",
        "operationId": "health",
        "responses": {
          "200": {
            "description": "Service healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthStatus"
                }
              }
            }
          },
          "503": {
            "description": "Data stale",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthStatus"
                }
              }
            }
          }
        }
      }
    },
    "/v1/info": {
      "get": {
        "tags": [
          "solver"
        ],
        "summary": "GET /v1/info - Return static metadata about this Fynd instance.",
        "operationId": "info",
        "responses": {
          "200": {
            "description": "Instance info",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InstanceInfo"
                }
              }
            }
          }
        }
      }
    },
    "/v1/quote": {
      "post": {
        "tags": [
          "solver"
        ],
        "summary": "POST /v1/quote - Request a quote.",
        "description": "Accepts a `QuoteRequest` and returns a `Quote` with the best routes found, or an error\nif the request could not be filled.\n\n# Errors\n\n- 400 Bad Request: Invalid request format\n- 422 Unprocessable Entity: No routes found\n- 503 Service Unavailable: Queue full or service overloaded\n- 503 Service Unavailable: Queue full, service overloaded, or quote timeout",
        "operationId": "quote",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuoteRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Quote completed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Quote"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "No route found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Queue full, overloaded, stale data, or timeout",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "BlockInfo": {
        "type": "object",
        "description": "Block information at which a quote was computed.\n\nQuotes are only valid for the block at which they were computed. Market\nconditions may change in subsequent blocks.",
        "required": [
          "number",
          "hash",
          "timestamp"
        ],
        "properties": {
          "hash": {
            "type": "string",
            "description": "Block hash as a hex string.",
            "example": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd"
          },
          "number": {
            "type": "integer",
            "format": "int64",
            "description": "Block number.",
            "example": 21000000,
            "minimum": 0
          },
          "timestamp": {
            "type": "integer",
            "format": "int64",
            "description": "Block timestamp in Unix seconds.",
            "example": 1730000000,
            "minimum": 0
          }
        }
      },
      "ClientFeeParams": {
        "type": "object",
        "description": "Client fee configuration for the Tycho Router.\n\nWhen provided, the router charges a client fee on the swap output. The `signature`\nmust be an EIP-712 signature by the `receiver` over the `ClientFee` typed data.",
        "required": [
          "bps",
          "receiver",
          "max_contribution",
          "deadline",
          "signature"
        ],
        "properties": {
          "bps": {
            "type": "integer",
            "format": "int32",
            "description": "Fee in basis points (0–10,000). 100 = 1%.",
            "example": 100,
            "minimum": 0
          },
          "deadline": {
            "type": "integer",
            "format": "int64",
            "description": "Unix timestamp after which the signature is invalid.",
            "example": 1893456000,
            "minimum": 0
          },
          "max_contribution": {
            "type": "string",
            "description": "Maximum subsidy from the client's vault balance.",
            "example": "0"
          },
          "receiver": {
            "type": "string",
            "description": "Address that receives the fee (also the required EIP-712 signer).",
            "example": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
          },
          "signature": {
            "type": "string",
            "description": "65-byte EIP-712 ECDSA signature by `receiver` (hex-encoded).",
            "example": "0xabcd..."
          }
        }
      },
      "EncodingOptions": {
        "type": "object",
        "description": "Options to customize the encoding behavior.",
        "required": [
          "slippage"
        ],
        "properties": {
          "client_fee_params": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/ClientFeeParams",
                "description": "Client fee configuration. When absent, no fee is charged."
              }
            ]
          },
          "permit": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/PermitSingle",
                "description": "Permit2 single-token authorization. Required when using `transfer_from_permit2`."
              }
            ]
          },
          "permit2_signature": {
            "type": [
              "string",
              "null"
            ],
            "description": "Permit2 signature (65 bytes, hex-encoded). Required when `permit` is set.",
            "example": "0xabcd..."
          },
          "price_guard": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/PriceGuardConfig",
                "description": "Per-request price guard configuration. If `None`, struct defaults are used."
              }
            ]
          },
          "slippage": {
            "type": "number",
            "format": "double",
            "example": "0.001"
          },
          "transfer_type": {
            "$ref": "#/components/schemas/UserTransferType",
            "description": "Token transfer method. Defaults to `transfer_from`."
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Error response body.",
        "required": [
          "error",
          "code"
        ],
        "properties": {
          "code": {
            "type": "string",
            "example": "BAD_REQUEST"
          },
          "details": {},
          "error": {
            "type": "string",
            "example": "bad request: no orders provided"
          }
        }
      },
      "FeeBreakdown": {
        "type": "object",
        "description": "Breakdown of fees applied to the swap output by the on-chain FeeCalculator.\n\nAll amounts are absolute values in output token units.",
        "required": [
          "router_fee",
          "client_fee",
          "max_slippage",
          "min_amount_received"
        ],
        "properties": {
          "client_fee": {
            "type": "string",
            "description": "Client's portion of the fee (after the router takes its share).",
            "example": "2800000"
          },
          "max_slippage": {
            "type": "string",
            "description": "Maximum slippage: (amount_out - router_fee - client_fee) * slippage.",
            "example": "3496850"
          },
          "min_amount_received": {
            "type": "string",
            "description": "Minimum amount the user receives on-chain.\nEqual to amount_out - router_fee - client_fee - max_slippage.",
            "example": "3493353150"
          },
          "router_fee": {
            "type": "string",
            "description": "Router protocol fee (fee on output + router's share of client fee).",
            "example": "350000"
          },
          "swaps_hash": {
            "type": [
              "string",
              "null"
            ],
            "description": "keccak256 of the ABI-encoded swap bytes, as a 0x-prefixed hex string.\nPresent only when client fee params were included in the request.\nUse this with `amount_in`, `token_in`, `token_out`, `min_amount_received`, and `receiver`\nto compute the 10-field EIP-712 `ClientFee` signing hash (see client library helpers).",
            "example": null
          }
        }
      },
      "HealthStatus": {
        "type": "object",
        "description": "Health check response.",
        "required": [
          "healthy",
          "last_update_ms",
          "num_solver_pools"
        ],
        "properties": {
          "derived_data_ready": {
            "type": "boolean",
            "description": "Whether derived data has been computed at least once.\n\nThis indicates overall readiness, not per-block freshness. Some algorithms\nrequire fresh derived data for each block — they are ready to receive orders\nbut will wait for recomputation before solving.",
            "example": true
          },
          "gas_price_age_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Time since last gas price update in milliseconds, if available.",
            "example": 12000,
            "minimum": 0
          },
          "healthy": {
            "type": "boolean",
            "description": "Whether the service is healthy.",
            "example": true
          },
          "last_update_ms": {
            "type": "integer",
            "format": "int64",
            "description": "Time since last market update in milliseconds.",
            "example": 1250,
            "minimum": 0
          },
          "num_solver_pools": {
            "type": "integer",
            "description": "Number of active solver pools.",
            "example": 2,
            "minimum": 0
          }
        }
      },
      "InstanceInfo": {
        "type": "object",
        "description": "Static metadata about this Fynd instance, returned by `GET /v1/info`.",
        "required": [
          "chain_id",
          "router_address",
          "permit2_address"
        ],
        "properties": {
          "chain_id": {
            "type": "integer",
            "format": "int64",
            "description": "EIP-155 chain ID (e.g. 1 for Ethereum mainnet).",
            "example": 1,
            "minimum": 0
          },
          "permit2_address": {
            "type": "string",
            "description": "Address of the canonical Permit2 contract (same on all EVM chains).",
            "example": "0x000000000022D473030F116dDEE9F6B43aC78BA3"
          },
          "router_address": {
            "type": "string",
            "description": "Address of the Tycho Router contract on this chain.",
            "example": "0xfD0b31d2E955fA55e3fa641Fe90e08b677188d35"
          }
        }
      },
      "Order": {
        "type": "object",
        "description": "A single swap order to be solved.\n\nAn order specifies an intent to swap one token for another.",
        "required": [
          "token_in",
          "token_out",
          "amount",
          "side",
          "sender"
        ],
        "properties": {
          "amount": {
            "type": "string",
            "description": "Amount to swap, interpreted according to `side` (in token units, as decimal string).",
            "example": "1000000000000000000"
          },
          "receiver": {
            "type": [
              "string",
              "null"
            ],
            "description": "Address that will receive the output tokens.\n\nDefaults to `sender` if not specified.",
            "example": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
          },
          "sender": {
            "type": "string",
            "description": "Address that will send the input tokens.",
            "example": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
          },
          "side": {
            "$ref": "#/components/schemas/OrderSide",
            "description": "Whether this is a sell (exact input) or buy (exact output) order."
          },
          "token_in": {
            "type": "string",
            "description": "Input token address (the token being sold).",
            "example": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
          },
          "token_out": {
            "type": "string",
            "description": "Output token address (the token being bought).",
            "example": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
          }
        }
      },
      "OrderQuote": {
        "type": "object",
        "description": "Quote for a single [`Order`].\n\nContains the route to execute (if found), along with expected amounts,\ngas estimates, and status information.",
        "required": [
          "order_id",
          "status",
          "amount_in",
          "amount_out",
          "gas_estimate",
          "amount_out_net_gas",
          "block"
        ],
        "properties": {
          "amount_in": {
            "type": "string",
            "description": "Amount of input token (in token units, as decimal string).",
            "example": "1000000000000000000"
          },
          "amount_out": {
            "type": "string",
            "description": "Amount of output token (in token units, as decimal string).",
            "example": "3500000000"
          },
          "amount_out_net_gas": {
            "type": "string",
            "description": "Amount out minus gas cost in output token terms.\nUsed by WorkerPoolRouter to compare solutions from different solvers.",
            "example": "3498000000"
          },
          "block": {
            "$ref": "#/components/schemas/BlockInfo",
            "description": "Block at which this quote was computed."
          },
          "fee_breakdown": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/FeeBreakdown",
                "description": "Fee breakdown (populated when encoding options are provided)."
              }
            ]
          },
          "gas_estimate": {
            "type": "string",
            "description": "Estimated gas cost for executing this route (as decimal string).",
            "example": "150000"
          },
          "gas_price": {
            "type": [
              "string",
              "null"
            ],
            "description": "Effective gas price (in wei) at the time the route was computed.",
            "example": "20000000000"
          },
          "order_id": {
            "type": "string",
            "description": "ID of the order this solution corresponds to.",
            "example": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
          },
          "price_impact_bps": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Price impact in basis points (1 bip = 0.01%)."
          },
          "route": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Route",
                "description": "The route to execute, if a valid route was found."
              }
            ]
          },
          "status": {
            "$ref": "#/components/schemas/QuoteStatus",
            "description": "Status indicating whether a route was found."
          },
          "transaction": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/Transaction",
                "description": "An encoded EVM transaction ready to be submitted on-chain."
              }
            ]
          }
        }
      },
      "OrderSide": {
        "type": "string",
        "description": "Specifies the side of an order: sell (exact input) or buy (exact output).\n\nCurrently only `Sell` is supported. `Buy` will be added in a future version.",
        "enum": [
          "sell"
        ]
      },
      "PermitDetails": {
        "type": "object",
        "description": "Details for a permit2 single-token permit.",
        "required": [
          "token",
          "amount",
          "expiration",
          "nonce"
        ],
        "properties": {
          "amount": {
            "type": "string",
            "description": "Amount of tokens approved.",
            "example": "1000000000000000000"
          },
          "expiration": {
            "type": "string",
            "description": "Expiration timestamp for the permit.",
            "example": "1893456000"
          },
          "nonce": {
            "type": "string",
            "description": "Nonce to prevent replay attacks.",
            "example": "0"
          },
          "token": {
            "type": "string",
            "description": "Token address for which the permit is granted.",
            "example": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
          }
        }
      },
      "PermitSingle": {
        "type": "object",
        "description": "A single permit for permit2 token transfer authorization.",
        "required": [
          "details",
          "spender",
          "sig_deadline"
        ],
        "properties": {
          "details": {
            "$ref": "#/components/schemas/PermitDetails",
            "description": "The permit details (token, amount, expiration, nonce)."
          },
          "sig_deadline": {
            "type": "string",
            "description": "Deadline timestamp for the permit signature.",
            "example": "1893456000"
          },
          "spender": {
            "type": "string",
            "description": "Address authorized to spend the tokens (typically the router).",
            "example": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
          }
        }
      },
      "PriceGuardConfig": {
        "type": "object",
        "description": "Per-request price guard configuration.\n\nAll fields are optional. When `None`, struct defaults are used.",
        "properties": {
          "enabled": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether price guard validation is enabled."
          },
          "fail_on_provider_error": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether to reject solutions when no provider can return a price."
          },
          "fail_on_token_price_not_found": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether to reject solutions when no provider returns price for token pair."
          },
          "lower_tolerance_bps": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Maximum allowed deviation when `amount_out < expected`, in basis points.",
            "example": 300,
            "minimum": 0
          },
          "upper_tolerance_bps": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Maximum allowed deviation when `amount_out >= expected`, in basis points.",
            "example": 10000,
            "minimum": 0
          }
        }
      },
      "Quote": {
        "type": "object",
        "description": "Complete solution for a [`QuoteRequest`].\n\nContains a solution for each order in the request, along with aggregate\ngas estimates and timing information.",
        "required": [
          "orders",
          "total_gas_estimate",
          "solve_time_ms"
        ],
        "properties": {
          "orders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderQuote"
            },
            "description": "Quotes for each order, in the same order as the request."
          },
          "solve_time_ms": {
            "type": "integer",
            "format": "int64",
            "description": "Time taken to compute this solution, in milliseconds.",
            "example": 12,
            "minimum": 0
          },
          "total_gas_estimate": {
            "type": "string",
            "description": "Total estimated gas for executing all swaps (as decimal string).",
            "example": "150000"
          }
        }
      },
      "QuoteOptions": {
        "type": "object",
        "description": "Options to customize the solving behavior.",
        "properties": {
          "encoding_options": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/EncodingOptions",
                "description": "Options during encoding. If None, quote will be returned without calldata."
              }
            ]
          },
          "max_gas": {
            "type": [
              "string",
              "null"
            ],
            "description": "Maximum gas cost allowed for a solution. Quotes exceeding this are filtered out.",
            "example": "500000"
          },
          "min_responses": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Minimum number of solver responses to wait for before returning.\nIf `None` or `0`, waits for all solvers to respond (or timeout).\n\nUse the `/health` endpoint to check `num_solver_pools` before setting this value.\nValues exceeding the number of active solver pools are clamped internally.",
            "minimum": 0
          },
          "timeout_ms": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Timeout in milliseconds. If `None`, uses server default.",
            "example": 2000,
            "minimum": 0
          }
        }
      },
      "QuoteRequest": {
        "type": "object",
        "description": "Request to solve one or more swap orders.",
        "required": [
          "orders"
        ],
        "properties": {
          "options": {
            "$ref": "#/components/schemas/QuoteOptions",
            "description": "Optional solving parameters that apply to all orders."
          },
          "orders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Order"
            },
            "description": "Orders to solve."
          }
        }
      },
      "QuoteStatus": {
        "type": "string",
        "description": "Status of an order quote.",
        "enum": [
          "success",
          "no_route_found",
          "insufficient_liquidity",
          "timeout",
          "not_ready",
          "price_check_failed"
        ]
      },
      "Route": {
        "type": "object",
        "description": "A route consisting of one or more sequential swaps.\n\nA route describes the path through liquidity pools to execute a swap.\nFor multi-hop swaps, the output of each swap becomes the input of the next.",
        "required": [
          "swaps"
        ],
        "properties": {
          "swaps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Swap"
            },
            "description": "Ordered sequence of swaps to execute."
          }
        }
      },
      "Swap": {
        "type": "object",
        "description": "A single swap within a route.\n\nRepresents an atomic swap on a specific liquidity pool (component).",
        "required": [
          "component_id",
          "protocol",
          "token_in",
          "token_out",
          "amount_in",
          "amount_out",
          "gas_estimate",
          "split"
        ],
        "properties": {
          "amount_in": {
            "type": "string",
            "description": "Amount of input token (in token units, as decimal string).",
            "example": "1000000000000000000"
          },
          "amount_out": {
            "type": "string",
            "description": "Amount of output token (in token units, as decimal string).",
            "example": "3500000000"
          },
          "component_id": {
            "type": "string",
            "description": "Identifier of the liquidity pool component.",
            "example": "0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc"
          },
          "gas_estimate": {
            "type": "string",
            "description": "Estimated gas cost for this swap (as decimal string).",
            "example": "150000"
          },
          "protocol": {
            "type": "string",
            "description": "Protocol system identifier (e.g., \"uniswap_v2\", \"uniswap_v3\", \"vm:balancer\").",
            "example": "uniswap_v2"
          },
          "split": {
            "type": "number",
            "format": "double",
            "description": "Decimal of the amount to be swapped in this operation (for example, 0.5 means 50%)",
            "example": "0.0"
          },
          "token_in": {
            "type": "string",
            "description": "Input token address.",
            "example": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
          },
          "token_out": {
            "type": "string",
            "description": "Output token address.",
            "example": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
          }
        }
      },
      "Transaction": {
        "type": "object",
        "description": "An encoded EVM transaction ready to be submitted on-chain.",
        "required": [
          "to",
          "value",
          "data"
        ],
        "properties": {
          "client_fee_signature_offset": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Byte offset of the client fee signature within `data`.\nClients use this to overwrite the placeholder signature with the real one.",
            "example": null,
            "minimum": 0
          },
          "data": {
            "type": "string",
            "description": "ABI-encoded calldata as hex string.",
            "example": "0x1234567890abcdef"
          },
          "to": {
            "type": "string",
            "description": "Contract address to call.",
            "example": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
          },
          "value": {
            "type": "string",
            "description": "Native token value to send with the transaction (as decimal string).",
            "example": "0"
          }
        }
      },
      "UserTransferType": {
        "type": "string",
        "description": "Token transfer method for moving funds into Tycho execution.",
        "enum": [
          "transfer_from_permit2",
          "transfer_from",
          "use_vaults_funds"
        ]
      }
    }
  }
}
