Errors
Every MyStocks Partner API error carries a machine-readable error.code and a human-readable error.message. Full reference of HTTP status codes, error codes, and structured order-rejection codes.
Every error response carries a top-level error object with a machine-readable code string and a
human-readable message. This applies to all endpoints. Check error.code for programmatic handling;
use error.message for logging or UI display.
HTTP status codes
| Field | Type | Required | Description |
|---|---|---|---|
| 200 | OK | No | Request succeeded. |
| 201 | Created | No | Resource created (register, create sub-account). |
| 202 | Accepted | No | Order accepted into the live fill flow (trade, subscribe). Funds escrowed immediately; settlement is asynchronous. |
| 400 | Bad Request | No | Missing or invalid parameters — check the error message. |
| 401 | Unauthorized | No | API key missing, invalid, revoked, or expired. |
| 403 | Forbidden | No | Action not permitted: account not yet approved, sub-account frozen, or an operation outside your tier. |
| 404 | Not Found | No | Stock symbol, sub-account, holding, or instrument not found. |
| 409 | Conflict | No | Idempotency collision — a concurrent request with the same Idempotency-Key is still in progress. Retry after it resolves. |
| 422 | Unprocessable | No | Business-rule violation: insufficient balance, KYC required, frozen sub-account, fund not open, or units exceed holdings. |
| 429 | Too Many Requests | No | Rate limit exceeded. Check X-RateLimit-Remaining and X-RateLimit-Reset headers. |
| 500 | Internal Server Error | No | Server-side failure — retry with exponential backoff or contact support. |
Machine-readable error codes
When the error field is an object, error.code is one of the values below.
| Field | Type | Required | Description |
|---|---|---|---|
| AUTH_MISSING | 401 | No | No API key supplied. Send Authorization: Bearer pk_live_... or X-Api-Key. |
| AUTH_INVALID | 401 | No | Key format is wrong or the key does not exist in the registry. |
| AUTH_SUSPENDED | 403 | No | Partner account temporarily suspended. Contact support@mystocks.africa. |
| AUTH_REVOKED | 403 | No | Key permanently revoked. A new key must be issued — revocation cannot be undone. |
| RATE_LIMITED | 429 | No | Too many requests. Back off and retry after X-RateLimit-Reset. |
| MISSING_PARAM | 400 | No | A required query/body parameter is absent. Check error.param or error.params[]. |
| MISSING_IDEMPOTENCY_KEY | 400 | No | A money-movement/state-changing POST was sent without the required Idempotency-Key header. |
| INVALID_SYMBOL | 400 | No | Symbol fails format validation (2–20 alphanumerics, optionally dot-separated). Check error.invalid[] in a batch. |
| UNKNOWN_EXCHANGE | 400 | No | Exchange code not recognised. See the supported codes list. |
| INVALID_TYPE | 400 | No | A parameter has the wrong type. |
| VALIDATION_ERROR | 400 | No | Request body or query param failed validation. See error.message. |
| BATCH_LIMIT_EXCEEDED | 400 | No | Batch exceeds the max symbol count. Check error.max and error.received. |
| NOT_FOUND | 404 | No | Requested resource does not exist. |
| CONFLICT | 409 | No | Concurrent request conflict: idempotency collision or order state changed mid-operation. |
| QUOTE_REQUIRED | 400 | No | No quoteId supplied on a trade. Every trade needs a fresh single-use quoteId from GET /quote/{symbol}. |
| QUOTE_NOT_FOUND | 404 | No | quoteId never issued, or already expired and garbage-collected. Fetch a fresh quote. |
| QUOTE_SCOPE_MISMATCH | 403 | No | quoteId belongs to a different account context. Fetch with the same subAccountId you trade on. |
| STALE_QUOTE | 409 | No | quoteId expired (60s TTL) or already used. Fetch a fresh quote and retry. |
| QUOTE_ORDER_MISMATCH | 409 | No | quoteId does not match the submitted symbol/side/quantity/cashValue. Request a new quote. |
| INSUFFICIENT_FUNDS | 400 | No | Wallet balance too low. Top up the master wallet or deposit into the sub-account first. |
| KYC_REQUIRED | 403 | No | Sub-account KYC not verified. Assert via POST /users/{userId}/kyc then retry. |
| FORBIDDEN | 403 | No | Authenticated but not authorised (e.g. read-only data key on a write endpoint). |
| INTERNAL_ERROR | 500 | No | Unexpected server-side failure. Safe to retry with backoff. |
Order rejection codes
When an order moves to REJECTED, both the order.rejected webhook and GET /orders/{orderId}
include a structured rejectionCode alongside the free-text rejectionReason.
| Field | Type | Required | Description |
|---|---|---|---|
| INSUFFICIENT_FUNDS | string | No | Wallet had insufficient balance at time of review. |
| KYC_REQUIRED | string | No | Sub-account KYC not verified. Assert via POST /users/{userId}/kyc before retrying. |
| MARKET_CLOSED | string | No | Exchange was closed or on a public holiday when the order was reviewed. |
| COMPLIANCE_HOLD | string | No | Order flagged for compliance review. Contact support. |
| TECHNICAL_ISSUE | string | No | A technical issue prevented execution. Safe to retry. |
| OTHER | string | No | Reason does not fit a standard code — see rejectionReason. |