Reference

Errors

One shape for every error, a stable machine-readable code, and a human message. Link to any code on this page with #partner-<code>, #sso-<code> or #trading-<code>.

#The error shape

Every non-2xx answer
{
  "error": {
    "code": "invalid_request",
    "message": "amount must be greater than 0",
    "details": { "errors": { "amount": "must be greater than 0" } }
  }
}
codeStable identifier. Switch on it; never on the message.
messagePlain English for logs and support tickets. May change.
detailsOptional object. Validation errors carry errors: { field: reason }; rate limits carry scope; open_api_disabled carries reason; order refusals carry reason or errors.

#Status codes

StatusMeansRetry?
200 / 201Done. 201 for created orders and postings; 200 with replayed: true when an idempotent call was repeated.-
302SSO login endpoint: the browser is sent on to the app (or to /login?sso_error=…).-
400The body is not JSON.No - fix the request
401No key, unknown key, or a bad SSO token.No
403Known key, but a scope, an IP list, a brand switch or a pause stands in the way.No - change the key or the setting
404No such path or record.No
409A state conflict: already linked, in progress, not pending, idempotency mismatch.Read the state first
422The request is understood but refused: validation, limits, market closed, margin.No - fix the request
429Rate limited. Honour Retry-After.Yes, after Retry-After
500Unexpected. For orders: look the order up before sending again.Yes, with backoff
503A dependency is not available (prices, history, rate-limit store). Nothing was changed.Yes, after Retry-After

#Partner API codes

401invalid_api_keyNo key, or an unknown / expired / revoked key.
403insufficient_scopeThe key does not carry the scope the call needs.
403ip_not_allowedThe request comes from outside the key's IP allow-list.
403api_disabledThe Partner API is switched off for the company.
403brand_disabledThe brand has the "Partner API" switch off.
403sso_disabledThe brand has the "Single sign-on" switch off.
403sso_not_configuredNo issuer / audience / key saved for the brand (SSO inbound).
403login_disabledThe user may not sign in.
403user_other_brandThe user belongs to another brand than the one in the URL.
403company_inactiveThe platform is paused.
403brand_inactiveThe brand is switched off.
403client_inactiveThe client profile is not active (trading on behalf).
403trading_inactiveTrading is switched off for this client (trading on behalf).
403trading_deniedTrading is not allowed for this account or client (trading on behalf).
404not_foundNo such path or record.
404user_not_foundNo client with that external_id in your company.
404brand_not_foundNo such brand id.
404account_not_foundNo such trading account for the user.
404symbol_not_foundNo such symbol.
409email_takenAnother client already uses that e-mail.
409brand_fixedbrand_id cannot change after the user was created.
409limit_reachedThe brand allows no further live / demo accounts for this client.
409already_linkedThat MT login on that server is already linked.
409no_brandThe user has no brand.
409no_app_domainThe brand has no trader / dashboard domain yet.
409mt_accountA MetaTrader account is not traded through this API.
409not_pendingThe order is not pending any more.
409idempotency_conflictSame idempotency key, different body (money posting).
409in_progressA posting with this key is still being booked; repeat in a moment.
409insufficient_fundsA withdrawal over the free margin or a credit_out over the credit; nothing booked.
422invalid_requestA field is missing, unknown or invalid; details.errors = { field: reason }.
422invalid_targettarget must be trader or dashboard.
422invalid_subjectThe JWT sub is not a valid external_id.
422create_failedThe client could not be auto-created on first sign-in.
422money_rejectedThe transaction service refused the posting; details says why.
422order_refusedRefused by the order checks; details.reason says why (trading on behalf).
422insufficient_marginNot enough free margin (trading on behalf).
422invalid_sizeLot / unit size outside the symbol rules.
422invalid_levelsStop loss / take profit on the wrong side of the price.
422invalid_priceLimit / stop price missing or invalid.
422invalid_leverageThis leverage is not offered for the symbol.
422market_closedThe market of this symbol is closed.
422symbol_not_allowedThe symbol is not allowed for this account type.
422too_many_ordersToo many open positions or pending orders on the account.
422balance_unavailableThe balance could not be read for the posting.
429rate_limitedOver the company's requests per minute; see Retry-After.
503history_unavailableChart history is loading; see Retry-After.
503quotes_unavailableThe price mirror has no quotes right now.
503no_priceNo trading price for the symbol right now.

#Single sign-on codes

Returned as JSON when the login endpoint is called with format=json, otherwise appended to the redirect as /login?sso_error=<code>.

401token_invalidNot a JWT, or a bad header / claims.
401token_signatureThe signature does not verify with the configured key or secret.
401token_algThe algorithm is not the one configured for the brand (RS256 / HS256).
401token_issueriss differs from the issuer saved for the brand.
401token_audienceaud differs from the audience saved for the brand.
401token_expiredexp is in the past.
401token_ageIssued more than max_age_seconds ago, or not yet valid (iat / nbf outside the window).
401token_jtijti missing.
401token_subjectsub missing.
401token_keyNo key found for the kid in the token header (JWKS).
401token_replayedThe jti was already used - every token works once.
403sso_disabledThe brand has single sign-on switched off.
403sso_not_configuredNo issuer / audience / key saved for the brand.
403login_disabledThe user may not sign in.
403user_other_brandThe user belongs to another brand.
403company_inactiveThe platform is paused.
403brand_inactiveThe brand is switched off.
404brand_not_foundNo such brand id.
404user_not_foundUnknown sub and "create unknown clients" is off.
409no_app_domainThe brand has no trader / dashboard domain yet.
422invalid_targettarget must be trader or dashboard.
422invalid_subjectsub is not a valid external_id (1-191 letters, digits, . _ @ : + -).
422create_failedThe client could not be auto-created.

