Skip to content

Place Orders

Place one or more orders on Synthetix's orderbook. This endpoint always accepts an array of orders for consistency, even when placing a single order.

Endpoint

POST https://papi.synthetix.io/v1/trade

Request

Request Format

{
  "params": {
    "action": "placeOrders",
    "subAccountId": "1867542890123456789",
    "orders": [
      {
        "symbol": "BTC-USDT",
        "side": "buy",
        "orderType": "limitGtc",
        "price": "50000.00",
        "triggerPrice": "",
        "quantity": "0.1",
        "reduceOnly": false,
        "postOnly": false,
        "isTriggerMarket": false,
        "closePosition": false,
        "clientOrderId": "0x1234567890abcdef1234567890abcdef"
      }
    ],
    "grouping": "na",
    "source": "direct"
  },
  "nonce": 1704067200000,
  "signature": {
    "v": 28,
    "r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
    "s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
  },
  "expiresAfter": 1704067300
}

Request Parameters

Action Parameters

ParameterTypeRequiredDescription
paramsobjectYesParameters object containing method details
params.actionstringYesMust be "placeOrders"
params.subAccountIdstringYesSubaccount identifier
params.ordersarrayYesArray of order objects (minimum 1 order)
params.groupingstringNoOrder grouping: "na", "normalTpsl", "positionTpsl"
params.sourcestringNoRequest source identifier for tracking and rebates (max 100 characters). Use "direct" for generic integrations

Common Request Parameters

ParameterTypeRequiredDescription
nonceintegerYesPositive integer, incrementing nonce
signatureobjectYesEIP-712 signature object
expiresAfterintegerNoExpiration timestamp (5x rate limit on stale cancels)

Order Object

ParameterTypeRequiredDescription
symbolstringYesMarket symbol (e.g., "BTC-USDT", "ETH-USDT")
sidestringYes"buy" or "sell"
orderTypestringYesOne of: limitGtc, limitIoc, limitAlo, market, triggerSl, triggerTp
pricestringYesPrice as string. Use empty string when not applicable (market orders and trigger market)
quantitystringYesOrder size as string
reduceOnlybooleanYesOnly reduce existing position
postOnlybooleanConditionalWhether order must be maker (no immediate match). Only used for limitGtc orders. Must be false for all other order types
triggerPricestringYesTrigger price as string. Required for triggerSl and triggerTp; empty string otherwise
isTriggerMarketbooleanYesExecution type for trigger orders. true for market-on-trigger, false for limit-on-trigger. Must be false for non-trigger types
closePositionbooleanYesClose entire position when triggered (TP/SL orders only). Must be false for non-trigger types
clientOrderIdstringNo128-bit hex string (0x + 32 hex chars)

Note on postOnly: The postOnly field is a request parameter but is not included in the EIP-712 signed Order type. It is processed server-side after signature verification. The EIP-712 Order type contains: symbol, side, quantity, orderType, price, triggerPrice, reduceOnly, isTriggerMarket, clientOrderId, closePosition.

Order Type Enum and Rules

  • limitGtc: price required; isTriggerMarket=false; triggerPrice=""
  • limitIoc: price required; isTriggerMarket=false; triggerPrice=""
  • limitAlo: price required; isTriggerMarket=false; triggerPrice=""
  • market: price=""; isTriggerMarket=false; triggerPrice=""
  • triggerSl: triggerPrice required; isTriggerMarket determines execution; if true then price="", if false then price required
  • triggerTp: same rules as triggerSl

Examples

Limit GTC

{
  "orderType": "limitGtc",
  "price": "50000.00",
  "triggerPrice": "",
  "isTriggerMarket": false,
  "postOnly": false,
  "closePosition": false
}

Limit GTC (Post-Only)

{
  "orderType": "limitGtc",
  "price": "50000.00",
  "triggerPrice": "",
  "isTriggerMarket": false,
  "postOnly": true,
  "closePosition": false
}

Market

{
  "orderType": "market",
  "price": "",
  "triggerPrice": "",
  "isTriggerMarket": false,
  "closePosition": false
}

Trigger SL (Market)

