Docs

Accounts and lifecycle

The account lifecycle: states, modes, and what to poll.

An account is an MT5 login we hold credentials for. Its state says what is true of it right now; its mode says how eagerly we keep a terminal running for it.

Modes

Set at creation, changed with /mode.

ModeA terminal is runningFirst orderIdle cost
always_onAlwaysImmediateHighest
warm_on_demandWhile in useAfter a warm-upLow
coldOnly when you askAfter an explicit warmNone

always_on is for accounts that must react to something outside their own control — a copied signal, a market open. The account rests at ready rather than standby, which is precisely what is being paid for.

warm_on_demand is the sensible default for most integrations. The first order after an idle period waits for the terminal; the rest do not.

cold is for accounts you drive on a schedule and are content to warm yourself.

Changing mode does not move a running terminal. Switching to always_on takes effect on the next warm, so the call stays fast and predictable — warm the account afterwards to apply it now.

States

created ─→ provisioning ─→ standby ─→ starting ─→ connecting ─→ synchronizing ─→ ready ⇄ executing
                                                                                   │
                            standby ←──────────── cooling ←─────────────────────────┘

Resting

StateMeaning
createdStored, never connected. Nothing is running.
provisioningBeing prepared. Brief.
standbyConnected and known-good; no terminal running.
offlineDisconnected. The credential has been erased.

Coming up

StateMeaning
startingA runtime is starting. No broker contact yet.
connectingLogging in at the broker.
synchronizingLogged in; symbols and prices still filling.

synchronizing is not cosmetic. The terminal will answer, and the prices behind it are incomplete. An order sent here goes out against data that is not there, so only ready accepts one.

Working

StateMeaning
readyLogged in, synchronized, accepting orders.
executingAn order is in flight.
coolingShutting down cleanly.

Unhappy

StateNeeds a humanMeaning
degradedNoConnected but unhealthy — stale quotes, a slow terminal. May recover on its own.
reconnectingNoThe broker connection dropped; we are re-establishing it.
errorNoSomething transient failed. Retryable.
invalid_credentialsYesThe broker rejected the login.
trading_disabledYesLogin succeeded, trading is refused.
needs_2faYesA second factor is required. Not supported headlessly.
needs_certificateYesThe broker requires a client certificate.

The four that need a human will not improve by being retried, and repeated failed logins are how a broker locks an account — so warming one returns 409 rather than trying again. Fix the underlying thing and reconnect.

Endpoints

Full request and response shapes are in the API reference. What follows is what the reference cannot tell you.

POST /v1/accounts

Stores the account and seals the password. Does not log in.

Duplicate login + server for one tenant is rejected with 409. Two records for one broker login would mean two execution authorities for the same money, which is the split-brain the runtime leases exist to prevent — so it is refused at the front door too.

If the credential cannot be stored, the account is not created and you get 503. A half-made account that can never connect is worse than no account.

POST /v1/accounts/{id}/warm

Starts a terminal. Returns 202 with a pollUrl.

Idempotent in the way that matters: warming an already-running account returns alreadyRunning: true and starts nothing. Exactly one terminal runs per account, enforced in the database rather than by a check — two terminals on one broker account would both accept an order, and the customer would get a double position.

POST /v1/accounts/{id}/cool

Stops the terminal. The account stays connected, in standby.

Refuses with 409 while executing. Stopping mid-order turns a known outcome into an unknown one, which then has to be reconciled against the broker — and a retry on top of that is a duplicate trade. Wait for the order to settle.

Open positions are untouched. A stop loss or take profit attached at the broker keeps working with no terminal running. What stops is anything conditional on our side.

POST /v1/accounts/{id}/restart

Cool then warm, for a terminal that is connected but misbehaving — degraded, stale quotes, a stuck sync. Same 409 while an order is in flight.

POST /v1/accounts/{id}/disconnect

Stops the terminal and deletes the stored password. The account record and its history remain, in offline. Reconnecting means sending the password again.

This is the endpoint for a customer leaving. A disconnected account that still holds a usable password is a credential nobody is watching.

POST /v1/accounts/{id}/mode

Changes the mode. Takes effect on the next warm.

GET /v1/accounts/{id}/status

The cheap one, for polling. Every two seconds is fine.

Polling well

import time, httpx

def wait_until_ready(client, account_id, timeout=120):
    """Polls until the account is ready, or until it is clear it will not be."""
    NEEDS_HUMAN = {"invalid_credentials", "needs_2fa", "needs_certificate", "trading_disabled"}
    deadline = time.monotonic() + timeout

    while time.monotonic() < deadline:
        state = client.get(f"/v1/accounts/{account_id}/status").json()["data"]

        if state["state"] == "ready":
            return state
        if state["state"] in NEEDS_HUMAN:
            # Not a timeout and not retryable. Fail now, with the reason, rather
            # than spending two minutes to report something less useful.
            raise RuntimeError(f"{account_id} needs attention: {state['state']} — {state['detail']}")

        time.sleep(2)

    raise TimeoutError(f"{account_id} did not reach ready within {timeout}s (last: {state['state']})")

Two things that separate a good client from one that generates support tickets:

Stop on a terminal state. Polling for two minutes on invalid_credentials tells you nothing that the first response did not.

Give it longer than feels necessary. Fifteen seconds is typical, thirty is not unusual, and a broker under load can take longer. A timeout of 120 seconds costs nothing when things go well.

On this page