Skip to content

API reference

pendle

Typed Python client for the Pendle Finance v2 API.

PendleAPIError

Bases: PendleError

Raised when the Pendle API returns an error response.

The Pendle API signals errors with a non-2xx HTTP status and a JSON body of the shape {"message", "error", "statusCode"} (e.g. 400 "Invalid receiver address" or 404 "Not Found").

Attributes:

Name Type Description
message

The API's message text, falling back to "HTTP <status>".

error

The API's short error label (e.g. "Bad Request", "Not Found"), or None if absent.

status_code

The HTTP status code of the response.

Example::

from pendle import PendleClient, PendleAPIError

with PendleClient() as client:
    try:
        client.get_market(1, "0xnot-a-market")
    except PendleAPIError as exc:
        print(exc.status_code, exc.message)  # 404 'Not Found'

PendleError

Bases: Exception

Base class for all errors raised by this library.

Catch this to handle any failure originating from pendle (currently just :class:PendleAPIError). Network-level failures from the underlying httpx client propagate as httpx exceptions and are not wrapped.

AsyncPendleClient

Bases: _BaseClient

Asynchronous counterpart of :class:PendleClient.

Exposes the same endpoints as coroutines, backed by httpx.AsyncClient. Use it as an async context manager so the connection pool is closed for you; otherwise call :meth:aclose.

Example::

import asyncio
from pendle import AsyncPendleClient

async def main():
    async with AsyncPendleClient() as client:
        markets = await client.get_markets(1, limit=5)
        print(markets.total)

asyncio.run(main())

__init__(base_url=DEFAULT_BASE_URL, *, timeout=30.0, client=None)

Create an asynchronous client.

Parameters:

Name Type Description Default
base_url str

Pendle Core API base URL. Defaults to the public endpoint (:data:pendle.constants.DEFAULT_BASE_URL); a trailing slash is tolerated.

DEFAULT_BASE_URL
timeout float

Per-request timeout in seconds, applied when this client creates its own httpx.AsyncClient. Ignored if client is given.

30.0
client Optional[AsyncClient]

An existing httpx.AsyncClient to reuse. When supplied, the caller owns its lifecycle and :meth:aclose will not close it.

None

aclose() async

Close the underlying async HTTP client.

