# Connect an MT5 account

URL: https://docs.fxapis.com/api-reference/accounts/connect-an-mt5-account

> Connect an MT5 account. Stores the account and encrypts its password.

`POST https://api.fxapis.com/v1/accounts`

Stores the account and encrypts its password. It does **not** log in: the account lands in `created`, and connects when you bring it online or when the first order arrives on a `warm_on_demand` account.

**Reconnecting.** If this login and server were connected before and then disconnected, the same account comes back — its id and history kept — with the new password, and the answer is `200` instead of `201`. If they are still connected, the answer is `409 ACCOUNT_EXISTS` with the account's id; to change its password, use `POST /v1/accounts/{id}/password`.

Authentication: `Authorization: Bearer <API key>`.

#### Request body (application/json, required)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `platform` | "mt5" | no |  |
| `login` | string | yes | The MT5 account number. Example: `"26177561"` |
| `server` | string | yes | Broker server name, e.g. `ICMarkets-Demo`. Example: `"VantageMarkets-Demo"` |
| `password` | string | yes | The MT5 password. Encrypted on arrival and never returned or logged. Send the *trading* password, not the investor password: an investor password can read the account but cannot place an order. Example: `"your-mt5-trading-password"` |
| `mode` | "always_on" \| "warm_on_demand" \| "cold" | no | `always_on`: the account stays connected. `warm_on_demand`: it connects on demand (the first order, or a prepare) and goes offline by itself when idle. `cold`: it connects only when you ask. Orders are fastest in that order; cost runs the other way. |
| `label` | string | no | Example: `"Demo — strategy A"` |

#### Responses

- `200`
- `201`
- `400`
- `401`
- `402`
- `409`
- `503`

Failures return `{ "error": { "code", "message" } }`; every code is listed at https://docs.fxapis.com/errors.

#### 200 response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `data` | object | no |  |
| `data.id` | string (uuid) | no |  |
| `data.label` | null \| string | no | Yours, for telling accounts apart. |
| `data.login` | string | no | The MT5 account number. |
| `data.server` | string | no | The broker server name, exactly as MetaTrader shows it. |
| `data.mode` | "always_on" \| "warm_on_demand" \| "cold" | no |  |
| `data.state` | "created" \| "provisioning" \| "standby" \| "starting" \| "connecting" \| "synchronizing" \| "ready" \| "executing" \| "cooling" \| "offline" \| "degraded" \| "reconnecting" \| "invalid_credentials" \| "trading_disabled" \| "needs_2fa" \| "needs_certificate" \| "error" | no | Online: `ready` (can trade) and `executing` (an order is in flight). Connecting: `provisioning`, `starting`, `connecting`, `synchronizing`, `reconnecting` — poll until `ready`. Offline: `created`, `standby`, `cooling` (going offline) and `offline` (after a disconnect, send the account's credentials again to reconnect). `degraded`: online but misbehaving — restart the connection. Need a human: `invalid_credentials`, `needs_2fa`, `needs_certificate`, `trading_disabled`. `error`: see `stateDetail`. |
| `data.stateDetail` | null \| string | no | Why it is in that state, when there is more to say. |
| `data.stateChangedAt` | string (date-time) | no |  |
| `data.problem` | null \| object | no | Set when the account needs you, null otherwise: what is wrong in words, what the broker said, and what fixes it. For a refused login it names the broker's other servers, most likely first — a login only works on the server it was opened on. |
| `data.problem.code` | "LOGIN_REFUSED" \| "TRADING_DISABLED" \| "NEEDS_2FA" \| "NEEDS_CERTIFICATE" \| "CONNECTION_FAILED" \| "PLATFORM_ISSUE" \| "SERVER_NOT_FOUND" | yes |  |
| `data.problem.title` | string | yes | Example: `"The broker refused the login"` |
| `data.problem.explanation` | string | yes |  |
| `data.problem.detail` | null \| string | yes | What the broker or terminal reported, verbatim. |
| `data.problem.otherServers` | string[] | yes | Example: `["JustMarkets-Demo","JustMarkets-Demo2"]` |
| `data.problem.actions` | object[] | yes | `switch_server`: `POST /v1/accounts/{id}/server` with that server. `replace_credentials`: send the account's corrected credentials (see Accounts in the reference). `connect`: `POST /v1/accounts/{id}/warm`. `contact_support`: write to support. |
| `data.problem.actions[].kind` | "switch_server" \| "replace_credentials" \| "connect" \| "contact_support" | yes |  |
| `data.problem.actions[].server` | string | no |  |
| `data.currency` | null \| string | no |  |
| `data.leverage` | null \| integer | no |  |
| `data.marginMode` | "netting" \| "hedging" \| null | no | How the broker holds positions: `hedging` keeps one per order, `netting` one per symbol. Null until the terminal has reported it. |
| `data.tradeAllowed` | null \| boolean | no |  |
| `data.brokerName` | null \| string | no |  |
| `data.environment` | "demo" \| "contest" \| "live" \| null | no | Demo, contest or live — from the terminal once it has logged in, or from the server's name until then. Plans give demo accounts free up to an allowance; a trial connects demo accounts only. |
| `data.tradingDisabled` | boolean | no | Set by us or by the broker. No order is accepted while true. |
| `data.createdAt` | string (date-time) | no |  |
| `data.balance` | null \| string | no | Balance, in the account's currency. Example: `"10012.25000000"` |
| `data.equity` | null \| string | no | Balance plus open profit and credit. Example: `"10012.25000000"` |
| `data.margin` | null \| string | no | Margin in use. Example: `"10012.25000000"` |
| `data.freeMargin` | null \| string | no | Equity minus margin in use. Example: `"10012.25000000"` |
| `data.marginLevel` | null \| string | no | Equity over margin, in percent. Null while no margin is used: the ratio is undefined, not zero. Example: `"10012.25000000"` |
| `data.credit` | null \| string | no | Credit the broker extended. Null from a terminal older than account.v2. Example: `"10012.25000000"` |
| `data.profit` | null \| string | no | Open profit across positions. Null from a terminal older than account.v2. Example: `"10012.25000000"` |
| `data.figuresObservedAt` | null \| string (date-time) | no | When the figures were read from the terminal: every 15 seconds while the account is online (60 from a terminal not yet updated). Null if never. |