Skip to content
MyStocks Developers
API v1

API v1

Current stable contract

Versioning policyRelease changelog
Sandbox console
Trading API

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.

Quote
GET /quote/{symbol}
→
PENDING
POST /trade — escrowed
→
FILLED
order.filled

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).

GET

/quote/{symbol}

Pre-trade fee quote

Full endpoint documentation
Sandbox availablegetQuote

Returns 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

symbolstringpathRequired

Exchange-qualified ticker (e.g. SCOM.KE) or bare ticker.

Example: SCOM.KE

typeBUY | SELLquery

Order direction. Defaults to BUY.

Example: BUY

quantitynumberquery

Number of shares to quote (fractional allowed). Mutually exclusive with cashValue. Defaults to 1 when neither is passed.

Example: 500

cashValuenumberquery

USD 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

subAccountIdstringquery

Optional sub-account ID when quoting a trade for /users/{userId}/trade. The account must exist under the authenticated partner key.

Example: usr_abc123

Headers

AuthorizationstringRequired

Bearer sk_sandbox_<your_key> for sandbox requests.

Response fields

quoteIdstring

Quote ID to submit in the subsequent trade request.

quoteTtlSecondsinteger

Example: 60

quoteIssuedAtstring
quoteExpiresAtstring
sourceUpdatedAtstring | null

Timestamp of the source market price used for this quote.

dataFreshnessSecondsinteger | null

Age in seconds of the source market price when the quote was issued.

asOfstring | null

Canonical timestamp of the upstream price observation; equivalent to sourceUpdatedAt.

ageSecondsinteger | null

Canonical price age in seconds; equivalent to dataFreshnessSeconds.

staleboolean

True when the price observation is older than two refresh intervals.

delayModeDELAYED | END_OF_DAY
delayMinutesinteger

Example: 15

refreshIntervalSecondsinteger

Example: 900

providermstocks | mansa
disclaimerstring

Plain-English delayed-price warning.

dataQualityobject

The 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 | nullRequired

Timestamp of the exchange observation, not the time the API response was generated.

dataQuality.ageSecondsinteger | nullRequired

Age of the price in seconds (now − asOf).

dataQuality.stalebooleanRequired

True when the price is older than two refresh intervals.

dataQuality.delayModeDELAYED | END_OF_DAYRequired

DELAYED — 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.delayMinutesintegerRequired

Exchange feed latency class in minutes. This is distinct from the API refresh target.

Example: 15

dataQuality.refreshIntervalSecondsintegerRequired

Target interval between API ingestion refreshes during the published coverage window.

Example: 900

dataQuality.providermstocks | mansaRequired

MyStocks ingestion connector for this exchange feed. This field does not describe exchange licensing or partner entitlement.

dataQuality.disclaimerstringRequired

Plain-English statement of what this price is and is not.

symbolstring

Example: "SCOM.KE"

namestring
exchangestring
currencystring

Example: "KES"

ledgerCurrencystring

Example: "USD"

fxRatenumber

Managed FX rate used to convert local price to USD.

fxSourcestring

Example: "MYSTOCKS_MANAGED_FX"

fxRateAsOfstring | null
fxConversionobject
fxConversion.sourceCurrencystring

Example: "KES"

fxConversion.sourceAmountnumber

Example: 65000

fxConversion.targetCurrencystring

Example: "USD"

fxConversion.targetAmountnumber

Example: 500

fxConversion.ratenumber

Example: 130

fxConversion.rateConventionstring

Example: "KES per USD"

fxConversion.sourceMYSTOCKS_MANAGED_FX | PARTNER_PROVIDED_LEGACY
fxConversion.asOfstring | null
typeBUY | SELL
quantityinteger
localPricenumber

Current price in the stock's local currency.

usdPricenumber

Current price converted to USD.

grossnumber

quantity × usdPrice.

baseFeenumber

MyStocks base broker fee (0.75% of gross).

partnerMarkupFeenumber

Partner markup component of the fee. Zero if markupBps = 0.

