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 dealing desk. 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