API reference
odos_py
odos-py: a modern Python client for the Odos DEX Aggregator API.
AsyncOdosClient
Async counterpart of :class:~odos_py.client.OdosClient.
Same configuration and behaviour, backed by httpx.AsyncClient. The core
flow is identical: :meth:quote returns a path_id, :meth:assemble
turns it into signable calldata, and :meth:swap chains both.
Use it as an async context manager so the connection pool is closed::
async with AsyncOdosClient(api_key="...") as client:
quote = await client.quote(request)
Example
async with AsyncOdosClient() as client: ... chains = await client.get_chains()
quote_and_assemble = swap
class-attribute
instance-attribute
Alias for :meth:swap: quote then assemble in one awaited call.
__init__(*, base_url=DEFAULT_BASE_URL, api_key=None, api_key_header=DEFAULT_API_KEY_HEADER, max_retries=DEFAULT_MAX_RETRIES, backoff_base=DEFAULT_BACKOFF_BASE, timeout=DEFAULT_TIMEOUT, transport=None)
Create an async client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_url
|
str
|
Base URL of the Odos API. Override to target a proxy or a self-hosted gateway. |
DEFAULT_BASE_URL
|
api_key
|
Optional[str]
|
Optional API key. Strongly recommended: the keyless tier is heavily rate limited. |
None
|
api_key_header
|
str
|
Header name the |
DEFAULT_API_KEY_HEADER
|
max_retries
|
int
|
Maximum number of automatic retries on HTTP 429. |
DEFAULT_MAX_RETRIES
|
backoff_base
|
float
|
Base delay (seconds) for exponential backoff between 429 retries. |
DEFAULT_BACKOFF_BASE
|
timeout
|
float
|
Per-request timeout in seconds. |
DEFAULT_TIMEOUT
|
transport
|
Optional[AsyncBaseTransport]
|
Optional custom |
None
|
aclose()
async
Close the underlying async HTTP connection pool.
Safe to await multiple times. Called automatically when the client is used as an async context manager.
quote(request)
async
Request a swap quote (POST /sor/quote/v2).
Prices the swap described by request and returns the best path,
including the path_id needed by :meth:assemble.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
QuoteRequest
|
The swap to price. |
required |
Returns:
| Type | Description |
|---|---|
QuoteResponse
|
The parsed quote, whose |
Raises:
| Type | Description |
|---|---|
OdosRateLimitError
|
If rate limited (HTTP 429) past |
OdosAPIError
|
For any other non-success HTTP status. |
assemble(*, user_addr, path_id, simulate=False)
async
Assemble a quoted path into a signable transaction (POST /sor/assemble).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user_addr
|
str
|
Address that will execute the swap. Must match the
|
required |
path_id
|
str
|
The |
required |
simulate
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
AssembleResponse
|
The assembled response; |
AssembleResponse
|
EVM transaction. |
Raises:
| Type | Description |
|---|---|
OdosRateLimitError
|
If rate limited (HTTP 429) past |
OdosAPIError
|
For any other non-success HTTP status. |
execute(*, user_addr, path_id)
async
Request assisted execution of a quoted path (POST /sor/execute).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user_addr
|
str
|
Address that will execute the swap. |
required |
path_id
|
str
|
The |
required |
Returns:
| Type | Description |
|---|---|
Any
|
The raw decoded JSON payload from the API (shape not modelled). |
Raises:
| Type | Description |
|---|---|
OdosRateLimitError
|
If rate limited (HTTP 429) past |
OdosAPIError
|
For any other non-success HTTP status. |
swap(request, *, simulate=False)
async
Quote then assemble a swap in a single awaited call.
Convenience helper that runs :meth:quote, threads the resulting
path_id into :meth:assemble, and returns both.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
QuoteRequest
|
The swap to quote and assemble. |
required |
simulate
|
bool
|
Forwarded to :meth: |
False
|
Returns:
| Type | Description |
|---|---|
QuoteResponse
|
A |
AssembleResponse
|
class: |
Raises:
| Type | Description |
|---|---|
OdosAPIError
|
If the quote returned no |
OdosRateLimitError
|
If rate limited (HTTP 429) past |
Example
async with AsyncOdosClient() as client: ... quote, assembled = await client.swap(request) ... assembled.transaction.to # router contract address
get_chains()
async
List supported chains (GET /info/chains).
Returns:
| Type | Description |
|---|---|
Any
|
Decoded JSON of the form |
Any
|
the EVM chain ids Odos supports. |
Raises:
| Type | Description |
|---|---|
OdosAPIError
|
On any non-success HTTP status. |
get_tokens(chain_id)
async
List tokens for a chain (GET /info/tokens/{chainId}).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chain_id
|
int
|
EVM chain id to list tokens for. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
Decoded JSON of the form ``{"tokenMap": { : {"symbol": |
Any
|
..., "decimals": ..., "name": ...}, ...}}`` keyed by token address. |
Raises:
| Type | Description |
|---|---|
OdosAPIError
|
On any non-success HTTP status. |
get_router(chain_id)
async
Get the router contract address for a chain (GET /info/router/v2/{chainId}).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chain_id
|
int
|
EVM chain id to look up. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
Decoded JSON containing the router contract |
Any
|
chain. |
Raises:
| Type | Description |
|---|---|
OdosAPIError
|
On any non-success HTTP status. |
get_contract_info(chain_id)
async
Get router contract metadata for a chain (GET /info/contract-info/v2/{chainId}).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chain_id
|
int
|
EVM chain id to look up. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
Decoded JSON with contract metadata (address and related details) |
Any
|
for the chain. |
Raises:
| Type | Description |
|---|---|
OdosAPIError
|
On any non-success HTTP status. |
get_token_price(chain_id, token_address)
async
Get the price of a token (GET /pricing/token/{chainId}/{tokenAddress}).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chain_id
|
int
|
EVM chain id the token lives on. |
required |
token_address
|
str
|
ERC-20 contract address of the token. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
Decoded JSON of the form |
Any
|
token's USD price. |
Raises:
| Type | Description |
|---|---|
OdosAPIError
|
On any non-success HTTP status. |
OdosClient
A synchronous client for the Odos DEX Aggregator API.
The core flow is two steps: :meth:quote returns a path_id, then
:meth:assemble turns that path_id into ready-to-sign transaction
calldata. :meth:swap chains both in one call.
The free keyless tier is heavily rate limited; pass api_key to raise
limits. api_key_header is configurable because the exact header name is
not publicly documented.
The client may be used as a context manager to ensure the underlying connection pool is closed::
with OdosClient(api_key="...") as client:
chains = client.get_chains()
Example
client = OdosClient(api_key="YOUR_KEY") quote = client.quote(request) client.close()
quote_and_assemble = swap
class-attribute
instance-attribute
Alias for :meth:swap: quote then assemble in one call.
__init__(*, base_url=DEFAULT_BASE_URL, api_key=None, api_key_header=DEFAULT_API_KEY_HEADER, max_retries=DEFAULT_MAX_RETRIES, backoff_base=DEFAULT_BACKOFF_BASE, timeout=DEFAULT_TIMEOUT, transport=None)
Create a client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_url
|
str
|
Base URL of the Odos API. Override to target a proxy or a self-hosted gateway. |
DEFAULT_BASE_URL
|
api_key
|
Optional[str]
|
Optional API key. Strongly recommended: the keyless tier is heavily rate limited. |
None
|
api_key_header
|
str
|
Header name the |
DEFAULT_API_KEY_HEADER
|
max_retries
|
int
|
Maximum number of automatic retries on HTTP 429. |
DEFAULT_MAX_RETRIES
|
backoff_base
|
float
|
Base delay (seconds) for exponential backoff between 429 retries. |
DEFAULT_BACKOFF_BASE
|
timeout
|
float
|
Per-request timeout in seconds. |
DEFAULT_TIMEOUT
|
transport
|
Optional[BaseTransport]
|
Optional custom |
None
|
close()
Close the underlying HTTP connection pool.
Safe to call multiple times. Called automatically when the client is used as a context manager.
quote(request)
Request a swap quote (POST /sor/quote/v2).
Prices the swap described by request and returns the best path,
including the path_id needed by :meth:assemble.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
QuoteRequest
|
The swap to price. |
required |
Returns:
| Type | Description |
|---|---|
QuoteResponse
|
The parsed quote, whose |
Raises:
| Type | Description |
|---|---|
OdosRateLimitError
|
If rate limited (HTTP 429) past |
OdosAPIError
|
For any other non-success HTTP status. |
assemble(*, user_addr, path_id, simulate=False)
Assemble a quoted path into a signable transaction (POST /sor/assemble).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user_addr
|
str
|
Address that will execute the swap. Must match the
|
required |
path_id
|
str
|
The |
required |
simulate
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
AssembleResponse
|
The assembled response; |
AssembleResponse
|
EVM transaction. |
Raises:
| Type | Description |
|---|---|
OdosRateLimitError
|
If rate limited (HTTP 429) past |
OdosAPIError
|
For any other non-success HTTP status. |
execute(*, user_addr, path_id)
Request assisted execution of a quoted path (POST /sor/execute).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user_addr
|
str
|
Address that will execute the swap. |
required |
path_id
|
str
|
The |
required |
Returns:
| Type | Description |
|---|---|
Any
|
The raw decoded JSON payload from the API (shape not modelled). |
Raises:
| Type | Description |
|---|---|
OdosRateLimitError
|
If rate limited (HTTP 429) past |
OdosAPIError
|
For any other non-success HTTP status. |
swap(request, *, simulate=False)
Quote then assemble a swap in a single call.
Convenience helper that runs :meth:quote, threads the resulting
path_id into :meth:assemble, and returns both. Use this when you
want signable calldata directly from a :class:QuoteRequest.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
QuoteRequest
|
The swap to quote and assemble. |
required |
simulate
|
bool
|
Forwarded to :meth: |
False
|
Returns:
| Type | Description |
|---|---|
QuoteResponse
|
A |
AssembleResponse
|
class: |
Raises:
| Type | Description |
|---|---|
OdosAPIError
|
If the quote returned no |
OdosRateLimitError
|
If rate limited (HTTP 429) past |
Example
request = QuoteRequest( ... chain_id=1, ... input_tokens=[InputToken( ... token_address="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", ... amount="1000000000000000000", ... )], ... output_tokens=[OutputToken( ... token_address="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", ... proportion=1, ... )], ... user_addr="0x47E2D28169738039755586743E2dfCF3bd643f86", ... slippage_limit_percent=0.3, ... ) quote, assembled = client.swap(request) assembled.transaction.to # router contract address
get_chains()
List supported chains (GET /info/chains).
Returns:
| Type | Description |
|---|---|
Any
|
Decoded JSON of the form |
Any
|
the EVM chain ids Odos supports. |
Raises:
| Type | Description |
|---|---|
OdosAPIError
|
On any non-success HTTP status. |
get_tokens(chain_id)
List tokens for a chain (GET /info/tokens/{chainId}).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chain_id
|
int
|
EVM chain id to list tokens for. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
Decoded JSON of the form ``{"tokenMap": { : {"symbol": |
Any
|
..., "decimals": ..., "name": ...}, ...}}`` keyed by token address. |
Raises:
| Type | Description |
|---|---|
OdosAPIError
|
On any non-success HTTP status. |
get_router(chain_id)
Get the router contract address for a chain (GET /info/router/v2/{chainId}).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chain_id
|
int
|
EVM chain id to look up. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
Decoded JSON containing the router contract |
Any
|
chain. |
Raises:
| Type | Description |
|---|---|
OdosAPIError
|
On any non-success HTTP status. |
get_contract_info(chain_id)
Get router contract metadata for a chain (GET /info/contract-info/v2/{chainId}).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chain_id
|
int
|
EVM chain id to look up. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
Decoded JSON with contract metadata (address and related details) |
Any
|
for the chain. |
Raises:
| Type | Description |
|---|---|
OdosAPIError
|
On any non-success HTTP status. |
get_token_price(chain_id, token_address)
Get the price of a token (GET /pricing/token/{chainId}/{tokenAddress}).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chain_id
|
int
|
EVM chain id the token lives on. |
required |
token_address
|
str
|
ERC-20 contract address of the token. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
Decoded JSON of the form |
Any
|
token's USD price. |
Raises:
| Type | Description |
|---|---|
OdosAPIError
|
On any non-success HTTP status. |
OdosAPIError
Bases: OdosError
Raised when the Odos API returns a non-success HTTP status.
Also raised for client-side protocol problems, such as a quote response
that lacks a path_id during :meth:~odos_py.OdosClient.swap.
Attributes:
| Name | Type | Description |
|---|---|---|
status_code |
The HTTP status code returned by the API, or |
|
body |
The parsed response body (JSON when decodable, otherwise the raw
text), or |
__init__(message, *, status_code=None, body=None)
Initialize the error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
Human-readable description of the failure. |
required |
status_code
|
Optional[int]
|
HTTP status code associated with the failure, if any. |
None
|
body
|
Any
|
Parsed response body associated with the failure, if any. |
None
|
OdosError
Bases: Exception
Base class for all errors raised by this library.
Catch this to handle any failure originating from odos_py without
distinguishing the specific subtype.
OdosRateLimitError
Bases: OdosAPIError
Raised on HTTP 429 after the client's retries are exhausted.
The client automatically retries 429 responses with exponential backoff
(honouring Retry-After); this is raised only once max_retries is
reached.
Attributes:
| Name | Type | Description |
|---|---|---|
retry_after |
The server-advised wait in seconds parsed from the
|
__init__(message, *, status_code=None, body=None, retry_after=None)
Initialize the rate-limit error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
Human-readable description of the failure. |
required |
status_code
|
Optional[int]
|
HTTP status code (typically |
None
|
body
|
Any
|
Parsed response body associated with the failure, if any. |
None
|
retry_after
|
Optional[float]
|
Server-advised wait in seconds, if provided. |
None
|
AssembleRequest
Bases: BaseModel
Body for POST /sor/assemble.
Attributes:
| Name | Type | Description |
|---|---|---|
user_addr |
str
|
Address that will execute the swap. Must match the
|
path_id |
str
|
The |
simulate |
bool
|
When |
AssembleResponse
Bases: BaseModel
Response from POST /sor/assemble.
Any fields the API returns beyond transaction (e.g. simulation output,
expected output amounts) are preserved via extra="allow" and reachable
through model_extra.
Attributes:
| Name | Type | Description |
|---|---|---|
transaction |
Optional[Transaction]
|
The ready-to-sign :class: |
InputToken
Bases: BaseModel
A token being sold, with its amount expressed in wei (base units).
Attributes:
| Name | Type | Description |
|---|---|---|
token_address |
str
|
Checksummed ERC-20 contract address of the token being
sold. Serialized as |
amount |
str
|
Amount to sell, as a decimal string in the token's smallest unit (wei for an 18-decimal token). A string is used to avoid precision loss on large integers. |
OutputToken
Bases: BaseModel
A token being bought, with its desired proportion of the output.
Attributes:
| Name | Type | Description |
|---|---|---|
token_address |
str
|
Checksummed ERC-20 contract address of the token to
receive. Serialized as |
proportion |
float
|
Share of the total output this token should represent, in
the range |
QuoteRequest
Bases: BaseModel
Body for POST /sor/quote/v2.
Describes the swap to price. The response (:class:QuoteResponse) carries
the path_id that :meth:~odos_py.OdosClient.assemble turns into
signable calldata.
Attributes:
| Name | Type | Description |
|---|---|---|
chain_id |
int
|
EVM chain id the swap executes on (e.g. |
input_tokens |
list[InputToken]
|
Tokens being sold and their amounts (in wei). |
output_tokens |
list[OutputToken]
|
Tokens to receive and their output proportions. |
user_addr |
str
|
Address that will execute the swap; also receives the
output tokens. Serialized as |
slippage_limit_percent |
float
|
Maximum acceptable slippage as a percentage
(e.g. |
QuoteResponse
Bases: BaseModel
Response from POST /sor/quote/v2.
Only the fields commonly needed by callers are typed explicitly; any other
fields the API returns are preserved (extra="allow") and accessible via
model_extra.
Attributes:
| Name | Type | Description |
|---|---|---|
path_id |
Optional[str]
|
Opaque identifier for the routed path. Pass it to
:meth: |
out_amounts |
list[str]
|
Expected output amounts (wei), parallel to the request's
|
in_amounts |
list[str]
|
Input amounts consumed (wei), parallel to |
gas_estimate |
Optional[float]
|
Estimated gas units for the swap. |
gas_estimate_value |
Optional[float]
|
Estimated gas cost expressed in USD. |
price_impact |
Optional[float]
|
Estimated price impact of the swap, as a percentage (may be negative). |
block_number |
Optional[int]
|
Block height the quote was computed against. |
Transaction
Bases: BaseModel
The ready-to-sign transaction returned by assemble.
The fields mirror a standard EVM transaction and can be passed to a signer
such as web3.py's eth.account.sign_transaction. All fields are
optional because the API may omit some depending on the request.
Attributes:
| Name | Type | Description |
|---|---|---|
to |
Optional[str]
|
Router contract address the transaction calls. |
data |
Optional[str]
|
ABI-encoded calldata ( |
value |
Optional[str]
|
Native-token amount to send with the call (wei, as a string). |
gas |
Optional[int]
|
Gas limit. |
gas_price |
Optional[int]
|
Gas price in wei. Serialized as |
nonce |
Optional[int]
|
Sender account nonce. |
chain_id |
Optional[int]
|
EVM chain id the transaction targets. Serialized as
|
from_ |
Optional[str]
|
Sender address. Serialized as |