Submit Order
Submits a trade order using a previously obtained quote. The order will be executed according to the quote parameters and current market conditions.
Endpoint
Portfolio API: POST https://ddp.definitive.fi/v2/portfolio/trade
Organization API: Replace
/v2/portfolio/with/v2/organization/portfolios/{portfolioId}/. See Portfolio vs. Organization API.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| externalOrderRequest | object | Yes | Original order request (without quote details) |
| quoteId | string | Same-chain only | Quote ID from the quote response. Omit for cross-chain — cross-chain quotes don't issue one |
| bridgeQuoteId | string | Cross-chain only | Bridge route id from the quote response (quote.quote.bridgeQuoteId) |
{
externalOrderRequest: {
type: string, // "market", "limit", "twap", "stop", "stop-loss", "take-profit", "trailing-stop", "trailing-stop-limit", "bracket"
chain: string,
targetAsset: string,
contraAsset: string,
qty: string,
orderSide: string,
slippageTolerance?: string,
maxPriceImpact?: string,
// Additional fields by type:
// limit: { price: string, isNotional: boolean }
// twap: { durationSeconds: number, targetTWAPBuckets?: number }
// stop / stop-loss / take-profit: { trigger, limit? }
// stop-only: { triggerType: "upper" | "lower" }
// trailing-stop / trailing-stop-limit: { trigger: { trailPercent, activationPrice? } } (no limit)
// bracket: { orderTrigger: { type: "Trigger_StopBracket", limits: [...] } }
// cross-chain market: { contraChain: string }
},
quoteId?: string, // required for same-chain; omit for cross-chain
bridgeQuoteId?: string // cross-chain only, from quote.quote.bridgeQuoteId
}Request Body Examples
// Build the order request once and reuse it for quote + submit
const externalOrderRequest = {
type: "market",
chain: "ethereum",
targetAsset: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // USDC
contraAsset: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", // WETH
qty: "1000",
orderSide: "buy",
slippageTolerance: "0.01",
maxPriceImpact: "0.01",
};
// First, get a quote
const quoteResponse = await AuthHelpers.signAndSend({
path: "/v2/portfolio/trade/quote",
method: "POST",
body: externalOrderRequest,
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
});
// Then, submit the trade with quoteId + the same order request
const tradeResponse = await AuthHelpers.signAndSend({
path: "/v2/portfolio/trade",
method: "POST",
body: {
externalOrderRequest,
quoteId: quoteResponse.quote.quote.id,
},
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
});
console.log("Trade Response:", tradeResponse);Cross-chain: forward bridgeQuoteId from the quote response, omit quoteId (cross-chain quotes don't issue one), and keep the externalOrderRequest (including slippageTolerance) identical to the quote call:
const xchainTradeResponse = await AuthHelpers.signAndSend({
path: "/v2/portfolio/trade",
method: "POST",
body: {
externalOrderRequest, // includes contraChain; same slippageTolerance as at quote time
bridgeQuoteId: quoteResponse.quote.quote.bridgeQuoteId,
},
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
});Response
{
"orderId": "00000000-0000-0000-0000-000000000005"
}Notes
- Quotes are short-lived and should be submitted immediately
- If the quote expires or market conditions change, submission may fail
- The
externalOrderRequestshould be the original order request without the quote details - The
quoteIdis found in thequote.quote.idfield of the quote response (same-chain only — cross-chain quotes return an empty id) - Cross-chain submits (market orders with
contraChain) must includebridgeQuoteIdfrom the quote response and omitquoteId. Within 60s of the quote the bridged route and price are binding; after 60s the submit still succeeds but is re-priced at execution - Do not change
slippageTolerancebetween quote and submit on cross-chain orders — a mismatch inside the 60s window is rejected with a400(see Error Codes)