Orders are how you buy and sell instruments on behalf of your customers. You submit an order through our API, and we handle validation, execution, and settlement asynchronously.
Before you start
To place an order, you’ll need:
- An authenticated API session with a valid Bearer token
- An account ID for the customer placing the order
- The instrument ID for the security being traded; you can look these up via the instruments endpoints
- Sufficient cash balance (for buy orders) or position units (for sell orders) in the account
You can check available cash and positions using the cash balances and positions endpoints before placing an order.In the sandbox environment, you can trigger predefined execution outcomes (cancel, partial fill, full fill) using specific cash_amount or quantity values. See Testing.
Placing an order
Send a POST request to /accounts/{account_id}/orders. The request body depends on whether you’re buying or selling.
Buy orders
Buy orders are cash-based: you specify how much money to invest, not how many units to buy. We calculate the quantity based on the current price.
import requests
response = requests.post(
"https://api.engine.usesophic.com/accounts/{account_id}/orders",
headers={
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json",
},
json={
"instrument": "ins_xyz789",
"order_type": "market",
"side": "buy",
"cash_amount": "100.00",
},
)
order = response.json()
Sell orders
Sell orders are unit-based: you specify how many units to sell, not how much cash to receive.
import requests
response = requests.post(
"https://api.engine.usesophic.com/accounts/{account_id}/orders",
headers={
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json",
},
json={
"instrument": "ins_xyz789",
"order_type": "market",
"side": "sell",
"quantity": "10",
},
)
order = response.json()
Request body
| Field | Type | Required | Description |
|---|
instrument | string | Yes | The ID of the instrument to buy or sell. |
order_type | string | Yes | The order type. Only market is supported. |
side | string | Yes | buy or sell. |
cash_amount | string | Buy orders | The amount to invest before fees. Buy orders are cash-based. Must be greater than 0. |
quantity | string | Sell orders | The number of units to sell. Sell orders are unit-based. Must be greater than 0. |
automatic_rollover | boolean | No | If true, the resulting position will automatically roll over upon maturity. Only applicable to buy orders on instruments that support it. Defaults to false. |
Buy orders require cash_amount. Sell orders require quantity. At least one of the two must be provided, and the value must be greater than zero.
The response
A successful request returns 201 Created with the order object:
{
"id": "ord_m4k7r9s2",
"account": "acc_abc123",
"status": "placed",
"order_type": "market",
"purpose": "user_request",
"position": null,
"side": "buy",
"instrument": {
"id": "ins_xyz789",
"instrument_type": "bond",
"symbol": "KE2024A",
"name": "Kenya 2024 Bond A"
},
"cash_amount": "100.00",
"net_cash_amount": "99.50",
"traded_quantity": "0",
"traded_notional": "0",
"fees": "0.50",
"quantity": null,
"currency": "USD",
"automatic_rollover": false,
"cancelled_reason": null,
"filled_at": null,
"settled_at": null,
"cancelled_at": null,
"trades": [],
"created_at": "2026-03-12T14:30:00Z",
"modified_at": "2026-03-12T14:30:00Z"
}
Key fields to note:
status starts at placed. See the order lifecycle for how it progresses.
position is null until the order is executed; it gets populated when a trade is recorded.
traded_quantity and traded_notional are "0" initially and increase as trades execute.
fees reflects the total fee amount for this order.
net_cash_amount is the amount that actually gets traded (cash amount minus fees).
trades is an empty array until execution happens.
purpose is set by us. Orders you place through the API will always have user_request.
Order creation is synchronous; we validate the request and return the order immediately. Everything after that (execution, settlement) happens asynchronously. Use webhooks or poll the Retrieve order endpoint to track progress.
Retrieving orders
You can check an order’s current status at any time:
curl https://api.engine.usesophic.com/accounts/{account_id}/orders/{order_id} \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
To list all orders for an account, use the List orders endpoint. To list only orders that haven’t reached a terminal state, use the List pending orders endpoint; this is useful for building dashboards or monitoring active trades.