No-op when an external httpx.AsyncClient was injected via the constructor (the caller owns that client's lifecycle).

__aenter__() async

Enter the async runtime context and return this client.

__aexit__(exc_type, exc, tb) async

Exit the async runtime context, closing the client via :meth:aclose.

get_markets(chain_id, *, limit=None, skip=None) async

Fetch the (paginated) list of markets on a chain.

Async equivalent of :meth:PendleClient.get_markets.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
limit Optional[int]

Page size. Omit to use the API default.

None
skip Optional[int]

Number of markets to skip (offset pagination).

None

Returns:

Name Type Description
A MarketsResponse

class:MarketsResponse.

Raises:

Type Description
PendleAPIError

If the API returns an error.

get_market(chain_id, address) async

Fetch detail for a single market.

Async equivalent of :meth:PendleClient.get_market.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
address str

Market (LP) contract address.

required

Returns:

Name Type Description
A Market

class:pendle.models.Market.

Raises:

Type Description
PendleAPIError

If the market is unknown or the address is malformed.

get_active_markets(chain_id) async

Fetch the chain's active markets with liquidity and APY metrics.

Async equivalent of :meth:PendleClient.get_active_markets.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required

Returns:

Name Type Description
An ActiveMarketsResponse

class:ActiveMarketsResponse.

Raises:

Type Description
PendleAPIError

If the API returns an error.

get_assets(chain_id) async

Fetch metadata for every asset Pendle knows about on a chain.

Async equivalent of :meth:PendleClient.get_assets.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required

Returns:

Type Description
List[Asset]

A list of :class:pendle.models.Asset.

Raises:

Type Description
PendleAPIError

If the API returns an error.

get_historical_data(chain_id, address, *, time_frame='day', timestamp_start=None, timestamp_end=None) async

Fetch a market's APY/TVL time series.

Async equivalent of :meth:PendleClient.get_historical_data.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
address str

Market (LP) contract address.

required
time_frame str

"hour", "day" (default), or "week".

'day'
timestamp_start Optional[str]

ISO-8601 start of the range (optional).

None
timestamp_end Optional[str]

ISO-8601 end of the range (optional).

None

Returns:

Name Type Description
A HistoricalDataResponse

class:HistoricalDataResponse.

Raises:

Type Description
PendleAPIError

If the API returns an error.

convert(chain_id, *, receiver, slippage, inputs, outputs, enable_aggregator=None, aggregators=None, redeem_rewards=None, use_limit_order=None, need_scale=None, additional_data=None, extra=None) async

Build calldata for any Pendle action via the universal convert endpoint.

Async equivalent of :meth:PendleClient.convert; see that method for full argument and return documentation.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
receiver str

Address that receives the output.

required
slippage float

Max slippage fraction in [0, 1].

required
inputs List[Dict[str, str]]

Input tokens as [{"token": addr, "amount": wei_str}, ...].

required
outputs List[str]

Output token addresses.

required
enable_aggregator Optional[bool]

Allow an external swap aggregator.

None
aggregators Optional[List[str]]

Restrict to these aggregator names.

None
redeem_rewards Optional[bool]

Also redeem accrued rewards.

None
use_limit_order Optional[bool]

Use the limit-order book (API default True).

None
need_scale Optional[bool]

Set True only for on-chain-updated amounts.

None
additional_data Optional[str]

Comma-separated extra fields, e.g. "impliedApy".

None
extra Optional[Dict[str, Any]]

Additional raw body fields, merged last.

None

Returns:

Name Type Description
A ConvertResponse

class:ConvertResponse.

Raises:

Type Description
PendleAPIError

If the API rejects the request.

swap(chain_id, *, token_in, amount_in, token_out, receiver, slippage, **kwargs) async

Build calldata to swap amount_in of token_in into token_out.

Async equivalent of :meth:PendleClient.swap.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
token_in str

Address of the token you are spending.

required
amount_in str

Amount of token_in in wei (decimal string).

required
token_out str

Address of the token you want to receive.

required
receiver str

Address that receives token_out.

required
slippage float

Max slippage fraction in [0, 1].

required

Returns:

Name Type Description
A ConvertResponse

class:ConvertResponse (action == "swap").

Raises:

Type Description
PendleAPIError

If the API rejects the request.

add_liquidity(chain_id, *, market, token_in, amount_in, receiver, slippage, **kwargs) async

Build calldata to add liquidity to market with token_in.

Async equivalent of :meth:PendleClient.add_liquidity.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
market str

Market (LP) contract address — the LP token you receive.

required
token_in str

Address of the token you are depositing.

required
amount_in str

Amount of token_in in wei (decimal string).

required
receiver str

Address that receives the LP token.

required
slippage float

Max slippage fraction in [0, 1].

required

Returns:

Name Type Description
A ConvertResponse

class:ConvertResponse (action == "add-liquidity").

Raises:

Type Description
PendleAPIError

If the API rejects the request.

remove_liquidity(chain_id, *, market, amount_in, token_out, receiver, slippage, **kwargs) async

Build calldata to remove liquidity from market into token_out.

Async equivalent of :meth:PendleClient.remove_liquidity.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
market str

Market (LP) contract address — the LP token you burn.

required
amount_in str

Amount of LP token to remove, in wei (decimal string).

required
token_out str

Address of the token you want to receive.

required
receiver str

Address that receives token_out.

required
slippage float

Max slippage fraction in [0, 1].

required

Returns:

Name Type Description
A ConvertResponse

class:ConvertResponse (action == "remove-liquidity").

Raises:

Type Description
PendleAPIError

If the API rejects the request.

mint_py(chain_id, *, token_in, amount_in, pt, yt, receiver, slippage, **kwargs) async

Build calldata to mint PT + YT from token_in.

Async equivalent of :meth:PendleClient.mint_py.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
token_in str

Address of the token you are depositing (SY or underlying).

required
amount_in str

Amount of token_in in wei (decimal string).

required
pt str

Principal-token address to receive.

required
yt str

Yield-token address to receive.

required
receiver str

Address that receives the PT and YT.

required
slippage float

Max slippage fraction in [0, 1].

required

Returns:

Name Type Description
A ConvertResponse

class:ConvertResponse (action == "mint-py").

Raises:

Type Description
PendleAPIError

If the API rejects the request.

redeem_py(chain_id, *, pt, yt, amount_in, token_out, receiver, slippage, **kwargs) async

Build calldata to redeem PT + YT back into token_out.

Async equivalent of :meth:PendleClient.redeem_py.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
pt str

Principal-token address to redeem.

required
yt str

Yield-token address to redeem.

required
amount_in str

Amount of each of PT and YT to redeem, in wei.

required
token_out str

Address of the token you want to receive.

required
receiver str

Address that receives token_out.

required
slippage float

Max slippage fraction in [0, 1].

required

Returns:

Name Type Description
A ConvertResponse

class:ConvertResponse (action == "redeem-py").

Raises:

Type Description
PendleAPIError

If the API rejects the request.

PendleClient

Bases: _BaseClient

Synchronous client for the Pendle Finance v2 API.

Wraps the public, keyless endpoints: market/asset data, APY history, and the universal convert calldata endpoint (with ergonomic swap / add_liquidity / remove_liquidity / mint_py / redeem_py wrappers). Every method raises :class:PendleAPIError on an API error.

Use it as a context manager so the underlying httpx connection pool is closed for you; otherwise call :meth:close when done.

Example::

from pendle import PendleClient
from pendle.constants import ChainId

with PendleClient() as client:
    markets = client.get_active_markets(ChainId.ETHEREUM)
    for m in markets.markets[:5]:
        print(m.name, m.details.implied_apy)

__init__(base_url=DEFAULT_BASE_URL, *, timeout=30.0, client=None)

Create a synchronous client.

Parameters:

Name Type Description Default
base_url str

Pendle Core API base URL. Defaults to the public endpoint (:data:pendle.constants.DEFAULT_BASE_URL); a trailing slash is tolerated. Point this at a compatible proxy if needed.

DEFAULT_BASE_URL
timeout float

Per-request timeout in seconds, applied when this client creates its own httpx.Client. Ignored if client is given.

30.0
client Optional[Client]

An existing httpx.Client to reuse. When supplied, the caller owns its lifecycle and :meth:close will not close it.

None

close()

Close the underlying HTTP client.

No-op when an external httpx.Client was injected via the constructor (the caller owns that client's lifecycle).

__enter__()

Enter the runtime context and return this client.

__exit__(exc_type, exc, tb)

Exit the runtime context, closing the client via :meth:close.

get_markets(chain_id, *, limit=None, skip=None)

Fetch the (paginated) list of markets on a chain.

Calls GET /v1/{chainId}/markets.

Parameters:

Name Type Description Default
chain_id int

Chain id (an int or a :class:pendle.constants.ChainId).

required
limit Optional[int]

Page size. Omit to use the API default.

None
skip Optional[int]

Number of markets to skip (offset pagination).

None

Returns:

Name Type Description
A MarketsResponse

class:MarketsResponse with total/limit/skip and the

MarketsResponse

page of :class:pendle.models.Market entries (each with its PT, YT,

MarketsResponse

SY and LP token legs).

Raises:

Type Description
PendleAPIError

If the API returns an error.

get_market(chain_id, address)

Fetch detail for a single market.

Calls GET /v1/{chainId}/markets/{address}.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
address str

Market (LP) contract address.

required

Returns:

Name Type Description
A Market

class:pendle.models.Market.

Raises:

Type Description
PendleAPIError

If the market is unknown or the address is malformed.

get_active_markets(chain_id)

Fetch the chain's active markets with liquidity and APY metrics.

Calls GET /v1/{chainId}/markets/active.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required

Returns:

Name Type Description
An ActiveMarketsResponse

class:ActiveMarketsResponse; each entry exposes implied/pendle

ActiveMarketsResponse

APY and liquidity under details.

Raises:

Type Description
PendleAPIError

If the API returns an error.

get_assets(chain_id)

Fetch metadata for every asset Pendle knows about on a chain.

Calls GET /v1/{chainId}/assets/all (which returns a bare array).

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required

Returns:

Type Description
List[Asset]

A list of :class:pendle.models.Asset.

Raises:

Type Description
PendleAPIError

If the API returns an error.

get_historical_data(chain_id, address, *, time_frame='day', timestamp_start=None, timestamp_end=None)

Fetch a market's APY/TVL time series.

Calls GET /v3/{chainId}/markets/{address}/historical-data.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
address str

Market (LP) contract address.

required
time_frame str

Sample granularity: "hour", "day" (default), or "week".

'day'
timestamp_start Optional[str]

ISO-8601 start of the range (optional).

None
timestamp_end Optional[str]

ISO-8601 end of the range (optional).

None

Returns:

Name Type Description
A HistoricalDataResponse

class:HistoricalDataResponse of

HistoricalDataResponse

class:pendle.models.HistoricalDataPoint samples (max/base/implied

HistoricalDataResponse

APY and TVL).

Raises:

Type Description
PendleAPIError

If the API returns an error.

convert(chain_id, *, receiver, slippage, inputs, outputs, enable_aggregator=None, aggregators=None, redeem_rewards=None, use_limit_order=None, need_scale=None, additional_data=None, extra=None)

Build calldata for any Pendle action via the universal convert endpoint.

Calls POST /v3/sdk/{chainId}/convert. Pendle infers the action (swap, add/remove-liquidity, mint/redeem PY, etc.) from the kinds of the inputs and outputs tokens. For common actions prefer the higher-level :meth:swap, :meth:add_liquidity, :meth:remove_liquidity, :meth:mint_py and :meth:redeem_py wrappers.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
receiver str

Address that receives the output (must be a valid address; the API rejects placeholders such as 0x...01).

required
slippage float

Max slippage as a fraction in [0, 1] (0.01 = 1%).

required
inputs List[Dict[str, str]]

Input tokens as [{"token": addr, "amount": wei_str}, ...].

required
outputs List[str]

Output token addresses (the asset(s) you want to receive).

required
enable_aggregator Optional[bool]

Allow an external swap aggregator for tokens that can't be natively converted.

None
aggregators Optional[List[str]]

Restrict to these aggregator names (see GET /v1/sdk/{chainId}/supported-aggregators).

None
redeem_rewards Optional[bool]

Also redeem accrued rewards (for redeem actions).

None
use_limit_order Optional[bool]

Use the limit-order book when converting (API default is True).

None
need_scale Optional[bool]

Set True only when amounts were updated on-chain; buffer amountIn by ~2% when enabling.

None
additional_data Optional[str]

Comma-separated extra fields to compute, e.g. "impliedApy,effectiveApy".

None
extra Optional[Dict[str, Any]]

Additional raw body fields, merged last (escape hatch).

None

Returns:

Name Type Description
A ConvertResponse

class:ConvertResponse with the inferred action,

ConvertResponse

required_approvals to grant, and the routes whose tx

ConvertResponse

calldata performs the action.

Raises:

Type Description
PendleAPIError

If the API rejects the request (bad token pair, invalid receiver, etc.).

Example

Swap 1 SY for PT on Ethereum::

resp = client.convert(
    1,
    receiver="0xYourAddress",
    slippage=0.01,
    inputs=[{"token": SY, "amount": "1000000000000000000"}],
    outputs=[PT],
)
tx = resp.routes[0].tx          # sign & broadcast
print(resp.action)              # "swap"

swap(chain_id, *, token_in, amount_in, token_out, receiver, slippage, **kwargs)

Build calldata to swap amount_in of token_in into token_out.

Thin wrapper over :meth:convert with a single input and output (e.g. token -> PT, PT -> token, token -> YT). Extra keyword args are forwarded to :meth:convert (e.g. enable_aggregator=True).

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
token_in str

Address of the token you are spending.

required
amount_in str

Amount of token_in in wei (decimal string).

required
token_out str

Address of the token you want to receive.

required
receiver str

Address that receives token_out.

required
slippage float

Max slippage fraction in [0, 1].

required

Returns:

Name Type Description
A ConvertResponse

class:ConvertResponse (action == "swap").

Raises:

Type Description
PendleAPIError

If the API rejects the request.

add_liquidity(chain_id, *, market, token_in, amount_in, receiver, slippage, **kwargs)

Build calldata to add liquidity to market with token_in.

Thin wrapper over :meth:convert whose output is the market (LP) token.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
market str

Market (LP) contract address — the LP token you receive.

required
token_in str

Address of the token you are depositing.

required
amount_in str

Amount of token_in in wei (decimal string).

required
receiver str

Address that receives the LP token.

required
slippage float

Max slippage fraction in [0, 1].

required

Returns:

Name Type Description
A ConvertResponse

class:ConvertResponse (action == "add-liquidity").

Raises:

Type Description
PendleAPIError

If the API rejects the request.

remove_liquidity(chain_id, *, market, amount_in, token_out, receiver, slippage, **kwargs)

Build calldata to remove liquidity from market into token_out.

Thin wrapper over :meth:convert whose input is the market (LP) token.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
market str

Market (LP) contract address — the LP token you burn.

required
amount_in str

Amount of LP token to remove, in wei (decimal string).

required
token_out str

Address of the token you want to receive.

required
receiver str

Address that receives token_out.

required
slippage float

Max slippage fraction in [0, 1].

required

Returns:

Name Type Description
A ConvertResponse

class:ConvertResponse (action == "remove-liquidity").

Raises:

Type Description
PendleAPIError

If the API rejects the request.

mint_py(chain_id, *, token_in, amount_in, pt, yt, receiver, slippage, **kwargs)

Build calldata to mint PT + YT from token_in.

Thin wrapper over :meth:convert whose outputs are the PT and YT.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
token_in str

Address of the token you are depositing (SY or underlying).

required
amount_in str

Amount of token_in in wei (decimal string).

required
pt str

Principal-token address to receive.

required
yt str

Yield-token address to receive.

required
receiver str

Address that receives the PT and YT.

required
slippage float

Max slippage fraction in [0, 1].

required

Returns:

Name Type Description
A ConvertResponse

class:ConvertResponse (action == "mint-py").

Raises:

Type Description
PendleAPIError

If the API rejects the request.

redeem_py(chain_id, *, pt, yt, amount_in, token_out, receiver, slippage, **kwargs)

Build calldata to redeem PT + YT back into token_out.

Thin wrapper over :meth:convert whose inputs are equal amounts of PT and YT.

Parameters:

Name Type Description Default
chain_id int

Chain id (int or ChainId).

required
pt str

Principal-token address to redeem.

required
yt str

Yield-token address to redeem.

required
amount_in str

Amount of each of PT and YT to redeem, in wei.

required
token_out str

Address of the token you want to receive (SY or underlying).

required
receiver str

Address that receives token_out.

required
slippage float

Max slippage fraction in [0, 1].

required

Returns:

Name Type Description
A ConvertResponse

class:ConvertResponse (action == "redeem-py").

Raises:

Type Description
PendleAPIError

If the API rejects the request.

ActiveMarket

Bases: _Model

An entry from GET /v1/{chainId}/markets/active.

Unlike :class:Market, the pt/yt/sy fields here are composite id strings ('<chainId>-<address>'), not nested token objects, and the APY/liquidity figures live under :attr:details.

ActiveMarketsResponse

Bases: _Model

Response of GET /v1/{chainId}/markets/active.

Asset

Bases: _Model

Asset metadata from GET /v1/{chainId}/assets/all (a bare array of these).

ConvertResponse

Bases: _Model

Response of POST /v3/sdk/{chainId}/convert.

Pendle infers the :attr:action (swap, add-liquidity, remove-liquidity, mint-py, redeem-py, etc.) from the input and output token kinds, and returns the calldata as one or more :attr:routes, plus the ERC-20 :attr:required_approvals you must grant before broadcasting.

Example::

resp = client.swap(
    chain_id=1, token_in="0x...sy", token_out="0x...pt",
    amount_in="1000000000000000000", receiver="0xYou", slippage=0.01,
)
for approval in resp.required_approvals:
    ...  # approve approval.token for approval.amount
for route in resp.routes:
    ...  # sign & broadcast route.tx

ConvertRoute

Bases: _Model

One executed route of a convert: its tx, outputs, and economics.

A convert may decompose into multiple routes; each carries its own :attr:tx to broadcast in order.

HistoricalDataPoint

Bases: _Model

One time-series sample of a market's APYs and TVL.

HistoricalDataResponse

Bases: _Model

Response of GET /v3/{chainId}/markets/{address}/historical-data.

Market

Bases: _Model

A Pendle market from GET /v1/{chainId}/markets (and /markets/{address}).

Bundles the four token legs of a Pendle market: the principal token (:attr:pt), yield token (:attr:yt), standardized-yield wrapper (:attr:sy), and the LP token (:attr:lp).

MarketsResponse

Bases: _Model

Paginated response of GET /v1/{chainId}/markets.

Token

Bases: _Model

A Pendle token leg (PT / YT / SY / LP), as embedded in a market.

The base_type discriminates the kind: "PT", "YT", "SY", "PENDLE_LP", or "GENERIC" for plain assets.

TokenAmount

Bases: _Model

A token address paired with an amount in wei (decimal string).

Transaction

Bases: _Model

An unsigned EVM transaction to broadcast.

value is only present when the input is the chain's native token; it is None otherwise.