Get Quote
Retrieves a quote for trading between two assets. The request body varies based on the order type.
Endpoint
Portfolio API: POST https://ddp.definitive.fi/v2/portfolio/trade/quote
Organization API: Replace
/v2/portfolio/with/v2/organization/portfolios/{portfolioId}/. See Portfolio vs. Organization API.
Base Fields
All order types require these base fields:
| Field | Type | Required | Description |
|---|---|---|---|
| type | string | Yes | "market", "limit", "twap", "stop", "stop-loss", "take-profit", "trailing-stop", "trailing-stop-limit", "bracket" |
| chain | string | Yes | Chain identifier (e.g., "ethereum", "solana") |
| targetAsset | string | Yes | Asset to buy or sell (contract address) |
| contraAsset | string | Yes | Asset to trade against (contract address) |
| qty | string | Yes | Amount to trade |
| orderSide | string | Yes | "buy" or "sell" |
| slippageTolerance | string | No | Max allowed slippage (e.g., "0.01" = 1%). Default: "0.01" |
| maxPriceImpact | string | No | Max allowed price impact (e.g., "0.01"). Default: "0.01" |
Market Order
Simplest order type with no additional fields beyond the base fields.
{
type: "market",
chain: "ethereum",
targetAsset: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
contraAsset: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
qty: "1000",
orderSide: "buy",
slippageTolerance: "0.01",
maxPriceImpact: "0.01"
}Cross-Chain Market Order
Market orders can swap across chains: set contraChain to the chain the contra asset lives on, while chain stays the chain of targetAsset. On a buy, funds come from contraChain and the output lands on chain; on a sell, targetAsset on chain is sold into the contra asset on contraChain.
| Field | Type | Required | Description |
|---|---|---|---|
| contraChain | string | No | Chain of contraAsset. Omit (or set equal to chain) for a normal single-chain order |
{
type: "market",
chain: "arbitrum", // chain of targetAsset
contraChain: "base", // chain of contraAsset
targetAsset: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // USDC on Arbitrum
contraAsset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC on Base
qty: "5",
orderSide: "buy",
slippageTolerance: "0.05",
maxPriceImpact: "0.05"
}Cross-chain rules:
- Market orders only.
contraChainis read only ontype: "market". On any other order type the field is ignored (not rejected) and the order executes onchainalone — so only set it on market orders. - The quote response echoes
contraChainand includesquote.quote.bridgeQuoteId(quote.quote.idis empty — cross-chain quotes don't issue one). Submit withbridgeQuoteIdand omitquoteId— see Submit Order. - Submit within 60 seconds of the quote. The quoted bridge route is binding for 60s; a later submit still succeeds but is re-priced at execution.
- Keep
slippageToleranceidentical between quote and submit — a mismatch inside the 60s window is rejected with a400. Do not change it between the two calls. - Both chains need an active trading vault. Quoting auto-provisions missing vaults; the first quote on a fresh chain pair can return
422 ERROR_TYPE_VAULT_NOT_READY— retry shortly. See Error Codes. - To move an asset across chains without swapping, use Bridge instead.
Limit Order
Limit orders require a limit object:
| Field | Type | Required | Description |
|---|---|---|---|
| limit.price | string | Yes | Limit price to trigger order |
| limit.isNotional | boolean | Yes | true = price is in USD, false = price is the asset-to-asset ratio |
{
type: "limit",
chain: "solana",
targetAsset: "...",
contraAsset: "...",
qty: "100.00",
orderSide: "sell",
slippageTolerance: "0.01",
maxPriceImpact: "0.05",
limit: {
price: "0.07",
isNotional: false
}
}TWAP Order
| Field | Type | Required | Description |
|---|---|---|---|
| durationSeconds | number | Yes | Duration in seconds |
| targetTWAPBuckets | number | No | Optional number of buckets |
{
type: "twap",
chain: "ethereum",
targetAsset: "...",
contraAsset: "...",
qty: "1000",
orderSide: "buy",
slippageTolerance: "0.01",
maxPriceImpact: "0.01",
durationSeconds: 3600,
targetTWAPBuckets: 6
}Stop-Loss Order
Stop-loss orders automatically trigger a market order when a price threshold is hit.
| Field | Type | Required | Description |
|---|---|---|---|
| orderSide | string | Yes | Must be "sell" for stop-loss orders |
| trigger | object | Yes | Trigger object with price and isNotional |
| limit | object | No | Optional fallback limit price |
{
type: "stop-loss",
chain: "ethereum",
targetAsset: "...",
contraAsset: "...",
qty: "1000",
orderSide: "sell",
slippageTolerance: "0.01",
maxPriceImpact: "0.01",
trigger: {
price: "1600.00",
isNotional: true
},
limit: {
price: "1590.00",
isNotional: true
}
}Take Profit Order
Take profit orders automatically sell when the price rises to a target level, allowing you to lock in gains.
| Field | Type | Required | Description |
|---|---|---|---|
| orderSide | string | Yes | Must be "sell" for take-profit orders |
| trigger | object | Yes | Price trigger to activate the order |
| limit | object | No | Optional minimum execution price |
Examples
Basic take profit (sell SOL when it hits $180):{
type: "take-profit",
chain: "solana",
targetAsset: "So11111111111111111111111111111111111111112", // SOL
contraAsset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC
qty: "0.5",
orderSide: "sell",
slippageTolerance: "0.01",
maxPriceImpact: "0.01",
trigger: {
price: "180.00",
isNotional: true // Price in USD
}
}{
type: "take-profit",
chain: "solana",
targetAsset: "So11111111111111111111111111111111111111112",
contraAsset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
qty: "0.5",
orderSide: "sell",
slippageTolerance: "0.01",
maxPriceImpact: "0.01",
trigger: {
price: "180.00",
isNotional: true
},
limit: {
price: "178.00",
isNotional: true
}
}{
type: "take-profit",
chain: "solana",
targetAsset: "So11111111111111111111111111111111111111112", // SOL
contraAsset: "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs", // ETH
qty: "0.5",
orderSide: "sell",
slippageTolerance: "0.01",
maxPriceImpact: "0.01",
trigger: {
price: "0.055", // SOL/ETH cross rate
isNotional: false // Cross-asset price, not USD
}
}Stop-Buy Order
Stop-buy orders are triggered when the price reaches a specific threshold, useful for buying breakouts or entering positions when momentum shifts.
| Field | Type | Required | Description |
|---|---|---|---|
| orderSide | string | Yes | Must be "buy" for stop-buy orders |
| triggerType | string | Yes | "upper" or "lower" |
| trigger | object | Yes | Price trigger condition |
| limit | object | No | Optional limit price |
Examples
Basic stop-buy (buy when SOL breaks above $158):{
type: "stop",
chain: "solana",
targetAsset: "So11111111111111111111111111111111111111112", // SOL
contraAsset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC
qty: "0.02",
orderSide: "buy",
slippageTolerance: "0.01",
maxPriceImpact: "0.01",
triggerType: "upper",
trigger: {
price: "158.00",
isNotional: true // Price in USD
}
}{
type: "stop",
chain: "ethereum",
targetAsset: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC
contraAsset: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // WETH
qty: "1000",
orderSide: "buy",
slippageTolerance: "0.01",
maxPriceImpact: "0.01",
triggerType: "lower",
trigger: {
price: "1700.00",
isNotional: false
}
}{
type: "stop",
chain: "solana",
targetAsset: "So11111111111111111111111111111111111111112",
contraAsset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
qty: "0.02",
orderSide: "buy",
slippageTolerance: "0.01",
maxPriceImpact: "0.01",
triggerType: "upper",
trigger: {
price: "158.00",
isNotional: false
},
limit: {
price: "160.00",
isNotional: false
}
}Trigger Types
"upper": Buy when price breaks above trigger price (breakout strategy)"lower": Buy when price falls below trigger price (dip buying strategy)
Trailing Stop Order
A trailing stop follows the market instead of sitting at a fixed price. Once armed, it tracks a watermark of the target asset's USD price — the highest price seen for a sell, the lowest for a buy — and fires when the price retraces from that watermark by trailPercent. A trailing-stop executes as a market order when it fires; a trailing-stop-limit places a limit order at the effective trigger price instead, so it never fills worse than the trail but may not fill at all in a fast move.
| Field | Type | Required | Description |
|---|---|---|---|
| type | string | Yes | "trailing-stop" or "trailing-stop-limit" |
| orderSide | string | Yes | "sell" trails below the high-water mark; "buy" trails above the low-water mark |
| trigger.trailPercent | string | Yes | Trail distance as a fraction of the watermark: "0.05" is 5%. Must be between "0.005" (0.5%) and "0.5" (50%) inclusive |
| trigger.activationPrice | string | No | USD price the market must reach before the trail arms. Omit to arm immediately at the current price |
Neither trailing type accepts a limit object — the limit of a trailing-stop-limit is the effective trigger price the server derives from the watermark, and a request carrying limit is rejected. A trailing order cannot be updated after it is accepted; cancel and resubmit instead.
{
type: "trailing-stop",
chain: "solana",
targetAsset: "So11111111111111111111111111111111111111112", // SOL
contraAsset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC
qty: "0.5",
orderSide: "sell",
slippageTolerance: "0.01",
maxPriceImpact: "0.01",
trigger: {
trailPercent: "0.05" // 5% below the high-water mark
}
}{
type: "trailing-stop-limit",
chain: "solana",
targetAsset: "So11111111111111111111111111111111111111112",
contraAsset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
qty: "0.5",
orderSide: "sell",
trigger: {
trailPercent: "0.03",
activationPrice: "200.00" // USD
}
}The quote echoes trigger as sent. The watermark and the effective trigger price only exist once the order is live; read them from Order Details.
Bracket Order
Bracket orders submit a paired stop-loss and/or take-profit trigger set in one request.
| Field | Type | Required | Description |
|---|---|---|---|
| orderSide | string | Yes | Must be "sell" |
| orderTrigger | object | Yes | Trigger payload with type: "Trigger_StopBracket" |
orderTrigger fields:
| Field | Type | Required | Description |
|---|---|---|---|
| orderTrigger.type | string | Yes | Must be "Trigger_StopBracket" |
| orderTrigger.limits | array | Yes | 1-2 trigger legs |
| orderTrigger.limits[].price | string | Yes | Trigger price |
| orderTrigger.limits[].baseAsset | string | Yes | Usually same as targetAsset |
| orderTrigger.limits[].quoteAsset | string | No | Optional quote asset |
| orderTrigger.limits[].isLower | boolean | Yes | true for stop-loss leg, false for take-profit leg |
| orderTrigger.dynamicSizePercent | string | No | Optional dynamic sizing fraction, e.g. "1" for 100% |
{
type: "bracket",
chain: "solana",
targetAsset: "So11111111111111111111111111111111111111112",
contraAsset: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
qty: "0.5",
orderSide: "sell",
slippageTolerance: "0.01",
maxPriceImpact: "0.01",
orderTrigger: {
type: "Trigger_StopBracket",
limits: [
{
price: "140.00",
baseAsset: "So11111111111111111111111111111111111111112",
quoteAsset: null,
isLower: true
},
{
price: "185.00",
baseAsset: "So11111111111111111111111111111111111111112",
quoteAsset: null,
isLower: false
}
]
}
}Request Body Examples
const json = await AuthHelpers.signAndSend({
path: "/v2/portfolio/trade/quote",
method: "POST",
body: {
type: "market",
chain: "ethereum",
targetAsset: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
contraAsset: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
qty: "1000",
orderSide: "buy",
slippageTolerance: "0.01",
maxPriceImpact: "0.01",
},
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
});Response
{
quote: {
type: "market",
chain: "ethereum",
targetAsset: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
contraAsset: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
qty: "1000",
orderSide: "buy",
quote: {
id: "00000000-0000-0000-0000-000000000004",
amountOut: "0.555555",
priceImpact: "0.0025"
},
slippageTolerance: "0.01",
maxPriceImpact: "0.01"
// ...order-type-specific fields (e.g., trigger, limit, durationSeconds)
},
metadata: {
toNotional: "1000.00",
fromNotional: "999.95",
estimatedPriceImpact: "0.0025",
estimatedFee: "1.50",
estimatedFeeNotional: "1.50",
buyAmount: "0.555555",
sellAmount: "1000",
sources: { "0x": "1.0" },
expectedSlippage: "0.005",
minAmountOut: "0.54999945",
minAmountOutNotional: "990.00",
price: "0.000556",
isMarketable: true,
warnings: [] // optional, present when order size is below minimum
}
}Response Fields
| Field | Type | Description |
|---|---|---|
quote.type | string | The order type requested |
quote.chain | string | Chain identifier |
quote.contraChain | string | Cross-chain only: chain of the contra asset, echoed from the request |
quote.targetAsset | string | Asset being bought or sold |
quote.contraAsset | string | Asset traded against |
quote.qty | string | Quantity requested |
quote.orderSide | string | "buy" or "sell" |
quote.quote.id | string | UUID of the quote — pass this to Submit Order (empty for cross-chain) |
quote.quote.bridgeQuoteId | string | Cross-chain only: bridge route id — pass it to Submit Order and omit quoteId |
quote.quote.amountOut | string | Estimated amount you receive, after gas and trading fees are deducted — the same value as metadata.buyAmount |
quote.quote.priceImpact | string | Estimated price impact |
quote.slippageTolerance | string | Slippage tolerance used |
quote.maxPriceImpact | string | Max price impact used |
metadata.toNotional | string | Notional value of the output asset |
metadata.fromNotional | string | Notional value of the input asset |
metadata.estimatedPriceImpact | string | Estimated price impact |
metadata.estimatedFee | string | Estimated fee amount |
metadata.estimatedFeeNotional | string | Estimated fee in notional (USD) terms |
metadata.buyAmount | string | Estimated amount being bought, after fees are deducted (matches quote.quote.amountOut) |
metadata.sellAmount | string | Amount being sold |
metadata.sources | object | Liquidity sources used for the quote |
metadata.expectedSlippage | string | Expected slippage |
metadata.minAmountOut | string | The estimated output reduced by slippage |
metadata.minAmountOutNotional | string | The estimated notional reduced by slippage |
metadata.price | string | Quoted price |
metadata.isMarketable | boolean | Whether the order can execute at current market conditions |
metadata.warnings | string[] | Optional warnings (e.g., minimum order size) |
Field Explanations
trigger vs limit
trigger: The price that activates the order. When this price is reached, the order becomes active.limit: Optional constraint on execution price. Protects against slippage by setting a minimum (for sell orders) or maximum (for buy orders) execution price.
Example: Take profit with trigger at $180 and limit at $178:
- Order activates when SOL hits $180
- But will only execute if price is $178 or higher (protects against immediate price drop)
isNotional Flag
true: Price is in USD (notional value)false: Price is the cross-rate between the two assets
Examples:
{ price: "180.00", isNotional: true }= SOL at $180 USD{ price: "0.055", isNotional: false }= SOL/ETH ratio of 0.055
Order Execution
- Stop-loss and take-profit without limit: Becomes a market order when triggered (executes immediately at best available price)
- With limit: Becomes a limit order when triggered (waits for favorable price, may not fill immediately)
Notes
- Always provide
isNotionalfor limit, stop-loss, take-profit, and stop-buy orders.true= USD price,false= asset-to-asset ratio. Trailing stops have noisNotional:trailPercentis a fraction andactivationPriceis always USD. - Quotes are time-sensitive and should be submitted immediately — cross-chain quotes are only binding for 60 seconds (see Cross-Chain Market Order)
- You must submit the quote to place the order
- Order Status: You must poll Order Details to track order status - websocket subscriptions are not yet available