Trading
Place BUY and SELL orders for your master account or any sub-account. MARKET orders use quoteId; LIMIT/STOP orders rest without quotes. Covers order types, time-in-force, history, cancellation, ledger, and portfolio.
Place BUY and SELL orders on behalf of your master account or any sub-account. MARKET orders use a
two-step quote -> trade flow in both sandbox and production: fetch a quote, then place the order with
that quoteId within 60 seconds. Resting LIMIT, STOP, and STOP_LIMIT orders are placed without
a quoteId because your request supplies the trigger price; they rest as WORKING until activated.
Sandbox market orders fill instantly; live production market orders submitted during exchange
hours target PENDING → FILLED / REJECTED within 5 minutes. v1 may emit legacy COMPLETED as an alias of FILLED. Always use Idempotency-Key on trade
calls.
Production and sandbox enforce the same single-use quote rule. Sandbox claims the quote atomically
only after funds or holdings validation, so an INSUFFICIENT_FUNDS rejection does not consume an
otherwise valid quote. Reusing a successfully claimed quote returns 409 STALE_QUOTE.
The full state machine — including LIMIT/STOP, cancellation, and expiry — is in Order & Money Lifecycles.
Get a quote
Step 1 of every MARKET trade (sandbox and production). Returns the fee breakdown -- gross value, base fee
(0.75%), optional partner markup, total cost (BUY) or estimated proceeds (SELL), sufficient-funds check
-- and a quoteId that the subsequent MARKET /trade call requires. Resting LIMIT/STOP orders skip
this endpoint. Quotes are single-use and expire after 60 seconds (quoteExpiresAt); a stale or reused quoteId returns 409 STALE_QUOTE, and a
quoteId whose symbol/side/quantity does not match the order returns 409 QUOTE_ORDER_MISMATCH. Quotes
are indicative, not binding: settlement executes at the market price, protected by a deviation band
(default +/-10% of the quoted price).
/quote/{symbol}
Pre-trade fee quote
Full endpoint documentationgetQuoteReturns a pre-trade fee quote using the latest delayed price observation. Includes the local and USD price, gross order cost, base fee, partner markup fee, and total cost for BUY or estimated proceeds for SELL. Also returns whether the partner wallet has sufficient balance/holdings. Size the quote with either quantity (share mode) or cashValue (cash mode) — they are mutually exclusive, and the subsequent trade must use the same mode and value. Cash-mode quotes return an indicative fractional quantity; the order is sized at execution price and validated against the quoted cashValue. Quotes remain valid for 60 seconds to protect quote-to-fill price integrity. Mobile clients should display quoteExpiresAt, refresh when 10 seconds remain or whenever the app resumes, and require confirmation again if the refreshed cost, proceeds, fee, or quantity changes. Fetching a replacement quote does not place an order. Always fetch a quote immediately before placing a trade to confirm the current cost.
Parameters
symbolstringpathRequiredExchange-qualified ticker (e.g. SCOM.KE) or bare ticker.
Example: SCOM.KE
typeBUY | SELLqueryOrder direction. Defaults to BUY.
Example: BUY
quantitynumberqueryNumber of shares to quote (fractional allowed). Mutually exclusive with cashValue. Defaults to 1 when neither is passed.
Example: 500
cashValuenumberqueryUSD amount to quote in cash mode (fractional investing). Mutually exclusive with quantity. The trade must then be placed with the same cashValue and this quoteId.
Example: 50
subAccountIdstringqueryOptional sub-account ID when quoting a trade for /users/{userId}/trade. The account must exist under the authenticated partner key.
Example: usr_abc123
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Response fields
quoteIdstringQuote ID to submit in the subsequent trade request.
quoteTtlSecondsintegerExample: 60
quoteIssuedAtstringquoteExpiresAtstringsourceUpdatedAtstring | nullTimestamp of the source market price used for this quote.
dataFreshnessSecondsinteger | nullAge in seconds of the source market price when the quote was issued.
asOfstring | nullCanonical timestamp of the upstream price observation; equivalent to sourceUpdatedAt.
ageSecondsinteger | nullCanonical price age in seconds; equivalent to dataFreshnessSeconds.
stalebooleanTrue when the price observation is older than two refresh intervals.
delayModeDELAYED | END_OF_DAYdelayMinutesintegerExample: 15
refreshIntervalSecondsintegerExample: 900
providermstocks | mansadisclaimerstringPlain-English delayed-price warning.
dataQualityobjectThe published market-data freshness contract. African equity quotes are supplied by the exchanges on a 15-minute-delayed basis, not in real time. MyStocks holds full exchange data rights. The API refresh target is 900 seconds during the published coverage window, with an end-of-day pass after market close.
dataQuality.asOfstring | nullRequiredTimestamp of the exchange observation, not the time the API response was generated.
dataQuality.ageSecondsinteger | nullRequiredAge of the price in seconds (now − asOf).
dataQuality.stalebooleanRequiredTrue when the price is older than two refresh intervals.
dataQuality.delayModeDELAYED | END_OF_DAYRequiredDELAYED — exchange-supplied data in the 15-minute-delayed latency class. END_OF_DAY — outside the window; this is the most recent close, not a live quote.
dataQuality.delayMinutesintegerRequiredExchange feed latency class in minutes. This is distinct from the API refresh target.
Example: 15
dataQuality.refreshIntervalSecondsintegerRequiredTarget interval between API ingestion refreshes during the published coverage window.
Example: 900
dataQuality.providermstocks | mansaRequiredMyStocks ingestion connector for this exchange feed. This field does not describe exchange licensing or partner entitlement.
dataQuality.disclaimerstringRequiredPlain-English statement of what this price is and is not.
symbolstringExample: "SCOM.KE"
namestringexchangestringcurrencystringExample: "KES"
ledgerCurrencystringExample: "USD"
fxRatenumberManaged FX rate used to convert local price to USD.
fxSourcestringExample: "MYSTOCKS_MANAGED_FX"
fxRateAsOfstring | nullfxConversionobjectfxConversion.sourceCurrencystringExample: "KES"
fxConversion.sourceAmountnumberExample: 65000
fxConversion.targetCurrencystringExample: "USD"
fxConversion.targetAmountnumberExample: 500
fxConversion.ratenumberExample: 130
fxConversion.rateConventionstringExample: "KES per USD"
fxConversion.sourceMYSTOCKS_MANAGED_FX | PARTNER_PROVIDED_LEGACYfxConversion.asOfstring | nulltypeBUY | SELLquantityintegerlocalPricenumberCurrent price in the stock's local currency.
usdPricenumberCurrent price converted to USD.
grossnumberquantity × usdPrice.
baseFeenumberMyStocks base broker fee (0.75% of gross).
partnerMarkupFeenumberPartner markup component of the fee. Zero if markupBps = 0.
feenumberTotal fee (baseFee + partnerMarkupFee).
feeRatenumberEffective fee rate as a percentage (e.g. 0.75).
totalCostnumberBUY only — gross + fee. The amount escrowed on order submission.
estimatedProceedsnumberSELL only — gross - fee. Estimated wallet credit on settlement.
walletBalancenumberPartner master wallet balance in USD.
sufficientFundsbooleanBUY only — true if walletBalance >= totalCost.
unitsnumberSELL only — units of this stock currently held.
sufficientHoldingsbooleanSELL only — true if units >= quantity.
notestringExample: "This is a quote only. No order has been placed."
Response codes
200Fee quote for the requested symbol, type, and quantity.404Symbol or scoped sub-account not found. Unknown sub-accounts return `SUBACCOUNT_NOT_FOUND` and no quote is created.Mobile quote refresh
The 60-second TTL protects quote-to-fill price integrity and is not extended for backgrounded mobile
sessions. Treat quoteExpiresAt as the source of truth: display a countdown, refresh automatically when
10 seconds remain, and request a new quote whenever the app resumes. Never submit an expired quoteId.
Refreshing a quote does not create an order and is safe without an idempotency key; only the subsequent
trade mutation requires one. Preserve the user's symbol, side, and sizing mode, but require confirmation
again if the refreshed total cost, proceeds, fee, or quantity changes.
Place a trade
Place a BUY or SELL order. BUY escrows the cost (gross + fee) from the wallet immediately; SELL checks
that the sub-account holds the required units. The symbol accepts exchange-qualified (SCOM.KE) or
bare ticker (SCOM).
Production returns PENDING with the reserved price as priceAtOrder (local) and usdPriceAtOrder.
In sandbox the same call resolves instantly to FILLED and instead carries usdPrice,
localPrice, currency, and the post-trade newSubBalance.
Sandbox cheat codes. Quantity 100 → instant auto-fill (FILLED). Quantity 999 → instant
auto-reject (REJECTED). Use them to test your webhook handlers without waiting for the admin queue.
/trade
Place trade
Full endpoint documentationcreateTradePlaces a BUY or SELL order on your own partner account (not a sub-account — use /users/{userId}/trade for those). Sandbox master trading is unsupported and returns HTTP 422; use POST /users/{userId}/trade with a funded sandbox sub-account instead. BUY — escrows USD from your master wallet. Settlement is T+3 for most African exchanges. SELL — requires you to hold the shares. Proceeds are credited on settlement. Pass Idempotency-Key to make retries safe. The same key returns the cached order within 24 h.
Parameters
This endpoint has no path or query parameters.
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Idempotency-KeystringheaderRequiredUnique string that makes write calls safe to retry on network failure. Required for money movement, trading, KYC, subscriptions, and webhook creation. Deduplicated for 24 hours -- duplicate keys return the cached response. HTTP 409 if a concurrent request with the same key is still in progress.
Example: dep_user42_1743152580
Request body
fundingWalletCurrencystringConvert explicitly to USD before submitting an order
symbolstringRequiredStock symbol. Accepts exchange-qualified (SCOM.KE, DANGCEM.NG) or bare ticker (SCOM) -- auto-resolved when unambiguous. Returns 422 with match list if ambiguous.
Example: "SCOM.KE"
typeBUY | SELLRequiredOrder direction.
Example: "BUY"
quantitynumberNumber of shares. Whole-share markets require integer quantities; fractional-enabled markets allow up to 6 decimal places. Mutually exclusive with cashValue.
Example: 500
cashValuenumberUSD notional amount for cash-mode fractional investing. Mutually exclusive with quantity and must match the cashValue used to obtain quoteId for MARKET orders.
Example: 50
quoteIdstringFresh pre-trade quote ID from GET /quote/{symbol}. Quotes expire after 60 seconds and can be used once. Required for MARKET orders, including the default when orderType is omitted; ignored for LIMIT/STOP/STOP_LIMIT.
Example: "qt_2f4d5a7b8c9e4f01a2b3c4d5e6f78901"
orderTypeMARKET | LIMIT | STOP | STOP_LIMITMARKET (default): quote-gated and routed to automatic MyStocks internal-book execution. LIMIT/STOP/STOP_LIMIT are resting orders — they are placed WITHOUT a quote, escrow at the trigger price, rest in status WORKING, and route to automatic internal-book execution when the latest delayed price observation crosses the trigger (during market hours). BUY LIMIT fills at/below limitPrice; SELL LIMIT at/above; BUY STOP triggers at/above stopPrice; SELL STOP at/below. Prices are in the stock's LOCAL trading currency. Fires order.triggered on activation.
limitPricenumberLocal-currency limit price. Required for LIMIT and STOP_LIMIT.
stopPricenumberLocal-currency stop/trigger price. Required for STOP and STOP_LIMIT.
clientOrderIdstringOptional partner-supplied order reference. Must be unique per partner when supplied.
Example: "partner-ord-10001"
timeInForceDAY | GTC | GTDOrder validity instruction, enforced by the OMS lifecycle daemon. GTC (default) keeps the order live until executed or cancelled. DAY orders auto-cancel if not executed within 24 hours; GTD orders auto-cancel at expiresAt. On expiry, BUY escrow is refunded, SELL reservations are released, and an order.cancelled webhook fires. IOC is not supported by the current MyStocks internal-book order contract.
expiresAtstringRequired for GTD orders. Stored for OMS expiry governance.
orderInstructionstringOptional free-text execution instruction for the MyStocks internal-book engine.
stopLossnumberOptional. Order auto-cancels if the stock falls below this USD price before settlement.
Example: 0.11
takeProfitnumberOptional. Order auto-settles if the stock rises above this USD price before settlement.
Example: 0.16
Response fields
orderIdstringUnique order ID. Use to poll status or cancel.
Example: "ord_abc123xyz"
symbolstringExample: "SCOM.KE"
namestringExample: "Safaricom PLC"
exchangestringExample: "NSE"
orderTypeMARKET | LIMIT | STOP | STOP_LIMITOrder type. MARKET orders are quote-gated; LIMIT/STOP/STOP_LIMIT rest as WORKING until triggered.
Example: "LIMIT"
limitPricenumber | nullLimit price in the stock's local currency (LIMIT / STOP_LIMIT only).
stopPricenumber | nullStop price in the stock's local currency (STOP / STOP_LIMIT only).
cancelablebooleanWhether the order can be cancelled now (DELETE). True while PENDING or WORKING.
replaceablebooleanWhether the order can be modified now (PATCH). True only for a WORKING resting order.
typeBUY | SELLstatusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIREDPENDING after submission. WORKING = resting LIMIT/STOP/STOP_LIMIT order waiting for its trigger price (becomes PENDING on trigger). PARTIALLY_FILLED and FILLED are the canonical execution states. REJECTED, CANCELLED, and EXPIRED are terminal outcomes. PROCESSING is a legacy transition alias and COMPLETED is a v1 compatibility alias of FILLED; neither represents custody settlement. Settlement is tracked separately as PENDING, SETTLED, or FAILED.
quoteIdstring | nullPre-trade quote ID consumed by this order.
quoteExpiresAtstring | nullquoteUsdPricenumber | nullclientOrderIdstring | nullPartner-supplied order reference.
omsStatusstring | nullCanonical OMS lifecycle status.
timeInForcestring | nullfilledQuantitynumberremainingQuantitynumberaverageFillPricenumber | nullexecutionVenuestring | nulllastExecutionReportIdstring | nullexecutionSlaunionLive execution SLA clock for orders that have entered the PENDING dealing-desk queue. Null while a resting order is still WORKING.
quantityintegerpriceAtOrdernumberStock price in local currency at submission.
usdPriceAtOrdernumberUSD equivalent of priceAtOrder.
fxRateAtOrdernumber | nullManaged FX rate used for local-to-USD conversion at order submission.
fxSourcestring | nullfxRateAsOfstring | nullfxConversionunionfeenumberTotal fee in USD (base + partner markup).
baseFeenumberMyStocks base broker fee (0.75% of gross).
partnerMarkupFeenumberYour markup fee component. Zero if markupBps = 0.
totalAmountnumberBUY: gross + fee. SELL: gross - fee.
currencystringExample: "USD"
localCurrencystringExample: "KES"
rejectionCodestring | nullStructured rejection code. Populated when status = REJECTED.
rejectionReasonstring | nullFree-text rejection detail provided by the MyStocks internal-book execution service. Populated when status = REJECTED.
cancelledAtstring | nullsettledAtstring | nullSet when custody settlement completes; independent of the canonical FILLED execution state. Legacy completed records that pre-date this field return their immutable completion/creation timestamp as compatibility evidence.
createdAtstringcanonicalStatusPENDING | WORKING | PARTIALLY_FILLED | FILLED | REJECTED | CANCELLED | EXPIREDsettlementStatusPENDING | SETTLED | FAILEDorderLifecyclestring | nullEXPIRED for expiry; expiry is not a rejection.
cancelReasonstring | nullResponse codes
201Order placed.400Insufficient wallet balance.409Idempotency conflict — duplicate in-flight.422Business rule violation in production; master-account trading is not available in sandbox./users/{userId}/trade
Trade on behalf
Full endpoint documentationcreateUserTradePlaces a BUY or SELL order on behalf of a sub-account. The sub-account's wallet is escrowed for BUY orders; holdings are checked for SELL. The sub-account must have kycStatus: VERIFIED to trade. Pass Idempotency-Key to make trade retries safe.
Parameters
userIdstringpathRequiredExample: usr_abc123
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Idempotency-KeystringheaderRequiredUnique string that makes write calls safe to retry on network failure. Required for money movement, trading, KYC, subscriptions, and webhook creation. Deduplicated for 24 hours -- duplicate keys return the cached response. HTTP 409 if a concurrent request with the same key is still in progress.
Example: dep_user42_1743152580
Request body
fundingWalletCurrencystringConvert explicitly to USD before submitting an order
symbolstringRequiredStock symbol. Accepts exchange-qualified (SCOM.KE, DANGCEM.NG) or bare ticker (SCOM) -- auto-resolved when unambiguous. Returns 422 with match list if ambiguous.
Example: "SCOM.KE"
typeBUY | SELLRequiredOrder direction.
Example: "BUY"
quantitynumberNumber of shares. Whole-share markets require integer quantities; fractional-enabled markets allow up to 6 decimal places. Mutually exclusive with cashValue.
Example: 500
cashValuenumberUSD notional amount for cash-mode fractional investing. Mutually exclusive with quantity and must match the cashValue used to obtain quoteId for MARKET orders.
Example: 50
quoteIdstringFresh pre-trade quote ID from GET /quote/{symbol}. Quotes expire after 60 seconds and can be used once. Required for MARKET orders, including the default when orderType is omitted; ignored for LIMIT/STOP/STOP_LIMIT.
Example: "qt_2f4d5a7b8c9e4f01a2b3c4d5e6f78901"
orderTypeMARKET | LIMIT | STOP | STOP_LIMITMARKET (default): quote-gated and routed to automatic MyStocks internal-book execution. LIMIT/STOP/STOP_LIMIT are resting orders — they are placed WITHOUT a quote, escrow at the trigger price, rest in status WORKING, and route to automatic internal-book execution when the latest delayed price observation crosses the trigger (during market hours). BUY LIMIT fills at/below limitPrice; SELL LIMIT at/above; BUY STOP triggers at/above stopPrice; SELL STOP at/below. Prices are in the stock's LOCAL trading currency. Fires order.triggered on activation.
limitPricenumberLocal-currency limit price. Required for LIMIT and STOP_LIMIT.
stopPricenumberLocal-currency stop/trigger price. Required for STOP and STOP_LIMIT.
clientOrderIdstringOptional partner-supplied order reference. Must be unique per partner when supplied.
Example: "partner-ord-10001"
timeInForceDAY | GTC | GTDOrder validity instruction, enforced by the OMS lifecycle daemon. GTC (default) keeps the order live until executed or cancelled. DAY orders auto-cancel if not executed within 24 hours; GTD orders auto-cancel at expiresAt. On expiry, BUY escrow is refunded, SELL reservations are released, and an order.cancelled webhook fires. IOC is not supported by the current MyStocks internal-book order contract.
expiresAtstringRequired for GTD orders. Stored for OMS expiry governance.
orderInstructionstringOptional free-text execution instruction for the MyStocks internal-book engine.
stopLossnumberOptional. Order auto-cancels if the stock falls below this USD price before settlement.
Example: 0.11
takeProfitnumberOptional. Order auto-settles if the stock rises above this USD price before settlement.
Example: 0.16
Response fields
orderIdstringUnique order ID. Use to poll status or cancel.
Example: "ord_abc123xyz"
symbolstringExample: "SCOM.KE"
namestringExample: "Safaricom PLC"
exchangestringExample: "NSE"
orderTypeMARKET | LIMIT | STOP | STOP_LIMITOrder type. MARKET orders are quote-gated; LIMIT/STOP/STOP_LIMIT rest as WORKING until triggered.
Example: "LIMIT"
limitPricenumber | nullLimit price in the stock's local currency (LIMIT / STOP_LIMIT only).
stopPricenumber | nullStop price in the stock's local currency (STOP / STOP_LIMIT only).
cancelablebooleanWhether the order can be cancelled now (DELETE). True while PENDING or WORKING.
replaceablebooleanWhether the order can be modified now (PATCH). True only for a WORKING resting order.
typeBUY | SELLstatusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIREDPENDING after submission. WORKING = resting LIMIT/STOP/STOP_LIMIT order waiting for its trigger price (becomes PENDING on trigger). PARTIALLY_FILLED and FILLED are the canonical execution states. REJECTED, CANCELLED, and EXPIRED are terminal outcomes. PROCESSING is a legacy transition alias and COMPLETED is a v1 compatibility alias of FILLED; neither represents custody settlement. Settlement is tracked separately as PENDING, SETTLED, or FAILED.
quoteIdstring | nullPre-trade quote ID consumed by this order.
quoteExpiresAtstring | nullquoteUsdPricenumber | nullclientOrderIdstring | nullPartner-supplied order reference.
omsStatusstring | nullCanonical OMS lifecycle status.
timeInForcestring | nullfilledQuantitynumberremainingQuantitynumberaverageFillPricenumber | nullexecutionVenuestring | nulllastExecutionReportIdstring | nullexecutionSlaunionLive execution SLA clock for orders that have entered the PENDING dealing-desk queue. Null while a resting order is still WORKING.
quantityintegerpriceAtOrdernumberStock price in local currency at submission.
usdPriceAtOrdernumberUSD equivalent of priceAtOrder.
fxRateAtOrdernumber | nullManaged FX rate used for local-to-USD conversion at order submission.
fxSourcestring | nullfxRateAsOfstring | nullfxConversionunionfeenumberTotal fee in USD (base + partner markup).
baseFeenumberMyStocks base broker fee (0.75% of gross).
partnerMarkupFeenumberYour markup fee component. Zero if markupBps = 0.
totalAmountnumberBUY: gross + fee. SELL: gross - fee.
currencystringExample: "USD"
localCurrencystringExample: "KES"
rejectionCodestring | nullStructured rejection code. Populated when status = REJECTED.
rejectionReasonstring | nullFree-text rejection detail provided by the MyStocks internal-book execution service. Populated when status = REJECTED.
cancelledAtstring | nullsettledAtstring | nullSet when custody settlement completes; independent of the canonical FILLED execution state. Legacy completed records that pre-date this field return their immutable completion/creation timestamp as compatibility evidence.
createdAtstringcanonicalStatusPENDING | WORKING | PARTIALLY_FILLED | FILLED | REJECTED | CANCELLED | EXPIREDsettlementStatusPENDING | SETTLED | FAILEDorderLifecyclestring | nullEXPIRED for expiry; expiry is not a rejection.
cancelReasonstring | nullResponse codes
201Order placed.400Sub-account has insufficient wallet balance.403Sub-account is frozen or KYC not verified.422Market closed, ambiguous symbol, or invalid quantity.Production execution behavior
Production orders are operationally constrained by the exchange, the broker, and the available market data. Treat these guarantees as part of your client-state model:
| Field | Type | Required | Description |
|---|---|---|---|
| partial fills | behavior | No | Orders may fill partially. Use order status plus execution reports to show filledQuantity, remainingQuantity, and averageFillPrice when present. |
| average price | field | No | averageFillPrice is the weighted average of fills, not necessarily the quote price or the last market price. |
| slippage | guardrail | No | MARKET orders execute at available market prices inside the configured deviation band (default +/-10%). Orders outside that band are rejected or left pending for manual handling. |
| halts and auctions | market state | No | If an exchange is halted, in auction, closed, or missing a valid market price, MARKET orders are rejected or held pending; resting orders remain WORKING until normal trading resumes and their trigger is crossed. |
| order book depth | coverage | No | The Partner API does not contractually expose Level-2 depth. Use quoted/last prices for retail UX, and design advanced depth views only after a market-data vendor agreement is in place. |
List & fetch orders
List orders for the master account or a specific sub-account (cursor-paginated), or fetch a single
order by ID to poll status. Order fields include status, rejectionCode, rejectionReason, fee,
baseFee, partnerMarkupFee, and timestamps. Filter by ?status=PENDING, ?symbol=, or
?from=/?to= date range.
For sub-accounts, ?symbol=SCOM.KE is an exact, case-insensitive filter and can be combined with
status in production or sandbox without requiring a database composite index.
/orders
List orders
Full endpoint documentationlistOrdersReturns your partner order history. Filter by status, symbol, or date range. Filters from/to are enforced against createdAt. ISO dates cover full UTC days. Sparse matches may yield an empty page with hasMore=true; follow nextCursor. Each call scans at most 1000 source records. Invalid limits, dates and cursors return 400.
Parameters
statusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIREDquerysymbolstringqueryExample: SCOM.KE
fromstringqueryISO date (whole UTC day) or timezone-qualified ISO date-time; invalid or reversed bounds return 400.
Example: 2026-01-01
tostringqueryISO date (whole UTC day) or timezone-qualified ISO date-time; invalid or reversed bounds return 400.
Example: 2026-03-31
cursorstringqueryOpaque cursor from nextCursor of the previous response. Omit for the first page.
limitintegerqueryExample: 50
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Response fields
ordersobject[]Requiredorders[].orderIdstringUnique order ID. Use to poll status or cancel.
Example: "ord_abc123xyz"
orders[].symbolstringExample: "SCOM.KE"
orders[].namestringExample: "Safaricom PLC"
orders[].exchangestringExample: "NSE"
orders[].orderTypeMARKET | LIMIT | STOP | STOP_LIMITOrder type. MARKET orders are quote-gated; LIMIT/STOP/STOP_LIMIT rest as WORKING until triggered.
Example: "LIMIT"
orders[].limitPricenumber | nullLimit price in the stock's local currency (LIMIT / STOP_LIMIT only).
orders[].stopPricenumber | nullStop price in the stock's local currency (STOP / STOP_LIMIT only).
orders[].cancelablebooleanWhether the order can be cancelled now (DELETE). True while PENDING or WORKING.
orders[].replaceablebooleanWhether the order can be modified now (PATCH). True only for a WORKING resting order.
orders[].typeBUY | SELLorders[].statusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIREDPENDING after submission. WORKING = resting LIMIT/STOP/STOP_LIMIT order waiting for its trigger price (becomes PENDING on trigger). PARTIALLY_FILLED and FILLED are the canonical execution states. REJECTED, CANCELLED, and EXPIRED are terminal outcomes. PROCESSING is a legacy transition alias and COMPLETED is a v1 compatibility alias of FILLED; neither represents custody settlement. Settlement is tracked separately as PENDING, SETTLED, or FAILED.
orders[].quoteIdstring | nullPre-trade quote ID consumed by this order.
orders[].quoteExpiresAtstring | nullorders[].quoteUsdPricenumber | nullorders[].clientOrderIdstring | nullPartner-supplied order reference.
orders[].omsStatusstring | nullCanonical OMS lifecycle status.
orders[].timeInForcestring | nullorders[].filledQuantitynumberorders[].remainingQuantitynumberorders[].averageFillPricenumber | nullorders[].executionVenuestring | nullorders[].lastExecutionReportIdstring | nullorders[].executionSlaunionLive execution SLA clock for orders that have entered the PENDING dealing-desk queue. Null while a resting order is still WORKING.
orders[].quantityintegerorders[].priceAtOrdernumberStock price in local currency at submission.
orders[].usdPriceAtOrdernumberUSD equivalent of priceAtOrder.
orders[].fxRateAtOrdernumber | nullManaged FX rate used for local-to-USD conversion at order submission.
orders[].fxSourcestring | nullorders[].fxRateAsOfstring | nullorders[].fxConversionunionorders[].feenumberTotal fee in USD (base + partner markup).
orders[].baseFeenumberMyStocks base broker fee (0.75% of gross).
orders[].partnerMarkupFeenumberYour markup fee component. Zero if markupBps = 0.
orders[].totalAmountnumberBUY: gross + fee. SELL: gross - fee.
orders[].currencystringExample: "USD"
orders[].localCurrencystringExample: "KES"
orders[].rejectionCodestring | nullStructured rejection code. Populated when status = REJECTED.
orders[].rejectionReasonstring | nullFree-text rejection detail provided by the MyStocks internal-book execution service. Populated when status = REJECTED.
orders[].cancelledAtstring | nullorders[].settledAtstring | nullSet when custody settlement completes; independent of the canonical FILLED execution state. Legacy completed records that pre-date this field return their immutable completion/creation timestamp as compatibility evidence.
orders[].createdAtstringorders[].canonicalStatusPENDING | WORKING | PARTIALLY_FILLED | FILLED | REJECTED | CANCELLED | EXPIREDorders[].settlementStatusPENDING | SETTLED | FAILEDorders[].orderLifecyclestring | nullEXPIRED for expiry; expiry is not a rejection.
orders[].cancelReasonstring | nullcountintegerRequiredhasMorebooleanRequirednextCursorstring | nullRequiredResponse codes
200Order list./orders/{orderId}
Get order
Full endpoint documentationgetOrderReturns a single order by ID.
Parameters
orderIdstringpathRequiredExample: ord_abc123xyz
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Response fields
orderIdstringUnique order ID. Use to poll status or cancel.
Example: "ord_abc123xyz"
symbolstringExample: "SCOM.KE"
namestringExample: "Safaricom PLC"
exchangestringExample: "NSE"
orderTypeMARKET | LIMIT | STOP | STOP_LIMITOrder type. MARKET orders are quote-gated; LIMIT/STOP/STOP_LIMIT rest as WORKING until triggered.
Example: "LIMIT"
limitPricenumber | nullLimit price in the stock's local currency (LIMIT / STOP_LIMIT only).
stopPricenumber | nullStop price in the stock's local currency (STOP / STOP_LIMIT only).
cancelablebooleanWhether the order can be cancelled now (DELETE). True while PENDING or WORKING.
replaceablebooleanWhether the order can be modified now (PATCH). True only for a WORKING resting order.
typeBUY | SELLstatusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIREDPENDING after submission. WORKING = resting LIMIT/STOP/STOP_LIMIT order waiting for its trigger price (becomes PENDING on trigger). PARTIALLY_FILLED and FILLED are the canonical execution states. REJECTED, CANCELLED, and EXPIRED are terminal outcomes. PROCESSING is a legacy transition alias and COMPLETED is a v1 compatibility alias of FILLED; neither represents custody settlement. Settlement is tracked separately as PENDING, SETTLED, or FAILED.
quoteIdstring | nullPre-trade quote ID consumed by this order.
quoteExpiresAtstring | nullquoteUsdPricenumber | nullclientOrderIdstring | nullPartner-supplied order reference.
omsStatusstring | nullCanonical OMS lifecycle status.
timeInForcestring | nullfilledQuantitynumberremainingQuantitynumberaverageFillPricenumber | nullexecutionVenuestring | nulllastExecutionReportIdstring | nullexecutionSlaunionLive execution SLA clock for orders that have entered the PENDING dealing-desk queue. Null while a resting order is still WORKING.
quantityintegerpriceAtOrdernumberStock price in local currency at submission.
usdPriceAtOrdernumberUSD equivalent of priceAtOrder.
fxRateAtOrdernumber | nullManaged FX rate used for local-to-USD conversion at order submission.
fxSourcestring | nullfxRateAsOfstring | nullfxConversionunionfeenumberTotal fee in USD (base + partner markup).
baseFeenumberMyStocks base broker fee (0.75% of gross).
partnerMarkupFeenumberYour markup fee component. Zero if markupBps = 0.
totalAmountnumberBUY: gross + fee. SELL: gross - fee.
currencystringExample: "USD"
localCurrencystringExample: "KES"
rejectionCodestring | nullStructured rejection code. Populated when status = REJECTED.
rejectionReasonstring | nullFree-text rejection detail provided by the MyStocks internal-book execution service. Populated when status = REJECTED.
cancelledAtstring | nullsettledAtstring | nullSet when custody settlement completes; independent of the canonical FILLED execution state. Legacy completed records that pre-date this field return their immutable completion/creation timestamp as compatibility evidence.
createdAtstringcanonicalStatusPENDING | WORKING | PARTIALLY_FILLED | FILLED | REJECTED | CANCELLED | EXPIREDsettlementStatusPENDING | SETTLED | FAILEDorderLifecyclestring | nullEXPIRED for expiry; expiry is not a rejection.
cancelReasonstring | nullResponse codes
200Order detail.404Order not found./users/{userId}/orders
Sub-account orders
Full endpoint documentationlistUserOrdersReturns order history for a sub-account. Symbol and status filtering are performed without a Firestore composite-index dependency and work identically in production and sandbox.
Parameters
userIdstringpathRequiredExample: usr_abc123
statusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIREDquerysymbolstringqueryExact, case-insensitive exchange-qualified symbol (for example SCOM.KE).
cursorstringqueryOpaque cursor from nextCursor of the previous response. Omit for the first page.
fromstringqueryInclusive UTC date or timezone-aware ISO timestamp.
tostringqueryInclusive full UTC day or timezone-aware ISO timestamp.
limitintegerqueryExample: 50
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Response fields
ordersobject[]orders[].orderIdstringUnique order ID. Use to poll status or cancel.
Example: "ord_abc123xyz"
orders[].symbolstringExample: "SCOM.KE"
orders[].namestringExample: "Safaricom PLC"
orders[].exchangestringExample: "NSE"
orders[].orderTypeMARKET | LIMIT | STOP | STOP_LIMITOrder type. MARKET orders are quote-gated; LIMIT/STOP/STOP_LIMIT rest as WORKING until triggered.
Example: "LIMIT"
orders[].limitPricenumber | nullLimit price in the stock's local currency (LIMIT / STOP_LIMIT only).
orders[].stopPricenumber | nullStop price in the stock's local currency (STOP / STOP_LIMIT only).
orders[].cancelablebooleanWhether the order can be cancelled now (DELETE). True while PENDING or WORKING.
orders[].replaceablebooleanWhether the order can be modified now (PATCH). True only for a WORKING resting order.
orders[].typeBUY | SELLorders[].statusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIREDPENDING after submission. WORKING = resting LIMIT/STOP/STOP_LIMIT order waiting for its trigger price (becomes PENDING on trigger). PARTIALLY_FILLED and FILLED are the canonical execution states. REJECTED, CANCELLED, and EXPIRED are terminal outcomes. PROCESSING is a legacy transition alias and COMPLETED is a v1 compatibility alias of FILLED; neither represents custody settlement. Settlement is tracked separately as PENDING, SETTLED, or FAILED.
orders[].quoteIdstring | nullPre-trade quote ID consumed by this order.
orders[].quoteExpiresAtstring | nullorders[].quoteUsdPricenumber | nullorders[].clientOrderIdstring | nullPartner-supplied order reference.
orders[].omsStatusstring | nullCanonical OMS lifecycle status.
orders[].timeInForcestring | nullorders[].filledQuantitynumberorders[].remainingQuantitynumberorders[].averageFillPricenumber | nullorders[].executionVenuestring | nullorders[].lastExecutionReportIdstring | nullorders[].executionSlaunionLive execution SLA clock for orders that have entered the PENDING dealing-desk queue. Null while a resting order is still WORKING.
orders[].quantityintegerorders[].priceAtOrdernumberStock price in local currency at submission.
orders[].usdPriceAtOrdernumberUSD equivalent of priceAtOrder.
orders[].fxRateAtOrdernumber | nullManaged FX rate used for local-to-USD conversion at order submission.
orders[].fxSourcestring | nullorders[].fxRateAsOfstring | nullorders[].fxConversionunionorders[].feenumberTotal fee in USD (base + partner markup).
orders[].baseFeenumberMyStocks base broker fee (0.75% of gross).
orders[].partnerMarkupFeenumberYour markup fee component. Zero if markupBps = 0.
orders[].totalAmountnumberBUY: gross + fee. SELL: gross - fee.
orders[].currencystringExample: "USD"
orders[].localCurrencystringExample: "KES"
orders[].rejectionCodestring | nullStructured rejection code. Populated when status = REJECTED.
orders[].rejectionReasonstring | nullFree-text rejection detail provided by the MyStocks internal-book execution service. Populated when status = REJECTED.
orders[].cancelledAtstring | nullorders[].settledAtstring | nullSet when custody settlement completes; independent of the canonical FILLED execution state. Legacy completed records that pre-date this field return their immutable completion/creation timestamp as compatibility evidence.
orders[].createdAtstringorders[].canonicalStatusPENDING | WORKING | PARTIALLY_FILLED | FILLED | REJECTED | CANCELLED | EXPIREDorders[].settlementStatusPENDING | SETTLED | FAILEDorders[].orderLifecyclestring | nullEXPIRED for expiry; expiry is not a rejection.
orders[].cancelReasonstring | nulltotalintegerpageintegerResponse codes
200Order list.Cancel an order
Cancel an order while it is still PENDING (market orders awaiting fill) or WORKING (resting limit/stop
orders). BUY escrow is refunded atomically. Returns HTTP 409 once the order has reached a terminal state
(FILLED, CANCELLED, EXPIRED, or REJECTED). A successful cancellation fires an order.cancelled webhook.
Sandbox uses the same cancellation behavior for active resting/simulator orders, including BUY cash refunds and SELL unit-reservation release.
/orders/{orderId}
Cancel order
Full endpoint documentationdeleteOrdersCancels a PENDING order. Returns 422 if the order has already been settled or rejected.
Parameters
orderIdstringpathRequiredExample: ord_abc123xyz
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Idempotency-KeystringheaderRequiredUnique string that makes write calls safe to retry on network failure. Required for money movement, trading, KYC, subscriptions, and webhook creation. Deduplicated for 24 hours -- duplicate keys return the cached response. HTTP 409 if a concurrent request with the same key is still in progress.
Example: dep_user42_1743152580
Response fields
orderIdstringstatusCANCELLEDrefundednumberUSD amount returned to master wallet. Present for BUY orders only.
currencystringExample: "USD"
messagestringResponse codes
200Order cancelled. BUY escrow refunded atomically.409Order cannot be cancelled — it is no longer PENDING or WORKING (already PROCESSING, COMPLETED, or REJECTED)./users/{userId}/orders/{orderId}
Cancel sub-account order
Full endpoint documentationdeleteUsersUserIdOrdersOrderIdCancels an active PENDING or WORKING order on a sub-account and releases reserved cash or units. Available in production and sandbox; terminal orders return a conflict/error response.
Parameters
userIdstringpathRequiredExample: usr_abc123
orderIdstringpathRequiredExample: ord_abc123xyz
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Idempotency-KeystringheaderRequiredUnique string that makes write calls safe to retry on network failure. Required for money movement, trading, KYC, subscriptions, and webhook creation. Deduplicated for 24 hours -- duplicate keys return the cached response. HTTP 409 if a concurrent request with the same key is still in progress.
Example: dep_user42_1743152580
Response fields
orderIdstringsubAccountIdstringexternalIdstring | nulltypeBUY | SELLsymbolstringquantitynumberstatusCANCELLEDrefundednumberUSD amount returned to sub-account wallet. Present for BUY orders only.
currencystringExample: "USD"
messagestringResponse codes
200Order cancelled. BUY escrow refunded to sub-account wallet atomically.409Order cannot be cancelled — it is no longer PENDING.Transaction ledger
Full wallet ledger for a sub-account — every credit and debit in chronological order: deposits,
withdrawals, trade escrows (INVEST), trade proceeds (SELL), dividend distributions (DISTRIBUTION),
fund redemptions (REDEEM), and fees. Cursor-paginated.
settledAt is populated for completed transactions. For a legacy completed row created before that
field existed, the API returns its immutable completion/creation timestamp as compatibility evidence.
/users/{userId}/transactions
Sub-account transactions
Full endpoint documentationlistTransactionsReturns the full ledger transaction history for a sub-account — deposits, withdrawals, trade escrows (INVEST), trade settlements (SELL), dividend distributions, fund redemptions, and fee entries. Cursor-paginated; use nextCursor from the previous response as the cursor query param to fetch the next page.
Parameters
userIdstringpathRequiredExample: usr_abc123
typeDEPOSIT | WITHDRAWAL | INVEST | SELL | DISTRIBUTION | REDEEM | FEE | TRANSFER_IN | TRANSFER_OUT | SWAP | ACCOUNT_CLOSUREqueryFilter to a single transaction type. Empty filtered pages can have hasMore=true; continue with nextCursor.
fromstringqueryInclusive lower bound: YYYY-MM-DD in UTC or a timezone-aware ISO timestamp.
Example: 2026-01-01
tostringqueryInclusive upper bound: full UTC day including final milliseconds, or a timezone-aware ISO timestamp.
Example: 2026-06-30
cursorstringqueryOpaque cursor from nextCursor of the previous response. Omit for the first page.
limitintegerqueryExample: 50
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Response fields
transactionsobject[]transactions[].idstringtransactions[].typeDEPOSIT | WITHDRAWAL | INVEST | SELL | DISTRIBUTION | REDEEM | FEE | TRANSFER_IN | TRANSFER_OUT | SWAP | ACCOUNT_CLOSUREtransactions[].statusPENDING | COMPLETED | FAILEDtransactions[].directionCREDIT | DEBITtransactions[].amountnumbertransactions[].currencystringExample: "USD"
transactions[].descriptionstring | nulltransactions[].referencestring | nulltransactions[].createdAtstringtransactions[].settledAtstring | nullSettlement timestamp for completed rows. Legacy completed records return their immutable completion/creation timestamp when the original field was absent.
countintegerhasMorebooleannextCursorstring | nullResponse codes
200Transaction ledger.Portfolio
Holdings with current market value, cost basis, unrealized P&L, and currency. Also includes fund and bond positions if the account holds subscriptions.
/portfolio
Portfolio
Full endpoint documentationlistPortfolioReturns all open equity positions on your partner account — current holdings, average cost, unrealised P&L, and market value in USD.
Parameters
This endpoint has no path or query parameters.
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Response fields
accountTypeMASTER | SUBACCOUNTRequiredsubAccountIdstringexternalIdstringsummaryobjectRequiredsummary.walletBalancenumberRequiredsummary.portfolioValuenumberRequiredsummary.investedCapitalnumberRequiredsummary.unrealisedPnlnumberRequiredsummary.totalValuenumberRequiredholdingsobject[]Requiredholdings[].symbolstringRequiredholdings[].stockNamestring | nullholdings[].exchangestring | nullholdings[].currencystringRequiredholdings[].unitsnumberRequiredholdings[].avgCostnumberRequiredholdings[].currentUsdPricenumberRequiredholdings[].localPricenumberholdings[].currentValuenumberRequiredholdings[].investedCapitalnumberRequiredholdings[].unrealisedPnlnumberRequiredholdings[].priceIsLivebooleanRequiredBackwards-compatible freshness flag. True only when the production catalogue price is within the delayed-feed freshness window; never implies real-time tick data.
holdings[].lastPriceUpdatestring | nullholdings[].asOfstring | nullRequiredUpstream capture timestamp for the price used in this valuation.
holdings[].stalebooleanRequiredTrue when the price timestamp is missing or older than the published freshness window.
holdings[].priceSourcePRODUCTION_CATALOGUE | SANDBOX_HOLDINGRequiredholdings[].dataQualityobjectRequiredThe published market-data freshness contract. African equity quotes are supplied by the exchanges on a 15-minute-delayed basis, not in real time. MyStocks holds full exchange data rights. The API refresh target is 900 seconds during the published coverage window, with an end-of-day pass after market close.
holdings[].idstringLegacy master-account alias.
holdings[].namestring | nullLegacy alias of stockName.
holdings[].costBasisnumberLegacy alias of avgCost.
holdings[].amountInvestednumberLegacy alias of investedCapital.
holdings[].localCurrencystring | nullholdings[].gainLossnumberLegacy alias of unrealisedPnl.
holdings[].liquidityStatusstring | nullcountintegerLegacy master-account total retained for compatibility.
totalValuenumbertotalInvestednumbercurrencyUSDResponse codes
200Portfolio positions./users/{userId}/portfolio
Sub-account portfolio
Full endpoint documentationgetUserPortfolioReturns all open equity positions held by a sub-account, with current market value and unrealised P&L in USD.
Parameters
userIdstringpathRequiredExample: usr_abc123
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Response fields
subAccountIdstringexternalIdstringsummaryobjectsummary.walletBalancenumbersummary.portfolioValuenumbersummary.investedCapitalnumbersummary.unrealisedPnlnumbersummary.totalValuenumberholdingsobject[]holdings[].symbolstringholdings[].stockNamestring | nullholdings[].exchangestring | nullholdings[].currencystringholdings[].unitsnumberholdings[].avgCostnumberholdings[].currentUsdPricenumberholdings[].localPricenumberholdings[].currentValuenumberholdings[].investedCapitalnumberholdings[].unrealisedPnlnumberholdings[].priceIsLivebooleanBackwards-compatible freshness flag for the delayed production catalogue; never implies real-time tick data.
holdings[].lastPriceUpdatestring | nullholdings[].asOfstring | nullUpstream capture timestamp for the price used in this valuation.
holdings[].stalebooleanholdings[].priceSourcePRODUCTION_CATALOGUE | SANDBOX_HOLDINGholdings[].dataQualityobjectThe published market-data freshness contract. African equity quotes are supplied by the exchanges on a 15-minute-delayed basis, not in real time. MyStocks holds full exchange data rights. The API refresh target is 900 seconds during the published coverage window, with an end-of-day pass after market close.
Response codes
200Sub-account portfolio holdings and aggregate values.Was this page useful?
Your signal helps us tighten partner onboarding docs.
Last updated on