Skip to content

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:

FieldTypeRequiredDescription
typestringYes"market", "limit", "twap", "stop", "stop-loss", "take-profit", "trailing-stop", "trailing-stop-limit", "bracket"
chainstringYesChain identifier (e.g., "ethereum", "solana")
targetAssetstringYesAsset to buy or sell (contract address)
contraAssetstringYesAsset to trade against (contract address)
qtystringYesAmount to trade
orderSidestringYes"buy" or "sell"
slippageTolerancestringNoMax allowed slippage (e.g., "0.01" = 1%). Default: "0.01"
maxPriceImpactstringNoMax 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.

FieldTypeRequiredDescription
contraChainstringNoChain 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. contraChain is read only on type: "market". On any other order type the field is ignored (not rejected) and the order executes on chain alone — so only set it on market orders.
  • The quote response echoes contraChain and includes quote.quote.bridgeQuoteId (quote.quote.id is empty — cross-chain quotes don't issue one). Submit with bridgeQuoteId and omit quoteId — 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 slippageTolerance identical between quote and submit — a mismatch inside the 60s window is rejected with a 400. 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:

FieldTypeRequiredDescription
limit.pricestringYesLimit price to trigger order
limit.isNotionalbooleanYestrue = 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

FieldTypeRequiredDescription
durationSecondsnumberYesDuration in seconds
targetTWAPBucketsnumberNoOptional 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.

FieldTypeRequiredDescription
orderSidestringYesMust be "sell" for stop-loss orders
triggerobjectYesTrigger object with price and isNotional
limitobjectNoOptional 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.

FieldTypeRequiredDescription
orderSidestringYesMust be "sell" for take-profit orders
triggerobjectYesPrice trigger to activate the order
limitobjectNoOptional 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
  }
}
Take profit with limit (trigger at $180, min execution price $178):
{
  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
  }
}
Cross-rate take profit (sell SOL when SOL/ETH ratio hits 0.055):
{
  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.

FieldTypeRequiredDescription
orderSidestringYesMust be "buy" for stop-buy orders
triggerTypestringYes"upper" or "lower"
triggerobjectYesPrice trigger condition
limitobjectNoOptional 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
  }
}
Buy USDC when ETH price drops below $1700 (dip buying):
{
  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
  }
}
Stop-buy with limit (triggered at $158, max price $160):
{
  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.

FieldTypeRequiredDescription
typestringYes"trailing-stop" or "trailing-stop-limit"
orderSidestringYes"sell" trails below the high-water mark; "buy" trails above the low-water mark
trigger.trailPercentstringYesTrail distance as a fraction of the watermark: "0.05" is 5%. Must be between "0.005" (0.5%) and "0.5" (50%) inclusive
trigger.activationPricestringNoUSD 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.

Trailing stop, armed immediately (sell SOL if it falls 5% from its high):
{
  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
  }
}
Trailing stop-limit with an activation price (arm once SOL reaches $200, then trail 3%):
{
  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.

FieldTypeRequiredDescription
orderSidestringYesMust be "sell"
orderTriggerobjectYesTrigger payload with type: "Trigger_StopBracket"

orderTrigger fields:

FieldTypeRequiredDescription
orderTrigger.typestringYesMust be "Trigger_StopBracket"
orderTrigger.limitsarrayYes1-2 trigger legs
orderTrigger.limits[].pricestringYesTrigger price
orderTrigger.limits[].baseAssetstringYesUsually same as targetAsset
orderTrigger.limits[].quoteAssetstringNoOptional quote asset
orderTrigger.limits[].isLowerbooleanYestrue for stop-loss leg, false for take-profit leg
orderTrigger.dynamicSizePercentstringNoOptional 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

FieldTypeDescription
quote.typestringThe order type requested
quote.chainstringChain identifier
quote.contraChainstringCross-chain only: chain of the contra asset, echoed from the request
quote.targetAssetstringAsset being bought or sold
quote.contraAssetstringAsset traded against
quote.qtystringQuantity requested
quote.orderSidestring"buy" or "sell"
quote.quote.idstringUUID of the quote — pass this to Submit Order (empty for cross-chain)
quote.quote.bridgeQuoteIdstringCross-chain only: bridge route id — pass it to Submit Order and omit quoteId
quote.quote.amountOutstringEstimated amount you receive, after gas and trading fees are deducted — the same value as metadata.buyAmount
quote.quote.priceImpactstringEstimated price impact
quote.slippageTolerancestringSlippage tolerance used
quote.maxPriceImpactstringMax price impact used
metadata.toNotionalstringNotional value of the output asset
metadata.fromNotionalstringNotional value of the input asset
metadata.estimatedPriceImpactstringEstimated price impact
metadata.estimatedFeestringEstimated fee amount
metadata.estimatedFeeNotionalstringEstimated fee in notional (USD) terms
metadata.buyAmountstringEstimated amount being bought, after fees are deducted (matches quote.quote.amountOut)
metadata.sellAmountstringAmount being sold
metadata.sourcesobjectLiquidity sources used for the quote
metadata.expectedSlippagestringExpected slippage
metadata.minAmountOutstringThe estimated output reduced by slippage
metadata.minAmountOutNotionalstringThe estimated notional reduced by slippage
metadata.pricestringQuoted price
metadata.isMarketablebooleanWhether the order can execute at current market conditions
metadata.warningsstring[]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 isNotional for limit, stop-loss, take-profit, and stop-buy orders. true = USD price, false = asset-to-asset ratio. Trailing stops have no isNotional: trailPercent is a fraction and activationPrice is 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