feenumber

Total fee (baseFee + partnerMarkupFee).

feeRatenumber

Effective fee rate as a percentage (e.g. 0.75).

totalCostnumber

BUY only — gross + fee. The amount escrowed on order submission.

estimatedProceedsnumber

SELL only — gross - fee. Estimated wallet credit on settlement.

walletBalancenumber

Partner master wallet balance in USD.

sufficientFundsboolean

BUY only — true if walletBalance >= totalCost.

unitsnumber

SELL only — units of this stock currently held.

sufficientHoldingsboolean

SELL only — true if units >= quantity.

notestring

Example: "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.

POST

/trade

Place trade

Full endpoint documentation
Sandbox unsupportedcreateTrade

Places 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

AuthorizationstringRequired

Bearer sk_sandbox_<your_key> for sandbox requests.

Idempotency-KeystringheaderRequired

Unique 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

fundingWalletCurrencystring

Convert explicitly to USD before submitting an order

symbolstringRequired

Stock 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 | SELLRequired

Order direction.

Example: "BUY"

quantitynumber

Number of shares. Whole-share markets require integer quantities; fractional-enabled markets allow up to 6 decimal places. Mutually exclusive with cashValue.

Example: 500

cashValuenumber

USD 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

quoteIdstring

Fresh 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_LIMIT