{
  "orderType": "triggerSl",
  "price": "",
  "triggerPrice": "50000",
  "isTriggerMarket": true,
  "closePosition": true
}

Trigger TP (Limit)

{
  "orderType": "triggerTp",
  "price": "49950.00",
  "triggerPrice": "50000.00",
  "isTriggerMarket": false,
  "closePosition": true
}

Time in Force (TIF) Options

ValueNameDescription
gtcGood Till CanceledOrder remains active until filled or canceled
iocImmediate or CancelFill immediately available quantity, cancel remainder
aloAdd Liquidity OnlyPost-only order, rejected if it would take liquidity

Response

Response Structure

FieldTypeDescription
statusstring"ok" for processed requests or "error" for request-level failures
responseobjectContains operation results (omitted when status is "error")
response.statusesarrayArray of status objects, one per order submitted (check each for success/error)
errorobjectError details (only present when status is "error")
requestIdstringRequest tracking identifier
traceIdstringTrace ID for debugging
timestampintegerUnix milliseconds timestamp

Order Status Types

Each order in the request receives one status response:

Status TypeDescriptionFields
restingOrder placed in orderbookorder (canonical), id (deprecated)
filledOrder completely filledorder (canonical), id (deprecated), avgPrice, totalSize
canceledOrder was canceledorder (canonical), id (deprecated)
errorOrder rejectederror (message string), errorCode (machine-readable code)

Success Response Examples

Single Order - Resting

{
  "status": "ok",
  "response": {
    "statuses": [
      {
        "resting": {
          "order": {
            "venueId": "1948058938469519360",
            "clientId": "cli-1948058938469519360"
          },
          "id": "1948058938469519360"
        }
      }
    ]
  },
  "requestId": "5ccf215d37e3ae6d"
}

Single Order - Filled

{
  "status": "ok",
  "response": {
    "statuses": [
      {
        "filled": {
          "order": {
            "venueId": "1948058938469519361",
            "clientId": "cli-1948058938469519361"
          },
          "id": "1948058938469519361",
          "avgPrice": "50001.25",
          "totalSize": "0.1"
        }
      }
    ]
  },
  "requestId": "5ccf215d37e3ae6d"
}

Single Order - Canceled

{
  "status": "ok",
  "response": {
    "statuses": [
      {
        "canceled": {
          "order": {
            "venueId": "1948058938469519362",
            "clientId": "cli-1948058938469519362"
          },
          "id": "1948058938469519362"
        }
      }
    ]
  },
  "requestId": "5ccf215d37e3ae6d"
}

Multiple Orders - Mixed Results (Partial Success)

Batch requests can have mixed results where some orders succeed and others fail. The response still has status: "ok" because the request was processed successfully—check each item in the statuses array:

{
  "status": "ok",
  "response": {
    "statuses": [
      {
        "resting": {
          "order": {
            "venueId": "1948058938469519360",
            "clientId": "cli-1948058938469519360"
          },
          "id": "1948058938469519360"
        }
      },
      {
        "filled": {
          "order": {
            "venueId": "1948058938469519361",
            "clientId": "cli-1948058938469519361"
          },
          "id": "1948058938469519361",
          "avgPrice": "2999.50",
          "totalSize": "1.0"
        }
      },
      {
        "error": "insufficient margin: additional needed 500.00, available 100.12",
        "errorCode": "INSUFFICIENT_MARGIN",
        "order": { "venueId": "0", "clientId": "cli-1948058938469519362" }
      }
    ]
  },
  "requestId": "5ccf215d37e3ae6d",
  "traceId": "abc123def456",
  "timestamp": 1704067200000
}

See Batch Request Error Handling for details on handling partial success scenarios.

Migration Note: Use *.order.venueId as canonical in each status payload. Legacy id remains for compatibility.

Error Response

Request-level errors return an error status. For per-item errors in batch requests, see Batch Request Error Handling.

{
  "status": "error",
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid signature",
    "category": "AUTH",
    "retryable": false
  },
  "requestId": "5ccf215d37e3ae6d",
  "traceId": "abc123def456",
  "timestamp": 1704067200000
}

Examples

Place Single Limit Order (GTC)

