Error catalogue
Every code the gateway answers, its HTTP status, what it means and what to do
Every error has one envelope
Branch on code, never on message: the sentence may be reworded, the code will not
docs links the code's row on this page, and details carries the numbers behind a refusal
The words are the gateway's own catalogue (packages/api/errors.mjs), and the same list is the Refusal enum in the OpenAPI file; a check in each repository fails when the gateway throws a code that is missing here
{
"error": {
"code": "RISK_MAX_LOTS",
"message": "Requested volume exceeds the account's maximum lots per order.",
"docs": "https://mirroapi.com/docs/errors#RISK_MAX_LOTS",
"details": { "arithmetic": { "requestedLots": "9.00", "maxLots": "2.00" } }
}
}
The envelope
Answered by every route
| Code | HTTP | What it means | What to do |
|---|---|---|---|
BAD_REQUEST | 400 | The request is malformed or a field has the wrong shape; the message names the field | Fix the field and send again |
UNAUTHORIZED | 401 | No key, an unknown key, a revoked or expired key, or an expired session | Send a live key as Authorization: Bearer; mint a new one in the console if this one was revoked |
FORBIDDEN | 403 | The key is real but may not do this: a missing scope, an account outside its restriction, or a session-only route | Use a key with the scope named in details.required, or one not limited to other accounts |
NOT_FOUND | 404 | No such route or object for this caller; an object another user owns is also 404 | Check the id and the path; list the collection to find what you own |
METHOD_NOT_ALLOWED | 405 | The path exists but not for this method; the Allow header lists the methods | Use a method from Allow |
CONFLICT | 409 | The request contradicts current state (a limit of 20 keys or webhooks, an account that cannot be removed, a role that cannot change); details.reason says which | Read details.reason, change state, then retry |
PAYLOAD_TOO_LARGE | 413 | The body is over 64 KB | Send less |
RATE_LIMITED | 429 | The key spent its per-minute budget for this bucket (read or trade) | Wait Retry-After seconds; the limits are in X-RateLimit-Limit |
NOT_IMPLEMENTED | 501 | This operation is not supported by the connected gateway or its current configuration | Check GET /v1/platforms and the operation’s documented requirements; contact support with the request ID if configuration is missing |
MIRA_BUSY | 503 | This workspace already has as many Mira model calls running as it may (two for /v1/mira/responses; the platform limit for chat completions) | Wait Retry-After and send the same request again (reuse the same requestId and input on /v1/mira/responses) |
MIRA_CREDIT_REQUIRED | 402 | Not enough Mira credit for this model call | Top up in Mira → Credit & usage; pending responses may still reserve credit |
MIRA_VERIFY_EMAIL | 403 | Email verification is required | Confirm the email address, then return to Mira |
MIRA_PAYMENTS_UNAVAILABLE | 503 | Top-ups are temporarily unavailable | Try again later or contact support |
MIRA_ALLOWANCE | 429 | Mira's allowance is used up: the workspace's daily allowance (details.reason daily, resets 00:00 UTC) or MIRRO's monthly model capacity (monthly) | Wait Retry-After seconds, or contact MIRRO to raise the allowance |
MIRA_UNAVAILABLE | 503 | Mira's model service did not complete this response; details.usage says whether the attempt may have been charged (none, recorded or unknown) | Wait Retry-After seconds and send the request again |
MIRA_NOT_ENABLED | 503 | This workspace or model is not enabled for the Mira API | Create a business workspace at mirroapi.cloud/mira/start, or contact support |
MIRA_BROWSING_UNAVAILABLE | 503 | Mira's public website reader or web search service is not available | Try again later or add the page text as a knowledge document; no page was saved |
API_BUSY | 503 | The gateway's bound on unfinished work is reached (reads and trade submissions have separate budgets) Nothing was started | Wait Retry-After seconds and send the same request again; keep a trade's Idempotency-Key unchanged |
INTERNAL | 500 | Something failed on our side | Retry once; report X-Request-Id if it persists |
IDEMPOTENCY_MISMATCH | 422 | This Idempotency-Key was already used with a different request | Use a new key for a new request; replay the same body to get the same answer |
UPGRADE_REQUIRED | 426 | GET /v1/stream over plain HTTP; the stream is a WebSocket | Connect with a WebSocket client and authenticate with the key |
The sandbox boundary
A test key (mk_test_…) stays on demo accounts; these are the two places it meets live money
| Code | HTTP | What it means | What to do |
|---|---|---|---|
TEST_KEY_LIVE_ACCOUNT | 403 | A test key (mk_test_) reached a live account: it may trade and consent on demo accounts only | Use a live key for live accounts, or a demo account with this key |
TEST_KEY_LIVE_KEY | 403 | A test key tried to mint a live key | Mint live keys with a live admin key or in the console |
Platforms and provisioning
GET /platforms, POST /accounts and the configuration links
selfOnboard.reason on a platform row is the same code POST /accounts answers
| Code | HTTP | What it means | What to do |
|---|---|---|---|
PLATFORM_UNSUPPORTED | 422 | This platform is disabled or unsupported on the connected gateway | Read GET /v1/platforms and use an available platform or ask support about access |
USE_OAUTH | 422 | cTrader requires its authorization flow instead of a password-based POST /v1/accounts request | Start POST /v1/ctrader/authorize, let the account holder sign in, then connect the selected grants with POST /v1/ctrader/connect |
FIRM_PERMISSION_REQUIRED | 422 | DXtrade access is switched on per firm, so a trader cannot connect it alone | Contact support with the firm; GET /v1/platforms reports it per-firm |
USE_PLATFORM_CONNECT | 422 | This platform has a dedicated account connection flow | Follow selfOnboard.via from GET /v1/platforms; TradeLocker uses /v1/tradelocker/discover followed by /v1/tradelocker/connect |
TRADELOCKER_UNAVAILABLE | 503 | TradeLocker account connection is unavailable on this gateway | Try again later or contact support with the request id |
RELIABILITY_UNAVAILABLE | 422 | reliability high needs a standby terminal on a second server, and none is in service | Send reliability standard or omit it |
ACCOUNT_REFUSED | 422 | The provisioning workflow refused the account for a reason not in the named list; details.reason carries it | Read details.reason; the console shows the same word |
TERMINAL_LOGIN_ON_OTHER_PLATFORM | 422 | This login and server are already connected on the other MetaTrader version | Create the account on the platform it is already on |
TERMINAL_SERVER_IS_OTHER_PLATFORM | 422 | The broker directory knows this server only on the other MetaTrader version | Check the server name in the terminal and send the matching platform |
TERMINAL_ACCOUNT_ALREADY_OWNED | 422 | This login on this server belongs to another user | Use a login you hold; contact support if it is yours |
TERMINAL_ACCOUNT_CHANGED | 422 | A removed account cannot come back under a fresh id | Re-add it with the id it had (the console does this) |
TERMINAL_BROKER_IDENTITY_AMBIGUOUS | 422 | The server name matches more than one broker in the directory | Send the exact server name the terminal shows |
TERMINAL_TENANT_CAPACITY_REACHED | 422 | Hosting is full: the box holds its maximum of terminals | Try later or ask for more capacity in a support ticket |
TERMINAL_USER_CAPACITY_REACHED | 422 | You hold your maximum of hosted terminals | Remove one, or request a higher quota (POST /v1/quotas/requests) |
TERMINAL_ONBOARDING_INVALID | 422 | The workflow refused the login, server or role as given | Check the fields against the terminal and send again |
LIVE_CONFIRMATION_REQUIRED | 422 | A live account is connected through a configuration link only with the trader's explicit phrase | The trader sends liveConfirmation exactly as the GET names it |
EA_UPGRADE_REQUIRED | 422 | A partial modify-order needs EA 1.7.3 or later on this terminal | Update the terminal, or send price, stopLoss and takeProfit together |
Trading and risk
Answered by POST /accounts/{id}/trades and PUT /risk before a command is queued
Nothing was sent unless the row says otherwise; a refusal is also written to the audit log as order.refused
| Code | HTTP | What it means | What to do |
|---|---|---|---|
INVALID_REQUEST | 422 | A trade field is missing, malformed, or not carried to the terminals (comment, expiration, a modify-order volume); details.field names it | Fix the field; nothing was queued |
NO_CONSENT | 422 | A live account has no recorded trader consent | POST /v1/accounts/{id}/consent with the trader's name, email and the statement they agreed to |
EXECUTION_ROLE_REQUIRED | 422 | The account is not enabled for execution (no follower role, or its setup check has not passed) | Grant the follower role in the console and pass the check |
ACCOUNT_DISCONNECTED | 422 | The terminal has not reported for two minutes, so the command would not reach the broker | Wait for connection CONNECTED on GET /v1/accounts/{id}; nothing was queued |
BROKER_DOWN | 422 | The terminal is up but its broker connection is down | Wait for brokerConnected true; nothing was queued |
FIRM_UNREACHABLE | 422 | The firm or broker has switched the application off, or revoked the authorisation | The trader re-authorises on the platform; nothing was queued |
RISK_MAX_LOTS | 422 | volume is over the account's maxLotsPerOrder; details.arithmetic shows both | Send a smaller order or raise the limit with PUT /risk |
RISK_MAX_OPEN_LOTS | 422 | Open lots plus this order would pass maxOpenLots; every position in the stored book counts | Close something or raise the limit |
RISK_MAX_POSITIONS | 422 | The account holds its maxOpenPositions | Close a position or raise the limit |
RISK_DAILY_LOSS | 422 | Today's loss from the day-start equity has reached maxDailyLossPercent | No new positions today; exits are never refused |
RISK_DAILY_LOSS_UNKNOWN | 422 | A daily-loss rule is set but the account has not reported equity today, so it cannot be checked | Wait for the terminal's first report of the UTC day |
RISK_OPEN_LOTS_UNKNOWN | 422 | A maxOpenLots rule is set but the account's current exposure cannot be counted: details.arithmetic.reason says why (book_unreadable, terminal_count_unknown, book_behind_terminal, book_stale, lots_missing) | Usually the next book (about 5 s) clears it; a terminal that reports no book cannot carry this rule Exits are never refused |
RISK_TRADING_HOURS | 422 | Now is outside the account's tradingHours; details.arithmetic.now is the local time used | Send inside the window or change the rule |
RISK_RULE_UNSUPPORTED | 422 | The risk rule named in details.rule has no enforcer yet (maxDrawdownPercent, flattenOnBreach, refuseToSend false), so it is refused rather than stored as if it held | Leave the rule out; GET /risk reads it as null |
TICKET_SUPERSEDED | 422 | On MetaTrader 4 a partial close gave the remainder a new ticket; a close-partial naming the old one is never re-addressed | Name details.liveTicket if you mean to reduce the remainder again |
TICKET_READDRESS_FAILED | 422 | The ledger row could not be re-addressed to the live MT4 ticket; nothing was sent | Retry naming the live ticket |
MARGIN_PRICE_UNSUPPORTED | 422 | MetaTrader 4 checks free margin at the current price only | Omit price on mt4 |
FIRM_TRADER_REQUIRED | 422 | A challenge is started for a trader on a seat of the firm; this user is not one | Invite the person as a trader and start the challenge once they have joined |
PROGRAM_INVALID | 422 | The program's stored rules no longer validate, so no challenge is started from them | Edit the program; details.field names the rule |
GATEWAY_UNAVAILABLE | 503 | MetaQuotes' multi-broker terminal, which opens MetaTrader 4 demo accounts, is not reachable from this gateway process. Try again in a minute; the catalogue's MetaTrader 5 brokers open through their own terminals and are unaffected. | |
OPS_UNAVAILABLE | 503 | The operators' desk lists every firm through the engine connection, which this gateway process does not have | Run the gateway with MIRRO_DATABASE_URL (the engine role) as in production |
TELEGRAM_UNAVAILABLE | 503 | The Telegram Bot API did not answer when a link code was requested; nothing was created | Try again in a moment E-mail notifications are unaffected |
CTRADER_UNAVAILABLE | 503 | cTrader could not be reached from the gateway, or this gateway has no cTrader application configured | Try again in a moment; if it persists the operator has not set MIRRO_CTRADER_CLIENT_ID and MIRRO_CTRADER_CLIENT_SECRET |
CTRADER_AUTHORIZATION_FAILED | 400 | cTrader refused the sign-in, or the code on the redirect was not one it would exchange | Start the connection again from the console |
CTRADER_FLOW_EXPIRED | 404 | This cTrader sign-in is not one the gateway is holding any more: ten minutes passed, it was already finished, or it belongs to another sign-in | Start the connection again |
CTRADER_TRADING_SCOPE_REQUIRED | 403 | The cTrader authorisation covers reading only, so no order could ever be placed with it | Authorise again and approve trading access |
CTRADER_GRANT_NOT_FOUND | 404 | That cTrader authorisation is not one this sign-in holds any more; it was superseded or revoked | Connect cTrader again |
CTRADER_ACCOUNT_NOT_GRANTED | 422 | That cTrader account is not one the authorisation covers | Authorise the account in cTrader, then connect it again |
TELEGRAM_SOURCES_UNAVAILABLE | 503 | This gateway has no Telegram application id and hash, so it cannot read channels through a person's own Telegram | Set MIRRO_TELEGRAM_APP_ID and MIRRO_TELEGRAM_APP_HASH from my.telegram.org and install the MTProto client, then connect again |
TELEGRAM_NOT_CONNECTED | 409 / 503 | No Telegram is connected to this sign-in, or the session it had was ended from Telegram's own devices screen | Connect a Telegram in Signals → Telegram, then choose the channel again |
TELEGRAM_PHONE_INVALID | 400 | Telegram does not recognise the phone number as written | Write it with the country code, e.g +2348012345678 |
TELEGRAM_CODE_INVALID | 400 | The code entered is not the one Telegram sent | Read the code in the Telegram app or the SMS and enter it again |
TELEGRAM_CODE_EXPIRED | 400 | The code Telegram sent has expired | Start the connection again to be sent a new code |
TELEGRAM_PASSWORD_NEEDED | 401 | This Telegram has two-step verification, so the code alone does not finish the sign-in | POST the same attemptId with the Telegram two-step password |
TELEGRAM_PASSWORD_INVALID | 400 | The Telegram two-step password was refused by Telegram | Enter the password set in Telegram → Settings → Privacy and Security → Two-Step Verification |
TELEGRAM_LOGIN_EXPIRED | 404 | This sign-in attempt is not one this gateway is holding any more: ten minutes passed, or it was started elsewhere | Enter the phone number again |
TELEGRAM_LOGIN_FAILED | 400 / 403 / 429 / 503 | Telegram refused or could not answer the sign-in: a banned or unregistered number, a pause it asks for, or a network it did not answer on | The message says which Wait, or use the number the Telegram account is really on |
TELEGRAM_CHANNEL_UNAVAILABLE | 404 | The connected Telegram can no longer read that channel — it left, was removed, or the channel is gone | Open the channel in Telegram, check the membership, then choose it again |
Command results
Not HTTP errors: these arrive in Command.result.code on GET /accounts/{id}/trades/{commandId} (and in the command.resolved webhook)
EXECUTION_UNKNOWN arrives there too, meaning a terminal took the command and never answered: the outcome is not known and it is never called rejected
| Code | HTTP | What it means | What to do |
|---|---|---|---|
EXECUTION_REFUSED | — | MIRRO's own engine refused the command before any terminal saw it; result.reason is the word (position_book_unknown, entry_price_required, stop_limit_unsupported, invalid_request, unsupported_action, opens_suppressed) and there is no result.broker | Read result.reason; for position_book_unknown send both stops, or wait for the terminal's next book |
BROKER_REJECTED | — | The terminal's final refusal; result.broker is its reason, including the permanent MetaTrader 4 words ticket_superseded (the live ticket in result.ticket), remainder_unproven and remainder_ambiguous, after which nothing was traded | Read the positions again and name the live ticket A transient reason is re-driven for you until the command expires |
EXECUTION_NOT_CLAIMED | — | On state: expired: nothing claimed the command before it expiredNothing was sent | Check the account is deployed and connected, then send again |
EXECUTION_TRANSIENT_EXHAUSTED | — | The terminal answered a transient reason (requote, off quotes) on every attempt until the command expired; result.broker is the last one | Read the positions before sending again; a late answer can still correct this row (result.correctedFrom) |
Execution diagnostics
A broker refusal has a code, a readable reason and its original terminal details
An unknown execution outcome stays unknown until evidence resolves it
Alongside result.code above, a resolved command carries result.diagnostic: the specific code, what it means and what to do next
The established result.code is unchanged, and REST, streams and command.resolved webhooks use the same diagnostic shape
{
"state": "rejected",
"result": {
"code": "BROKER_REJECTED",
"native": { "code": 10016, "message": "Invalid stops" },
"diagnostic": {
"code": "MT5_INVALID_STOPS",
"known": true,
"source": "mt5",
"reason": "A stop or pending price violates the broker’s price or distance rules.",
"outcome": "rejected"
}
}
}
This is an abbreviated example
The diagnostic also includes the original response, catalogue version, retry guidance and a next step
The console shows the specific code and reason on the order, beside the words above
Discover the codes
curl --fail-with-body \ -H "Authorization: Bearer $MIRRO_API_KEY" \ https://api.mirroapi.cloud/v1/error-codes
The versioned catalogue covers published MetaTrader 4 and MetaTrader 5 trade return codes and MIRRO execution preflight reasons
Future, runtime and vendor-specific codes can be unclassified: known: false keeps the original value and message rather than inventing an explanation
HTTP refusals also include error.code, error.message, optional details and an X-Request-Id support reference
Handle uncertainty without duplicating trades
EXECUTION_UNKNOWN means the trade may have executed
A native timeout or connection failure can produce this state immediately
Automatic dispatch stops for that command
Keep its command id and original idempotency key, inspect the account’s orders, positions and deals, and wait for a definitive result or escalate with that id
A later definitive acknowledgement can correct the command
Never treat a missing response as permission to submit the same trade under a new identity
Use the rules of the connected account
- Read the account’s symbol catalogue and preserve exact spelling, case and broker suffixes
- Read symbol specifications before choosing lot size
MT4 1.9.7 and MT5 1.9.5 reject API sizes outside the minimum, maximum or step; they do not silently resize an explicit trade - Honour trading sessions, margin, allowed order types, stop and freeze distances, account permissions, hedging and FIFO restrictions
These rules can change at the broker - MT5 filling selection accounts for execution mode and symbol flags
Pending orders request RETURN
Unsupported rules produce a diagnostic instead of a guessed policy - Native details require the updated EA
Older errors carrying a recognised numeric code can still receive a readable explanation; missing measurements or messages are never fabricated
MetaTrader 4 and MetaTrader 5 support does not certify every broker or every account type
Brokers control acceptance, prices, sessions and connectivity
MIRRO cannot override those decisions or guarantee zero failures
Native code references: MetaQuotes MT4 and MetaQuotes MT5
Reads: the book, history and the terminal
A read that could not be made is answered as such, never as an empty book, empty history or an invented price
| Code | HTTP | What it means | What to do |
|---|---|---|---|
BOOK_UNAVAILABLE | 503 | The positions or orders could not be read; nothing about them is known from this answer | Retry; never treat it as an empty book |
HISTORY_UNAVAILABLE | 503 | The deal history could not be read | Retry; never treat it as empty history |
SYMBOL_CATALOG_UNAVAILABLE | 503 | The symbol catalogue could not be read | Retry |
TERMINAL_UNAVAILABLE | 503 | The terminal is not connected, so a native read cannot be answered | Wait for connection CONNECTED, then retry |
TERMINAL_READ_TIMEOUT | 503 | The terminal did not answer the read within its deadline | Retry; the terminal may be busy |
TERMINAL_READ_INVALID | 503 | The terminal answered the read with something the gateway could not verify | Retry; report X-Request-Id if it repeats |
TERMINAL_READ_UNAVAILABLE | 503 | The read could not be placed (too many reads in flight, or the read table is missing) | Retry after a moment |
TERMINAL_READ_CANCELLED | 503 | The read was cancelled because the request ended before the terminal answered | Send it again |
TERMINAL_CLOCK_UNCERTAIN | 503 | The terminal's clock offset is unknown, so the quote age cannot be verified | Pass allowStale=true to accept an unverified age, or wait for the terminal to report its clock |
QUOTE_STALE | 503 | The quote is older than maxAgeSeconds | Raise maxAgeSeconds or pass allowStale=true |
EXECUTION_UNKNOWN | 503 | The gateway meant to refuse but could not record it, so the command may still execute; details.command names it | Read GET /v1/accounts/{id}/trades/{command} before sending anything again |
EXECUTION_NETTED | — | A Command.result.code, never an HTTP error: the order was executed, but on a MetaTrader 5 netting account it reduced a position already open on the symbol instead of opening one of its own, so there is no ticket of MIRRO's to name (result.executed is true, result.broker is netted_against_existing) | Read GET /v1/accounts/{id}/positions before deciding anything Never resend on this code: a resend nets the position again |
Copies
POST and PATCH /copies; the copy engine's own words are named codes with the raw reason in details.reason
| Code | HTTP | What it means | What to do |
|---|---|---|---|
COPY_REFUSED | 422 | The copy link was refused for a reason not in the named list; details.reason carries it | Read details.reason |
COPY_SAME_ACCOUNT | 422 | A copy needs two different accounts | Name a master and a follower that differ |
FOLLOWER_ALREADY_LINKED | 422 | The follower already has an active copy; details.linkId names it | Pause or delete that copy first |
FOLLOWER_UNAVAILABLE | 422 | The follower is not live, cannot follow, or has not reported in two minutes | Connect the follower and grant it the follower role |
MASTER_UNAVAILABLE | 422 | The master is not live, cannot master, or has not reported in two minutes | Connect the master and grant it the master role |
MAX_PROGRAM_UNAVAILABLE | 422 | The MAX program this copy belongs to is not open | Check the program |
SIZING_INVALID | 422 | The sizing figures do not fit the mode | Send ratio, riskPercent or lots for the mode |
LINK_NOT_FOUND | 422 | The copy to update is not yours or no longer exists | List GET /v1/copies |
PATCH_EMPTY | 422 | The update changes nothing | Send a field to change |
Billing and card payments
A failed payment-status read does not prove a payment failed
Check its saved reference before retrying and keep the same request id
| Code | HTTP | What it means | What to do |
|---|---|---|---|
ACCOUNT_PLAN_REQUIRED | 402 | This MIRRO HQ account needs an active account plan | Activate or renew its plan in Plans & payments — HQ has no hourly charges |
BILLING_ENROLLMENT_REQUIRED | 402 | Prepaid billing is on and this user has not accepted the offer or added credit | Accept the offer and add credit at details.billingPath |
FIRM_HOSTING_REQUIRED | 402 | Company hosting coverage has expired or been suspended — exits remain available | Contact the firm’s support team to review company coverage — no personal top-up is required |
INSUFFICIENT_BALANCE | 402 | The prepaid balance cannot cover a new deployment or new risk; exits and protective changes still work | Add credit in Billing |
BILLING_UNAVAILABLE | 503 | A billing check or usage read could not be verified — do not assume zero usage or unpaid coverage; new risk stays protected while exits remain available | Retry shortly; closing and cancelling are not gated |
BILLING_SESSION_REQUIRED | 403 | Billing is managed from a signed-in session, never with an API key | Sign in to the console |
BILLING_OFFER_UNAVAILABLE | 503 | The billing offer could not be read, so it cannot be accepted right now | Refresh, read the current offer, then accept |
PAYMENTS_DISABLED | 503 | Payments are not enabled or not approved on this gateway; do not send funds | Nothing to do until the operator enables them |
PAYMENT_UNAVAILABLE | 422 | The processor refused to open a payment page; details.reason carries its word | Try again in a moment |
PAYMENT_CHECKOUT_UNAVAILABLE | 503 | A checkout page could not be opened with the processor | Retry later |
PAYMENT_MINIMUM_TOPUP | 400 | The top-up is below the minimum of 5 USD of service credit | Send at least the minimum |
PAYMENT_PENDING_LIMIT | 503 | Five payments are already waiting to be confirmed | Finish or leave one, then start another |
PRICING_UNAVAILABLE | 422 | Today's exchange rate is not available yet, so the charge cannot be priced | Try again shortly |
CARD_PAYMENTS_DISABLED | 503 | Card top-ups are off on this gateway | Use another way to add credit, or wait |
CARD_CURRENCY_UNAVAILABLE | 503 | A card cannot be charged from this country right now | Pay with USDC or USDT instead |
CARD_PROVIDER_UNAVAILABLE | 422 | A payment method was asked for that is not offered in your country Paystack settles in a few African markets only, so it is not available elsewhere | Use a method from the checkout's own list; GET /billing returns the ones on offer |
CARD_AMOUNT_NOT_SUPPORTED | 400 | A card is charged in whole cents only | Use at most two decimal places |
Console sign-in
Answered to the console's session routes, not to API keys
| Code | HTTP | What it means | What to do |
|---|---|---|---|
PASSWORD_INCORRECT | 401 | The current password is wrong; it counts toward the lockout | Send the right password, or reset it |
ACCOUNT_LOCKED | 423 | Too many failed sign-ins; the account is locked for a while | Wait, or reset the password |
PASSWORD_CHANGE_REQUIRED | 403 | The session signed in with a password an operator issued (a new staff login, a locked-out customer); until the person chooses their own, only GET /v1/auth/me, POST /v1/auth/password and POST /v1/auth/logout answer | POST /v1/auth/password with currentPassword (the issued one) and newPassword, then carry on |
ACCOUNT_DISABLED | 403 | An operator switched this sign-in off; the password was right, and details / the message say why when a reason was given | Contact support Sessions the person still holds end at their next call |
TOKEN_INVALID | 422 | The verification or reset token is unknown, expired or used | Request a new one |
OTP_INVALID | 401 / 422 | The one-time code or backup code is wrong: 401 at sign-in (details.attemptsRemaining says how many tries are left), 422 when enabling or disabling two-factor | Send a fresh code |
CHALLENGE_INVALID | 401 | The two-factor challenge is unknown, expired, used or exhausted | Sign in again to get a new challenge |
EMAIL_REQUIRED | 422 | A confirmed email address is needed before paying by card | Confirm the address from the sign-up email, then retry |
MAX copy trading
A console product: a provider's master copied into the accounts of the people they invite
Its routes are console routes, not in the OpenAPI file; the codes are listed so the catalogue is complete
| Code | HTTP | What it means | What to do |
|---|---|---|---|
MAX_PLATFORM_UNSUPPORTED | 422 | MAX programs run on MetaTrader masters only | Use an mt4 or mt5 master |
MAX_OWN_PROGRAM | 422 | A provider cannot join their own program | Invite someone else |
MAX_INVITE_NOT_YOURS | 422 | This personal invite was sent to another address | Sign in with the invited address |
MAX_CONSENT_REQUIRED | 422 | Joining needs consent: true | Send consent: true once the person agrees |
MAX_ALREADY_MEMBER | 422 | This account already holds a place in the program | Nothing to do |
MAX_ACCOUNT_ALREADY_COPYING | 422 | The account already copies another master | Stop that copy first |
MAX_API_UNAVAILABLE | 422 | This MAX place has ended, so there is nothing to add the API to | Join again, then buy the add-on |
PROGRAM_INACTIVE | 422 | The program is closed or unpaid | Renew or reopen it |
LOGIN_IMMUTABLE | 422 | The account number of an existing MAX membership cannot change | Stop copying and use the invite link again with the right number |
MAX_ACCOUNT_VIEW_ONLY | 403 | This account copies someone, so only watching it and closing its trades is allowed | Buy Manage on the account, or stop copying |
MAX_MASTER_IN_USE | 409 | People still hold copies of this account’s trades | Close your trades, or remove the subscribers first |
MAX_MASTER_OFFLINE | 409 | The account people copy is offline, so copying cannot start again yet | Bring it back online and try again |
MAX_RESUME_REFUSED | 409 | Copying could not be started again | Read details.reason and try again |
MAX_MASTER_IS_COPYING | 422 | This account copies someone else, so it cannot be the account people copy | Use an account you trade yourself |
MAX_ACCOUNT_IS_COPIED | 422 | Other people copy this account, so it cannot join and copy someone | Use a different account |
MAX_CONSENT_VERSION | 422 | The consent wording shown is out of date | Reload the page and agree to the current wording |
MAX_EMAIL_NOT_VERIFIED | 422 | An open invite link on an offer that takes confirmed addresses only, and this address is not confirmed yet A fresh confirmation link is emailed by the refusal itself; nothing was created and no spot was taken details: sentTo (masked), sent, method: "link" | Open the link in that email, then send the same request again There is no code to type |
MAX_REMOVED_BY_PROVIDER | 422 | This person was removed and cannot rejoin on an open link | Ask for a fresh personal invite |
MAX_DEMO_NOT_ALLOWED | 422 | This offer takes real-money accounts only | Use a live account |
MAX_ONBOARD_ATTEST_REQUIRED | 422 | Adding someone yourself needs the attestation that you have their permission | Send attest: true |
MAX_ONBOARD_EMAIL_IN_PROGRAM | 422 | That address already holds a spot here | Nothing to do |
SPOTS_BELOW_MINIMUM | 422 | Spots come in packs of 30 or more | Ask for at least details.minimum spots |
SPOTS_NO_ROOM | 422 | The hosting cannot serve that many spots right now | Ask for details.canServeNow or fewer, or try later |
SPOTS_NONE_FREE | 422 | Every paid spot is taken | Add more spots first |
MAX_GUARD_UNAVAILABLE | 503 | The account’s MAX status could not be checked, so nothing was changed | Retry; the request had no effect |
MAIL_UNAVAILABLE | 503 | The email could not be sent, so nothing was created | Check the address and try again |
MAX_INVALID | 422 | This invite link does not exist | Check the whole link, or ask for a new one |
MAX_EXPIRED | 422 | This invite link has expired | Ask for a new one |
MAX_REVOKED | 422 | This invite link has been replaced | Ask for the new link |
MAX_USED | 422 | This personal invite has already been used | Ask for a fresh one |
MAX_PAUSED | 422 | This invite link is not taking new people right now | Try again later |
MAX_CLOSED | 422 | MAX copy trading has been stopped for this account | Nothing to do |
MAX_FULL | 422 | Every spot is taken | Ask the person who invited you to add more spots |
MAX_REFUSED | 422 | The join was refused; details.reason says why | Read details.reason |
ACCOUNT_NOT_HOSTED | 422 | This account has no hosted terminal to reconnect | Nothing to re-enter; the account is not hosted |