Health
How Tickwire decides whether an account is working.
A running terminal isn’t necessarily a working one. A terminal can be alive while logged out, stuck on a dialog, or connected to a broker whose price feed has stopped. So Tickwire measures health from work that succeeded, using three independent signals:
- Broker link: the connection state the terminal itself reports.
- Account reads: when we last read the account successfully. That shows the broker is answering, not just that a socket is open.
- Tick advance: whether the broker’s clock on a reference symbol is moving.
The ladder
| Status | Meaning | What to do |
|---|---|---|
healthy | Connected, account readable, ticks advancing | Nothing |
stale | Connected and readable, but ticks haven’t advanced within 30 s | Usually the broker or a closed market. Treat prices as frozen; don’t page yourself |
disconnected | Terminal up, no broker link | Usually the broker. We reconnect automatically and escalate if it persists |
down | We can’t read the terminal at all, or the account isn’t running | A running account: ours to fix, and you’ll get a webhook. An account that isn’t running: reason_code says why (see below) |
A health snapshot
curl -s https://api.tickwire.io/users/current/accounts/acc_7Qx/health -H "auth-token: $TW_KEY"
{
"status": "healthy",
"connected": true,
"read_only": false,
"trading_enabled": true,
"reasons": [],
"last_account_read_age_s": 2.1,
"last_tick_age_s": 0.4,
"last_action_age_s": 812.0,
"broker_time": "2026-09-23 14:02:11.480",
"checked_at": "2026-09-23T11:02:13Z"
}
trading_enabledis true only if an order could be accepted right now: connected, not an investor login, and trading switched on in the terminal.reasonsexplains any status other thanhealthyin plain words.- The ages let you apply your own, stricter thresholds.
- A quote older than four days never counts as “ticks advancing”. Some brokers serve a cached quote from years ago right after login.
Accounts that aren’t running
An account can exist without a terminal: its deploy failed (for example the broker asked for a
one-time password), or you undeployed it. There is nothing to measure, but the answer is still
known, so health says so instead of returning 404:
curl -s https://api.tickwire.io/users/current/accounts/acc_7Qx/health -H "auth-token: $TW_KEY"
{
"status": "down",
"connected": false,
"read_only": null,
"trading_enabled": false,
"reasons": ["account is not running (state DEPLOY_FAILED)",
"ERR_OTP_REQUIRED: the broker asks for a one-time password"],
"last_account_read_age_s": null,
"last_tick_age_s": null,
"last_action_age_s": null,
"broker_time": null,
"checked_at": "2026-09-23T11:02:13Z",
"fx_status": "error",
"deployed": false,
"state": "DEPLOY_FAILED",
"reason_code": "ERR_OTP_REQUIRED",
"error": "ERR_OTP_REQUIRED: the broker asks for a one-time password"
}
- The answer is
200.stateis the account’s lifecycle state, andreason_codethe code at the start of its error (ERR_OTP_REQUIRED,E_AUTH, …), ornullwhen the error has no code or there is none.erroris the same text ashealth.erroron the account object. - Anything we can’t know without a terminal, such as
read_onlyand the ages, isnull. - The terminal routes match:
GET /mt5/{id}/status(and/mt4/…) is200withstatus: "down"plusdeployed,state,reasonCodeanderror;/healthzand/livezare503. - Agents:
GET /v1/agent/accounts/{id}/healthsaysdisconnected, withstateandreason_codein itsevidence. - An account that is still deploying answers
503account_deployingwithRetry-After: it may be up in a moment. An account that doesn’t exist, or isn’t yours, is404account_not_found. - Other data calls on an account that isn’t running are
404account_not_deployed. Fix the cause and redeploy it.
How it reaches you
- Polling:
GET …/health, as above. - Streaming:
healthandbrokerConnectionStatusframes on the account stream. - Webhooks:
account.health_changedon every transition, within 60 seconds. See Webhooks. /users/current/…fields:connectionStatuson the account isCONNECTEDonly when health ishealthyorstaleand the broker link is up; otherwiseDISCONNECTED_FROM_BROKERorDISCONNECTED./v1and terminal-route fields:statusmapshealthyandstaletoconnected,disconnectedtodisconnected, anddowntoerror.
Account snapshot
GET /users/current/accounts/{id}/snapshot (agents: GET /v1/agent/accounts/{id}/snapshot) returns
everything needed to rebuild your picture of an MT4 or MT5 account in one call: account information,
open positions, pending orders, health and the broker’s server time.
{
"account_id": "acc_7Qx", "platform": "mt5",
"as_of": "2026-09-23T11:02:13.412Z", "complete": true, "terminal_connected": true,
"account_information": { "status": "ok", "read_at": "2026-09-23T11:02:13.380Z", "age_ms": 32, "data": { "balance": 10000, "equity": 10012.5 } },
"positions": { "status": "ok", "read_at": "…", "age_ms": 25, "data": [] },
"orders": { "status": "ok", "read_at": "…", "age_ms": 18, "data": [] },
"health": { "status": "ok", "read_at": "…", "age_ms": 9, "data": { "status": "healthy" } },
"server_time": { "status": "ok", "read_at": "…", "age_ms": 2,
"data": { "time": "2026-09-23T11:02:13.410Z", "brokerTime": "2026-09-23 14:02:13.410", "brokerUtcOffsetMinutes": 180 } }
}
- Each section has its own
status:ok(read from a terminal connected to its broker),stale(read, but the terminal was not connected, so values may be out of date) orunavailable(the read failed;dataisnullanderrorsays why).completeistrueonly when every section isok. read_atandage_msshow how fresh each section is. Sections are read one after another, not atomically.datauses the same shapes as the individual routes.brokerUtcOffsetMinutesis explicit and isnulluntil measured; broker time is never assumed to be UTC.- The answer is
200whenever anything could be read, and503only when no section could be.
Missing data shows as unknown
If a measurement is missing, the answer is unknown. The status page works the same way: a component without a recent check shows as unknown.