{
  "openapi": "3.1.0",
  "info": {
    "title": "Epsilon Public API",
    "version": "1.0.0",
    "description": "Public API for the Epsilon order engine on Robinhood Chain. Quotes, routes, market data, and EIP-712 signed order submission (limit, stop-loss, DCA, trailing). Authenticate with an API key (`X-API-Key: eps_...`) created via the developer surface; order authorization is the maker's signature. Docs: https://developers.epsilon.exchange"
  },
  "servers": [
    {
      "url": "https://api.epsilon.exchange"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Developer key (eps_ prefix). Also accepted as Authorization: Bearer eps_..."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "description": "Stable machine-readable code \u2014 full catalog at GET /v1/errors"
          }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing or invalid API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Per-key rate limit exceeded \u2014 see X-RateLimit-* and Retry-After headers",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/v1/route": {
      "get": {
        "summary": "Best route for a swap",
        "description": "Returns the best execution route (targets, calldatas, amounts, minAmountOut), measured price impact in ppm, split suggestions for large orders, and server-resolved fee legs. Amounts are raw integer token units.",
        "parameters": [
          {
            "name": "tokenIn",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ERC-20 address (0x-hex)"
          },
          {
            "name": "tokenOut",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ERC-20 address (0x-hex)"
          },
          {
            "name": "amountIn",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Raw integer amount in tokenIn's smallest unit"
          },
          {
            "name": "slippagePpm",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Slippage tolerance in parts-per-million"
          },
          {
            "name": "directSwap",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ]
            },
            "description": "1 = quote the direct swap path, 0 = quote the signed-order (keeper) path"
          },
          {
            "name": "wallet",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Trading wallet \u2014 resolves account-specific fee legs"
          }
        ],
        "responses": {
          "200": {
            "description": "Route",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/quote": {
      "get": {
        "summary": "Indicative quotes across venues",
        "parameters": [
          {
            "name": "tokenIn",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tokenOut",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amountIn",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Quotes",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/order-preflight": {
      "get": {
        "summary": "Simulate an order before signing",
        "description": "Checks balances, allowances, route viability, and fee-leg consistency for an order as it would be signed.",
        "parameters": [
          {
            "name": "tokenIn",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tokenOut",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amountIn",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "wallet",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slippagePpm",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "isStopLoss",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "0",
                "1"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Preflight result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/orders/{hash}": {
      "get": {
        "summary": "Order detail by hash",
        "parameters": [
          {
            "name": "hash",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "EIP-712 order hash (0x-hex)"
          }
        ],
        "responses": {
          "200": {
            "description": "Order",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Unknown order"
          }
        }
      },
      "delete": {
        "summary": "Cancel a pending order",
        "description": "Cancels an order that has not been picked up on-chain yet (status pending). Requires an EIP-712 OrderCancel(bytes32 orderHash) signature from the order's maker under the same domain. Active orders must be cancelled on-chain via the router.",
        "parameters": [
          {
            "name": "hash",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "EIP-712 order hash (0x-hex)"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "signature"
                ],
                "properties": {
                  "signature": {
                    "type": "string",
                    "description": "maker's OrderCancel signature"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Unknown order"
          },
          "409": {
            "description": "Order is no longer cancellable off-chain",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/orders/{hash}/fills": {
      "get": {
        "summary": "Fills for an order",
        "parameters": [
          {
            "name": "hash",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Fills",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/orderbook/{pair}": {
      "get": {
        "summary": "Open orders for a pair",
        "parameters": [
          {
            "name": "pair",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "tokenIn-tokenOut address pair, e.g. 0xabc...-0xdef..."
          }
        ],
        "responses": {
          "200": {
            "description": "Orderbook",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/swaps": {
      "get": {
        "summary": "Recent swaps",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "wallet",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Swaps",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/volume": {
      "get": {
        "summary": "Volume aggregates",
        "responses": {
          "200": {
            "description": "Volume",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/stats": {
      "get": {
        "summary": "Engine-wide counters",
        "responses": {
          "200": {
            "description": "Stats",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/errors": {
      "get": {
        "summary": "Machine-readable error catalog",
        "security": [],
        "responses": {
          "200": {
            "description": "Catalog",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/v1/config": {
      "get": {
        "summary": "Chain and router configuration",
        "security": [],
        "responses": {
          "200": {
            "description": "Config",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/v1/orders": {
      "post": {
        "summary": "Submit a signed order",
        "description": "Places an EIP-712-signed limit/stop-loss/DCA/trailing order. The developer key provides attribution and rate limiting; authorization is the maker's signature over the Order struct (domain EpsilonRouter v7, chain 4663). Fee fields must exact-match the feeLegs served by GET /v1/route for the same maker. Per-maker submit limits apply in addition to per-key limits.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "orderType",
                  "order",
                  "signature",
                  "orderHash"
                ],
                "properties": {
                  "orderType": {
                    "type": "string",
                    "enum": [
                      "limit",
                      "stop_loss",
                      "take_profit",
                      "dca",
                      "trailing"
                    ]
                  },
                  "order": {
                    "type": "object",
                    "required": [
                      "salt",
                      "maker",
                      "receiver",
                      "tokenIn",
                      "tokenOut",
                      "amountIn",
                      "triggerPrice",
                      "makerTraits",
                      "referrer",
                      "referralFeePpm"
                    ],
                    "properties": {
                      "salt": {
                        "type": "string",
                        "description": "random 32-byte salt, 0x-hex uint256"
                      },
                      "maker": {
                        "type": "string",
                        "description": "maker wallet address"
                      },
                      "receiver": {
                        "type": "string",
                        "description": "output receiver (normally the maker)"
                      },
                      "tokenIn": {
                        "type": "string"
                      },
                      "tokenOut": {
                        "type": "string"
                      },
                      "amountIn": {
                        "type": "string",
                        "description": "raw token units, decimal string"
                      },
                      "triggerPrice": {
                        "type": "string",
                        "description": "price scaled to tokenOut decimals, decimal string; 0 = market"
                      },
                      "makerTraits": {
                        "type": "string",
                        "description": "packed traits (nonce, deadline, slippage ppm, flags), decimal string"
                      },
                      "referrer": {
                        "type": "string",
                        "description": "fee vault address from the route's feeLegs (never invent)"
                      },
                      "referralFeePpm": {
                        "type": "integer",
                        "description": "must exact-match the route's feeLegs.fees.triggered.referralPpm"
                      }
                    }
                  },
                  "signature": {
                    "type": "string",
                    "description": "EIP-712 signature by maker (EOA or EIP-1271)"
                  },
                  "orderHash": {
                    "type": "string",
                    "description": "client-computed hash; the server recomputes and uses its own"
                  },
                  "intervalSeconds": {
                    "type": "string",
                    "description": "DCA only: seconds between executions"
                  },
                  "totalExecutions": {
                    "type": "string",
                    "description": "DCA only: number of chunks"
                  },
                  "totalAmountIn": {
                    "type": "string",
                    "description": "DCA only: total raw amount across all executions"
                  },
                  "flexibilityPpm": {
                    "type": "integer",
                    "description": "DCA only: timing flexibility in ppm"
                  },
                  "shortCircuit": {
                    "type": "boolean",
                    "description": "DCA only: stop early once totalAmountIn is spent"
                  },
                  "trailPpm": {
                    "type": "integer",
                    "description": "trailing only: trail distance in ppm"
                  },
                  "designatedKeeper": {
                    "type": "string",
                    "description": "trailing only: optional keeper address"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Order accepted (status pending)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "orderHash": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed order, traits invalid for orderType, or fee params mismatch",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "description": "Order already indexed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Per-key or per-maker rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  }
}