Placing orders
Boursa's order model follows Alpaca. You submit an order with a type, a side, a qty, and a time_in_force; the licensed broker executes it; the platform tracks the lifecycle and books every fill to the ledger.
POST /v1/orders is a signed money endpoint.
Request
{
"investor_id": "inv_…",
"symbol": "COMI",
"side": "buy",
"type": "limit",
"qty": 10,
"limit_price_micros": 80000000,
"time_in_force": "gtc",
"client_order_id": "my-unique-id-001"
}| Field | Required | Notes |
|---|---|---|
investor_id | yes | The approved investor placing the order. |
symbol | yes | EGX symbol, e.g. COMI. |
side | yes | buy or sell. |
type | yes | market or limit. |
qty | yes | Whole shares (integer > 0). |
limit_price_micros | for limit | Must be inside the ±20% band and a tick multiple. |
time_in_force | no (default day) | day, gtc, ioc, fok. |
client_order_id | no | Tenant-unique idempotency/dedup key. |
Order types
Market
Executes immediately at the best available price inside the band. The reservation holds the band ceiling (so the fill is always covered); the unspent remainder is released on fill.
{ "investor_id": "inv_…", "symbol": "COMI", "side": "buy",
"type": "market", "qty": 10, "time_in_force": "day" }Limit
Executes at your price or better. If marketable (a buy at/above the market, a sell at/below), it fills at the live price — price improvement, never worse than your limit. If it's away from the market, it rests in the book until the price reaches it (see Order lifecycle).
{ "investor_id": "inv_…", "symbol": "COMI", "side": "buy",
"type": "limit", "qty": 10, "limit_price_micros": 80000000,
"time_in_force": "gtc" }Stop, stop-limit, and trailing-stop types are on the roadmap. See Alpaca parity.
Time-in-force
This is the heart of order behavior, and it follows Alpaca:
| TIF | Behavior |
|---|---|
day | The default. A resting day order expires at session close. |
gtc | Good-till-canceled. Persists across sessions and never self-expires — it rests until it fills or you cancel it. |
ioc | Immediate-or-cancel. Fills what it can right now, cancels the rest. Never rests. |
fok | Fill-or-kill. Fills only if the whole quantity is marketable now, else cancels. Never rests. |
Orders placed while the market is closed are accepted, reserved, and queued — they transmit at the next session open (an after-hours order shows status: accepted).
Response
The response is an order object carrying both the internal state and the Alpaca-aligned status, the time_in_force, client_order_id, and lifecycle timestamps:
{
"order_id": "ord_…",
"client_order_id": "my-unique-id-001",
"investor_id": "inv_…",
"symbol": "COMI",
"asset_class": "egx_equity",
"side": "buy",
"type": "limit",
"order_class": "simple",
"time_in_force": "gtc",
"qty": 10,
"limit_price_micros": 80000000,
"state": "acked",
"status": "new",
"filled_qty": 0,
"submitted_at": "2026-06-14T11:00:01+03:00",
"created_at": "2026-06-14T11:00:01+03:00"
}Canceling
DELETE /v1/orders/{id} (signed)Cancellation is asynchronous: the order moves to pending_cancel, then canceled once the broker confirms — unless a fill wins the race (a fill is always truth). A non-cancelable order returns ORDER_NOT_CANCELLABLE.
Sandbox demo values
The sandbox honors a few deterministic magic inputs for demos:
| Input | Behavior |
|---|---|
order qty = 13 | fills in two partial executions (the second a sim-minute later) |
national_id ends 0000 | broker rejects the KYC application |
national_id ends 9999 | KYC screening referral (cleared from the dealer desk) |
| transfer of exactly EGP 666 | payment-rail failure (hold released) |