For the complete documentation index, see llms.txt. This page is also available as Markdown.
Authentication
Turbine supports two types of authentication: SIWE and EIP-712
Session-Based SIWE Authentication
Turbine authenticates users with sessions. The session ID arrives in a Set-Cookie response header. Send id=<SESSION_ID> as a cookie with each subsequent request.
The Typescript SDK handles authentication automatically.
Sign a specific message containing the nonce with your Ethereum wallet.
The message format is:
app.turbine.exchange wants you to sign in with your Ethereum account:
<YOUR_WALLET_ADDRESS>
Sign in to Turbine with your Ethereum wallet
URI: https://api.turbine.exchange/api
Version: 1
Chain ID: 1
Nonce: <YOUR_NONCE>
Issued At: <TIMESTAMP>
3
Verify the signature
Make a POST request to /api/verify (see the Swagger UI).
The body must contain the signed message and the signature:
{"message":"...message with newlines represented as \n...","signature":{"r":"0x...","s":"0x...","yParity":"0x...","v":"0x..."}}
If verification passes, the response includes a Set-Cookie header with session ID id=....
Make an Authenticated Request
Include a Cookie header with id=<YOUR_SESSION_ID> in subsequent requests. For example, check your authentication status again with /api/me.
Session Expiration
A session is valid for 5 minutes.
Keep it active by making authenticated requests before it expires, for example by calling /api/me. Each call before expiration extends the session by another 5 minutes.
EIP-712 Authentication
Authenticate by signing each message according to EIP-712 standard. No session, no cookies. Useful for automated workflows.
The Typescript SDK handles EIP-712 authentication automatically starting with version 0.33.0.
Endpoints supporting EIP-712
Endpoints that support EIP-712 authentication have an /api/eip712/ prefix.
Each endpoint that requires authentication has an EIP-712 sibling. E.g. there is /api/add_order that supports SIWE authentication and /api/eip712/add_order that supports EIP-712 authentication.
Body of a request to each EIP-712 endpoint has the following structure:
What to put in `signature`?
For each EIP-712 endpoint, there is a specific struct to sign.
In most cases, the signed struct consists of all payload's fields + deadline and nonce.
The exact structs are defined in a Solidity code snippet below.
Signed Types definitions
endpoint
struct to sign
add_order
AddOrder
add_orders
sign one AddOrder per submitted order
cancel_order
CancelOrder
orders
QueryOrders
add_liquidity
AddLiquidityEip712
remove_liquidity
RemoveLiquidityEip712
liquidity_intents
QueryLiquidityIntents
Examples
The Typescript SDK handles EIP-712 authentication for you. These examples show how to do it manually.
Submitting an Order
Submit an order via /api/eip712/add_order using Typescript and viem.
The spreadCurve gotcha: in the wire payload, spreadCurve is a sibling of order and its knots are relative to the order window (windowBps). But the signed OrderIntent inlines the curve: startDeltaBps, endDeltaBps, and points with each knot resolved to an absolute timestamp:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// Canonical EIP-712 typed-data structs for the Turbine signed API (`/api/eip712/*`).
//
// This is the single source of truth for the signing types. SDK authors can copy these struct
// definitions verbatim to build the EIP-712 `types` their signing library expects. Field names,
// order, and types here define the EIP-712 type hashes.
/// Sign this: EIP-712 signed envelope for order submission.
struct AddOrder {
OrderIntent order;
uint64 nonce;
uint64 deadline;
}
/// A struct for the order intent
///
/// # Fields
/// * `owner` - The address of the order creator and owner
/// * `sellToken` - The token address being sold
/// * `buyToken` - The token address being bought
/// * `sellAmount` - The amount of sellToken to sell
/// * `minBuyAmount` - The minimum amount of buyToken to receive
/// * `startDeltaBps` - The spread curve's delta at the order start, in basis points (100 = 1%)
/// * `endDeltaBps` - The spread curve's delta at the order end, in basis points (100 = 1%)
/// * `points` - The spread curve's interior knots
/// * `startTime` - Unix timestamp when the order becomes valid
/// * `endTime` - Unix timestamp when the order expires
/// * `partialFill` - Whether partial fills of the order are allowed
/// * `callData` - Optional call data for smart orders
/// * `callDataTarget` - Target contract address for the call data
/// * `salt` - Arbitrary value differentiating orders whose other fields are the same
struct OrderIntent {
address owner;
address sellToken;
address buyToken;
uint256 sellAmount;
uint256 minBuyAmount;
int32 startDeltaBps;
int32 endDeltaBps;
SpreadCurvePoint[] points;
uint256 startTime;
uint256 endTime;
bool partialFill;
bytes callData;
address callDataTarget;
bytes32 salt;
}
/// A single knot of an order's spread curve
///
/// # Fields
/// * `timeSecs` - Absolute unix timestamp of the knot
/// * `deltaBps` - Mid-price delta at the knot, in basis points (100 = 1%)
struct SpreadCurvePoint {
uint64 timeSecs;
int32 deltaBps;
}
/// Sign this: EIP-712 signed envelope for order cancellation.
struct CancelOrder {
bytes32 orderHash;
uint64 nonce;
uint64 deadline;
}
/// Sign this: EIP-712 signed envelope for adding liquidity.
struct AddLiquidityEip712 {
AddLiquidityIntent intent;
uint64 nonce;
uint64 deadline;
}
/// A struct for the intent to add liquidity
///
/// # Fields
/// * `owner` - The account providing the liquidity
/// * `token0` - token0 of the pool to which the liquidity is provided
/// * `token1` - token1 of the pool to which the liquidity is provided
/// * `fee` - fee of the pool to which the liquidity is provided, in 1/100 of bip (3000=0.3%)
/// * `token0Amount` - Maximum amount of token0 of the pool that the user is willing to provide
/// * `token1Amount` - Maximum amount of token1 of the pool that the user is willing to provide
/// * `exact` - If true, provide exactly the specified amounts (paying a swap fee to rebalance);
/// if false, treat them as maximums and provide in the pool's current reserve ratio.
/// * `salt` - Arbitrary value differentiating intents whose other fields are the same
struct AddLiquidityIntent {
address owner;
address token0;
address token1;
uint24 fee;
uint256 token0Amount;
uint256 token1Amount;
bool exact;
bytes32 salt;
}
/// Sign this: EIP-712 signed envelope for removing liquidity.
struct RemoveLiquidityEip712 {
RemoveLiquidityIntent intent;
uint64 nonce;
uint64 deadline;
}
/// A struct for the intent to remove liquidity
///
/// # Fields
/// * `owner` - The account withdrawing the liquidity
/// * `token0` - token0 of the pool to which the liquidity is withdrawn
/// * `token1` - token1 of the pool to which the liquidity is withdrawing
/// * `fee` - fee of the pool to which the liquidity is withdrawing, in 1/100 of bip (3000=0.3%)
/// * `lpToken` - Address of the LP token that the user wants to burn.
/// * `lpTokenAmount` - Quantity of LP tokens that the user wants to burn.
/// * `salt` - Arbitrary value differentiating intents whose other fields are the same
struct RemoveLiquidityIntent {
address owner;
address token0;
address token1;
uint24 fee;
address lpToken;
uint256 lpTokenAmount;
bytes32 salt;
}
/// Sign this: EIP-712 signed order query.
/// Zero values mean "unset": empty arrays are no filter, empty `cursor` is the first page,
/// `limit` 0 is the server default page size.
struct QueryOrders {
bytes32[] hashes;
string[] statuses;
string cursor;
uint64 limit;
uint64 nonce;
uint64 deadline;
}
/// Sign this: EIP-712 signed liquidity-intent lookup.
struct QueryLiquidityIntents {
bytes32[] hashes;
uint64 nonce;
uint64 deadline;
}