API changelog
Every API version, breaking change and deprecation, newest first.
Breaking changes to the native /v1 API ship only under a new dated version, and anything deprecated
keeps working for at least six months. The versioning policy explains the rules.
The compatible surfaces (/users/current/… and the terminal routes) are frozen to their existing
shapes and are not listed here unless we fix a divergence from those shapes.
Unreleased (no version change)
-
New API key prefixes. New full keys start with
tw_live_and new read-only keys withtw_ro_. Keys issued before 2026-10-03 keep working unchanged, with the same rights. If your code checks a key’s prefix, accept both. No shape changes. -
Idempotency-Keyon calls that create a secret.POST /v1/agent-keys,POST /v1/pretrade-hooks,POST /v1/pretrade-hooks/{id}/rotate-secret,POST /users/current/tokens,POST /v1/readonly-keys,POST /v1/readonly-keys/{id}/rotateandPOST /v1/sandbox/keysnow honour it (a replayed rotate rotates nothing): a retry with the same key answers the first result withIdempotent-Replayed: true, the secret field set tonulland a notice (key_notice,secret_notice,tokenNotice,apiKeyNotice) that it was already shown. Before, every retry created a second live credential. The key is scoped to the calling credential, and the protection is short-lived: a retry after one of our restarts or deploys may still create a second credential, so list and revoke duplicates. A call that fails after the credential exists answers500,outcome: unknownandcreated_id. See Idempotency. -
Full and sandbox keys are stored hashed. Full (
tw_live_) and sandboxtwsk_keys are now stored as a SHA-256 digest with a short preview, like read-only keys, API tokens and agent keys. Their values were already shown only once (POST /dashboard/api-keys,POST /v1/sandbox/signup,POST /v1/sandbox/keys, the dashboard’s sandbox quickstart); now nothing on our side keeps them. Lists answer onlykey_preview(tw_live_ab12…,twsk_ab12…), and the dashboard’s reveal answers400not_revealablefor every key. Existing keys keep working, with every header and query form, over REST and WebSocket. No shape changes. -
Breaking (pre-launch): read-only keys are shown once. Read-only (
tw_ro_) keys are now stored as a SHA-256 digest, like agent keys and API tokens. The value is inkeyonly in the answer toPOST /v1/readonly-keysandPOST /v1/readonly-keys/{id}/rotate(withkey_notice); every other read (GET /v1/readonly-keys,GETandPATCH /v1/readonly-keys/{id}) answerskey: nulland akey_preview(tw_ro_ab12…). Existing keys keep working. The dashboard can no longer reveal a read-only key; rotate it to get a new value. -
Request logs.
GET /v1/request-logs,GET /v1/request-logs/summaryandGET /v1/request-logs/{id}: every authenticated call of the last 14 days, with redacted body excerpts for errors. See Request logs. New error coderequest_log_not_found. Additive; no version change. -
Health of an account that isn’t running.
GET /users/current/accounts/{id}/healthandGET /mt4|mt5/{id}/statusused to answer404account_not_deployedfor an account whose deploy failed or that was undeployed. They now answer200withstatus: "down",deployed: false, the lifecyclestateand the reason code from the account’s error (for exampleERR_OTP_REQUIREDfor sandbox login1060);/healthzand/livezanswer503. Agent health (GET /v1/agent/accounts/{id}/health) saysdisconnectedwith that reason instead ofunknown. Unknown accounts and other tenants’ accounts are still404. See Health. -
Fewer one-off
500s on listings.GET /v1/connected-appsandGET /v1/dedicated-ips(and their dashboard versions) could answer500 internal_errorabout once in a hundred calls when a database connection had been dropped while idle. Connections are now checked before use, the read is retried once on a fresh connection, and if the database still can’t be reached the answer is503temporarily_unavailablewithRetry-After. Nothing was changed by such a call; retry it.
2026-09-27: pagination, account snapshot, trade and account events
Additions and one pre-launch shape change to version 2026-09-25. No new version was cut: the API
has no customers yet, so the change is made in place before launch rather than behind a new version.
- Breaking (pre-launch): three lists changed from a bare JSON array to a page.
GET /v1/agent-keys,GET /v1/pretrade-hooksandGET /v1/pretrade-holdsnow answer{"data": [...], "has_more": false, "next_cursor": null}instead of[...]. Read the items fromdata. The SDKs changed with them (list_agent_keys/listAgentKeys,list_pretrade_hooks/listPretradeHooks,list_holds/listHoldsreturn the page). - Cursor pagination on native
/v1lists:limit(1 to 500, default 100) andcursorin;has_moreandnext_cursorout. Also onGET /v1/agent-kill-switches,GET /v1/agent-audit,GET /v1/agent/audit,GET /v1/connected-appsandGET /v1/agent/accounts, where the existing items field is unchanged and the two fields are added. The lists on the compatible routes are unchanged. See Pagination. - New error code:
invalid_cursor. - Account snapshot:
GET /users/current/accounts/{id}/snapshotandGET /v1/agent/accounts/{id}/snapshot: account information, positions, orders, health and server time in one read, with per-section freshness and an explicit broker UTC offset. MT4 and MT5. See Health. - New webhook events, each sent only on evidence from the terminal:
position.opened,position.modified,position.closed,order.filled,order.cancelled,order.rejected,trade.outcome_unknown,account.connected,account.disconnected,account.login_failed,account.margin_call,account.stop_out,dedicated_ip.active,dedicated_ip.released.position.closedcarriesevidence:closing_deal(sent at once, with the deal) orunknown(the position was missing from two consecutive reads and no closing deal was found). See Webhooks. - New response header:
Idempotent-Replayed: trueon every answer served from the idempotency store; first executions never carry it. See Idempotency.
Deprecations: none.
2026-09-25: first version
- Version
2026-09-25published. This is the baseline for the native/v1API. SendTickwire-Version: 2026-09-25to pin it per request; every/v1response echoes the version that served it. - Rate limits published and enforced with per-endpoint weights: standard calls and trades cost 1 unit, history 5, batch orders 10, a WebSocket connect 5. Trades have their own per-account budget. See Rate limits.
- New response headers:
RateLimit-Limit,RateLimit-Remaining,RateLimit-ResetandRateLimit-Policy(IETF draft) on every response, next to the existingX-RateLimit-*. - Organisation pin. Each organisation is pinned to a version (new organisations to the latest,
existing ones to
2026-09-25), used by/v1calls withoutTickwire-Version. Read it withGET /v1/api-versionand move it withPOST /v1/api-versionor in the dashboard settings; see Versioning. - New error codes:
invalid_api_versionandapi_version_unsupported. - A
429on a trade or batch order now says"sent": false,"outcome": "not_sent".
Deprecations: none.