Webhooks
Register HTTPS endpoints for real-time event notifications, HMAC-SHA256-signed over the raw body. Full event catalogue, per-event payloads, signature-verification code (Node & Python), at-least-once delivery semantics, and the delivery log.
Register HTTPS endpoints to receive real-time event notifications. MyStocks signs every delivery with
an HMAC-SHA256 signature over the raw request body using your webhook secret. Your endpoint must
respond HTTP 2xx within 8 seconds; heavy processing should be deferred to a background queue.
Failed deliveries are retried with exponential backoff — check the delivery log via
GET /webhooks/{id}/deliveries.
For mobile foreground UX, use GET /stream Server-Sent Events to receive the same partner events
with near-real-time delivery and resume via Last-Event-ID / ?since=. Webhooks and SSE carry order,
wallet, KYC, dividend, account, and market-status events; they do not provide tick-by-tick quotes
or Level-2 order book depth. Poll /market/quotes for fresh displayed prices, and use the
/users/{userId}/devices endpoints to manage your own APNs/FCM/Expo/Web Push fanout.
Register a webhook
/webhooks
Register webhook
Full endpoint documentationcreateWebhooksRegisters a new HTTPS webhook endpoint. MyStocks sends a POST to your URL for each subscribed event. Verification — every delivery includes an x-mystocks-signature header: HMAC-SHA256(secret, rawBody) hex-encoded. Verify it before processing. Retries — failed deliveries are retried with exponential back-off: up to 6 attempts total (immediate, then 5 s, 30 s, 5 min, 30 min, 2 h). Your endpoint must respond 2xx within 8 seconds or the delivery attempt is marked failed. Delivery semantics — at-least-once. The same event can be delivered more than once (e.g. your endpoint responded slowly and the delivery was retried), and events are not guaranteed to arrive in order. Deduplicate by event id and treat handlers as idempotent.
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
urlstringRequiredHTTPS endpoint that receives POST requests. Must respond 2xx within 8 seconds.
Example: "https://yourapp.com/webhooks/mystocks"
eventsstring[]RequiredEvent types to subscribe to.
Example: ["trade.settled","deposit.confirmed","kyc.updated"]
secretstringHMAC-SHA256 signing secret (min 16 chars). MyStocks sends x-mystocks-signature on every delivery.
Example: "my-signing-secret-min-16-chars"
Response fields
idstringUnique webhook ID.
Example: "wh_abc123"
urlstringExample: "https://yourapp.com/webhooks/mystocks"
eventsstring[]Subscribed event types.
statusactive | disabledResponse codes
201Webhook registered.Event catalogue
| Event | Trigger |
|---|---|
order.pending | An order was submitted and is awaiting live fill. |
order.filled | An order was filled and executed. Shares/proceeds credited. |
order.rejected | An order was declined. Includes rejectionCode and rejectionReason. |
order.cancelled | An order was cancelled via DELETE /orders/{orderId}. |
order.replaced | A resting order was modified via PATCH /users/{userId}/orders/{orderId} (same orderId). |
trade.settled | Alias for order.filled — use order.filled in new integrations. |
trade.rejected | Alias for order.rejected — use order.rejected in new integrations. |
deposit.confirmed | A sub-account deposit was recorded. |
withdraw.confirmed | A sub-account withdrawal was processed. |
wallet.credited | Master wallet received a top-up from MyStocks ops. |
kyc.updated | A sub-account KYC status changed. Inspect kycStatus: VERIFIED unlocks trading; REJECTED includes reason evidence and remains blocked. |
account.frozen | A sub-account was frozen (or unfrozen) by partner or MyStocks compliance. |
account.closed | A sub-account was soft-closed/offboarded via DELETE /users/{userId}. |
dividend.paid | A dividend was received and credited to a sub-account. |
corporateaction.declared | Generic corporate-action event for backwards compatibility. |
corporateaction.split | Stock split, reverse split, or bonus issue affecting holdings. |
corporateaction.suspension | Trading suspension or halt affecting a listed security. |
corporateaction.delisting | Delisting event for a listed security. |
corporateaction.rights_issue | Rights issue or similar subscription entitlement. |
corporateaction.symbol_changed | Ticker/symbol migration, rename, or exchange code change. |
quote.expired | A tradeable quote reached its 60-second TTL without being used. |
price.alert | A price alert you registered crossed its threshold. See Price alerts. |
market.status | An exchange changed phase (OPEN/CLOSED/HOLIDAY). |
incident.declared | A platform incident affecting your integration was opened. |
incident.resolved | A previously declared incident was closed. |
Price alerts
price.alert does not fire on its own — you subscribe to the thresholds you care about. Register one
with POST /price-alerts; threshold is in the instrument's local trading currency, the same
basis as a quote's price.
Alerts are evaluated against the live price and only while the exchange is open, so a stale
closing price can never trigger one. Because quotes are polled on a ~15-minute cycle
(see Data freshness), an alert fires on the first poll after the
crossing — not at the instant of the tick. Do not use price.alert as an execution trigger; use a
resting LIMIT or STOP order, which is evaluated on the same cycle but actually places the trade.
List with GET /price-alerts, inspect one with GET /price-alerts/{alertId}, and remove one with
DELETE /price-alerts/{alertId}. You may hold up to 200 active alerts.
/price-alerts
Create a price alert
Full endpoint documentationcreatePriceAlertRegisters a price alert. When the latest delayed price observation crosses the threshold while the exchange is open, a price.alert webhook fires and the event is streamed on GET /stream. threshold is in the instrument's LOCAL trading currency — the same basis as a quote's price. Alerts are evaluated on the same ~15-minute polling cycle as quotes, so an alert fires on the first poll after the crossing, not at the instant of the tick. Do not use a price alert as an execution trigger — place a resting LIMIT or STOP order instead. Maximum 200 active alerts per partner. Requires a full key (pk_live_).
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
symbolstringRequiredExample: "SCOM.KE"
exchangestringRequiredExample: "NSE"
conditionabove | belowRequiredthresholdnumberRequiredPositive, in the instrument's local trading currency.
Example: 20
repeatbooleanWhen false (default) the alert fires once and disarms. When true it re-arms, but only after the price crosses back through the threshold, so a price hovering at the threshold cannot spam your endpoint.
clientAlertIdstringYour own reference, echoed back on the alert and in the webhook payload.
Response fields
alertIdstringExample: "alr_abc123"
clientAlertIdstringYour own reference, supplied at creation.
symbolstringExample: "SCOM.KE"
exchangestringExample: "NSE"
conditionabove | belowthresholdnumberIn the instrument's local trading currency.
Example: 20
currencystringThe local trading currency the threshold is denominated in.
Example: "KES"
repeatbooleanstateARMED | TRIGGERED | DISARMEDARMED — waiting for the threshold to be crossed. TRIGGERED — a repeat alert that has fired and is waiting for the price to cross back before re-arming. DISARMED — a one-shot alert that has fired and is spent.
lastPriceLocalnumbertriggerCountintegercreatedAtstringlastTriggeredAtstringResponse codes
201Alert created and armed.400Invalid body, unknown symbol, or the active-alert cap was reached./price-alerts
List price alerts
Full endpoint documentationlistPriceAlertsReturns the price alerts registered by this partner.
Parameters
stateARMED | TRIGGERED | DISARMEDqueryFilter by alert state.
limitintegerqueryExample: 100
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Response fields
dataobject[]data[].alertIdstringExample: "alr_abc123"
data[].clientAlertIdstringYour own reference, supplied at creation.
data[].symbolstringExample: "SCOM.KE"
data[].exchangestringExample: "NSE"
data[].conditionabove | belowdata[].thresholdnumberIn the instrument's local trading currency.
Example: 20
data[].currencystringThe local trading currency the threshold is denominated in.
Example: "KES"
data[].repeatbooleandata[].stateARMED | TRIGGERED | DISARMEDARMED — waiting for the threshold to be crossed. TRIGGERED — a repeat alert that has fired and is waiting for the price to cross back before re-arming. DISARMED — a one-shot alert that has fired and is spent.
data[].lastPriceLocalnumberdata[].triggerCountintegerdata[].createdAtstringdata[].lastTriggeredAtstringResponse codes
200The partner's price alerts./price-alerts/{alertId}
Get a price alert
Full endpoint documentationgetPriceAlertParameters
alertIdstringpathRequiredExample: alr_abc123
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Response fields
alertIdstringExample: "alr_abc123"
clientAlertIdstringYour own reference, supplied at creation.
symbolstringExample: "SCOM.KE"
exchangestringExample: "NSE"
conditionabove | belowthresholdnumberIn the instrument's local trading currency.
Example: 20
currencystringThe local trading currency the threshold is denominated in.
Example: "KES"
repeatbooleanstateARMED | TRIGGERED | DISARMEDARMED — waiting for the threshold to be crossed. TRIGGERED — a repeat alert that has fired and is waiting for the price to cross back before re-arming. DISARMED — a one-shot alert that has fired and is spent.
lastPriceLocalnumbertriggerCountintegercreatedAtstringlastTriggeredAtstringResponse codes
200The price alert.404Price alert not found./price-alerts/{alertId}
Delete a price alert
Full endpoint documentationdeletePriceAlertRemoves a price alert. Requires a full key (pk_live_).
Parameters
alertIdstringpathRequiredExample: alr_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
Response fields
alertIdstringdeletedbooleanmessagestringResponse codes
200Alert deleted.404Price alert not found.Delivery envelope
Every delivery wraps the event-specific payload in a standard three-field envelope. Sandbox deliveries
add isSandbox: true at the top level.
Event payloads
Signature verification
Every delivery includes an x-mystocks-signature header containing an HMAC-SHA256 hex digest of the
raw request body signed with your webhook secret. Always verify using a constant-time comparison.
Delivery semantics — at-least-once, not exactly-once. The same event can arrive more than once;
events are not guaranteed to arrive in order (a retried order.pending can land after
order.filled); and a delivery can fail all retries. The robust pattern: dedupe by eventId,
treat handlers as idempotent, and derive state from the event payload rather than arrival order.
Respond 2xx quickly and process asynchronously — you have 8 seconds before the attempt fails.
Manage & inspect
List registered webhooks, delete one, fire a test event, or inspect delivery history.
POST /webhooks/{id}/test sends a test.event payload immediately and logs the delivery — useful for
verifying reachability and signature verification before going live. /deliveries returns each attempt
with HTTP status, response snippet, duration (ms), and the retry schedule if it failed. Retry schedule:
immediate → 5 s → 30 s → 5 min → 30 min → 2 h (6 attempts max).
/webhooks
List webhooks
Full endpoint documentationlistWebhooksReturns all registered webhook endpoints for your partner account.
Parameters
This endpoint has no path or query parameters.
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Response fields
webhooksobject[]webhooks[].idstringUnique webhook ID.
Example: "wh_abc123"
webhooks[].urlstringExample: "https://yourapp.com/webhooks/mystocks"
webhooks[].eventsstring[]Subscribed event types.
webhooks[].statusactive | disabledResponse codes
200Webhook list./webhooks/{id}
Delete webhook
Full endpoint documentationdeleteWebhooksPermanently removes a webhook registration. In-flight deliveries will still complete.
Parameters
idstringpathRequiredExample: wh_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
Response fields
messagestringExample: "Webhook deleted."
Response codes
200Webhook deleted.404Webhook not found./webhooks/{id}/test
Test webhook
Full endpoint documentationcreateTestSends a signed synthetic test.event to the registered webhook URL. Use this to verify connectivity and HMAC signature verification before going live. This operation does not simulate business events such as order fills.
Parameters
idstringpathRequiredExample: wh_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
Response fields
successbooleaneventIdstringmessagestringwebhookIdstringurlstringhttpStatusinteger | nullHTTP status your endpoint returned.
Response codes
200Test delivery result.502The registered endpoint could not be reached or returned a non-2xx response./webhooks/{id}/deliveries
Webhook deliveries
Full endpoint documentationlistDeliveriesReturns the delivery log for a webhook endpoint — each attempt, response code, and body.
Parameters
idstringpathRequiredExample: wh_abc123
limitintegerqueryExample: 50
Headers
AuthorizationstringRequiredBearer sk_sandbox_<your_key> for sandbox requests.
Response fields
deliveriesobject[]deliveries[].deliveryIdstringdeliveries[].eventstringdeliveries[].statusCodeinteger | nulldeliveries[].successbooleandeliveries[].latencyMsinteger | nulldeliveries[].attemptsintegerdeliveries[].deliveredAtstringResponse codes
200Delivery log.Was this page useful?
Your signal helps us tighten partner onboarding docs.
Last updated on