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, a missing idempotency key, or insufficient funds. Check error.code. |
| 401 | Unauthorized | No | API key missing, invalid, or expired. |
| 403 | Forbidden | No | Action not permitted: revoked/suspended key, missing scope, KYC required, frozen sub-account, 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 such as MARKET_CLOSED, a fund not being open, or requested units exceeding 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. |
| 503 | Service Unavailable | No | Planned maintenance (MAINTENANCE) or an unplanned dependency outage (SERVICE_UNAVAILABLE). Always carries Retry-After. Never means your request was wrong — retry it unchanged. |
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 | An authenticated POST, PATCH, PUT, or DELETE was sent without the required Idempotency-Key header. The documented registration, reset, application, upgrade, and OAuth token endpoints are exempt. |
| 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. |
| MARKET_CLOSED | 422 | No | The exchange is closed. Check GET /market/status and retry when the venue is open. |
| 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. |
| MAINTENANCE | 503 | No | Planned maintenance window. Honour the Retry-After header. In read-only maintenance, GETs still succeed and only mutations return this. |
| SERVICE_UNAVAILABLE | 503 | No | Unplanned outage in a downstream dependency. Retry with exponential backoff; check the status page. |
Maintenance and downtime
During a maintenance window the Partner API returns 503 with a Retry-After header (in seconds).
There are two modes, reported as error.mode:
| Field | Type | Required | Description |
|---|---|---|---|
| full | mode | No | Every request is refused with 503 MAINTENANCE. |
| read_only | mode | No | GET and HEAD are served normally; every mutation (orders, payments, account changes) is refused with 503 MAINTENANCE. Used during a settlement or payment-rail incident so you can still read positions and reconcile while money movement is frozen. |
Do not treat a 503 as a rejected request — nothing was processed, and the same request is safe to
send again once Retry-After elapses. Keep your Idempotency-Key the same when you retry.
Live status, uptime, and incident history are published at
mystocks.africa/status (raw JSON: GET /api/v1/status). You do not
need to poll it: incidents are pushed to your webhooks as incident.declared / incident.resolved.
Order rejection codes
The codes above are returned synchronously — the HTTP call itself fails and no order is created.
A rejectionCode is different: it is attached asynchronously, when an order that was already
accepted (202, status PENDING) is later rejected by the MyStocks internal-book execution engine. You learn about it through
the order.rejected webhook, the execution report, or rejectionCode on GET /orders/{orderId} —
always alongside the free-text rejectionReason.
This is the exhaustive list. No other value is ever written.
| Field | Type | Required | Description |
|---|---|---|---|
| INSUFFICIENT_FUNDS | retriable | No | The account lacked settled balance at settlement time. Top up and resubmit. |
| MARKET_CLOSED | retriable | No | The exchange was closed when the desk attempted execution. Orders placed outside market hours are normally queued rather than rejected, so this usually indicates an unscheduled closure. Check GET /market/status, then resubmit. |
| TECHNICAL_ISSUE | retriable | No | Execution failed for an operational reason at the venue or on the desk. Safe to resubmit; if it recurs, check /status for an open incident. |
| KYC_REQUIRED | not retriable | No | The account is not KYC-approved. Complete KYC via POST /users/{userId}/kyc, wait for kyc.updated, then resubmit. Retrying as-is will be rejected again. |
| COMPLIANCE_HOLD | not retriable | No | Blocked by compliance review (sanctions, market-abuse check, restricted security, or an account hold). Do not resubmit — contact support@mystocks.africa. |
| OTHER | not retriable | No | Does not fit a category above. rejectionReason always carries the specific explanation. |
retriable means resubmitting the same order unchanged could plausibly succeed later. not retriable
means something must change first — funds, KYC, the order itself — or the same rejection will repeat.
Order expiry is not a rejection. When a DAY or GTD order reaches its deadline it is
cancelled, carrying orderLifecycle: "EXPIRED" and a cancelReason — never a rejectionCode.
Was this page useful?
Your signal helps us tighten partner onboarding docs.
Last updated on