{
  "params": {
    "action": "placeOrders",
    "subAccountId": "1867542890123456789",
    "orders": [
      {
        "symbol": "BTC-USDT",
        "side": "buy",
        "orderType": "limitGtc",
        "price": "50000.00",
        "triggerPrice": "",
        "quantity": "0.1",
        "reduceOnly": false,
        "postOnly": false,
        "isTriggerMarket": false,
        "closePosition": false
      }
    ]
  },
  "nonce": 1704067200000,
  "signature": {
    "v": 28,
    "r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
    "s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
  }
}

Place Multiple Orders (Batch) — Mixed types

{
  "params": {
    "action": "placeOrders",
    "subAccountId": "1867542890123456789",
    "orders": [
      {
        "symbol": "BTC-USDT",
        "side": "buy",
        "orderType": "limitGtc",
        "price": "49000.00",
        "triggerPrice": "",
        "quantity": "0.05",
        "reduceOnly": false,
        "postOnly": false,
        "isTriggerMarket": false,
        "closePosition": false
      },
      {
        "symbol": "BTC-USDT",
        "side": "buy",
        "orderType": "limitGtc",
        "price": "48000.00",
        "triggerPrice": "",
        "quantity": "0.1",
        "reduceOnly": false,
        "postOnly": false,
        "isTriggerMarket": false,
        "closePosition": false
      },
      {
        "symbol": "BTC-USDT",
        "side": "sell",
        "quantity": "0.15",
        "reduceOnly": true,
        "orderType": "triggerSl",
        "price": "",
        "triggerPrice": "45000",
        "isTriggerMarket": true,
        "closePosition": false
      }
    ],
    "grouping": "na"
  },
  "nonce": 1704067200000,
  "signature": {
    "v": 28,
    "r": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
    "s": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
  }
}

:::info Rate Limiting This batch contains 3 orders, so it consumes 3 orders from your per-subaccount rate limit (100 orders/second). See Rate Limits for details. :::

Implementation Notes

  • Order nonces must be positive integers, incrementing and unique per request
  • Client order IDs enable request tracking with 128-bit hex format (0x prefix + 32 hex characters)
  • Limit orders require price specification, trigger orders require trigger price
  • Batch operations process orders independently with individual status responses
  • Order grouping types: "na" (none), "normalTpsl" (stop-loss/take-profit), "positionTpsl" (position-based)
  • All price and quantity values must be provided as strings for precision preservation

Error Handling

Common Errors

Error CodeDescriptionSolution
INSUFFICIENT_MARGINAccount lacks required marginAdd collateral or reduce order size
REQUEST_EXPIREDexpiresAfter timestamp has passedUse longer expiration or remove
INVALID_VALUEMarket symbol not recognizedCheck supported markets
QUANTITY_TOO_SMALLBelow minimum order sizeCheck market minimums
POST_ONLY_WOULD_TRADEPost-only order would take liquidityAdjust price or use different TIF
MAX_ORDERS_EXCEEDEDMaximum order limit reachedCancel existing orders first
REDUCE_ONLY_NO_POSITIONNo position for reduce-only orderRemove reduce-only flag
MARKET_CLOSEDMarket is not open for tradingWait for market to open

Batch Order Errors

For batch orders, each order is validated and processed independently:

  • Request-level errors (invalid signature, rate limit) fail the entire batch with an error response
  • Per-item errors (insufficient margin, invalid price) return HTTP 200 with individual error statuses
  • The statuses array preserves the order of your request—index 0 corresponds to your first order
  • Successfully processed orders are not rolled back if other orders fail

See Batch Request Error Handling for complete details and code examples.

Implementation Notes

  • Batch operations support multiple orders in a single request
  • Client order IDs enable tracking across WebSocket sessions
  • Expiration timestamps prevent stale order execution (5x rate limit on stale cancels)
  • Partial success responses indicate individual order status in batch operations

Rate Limiting

  • Each order in the batch counts separately - A request with 5 orders consumes 5 from your rate limit
  • Default limit: 100 orders per second per subaccount
  • Failed orders due to validation errors still count against rate limits
  • See Rate Limits for complete details

Next Steps