# Connecting accounts

> MetaTrader API docs for developers and coding agents. Last updated: 2026-10-14. Index: https://www.metatraderapi.net/llms.txt
>
> © 2026 Apex Vanguard Dynamics LLC. You, and the software tools and AI agents working for you, may read and use this documentation to build, run and support integrations with MetaTrader API; its code examples may be copied into your own software. Republishing or redistributing the documentation, in whole or in substantial part, is not permitted. Terms: https://www.metatraderapi.net/en/terms/

## Three ways to connect an account

| Way | Use when | Credential |
|---|---|---|
| Dashboard (https://app.metatraderapi.net/) | a handful of your own accounts | your login |
| `POST /v1/seats` (JSON body) | your backend connects accounts for your users | management key, see https://www.metatraderapi.net/docs/provisioning.md |
| `GET /ConnectEx` | code written for the classic MetaTrader REST API conventions | management key, or an API key that is neither read-only nor account-scoped |

Every way creates a paid seat (see https://www.metatraderapi.net/docs/provisioning.md for billing). Prefer `POST /v1/seats` from a backend: `/ConnectEx` takes the broker password as a URL query parameter, and URLs end up in logs.

## What you need from the account holder

- **Broker server name**, exactly as the broker spells it (e.g. `ICMarketsSC-Demo`). Demo and live accounts are on different servers.
- **Login**: the numeric MT account number, not an email address.
- **Main (trading) password.** An investor (read-only) password connects too, but its trading requests are refused.
- **Platform**: `MT4` or `MT5` (default `MT5`).

## /ConnectEx

```bash
curl -s -H "Authorization: Bearer $MTAPI_MGMT_KEY" \
  "https://api.metatraderapi.net/ConnectEx?user=12345678&password=...&server=ICMarketsSC-Demo&platform=MT5&wait=60"
```

| Param | Meaning |
|---|---|
| `user` (alias `login`) | numeric account login |
| `password` | main password (1–200 characters, no line breaks) |
| `server` or `host` | broker server name, or `host:port` |
| `port` | only used when `host` is a hostname without a port |
| `platform` | `MT4` or `MT5`, default `MT5` |
| `label` | your own name for it, up to 80 characters |
| `wait` | seconds to wait for `ACTIVE` before answering, 0–180, default 120. **Send `wait=60` or less**: the CDN in front of the API ends requests after about 100 seconds, and the one-time `apiKey` would be lost with the answer. Then poll `/ConnectState?id=`. |

Response (`200`, or `500` if the connection ended in `ERROR`):

```json
{"id": "7f123497-63b2-496d-864d-cf3657f73b1f", "status": "ACTIVE", "connected": true, "statusReason": null, "apiKey": "mt5api_...", "apiKeyId": "fd41e389-2fd9-44fc-86e3-06fe13f775c1", "platform": "MT5", "brokerServer": "ICMarketsSC-Demo", "note": "..."}
```

`id` is the account id for `?id=`. `apiKey` is a new full-access key, shown only in this response. It is not account-scoped: it works for all your accounts. To hand a key to one end user, create an `accountScoped` key (https://www.metatraderapi.net/docs/provisioning.md).

`/ConnectProxy` takes the same parameters and creates a private-hosting seat (dedicated IP and device id, $17 per month) — see https://www.metatraderapi.net/docs/provisioning.md.

## Connection states

| `status` | Meaning | What to do |
|---|---|---|
| `PENDING`, `CONNECTING` | being set up and logged in | wait; poll |
| `BUILDING_SERVER` | a private-hosting seat whose dedicated server is being prepared, or a seat waiting for free capacity; it continues automatically | wait; poll |
| `ACTIVE` | logged in at the broker; ready | trade |
| `ERROR` | the connection failed; `statusReason` says why | fix the cause, then reconnect |
| `DISCONNECTED`, `SUSPENDED` | not connected right now | `/ConnectByToken?id=` or `/Reconnect?id=` |

A new connection usually becomes `ACTIVE` within 1–2 minutes (the broker login itself takes 7–40 seconds once the connection is set up). Check state with `/ConnectState?id=` (or without `id`, for all your accounts). It returns `{id, status, connected, statusReason, platform, brokerLogin, brokerServer, lastConnectedAt, createdAt}`.

## Why a connection fails (`statusReason`)

| Cause | `statusReason` says |
|---|---|
| wrong login or password | the broker refused the login; use the main password and the exact server name |
| investor password | logged in read-only; trading needs the main password |
| demo account on a live server (or vice versa) | "Service is not available": the account belongs to a different server |
| account disabled or archived | contact the broker |
| broker unreachable | the trade server did not answer; check the server name |

A wrong password is never retried automatically: correct it and connect again. An unknown server name is refused at once with `400 UNKNOWN_BROKER_SERVER` and up to 8 `suggestions`.

## After connecting

- Dropped connections are restored automatically. While that happens, requests answer `503` and the WebSocket heartbeat reports `"connection": "reconnecting"`.
- `/Disconnect?id=` removes a connection. Its seat stays paid for the rest of the billing month, and your next connection reuses it at no charge. An unused paid seat keeps renewing with your subscription until you release it (dashboard, or `POST /v1/seat-capacity/release`).
- `/GetId?user=&server=` finds the account id of a login you already connected.
- `/GetBrokerServersByBrokerName?brokerName=` lists server names for a broker.