MARKET (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.

limitPricenumber

Local-currency limit price. Required for LIMIT and STOP_LIMIT.

stopPricenumber

Local-currency stop/trigger price. Required for STOP and STOP_LIMIT.

clientOrderIdstring

Optional partner-supplied order reference. Must be unique per partner when supplied.

Example: "partner-ord-10001"

timeInForceDAY | GTC | GTD

Order 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.

expiresAtstring

Required for GTD orders. Stored for OMS expiry governance.

orderInstructionstring

Optional free-text execution instruction for the MyStocks internal-book engine.

stopLossnumber

Optional. Order auto-cancels if the stock falls below this USD price before settlement.

Example: 0.11

takeProfitnumber

Optional. Order auto-settles if the stock rises above this USD price before settlement.

Example: 0.16

Response fields

orderIdstring

Unique order ID. Use to poll status or cancel.

Example: "ord_abc123xyz"

symbolstring

Example: "SCOM.KE"

namestring

Example: "Safaricom PLC"

exchangestring

Example: "NSE"

orderTypeMARKET | LIMIT | STOP | STOP_LIMIT

Order type. MARKET orders are quote-gated; LIMIT/STOP/STOP_LIMIT rest as WORKING until triggered.

Example: "LIMIT"

limitPricenumber | null

Limit price in the stock's local currency (LIMIT / STOP_LIMIT only).

stopPricenumber | null

Stop price in the stock's local currency (STOP / STOP_LIMIT only).

cancelableboolean

Whether the order can be cancelled now (DELETE). True while PENDING or WORKING.

replaceableboolean

Whether the order can be modified now (PATCH). True only for a WORKING resting order.

typeBUY | SELL
statusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIRED

PENDING 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 | null

Pre-trade quote ID consumed by this order.

quoteExpiresAtstring | null
quoteUsdPricenumber | null
clientOrderIdstring | null

Partner-supplied order reference.

omsStatusstring | null

Canonical OMS lifecycle status.

timeInForcestring | null
filledQuantitynumber
remainingQuantitynumber
averageFillPricenumber | null
executionVenuestring | null
lastExecutionReportIdstring | null
executionSlaunion

Live execution SLA clock for orders that have entered the PENDING dealing-desk queue. Null while a resting order is still WORKING.

quantityinteger
priceAtOrdernumber

Stock price in local currency at submission.

usdPriceAtOrdernumber

USD equivalent of priceAtOrder.

fxRateAtOrdernumber | null

Managed FX rate used for local-to-USD conversion at order submission.

fxSourcestring | null
fxRateAsOfstring | null
fxConversionunion
feenumber

Total fee in USD (base + partner markup).

baseFeenumber

MyStocks base broker fee (0.75% of gross).

partnerMarkupFeenumber

Your markup fee component. Zero if markupBps = 0.

totalAmountnumber

BUY: gross + fee. SELL: gross - fee.

currencystring

Example: "USD"

localCurrencystring

Example: "KES"

rejectionCodestring | null

Structured rejection code. Populated when status = REJECTED.

rejectionReasonstring | null

Free-text rejection detail provided by the MyStocks internal-book execution service. Populated when status = REJECTED.

cancelledAtstring | null
settledAtstring | null

Set 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.

createdAtstring
canonicalStatusPENDING | WORKING | PARTIALLY_FILLED | FILLED | REJECTED | CANCELLED | EXPIRED
settlementStatusPENDING | SETTLED | FAILED
orderLifecyclestring | null

EXPIRED for expiry; expiry is not a rejection.

cancelReasonstring | null

Response codes

201Order placed.
400Insufficient wallet balance.
409Idempotency conflict — duplicate in-flight.
422Business rule violation in production; master-account trading is not available in sandbox.
POST

/users/{userId}/trade

Trade on behalf

Full endpoint documentation
Sandbox availablecreateUserTrade

Places 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

userIdstringpathRequired

Example: usr_abc123

Headers

AuthorizationstringRequired

Bearer sk_sandbox_<your_key> for sandbox requests.

Idempotency-KeystringheaderRequired

Unique 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

fundingWalletCurrencystring

Convert explicitly to USD before submitting an order

symbolstringRequired

Stock 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 | SELLRequired

Order direction.

Example: "BUY"

quantitynumber

Number of shares. Whole-share markets require integer quantities; fractional-enabled markets allow up to 6 decimal places. Mutually exclusive with cashValue.

Example: 500

cashValuenumber

USD 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

quoteIdstring

Fresh 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_LIMIT

MARKET (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.

limitPricenumber

Local-currency limit price. Required for LIMIT and STOP_LIMIT.

stopPricenumber

Local-currency stop/trigger price. Required for STOP and STOP_LIMIT.

clientOrderIdstring

Optional partner-supplied order reference. Must be unique per partner when supplied.

Example: "partner-ord-10001"

timeInForceDAY | GTC | GTD

Order 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.

expiresAtstring

Required for GTD orders. Stored for OMS expiry governance.

orderInstructionstring

Optional free-text execution instruction for the MyStocks internal-book engine.

stopLossnumber

Optional. Order auto-cancels if the stock falls below this USD price before settlement.

Example: 0.11

takeProfitnumber

Optional. Order auto-settles if the stock rises above this USD price before settlement.

Example: 0.16

Response fields

orderIdstring

Unique order ID. Use to poll status or cancel.

Example: "ord_abc123xyz"

symbolstring

Example: "SCOM.KE"

namestring

Example: "Safaricom PLC"

exchangestring

Example: "NSE"

orderTypeMARKET | LIMIT | STOP | STOP_LIMIT

Order type. MARKET orders are quote-gated; LIMIT/STOP/STOP_LIMIT rest as WORKING until triggered.

Example: "LIMIT"

limitPricenumber | null

Limit price in the stock's local currency (LIMIT / STOP_LIMIT only).

stopPricenumber | null

Stop price in the stock's local currency (STOP / STOP_LIMIT only).

cancelableboolean

Whether the order can be cancelled now (DELETE). True while PENDING or WORKING.

replaceableboolean

Whether the order can be modified now (PATCH). True only for a WORKING resting order.

typeBUY | SELL
statusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIRED

PENDING 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 | null

Pre-trade quote ID consumed by this order.

quoteExpiresAtstring | null
quoteUsdPricenumber | null
clientOrderIdstring | null

Partner-supplied order reference.

omsStatusstring | null

Canonical OMS lifecycle status.

timeInForcestring | null
filledQuantitynumber
remainingQuantitynumber
averageFillPricenumber | null
executionVenuestring | null
lastExecutionReportIdstring | null
executionSlaunion

Live execution SLA clock for orders that have entered the PENDING dealing-desk queue. Null while a resting order is still WORKING.

quantityinteger
priceAtOrdernumber

Stock price in local currency at submission.

usdPriceAtOrdernumber

USD equivalent of priceAtOrder.

fxRateAtOrdernumber | null

Managed FX rate used for local-to-USD conversion at order submission.

fxSourcestring | null
fxRateAsOfstring | null
fxConversionunion
feenumber

Total fee in USD (base + partner markup).

baseFeenumber

MyStocks base broker fee (0.75% of gross).

partnerMarkupFeenumber

Your markup fee component. Zero if markupBps = 0.

totalAmountnumber

BUY: gross + fee. SELL: gross - fee.

currencystring

Example: "USD"

localCurrencystring

Example: "KES"

rejectionCodestring | null

Structured rejection code. Populated when status = REJECTED.

rejectionReasonstring | null

Free-text rejection detail provided by the MyStocks internal-book execution service. Populated when status = REJECTED.

cancelledAtstring | null
settledAtstring | null

Set 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.

createdAtstring
canonicalStatusPENDING | WORKING | PARTIALLY_FILLED | FILLED | REJECTED | CANCELLED | EXPIRED
settlementStatusPENDING | SETTLED | FAILED
orderLifecyclestring | null

EXPIRED for expiry; expiry is not a rejection.

cancelReasonstring | null

Response 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:

FieldTypeRequiredDescription
partial fillsbehaviorNoOrders may fill partially. Use order status plus execution reports to show filledQuantity, remainingQuantity, and averageFillPrice when present.
average pricefieldNoaverageFillPrice is the weighted average of fills, not necessarily the quote price or the last market price.
slippageguardrailNoMARKET 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 auctionsmarket stateNoIf 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 depthcoverageNoThe 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.

GET

/orders

List orders

Full endpoint documentation
Sandbox availablelistOrders

Returns 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 | EXPIREDquery
symbolstringquery

Example: SCOM.KE

fromstringquery

ISO date (whole UTC day) or timezone-qualified ISO date-time; invalid or reversed bounds return 400.

Example: 2026-01-01

tostringquery

ISO date (whole UTC day) or timezone-qualified ISO date-time; invalid or reversed bounds return 400.

Example: 2026-03-31

cursorstringquery

Opaque cursor from nextCursor of the previous response. Omit for the first page.

limitintegerquery

Example: 50

Headers

AuthorizationstringRequired

Bearer sk_sandbox_<your_key> for sandbox requests.

Response fields

ordersobject[]Required
orders[].orderIdstring

Unique order ID. Use to poll status or cancel.

Example: "ord_abc123xyz"

orders[].symbolstring

Example: "SCOM.KE"

orders[].namestring

Example: "Safaricom PLC"

orders[].exchangestring

Example: "NSE"

orders[].orderTypeMARKET | LIMIT | STOP | STOP_LIMIT

Order type. MARKET orders are quote-gated; LIMIT/STOP/STOP_LIMIT rest as WORKING until triggered.

Example: "LIMIT"

orders[].limitPricenumber | null

Limit price in the stock's local currency (LIMIT / STOP_LIMIT only).

orders[].stopPricenumber | null

Stop price in the stock's local currency (STOP / STOP_LIMIT only).

orders[].cancelableboolean

Whether the order can be cancelled now (DELETE). True while PENDING or WORKING.

orders[].replaceableboolean

Whether the order can be modified now (PATCH). True only for a WORKING resting order.

orders[].typeBUY | SELL
orders[].statusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIRED

PENDING 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 | null

Pre-trade quote ID consumed by this order.

orders[].quoteExpiresAtstring | null
orders[].quoteUsdPricenumber | null
orders[].clientOrderIdstring | null

Partner-supplied order reference.

orders[].omsStatusstring | null

Canonical OMS lifecycle status.

orders[].timeInForcestring | null
orders[].filledQuantitynumber
orders[].remainingQuantitynumber
orders[].averageFillPricenumber | null
orders[].executionVenuestring | null
orders[].lastExecutionReportIdstring | null
orders[].executionSlaunion

Live execution SLA clock for orders that have entered the PENDING dealing-desk queue. Null while a resting order is still WORKING.

orders[].quantityinteger
orders[].priceAtOrdernumber

Stock price in local currency at submission.

orders[].usdPriceAtOrdernumber

USD equivalent of priceAtOrder.

orders[].fxRateAtOrdernumber | null

Managed FX rate used for local-to-USD conversion at order submission.

orders[].fxSourcestring | null
orders[].fxRateAsOfstring | null
orders[].fxConversionunion
orders[].feenumber

Total fee in USD (base + partner markup).

orders[].baseFeenumber

MyStocks base broker fee (0.75% of gross).

orders[].partnerMarkupFeenumber

Your markup fee component. Zero if markupBps = 0.

orders[].totalAmountnumber

BUY: gross + fee. SELL: gross - fee.

orders[].currencystring

Example: "USD"

orders[].localCurrencystring

Example: "KES"

orders[].rejectionCodestring | null

Structured rejection code. Populated when status = REJECTED.

orders[].rejectionReasonstring | null

Free-text rejection detail provided by the MyStocks internal-book execution service. Populated when status = REJECTED.

orders[].cancelledAtstring | null
orders[].settledAtstring | null

Set 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[].createdAtstring
orders[].canonicalStatusPENDING | WORKING | PARTIALLY_FILLED | FILLED | REJECTED | CANCELLED | EXPIRED
orders[].settlementStatusPENDING | SETTLED | FAILED
orders[].orderLifecyclestring | null

EXPIRED for expiry; expiry is not a rejection.

orders[].cancelReasonstring | null
countintegerRequired
hasMorebooleanRequired
nextCursorstring | nullRequired

Response codes

200Order list.
GET

/orders/{orderId}

Get order

Full endpoint documentation
Sandbox unsupportedgetOrder

Returns a single order by ID.

Parameters

orderIdstringpathRequired

Example: ord_abc123xyz

Headers

AuthorizationstringRequired

Bearer sk_sandbox_<your_key> for sandbox requests.

Response fields

orderIdstring

Unique order ID. Use to poll status or cancel.

Example: "ord_abc123xyz"

symbolstring

Example: "SCOM.KE"

namestring

Example: "Safaricom PLC"

exchangestring

Example: "NSE"

orderTypeMARKET | LIMIT | STOP | STOP_LIMIT

Order type. MARKET orders are quote-gated; LIMIT/STOP/STOP_LIMIT rest as WORKING until triggered.

Example: "LIMIT"

limitPricenumber | null

Limit price in the stock's local currency (LIMIT / STOP_LIMIT only).

stopPricenumber | null

Stop price in the stock's local currency (STOP / STOP_LIMIT only).

cancelableboolean

Whether the order can be cancelled now (DELETE). True while PENDING or WORKING.

replaceableboolean

Whether the order can be modified now (PATCH). True only for a WORKING resting order.

typeBUY | SELL
statusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIRED

PENDING 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 | null

Pre-trade quote ID consumed by this order.

quoteExpiresAtstring | null
quoteUsdPricenumber | null
clientOrderIdstring | null

Partner-supplied order reference.

omsStatusstring | null

Canonical OMS lifecycle status.

timeInForcestring | null
filledQuantitynumber
remainingQuantitynumber
averageFillPricenumber | null
executionVenuestring | null
lastExecutionReportIdstring | null
executionSlaunion

Live execution SLA clock for orders that have entered the PENDING dealing-desk queue. Null while a resting order is still WORKING.

quantityinteger
priceAtOrdernumber

Stock price in local currency at submission.

usdPriceAtOrdernumber

USD equivalent of priceAtOrder.

fxRateAtOrdernumber | null

Managed FX rate used for local-to-USD conversion at order submission.

fxSourcestring | null
fxRateAsOfstring | null
fxConversionunion
feenumber

Total fee in USD (base + partner markup).

baseFeenumber

MyStocks base broker fee (0.75% of gross).

partnerMarkupFeenumber

Your markup fee component. Zero if markupBps = 0.

totalAmountnumber

BUY: gross + fee. SELL: gross - fee.

currencystring

Example: "USD"

localCurrencystring

Example: "KES"

rejectionCodestring | null

Structured rejection code. Populated when status = REJECTED.

rejectionReasonstring | null

Free-text rejection detail provided by the MyStocks internal-book execution service. Populated when status = REJECTED.

cancelledAtstring | null
settledAtstring | null

Set 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.

createdAtstring
canonicalStatusPENDING | WORKING | PARTIALLY_FILLED | FILLED | REJECTED | CANCELLED | EXPIRED
settlementStatusPENDING | SETTLED | FAILED
orderLifecyclestring | null

EXPIRED for expiry; expiry is not a rejection.

cancelReasonstring | null

Response codes

200Order detail.
404Order not found.
GET

/users/{userId}/orders

Sub-account orders

Full endpoint documentation
Sandbox availablelistUserOrders

Returns 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

userIdstringpathRequired

Example: usr_abc123

statusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIREDquery
symbolstringquery

Exact, case-insensitive exchange-qualified symbol (for example SCOM.KE).

cursorstringquery

Opaque cursor from nextCursor of the previous response. Omit for the first page.

fromstringquery

Inclusive UTC date or timezone-aware ISO timestamp.

tostringquery

Inclusive full UTC day or timezone-aware ISO timestamp.

limitintegerquery

Example: 50

Headers

AuthorizationstringRequired

Bearer sk_sandbox_<your_key> for sandbox requests.

Response fields

ordersobject[]
orders[].orderIdstring

Unique order ID. Use to poll status or cancel.

Example: "ord_abc123xyz"

orders[].symbolstring

Example: "SCOM.KE"

orders[].namestring

Example: "Safaricom PLC"

orders[].exchangestring

Example: "NSE"

orders[].orderTypeMARKET | LIMIT | STOP | STOP_LIMIT

Order type. MARKET orders are quote-gated; LIMIT/STOP/STOP_LIMIT rest as WORKING until triggered.

Example: "LIMIT"

orders[].limitPricenumber | null

Limit price in the stock's local currency (LIMIT / STOP_LIMIT only).

orders[].stopPricenumber | null

Stop price in the stock's local currency (STOP / STOP_LIMIT only).

orders[].cancelableboolean

Whether the order can be cancelled now (DELETE). True while PENDING or WORKING.

orders[].replaceableboolean

Whether the order can be modified now (PATCH). True only for a WORKING resting order.

orders[].typeBUY | SELL
orders[].statusPENDING | WORKING | PARTIALLY_FILLED | PROCESSING | COMPLETED | FILLED | REJECTED | CANCELLED | EXPIRED

PENDING 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 | null

Pre-trade quote ID consumed by this order.

orders[].quoteExpiresAtstring | null
orders[].quoteUsdPricenumber | null
orders[].clientOrderIdstring | null

Partner-supplied order reference.

orders[].omsStatusstring | null

Canonical OMS lifecycle status.

orders[].timeInForcestring | null
orders[].filledQuantitynumber
orders[].remainingQuantitynumber
orders[].averageFillPricenumber | null
orders[].executionVenuestring | null
orders[].lastExecutionReportIdstring | null
orders[].executionSlaunion

Live execution SLA clock for orders that have entered the PENDING dealing-desk queue. Null while a resting order is still WORKING.

orders[].quantityinteger
orders[].priceAtOrdernumber

Stock price in local currency at submission.

orders[].usdPriceAtOrdernumber

USD equivalent of priceAtOrder.

orders[].fxRateAtOrdernumber | null

Managed FX rate used for local-to-USD conversion at order submission.

orders[].fxSourcestring | null
orders[].fxRateAsOfstring | null
orders[].fxConversionunion
orders[].feenumber

Total fee in USD (base + partner markup).

orders[].baseFeenumber

MyStocks base broker fee (0.75% of gross).

orders[].partnerMarkupFeenumber

Your markup fee component. Zero if markupBps = 0.

orders[].totalAmountnumber

BUY: gross + fee. SELL: gross - fee.

orders[].currencystring

Example: "USD"

orders[].localCurrencystring

Example: "KES"

orders[].rejectionCodestring | null

Structured rejection code. Populated when status = REJECTED.

orders[].rejectionReasonstring | null

Free-text rejection detail provided by the MyStocks internal-book execution service. Populated when status = REJECTED.

orders[].cancelledAtstring | null
orders[].settledAtstring | null

Set 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[].createdAtstring
orders[].canonicalStatusPENDING | WORKING | PARTIALLY_FILLED | FILLED | REJECTED | CANCELLED | EXPIRED
orders[].settlementStatusPENDING | SETTLED | FAILED
orders[].orderLifecyclestring | null

EXPIRED for expiry; expiry is not a rejection.

orders[].cancelReasonstring | null
totalinteger
pageinteger

Response 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.

DELETE

/orders/{orderId}

Cancel order

Full endpoint documentation
Sandbox unsupporteddeleteOrders

Cancels a PENDING order. Returns 422 if the order has already been settled or rejected.

Parameters

orderIdstringpathRequired

Example: ord_abc123xyz

Headers

AuthorizationstringRequired

Bearer sk_sandbox_<your_key> for sandbox requests.

Idempotency-KeystringheaderRequired

Unique 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

orderIdstring
statusCANCELLED
refundednumber

USD amount returned to master wallet. Present for BUY orders only.

currencystring

Example: "USD"

messagestring

Response codes

200Order cancelled. BUY escrow refunded atomically.
409Order cannot be cancelled — it is no longer PENDING or WORKING (already PROCESSING, COMPLETED, or REJECTED).
DELETE

/users/{userId}/orders/{orderId}

Cancel sub-account order

Full endpoint documentation
Sandbox availabledeleteUsersUserIdOrdersOrderId

Cancels 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

userIdstringpathRequired

Example: usr_abc123

orderIdstringpathRequired

Example: ord_abc123xyz

Headers

AuthorizationstringRequired

Bearer sk_sandbox_<your_key> for sandbox requests.

Idempotency-KeystringheaderRequired

Unique 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

orderIdstring
subAccountIdstring
externalIdstring | null
typeBUY | SELL
symbolstring
quantitynumber
statusCANCELLED
refundednumber

USD amount returned to sub-account wallet. Present for BUY orders only.

currencystring

Example: "USD"

messagestring

Response 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.

GET

/users/{userId}/transactions

Sub-account transactions

Full endpoint documentation
Sandbox availablelistTransactions

Returns 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

userIdstringpathRequired

Example: usr_abc123

typeDEPOSIT | WITHDRAWAL | INVEST | SELL | DISTRIBUTION | REDEEM | FEE | TRANSFER_IN | TRANSFER_OUT | SWAP | ACCOUNT_CLOSUREquery

Filter to a single transaction type. Empty filtered pages can have hasMore=true; continue with nextCursor.

fromstringquery

Inclusive lower bound: YYYY-MM-DD in UTC or a timezone-aware ISO timestamp.

Example: 2026-01-01

tostringquery

Inclusive upper bound: full UTC day including final milliseconds, or a timezone-aware ISO timestamp.

Example: 2026-06-30

cursorstringquery

Opaque cursor from nextCursor of the previous response. Omit for the first page.

limitintegerquery

Example: 50

Headers

AuthorizationstringRequired

Bearer sk_sandbox_<your_key> for sandbox requests.

Response fields

transactionsobject[]
transactions[].idstring
transactions[].typeDEPOSIT | WITHDRAWAL | INVEST | SELL | DISTRIBUTION | REDEEM | FEE | TRANSFER_IN | TRANSFER_OUT | SWAP | ACCOUNT_CLOSURE
transactions[].statusPENDING | COMPLETED | FAILED
transactions[].directionCREDIT | DEBIT
transactions[].amountnumber
transactions[].currencystring

Example: "USD"

transactions[].descriptionstring | null
transactions[].referencestring | null
transactions[].createdAtstring
transactions[].settledAtstring | null

Settlement timestamp for completed rows. Legacy completed records return their immutable completion/creation timestamp when the original field was absent.

countinteger
hasMoreboolean
nextCursorstring | null

Response 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.

GET

/portfolio

Portfolio

Full endpoint documentation
Sandbox availablelistPortfolio

Returns 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

AuthorizationstringRequired

Bearer sk_sandbox_<your_key> for sandbox requests.

Response fields

accountTypeMASTER | SUBACCOUNTRequired
subAccountIdstring
externalIdstring
summaryobjectRequired
summary.walletBalancenumberRequired
summary.portfolioValuenumberRequired
summary.investedCapitalnumberRequired
summary.unrealisedPnlnumberRequired
summary.totalValuenumberRequired
holdingsobject[]Required
holdings[].symbolstringRequired
holdings[].stockNamestring | null
holdings[].exchangestring | null
holdings[].currencystringRequired
holdings[].unitsnumberRequired
holdings[].avgCostnumberRequired
holdings[].currentUsdPricenumberRequired
holdings[].localPricenumber
holdings[].currentValuenumberRequired
holdings[].investedCapitalnumberRequired
holdings[].unrealisedPnlnumberRequired
holdings[].priceIsLivebooleanRequired

Backwards-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 | null
holdings[].asOfstring | nullRequired

Upstream capture timestamp for the price used in this valuation.

holdings[].stalebooleanRequired

True when the price timestamp is missing or older than the published freshness window.

holdings[].priceSourcePRODUCTION_CATALOGUE | SANDBOX_HOLDINGRequired
holdings[].dataQualityobjectRequired

The 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[].idstring

Legacy master-account alias.

holdings[].namestring | null

Legacy alias of stockName.

holdings[].costBasisnumber

Legacy alias of avgCost.

holdings[].amountInvestednumber

Legacy alias of investedCapital.

holdings[].localCurrencystring | null
holdings[].gainLossnumber

Legacy alias of unrealisedPnl.

holdings[].liquidityStatusstring | null
countinteger

Legacy master-account total retained for compatibility.

totalValuenumber
totalInvestednumber
currencyUSD

Response codes

200Portfolio positions.
GET

/users/{userId}/portfolio

Sub-account portfolio

Full endpoint documentation
Sandbox availablegetUserPortfolio

Returns all open equity positions held by a sub-account, with current market value and unrealised P&L in USD.

Parameters

userIdstringpathRequired

Example: usr_abc123

Headers

AuthorizationstringRequired

Bearer sk_sandbox_<your_key> for sandbox requests.

Response fields

subAccountIdstring
externalIdstring
summaryobject
summary.walletBalancenumber
summary.portfolioValuenumber
summary.investedCapitalnumber
summary.unrealisedPnlnumber
summary.totalValuenumber
holdingsobject[]
holdings[].symbolstring
holdings[].stockNamestring | null
holdings[].exchangestring | null
holdings[].currencystring
holdings[].unitsnumber
holdings[].avgCostnumber
holdings[].currentUsdPricenumber
holdings[].localPricenumber
holdings[].currentValuenumber
holdings[].investedCapitalnumber
holdings[].unrealisedPnlnumber
holdings[].priceIsLiveboolean

Backwards-compatible freshness flag for the delayed production catalogue; never implies real-time tick data.

holdings[].lastPriceUpdatestring | null
holdings[].asOfstring | null

Upstream capture timestamp for the price used in this valuation.

holdings[].staleboolean
holdings[].priceSourcePRODUCTION_CATALOGUE | SANDBOX_HOLDING
holdings[].dataQualityobject

The 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.

Send note

Last updated on

On this page