#Trading API codes

422account_invalidThe trading account cannot trade (inactive or not a trading account).
403account_not_allowedThis key may not use that trading account.
404account_not_foundNo such trading account for this key.
401api_key_expiredThe key has expired. Create a new one.
401api_key_requiredNo key was sent (header X-API-Key or Authorization: Bearer).
401api_key_revokedThe key was revoked (by you, the broker or the system).
403api_trading_stoppedThe broker has stopped API trading for now. Reads still work.
503balance_unavailableThe account balance cannot be read right now. Try again.
403brand_inactiveThe brand is switched off.
403client_inactiveThe client profile is not active.
422client_order_id_requiredOrder actions need a client_order_id (body or Idempotency-Key header).
403company_inactiveThe platform is paused.
503history_unavailableChart history cannot be read right now (the chart feed is loading). Retry-After is set.
422insufficient_marginNot enough free margin for this order.
500internal_errorUnexpected server error.
401invalid_api_keyUnknown key.
422invalid_client_order_idclient_order_id must be 1-64 characters: letters, digits, _ - : .
400invalid_jsonThe body is not valid JSON.
422invalid_levelsStop loss / take profit on the wrong side of the price or too close to it.
422invalid_leverageThis leverage is not offered for the symbol on this account.
422invalid_priceThe limit / stop price is missing or invalid.
422invalid_requestA field is missing, unknown or invalid; details.errors names it.
422invalid_sizeThe order size is below the minimum, above the maximum or not a valid step.
403ip_not_allowedThe request comes from an address outside the key's IP allow-list.
403ip_unverifiableYour address could not be determined, so the IP allow-list cannot be checked.
422market_closedThe market of this symbol is closed.
409mt_accountA MetaTrader account without a connected MT server cannot trade through this API (its orders are placed in MetaTrader).
409mt_positionA MetaTrader position without a connected MT server cannot be changed through this API.
503no_conversion_rateNo conversion rate to the account currency right now. Try again.
503no_priceNo trading price for the symbol right now. Try again.
404not_foundNo such path or record. Every path answers this while the Trading API is off on the server.
409not_openThe position is not open.
409not_pendingThe order is not pending any more (filled, cancelled or closed).
500not_placedThe order was not placed. Look it up, then send it again.
503not_readyThis server is not ready for this action yet.
403open_api_disabledThe Trading API is not enabled for you; details.reason = brand_off | pro_locked | server_off | not_ready.
409order_in_flightAn order with this client_order_id is still being processed. Wait, then look it up.
429order_rate_limitedToo many order actions per second (per key or per trading account). Retry-After is set.
422order_refusedRefused by the order checks; details.errors says why.
409pending_orderThis is a pending order: use /orders/{id}.
409position_stateThe position changed while the action ran. Fetch it and try again.
503quotes_unavailableTrading quotes are not available right now (switched off, paused or stale).
503rate_limit_unavailableThe rate-limit store is down: order actions are refused and nothing was placed. Try again.
429rate_limitedToo many requests per minute; details.scope = key | client. Retry-After is set.
409still_openThe close did not complete; the position is still open. Fetch it and try again.
503stream_unavailableThis server cannot issue stream tickets right now.
422symbol_invalidThe symbol cannot be traded (inactive or not set up).
422symbol_not_allowedThe symbol is not allowed for this account type.
404symbol_not_foundNo such symbol.
429too_many_invalid_keysMore than 60 wrong keys a minute from your address. Wait a minute.
422too_many_ordersToo many open positions or pending orders on the account.
403trade_scope_requiredThe key is read-only. Create a key with the trade scope.
403trading_deniedTrading is not allowed for this account or client.
403trading_inactiveTrading is switched off for this client.
500unknown_outcomeThe order may or may not have been executed. Look it up (GET /orders/lookup) before sending anything new.
403websocket_disabledThe WebSocket stream is switched off on this server.

#Handling errors

A rate-limited answer
HTTP/1.1 429 Too Many Requests
Retry-After: 12
Content-Type: application/json

{ "error": { "code": "rate_limited", "message": "Too many requests", "details": { "scope": "key" } } }
  • Validation (422 invalid_request): show details.errors to the developer; it names each field.
  • Orders: on 500 unknown_outcome, 500 not_placed or a network timeout, call GET /orders/lookup?client_order_id=… before sending anything else. The same client_order_id can never fill twice.
  • Money: repeat the same posting with the same idempotency_key and you get 200 with replayed: true; a different body answers 409 idempotency_conflict.
  • Webhooks: an error from your endpoint is not an API error - the platform retries. See retries.
Tip
All codes are lowercase snake_case and never change meaning. New codes may be added; treat an unknown code by status.