{"openapi":"3.1.0","info":{"title":"fxapis","version":"0.1.0","description":"fxapis is the MetaTrader 5 API. Connect an MT5 account once, then trade it, read its positions\nand its history over plain HTTP. Choose whether each account stays connected or comes online\nonly when you need it.\n\n### Conventions\n\n- Every successful response is `{ \"data\": … }`; every failure is `{ \"error\": { \"code\", \"message\" } }`.\n  Match on `code`, which is stable. `message` is written for a human and may change.\n- Every response carries `requestId`. Quote it in a support request and the entire call can be found.\n- Times are RFC 3339 in UTC. Money and prices are never floats in a request body.\n\n### Bringing an account online is not instant\n\nA broker login takes as long as the broker takes — usually seconds, occasionally much longer.\n`POST /accounts/{id}/warm` brings an account online and returns **202** with a `pollUrl` rather than\nholding the request open, so your client's timeout never becomes a question about someone else's\nnetwork. Poll `GET /accounts/{id}/status` until `state` is `ready`.\n\n### Credentials\n\nThe MT5 password you send is encrypted before it is stored, with a data key that is bound to that\none account, and is never returned by any endpoint, written to the account record or included in\na log line. We cannot show it back to you — if it is lost, it is reset at the broker."},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"`Authorization: Bearer fx_live_<id>_<secret>`.\n\nA key is shown once, at creation. We cannot show it again or recover it for you.\nKeys carry a label (`live` or `test`) in the key itself, so each configuration is easy to tell\napart. Both reach real brokers: test with a broker demo account.\n\nScopes are per key. A key without `accounts:write` can read accounts and nothing else."}},"schemas":{}},"paths":{"/healthz":{"get":{"summary":"Liveness","tags":["Health"],"description":"Says the fxapis API process is up, for liveness probes and uptime monitors. Checks nothing else and never returns anything but 200; use /readyz to know whether it can serve traffic.","security":[],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"}}}}}}}}},"/readyz":{"get":{"summary":"Readiness","tags":["Health"],"description":"Says the API can serve traffic right now, including storing and using account credentials. Returns 503 when it cannot.","security":[],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"checks":{"type":"object","additionalProperties":{"type":"string"}}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"checks":{"type":"object","additionalProperties":{"type":"string"}}}}}}}}}},"/v1/accounts":{"get":{"summary":"List connected accounts","tags":["Accounts"],"description":"Every account in this workspace, newest first.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":["null","string"],"description":"Yours, for telling accounts apart."},"login":{"type":"string","description":"The MT5 account number."},"server":{"type":"string","description":"The broker server name, exactly as MetaTrader shows it."},"mode":{"type":"string","enum":["always_on","warm_on_demand","cold"]},"state":{"type":"string","enum":["created","provisioning","standby","starting","connecting","synchronizing","ready","executing","cooling","offline","degraded","reconnecting","invalid_credentials","trading_disabled","needs_2fa","needs_certificate","error"],"description":"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`."},"stateDetail":{"type":["null","string"],"description":"Why it is in that state, when there is more to say."},"stateChangedAt":{"type":"string","format":"date-time"},"problem":{"type":["null","object"],"description":"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.","properties":{"code":{"type":"string","enum":["LOGIN_REFUSED","TRADING_DISABLED","NEEDS_2FA","NEEDS_CERTIFICATE","CONNECTION_FAILED"]},"title":{"type":"string","examples":["The broker refused the login"]},"explanation":{"type":"string"},"detail":{"type":["null","string"],"description":"What the broker or terminal reported, verbatim."},"otherServers":{"type":"array","items":{"type":"string"},"examples":[["JustMarkets-Demo","JustMarkets-Demo2"]]},"actions":{"type":"array","description":"`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.","items":{"type":"object","properties":{"kind":{"type":"string","enum":["switch_server","replace_credentials","connect","contact_support"]},"server":{"type":"string"}},"required":["kind"]}}},"required":["code","title","explanation","detail","otherServers","actions"]},"currency":{"type":["null","string"]},"leverage":{"type":["null","integer"]},"marginMode":{"type":["null","string"]},"tradeAllowed":{"type":["null","boolean"]},"brokerName":{"type":["null","string"]},"environment":{"type":["null","string"],"enum":["demo","contest","live",null],"description":"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."},"tradingDisabled":{"type":"boolean","description":"Set by us or by the broker. No order is accepted while true."},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}},"post":{"summary":"Connect an MT5 account","tags":["Accounts"],"description":"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.\n\n**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`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["login","server","password"],"properties":{"platform":{"type":"string","enum":["mt5"],"default":"mt5"},"login":{"type":"string","pattern":"^\\d+$","minLength":1,"maxLength":32,"description":"The MT5 account number.","example":"26177561"},"server":{"type":"string","minLength":1,"maxLength":128,"description":"Broker server name, e.g. `ICMarkets-Demo`.","example":"VantageMarkets-Demo"},"password":{"type":"string","minLength":1,"maxLength":256,"description":"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":{"type":"string","enum":["always_on","warm_on_demand","cold"],"default":"cold","description":"`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":{"type":"string","maxLength":120,"example":"Demo — strategy A"}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":["null","string"],"description":"Yours, for telling accounts apart."},"login":{"type":"string","description":"The MT5 account number."},"server":{"type":"string","description":"The broker server name, exactly as MetaTrader shows it."},"mode":{"type":"string","enum":["always_on","warm_on_demand","cold"]},"state":{"type":"string","enum":["created","provisioning","standby","starting","connecting","synchronizing","ready","executing","cooling","offline","degraded","reconnecting","invalid_credentials","trading_disabled","needs_2fa","needs_certificate","error"],"description":"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`."},"stateDetail":{"type":["null","string"],"description":"Why it is in that state, when there is more to say."},"stateChangedAt":{"type":"string","format":"date-time"},"problem":{"type":["null","object"],"description":"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.","properties":{"code":{"type":"string","enum":["LOGIN_REFUSED","TRADING_DISABLED","NEEDS_2FA","NEEDS_CERTIFICATE","CONNECTION_FAILED"]},"title":{"type":"string","examples":["The broker refused the login"]},"explanation":{"type":"string"},"detail":{"type":["null","string"],"description":"What the broker or terminal reported, verbatim."},"otherServers":{"type":"array","items":{"type":"string"},"examples":[["JustMarkets-Demo","JustMarkets-Demo2"]]},"actions":{"type":"array","description":"`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.","items":{"type":"object","properties":{"kind":{"type":"string","enum":["switch_server","replace_credentials","connect","contact_support"]},"server":{"type":"string"}},"required":["kind"]}}},"required":["code","title","explanation","detail","otherServers","actions"]},"currency":{"type":["null","string"]},"leverage":{"type":["null","integer"]},"marginMode":{"type":["null","string"]},"tradeAllowed":{"type":["null","boolean"]},"brokerName":{"type":["null","string"]},"environment":{"type":["null","string"],"enum":["demo","contest","live",null],"description":"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."},"tradingDisabled":{"type":"boolean","description":"Set by us or by the broker. No order is accepted while true."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":["null","string"],"description":"Yours, for telling accounts apart."},"login":{"type":"string","description":"The MT5 account number."},"server":{"type":"string","description":"The broker server name, exactly as MetaTrader shows it."},"mode":{"type":"string","enum":["always_on","warm_on_demand","cold"]},"state":{"type":"string","enum":["created","provisioning","standby","starting","connecting","synchronizing","ready","executing","cooling","offline","degraded","reconnecting","invalid_credentials","trading_disabled","needs_2fa","needs_certificate","error"],"description":"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`."},"stateDetail":{"type":["null","string"],"description":"Why it is in that state, when there is more to say."},"stateChangedAt":{"type":"string","format":"date-time"},"problem":{"type":["null","object"],"description":"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.","properties":{"code":{"type":"string","enum":["LOGIN_REFUSED","TRADING_DISABLED","NEEDS_2FA","NEEDS_CERTIFICATE","CONNECTION_FAILED"]},"title":{"type":"string","examples":["The broker refused the login"]},"explanation":{"type":"string"},"detail":{"type":["null","string"],"description":"What the broker or terminal reported, verbatim."},"otherServers":{"type":"array","items":{"type":"string"},"examples":[["JustMarkets-Demo","JustMarkets-Demo2"]]},"actions":{"type":"array","description":"`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.","items":{"type":"object","properties":{"kind":{"type":"string","enum":["switch_server","replace_credentials","connect","contact_support"]},"server":{"type":"string"}},"required":["kind"]}}},"required":["code","title","explanation","detail","otherServers","actions"]},"currency":{"type":["null","string"]},"leverage":{"type":["null","integer"]},"marginMode":{"type":["null","string"]},"tradeAllowed":{"type":["null","boolean"]},"brokerName":{"type":["null","string"]},"environment":{"type":["null","string"],"enum":["demo","contest","live",null],"description":"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."},"tradingDisabled":{"type":"boolean","description":"Set by us or by the broker. No order is accepted while true."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}":{"get":{"summary":"Fetch one account","tags":["Accounts"],"description":"One connected account: its login, server, label, mode, current state and when it last changed. The password is never included. Another workspace's account is 404.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":["null","string"],"description":"Yours, for telling accounts apart."},"login":{"type":"string","description":"The MT5 account number."},"server":{"type":"string","description":"The broker server name, exactly as MetaTrader shows it."},"mode":{"type":"string","enum":["always_on","warm_on_demand","cold"]},"state":{"type":"string","enum":["created","provisioning","standby","starting","connecting","synchronizing","ready","executing","cooling","offline","degraded","reconnecting","invalid_credentials","trading_disabled","needs_2fa","needs_certificate","error"],"description":"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`."},"stateDetail":{"type":["null","string"],"description":"Why it is in that state, when there is more to say."},"stateChangedAt":{"type":"string","format":"date-time"},"problem":{"type":["null","object"],"description":"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.","properties":{"code":{"type":"string","enum":["LOGIN_REFUSED","TRADING_DISABLED","NEEDS_2FA","NEEDS_CERTIFICATE","CONNECTION_FAILED"]},"title":{"type":"string","examples":["The broker refused the login"]},"explanation":{"type":"string"},"detail":{"type":["null","string"],"description":"What the broker or terminal reported, verbatim."},"otherServers":{"type":"array","items":{"type":"string"},"examples":[["JustMarkets-Demo","JustMarkets-Demo2"]]},"actions":{"type":"array","description":"`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.","items":{"type":"object","properties":{"kind":{"type":"string","enum":["switch_server","replace_credentials","connect","contact_support"]},"server":{"type":"string"}},"required":["kind"]}}},"required":["code","title","explanation","detail","otherServers","actions"]},"currency":{"type":["null","string"]},"leverage":{"type":["null","integer"]},"marginMode":{"type":["null","string"]},"tradeAllowed":{"type":["null","boolean"]},"brokerName":{"type":["null","string"]},"environment":{"type":["null","string"],"enum":["demo","contest","live",null],"description":"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."},"tradingDisabled":{"type":"boolean","description":"Set by us or by the broker. No order is accepted while true."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}},"delete":{"summary":"Delete an account and its history","tags":["Accounts"],"description":"Removes the account for good: its terminal is stopped, its password erased, and the record deleted with its orders, deals and positions. **This cannot be undone.** To stop trading on an account but keep its history readable, disconnect it instead.\n\nRefused with `409` while an order is in flight (`ACCOUNT_EXECUTING`), while a multi-account order that includes it has not finished (`ACCOUNT_IN_WAVE`), and when our last look found open positions (`ACCOUNT_HAS_POSITIONS`): those stay open at the broker with their stops, but could no longer be shown or closed here. Close them first, or send `force=true` to delete anyway.\n\nAlert hooks stop sending to the account; a hook left with no accounts is switched off. This month's usage is unaffected. The same login and server can be connected again afterwards, as a new account.","parameters":[{"schema":{"type":"string","enum":["true","false"]},"in":"query","name":"force","required":false,"description":"`true` deletes even with open positions, which stay open at the broker."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","enum":[true]},"removed":{"type":"object","description":"What went with it.","properties":{"orders":{"type":"integer"},"deals":{"type":"integer"},"positions":{"type":"integer"},"alertHooksUpdated":{"type":"integer"}}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/status":{"get":{"summary":"Poll lifecycle state","tags":["Accounts"],"description":"The endpoint to poll after bringing an account online. Cheap enough to call every second or two; `state` reaches `ready` when the account is logged in and ready to trade.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["created","provisioning","standby","starting","connecting","synchronizing","ready","executing","cooling","offline","degraded","reconnecting","invalid_credentials","trading_disabled","needs_2fa","needs_certificate","error"],"description":"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`."},"detail":{"type":["null","string"]},"since":{"type":"string","format":"date-time"},"mode":{"type":"string","enum":["always_on","warm_on_demand","cold"]},"tradingDisabled":{"type":"boolean"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/password":{"post":{"summary":"Replace an account's password","tags":["Accounts"],"description":"Gives a connected account a new trading password — after the member changed it at the broker, or when the account is in `invalid_credentials` because the one it had was wrong. Send `server` as well to correct the server name.\n\nThe account is taken offline first (refused with `409` while an order is in flight), the new password is encrypted and stored, and only then is the old one erased — a failure leaves the old credential in place. The account lands in `created` and comes online on the next order or when you bring it online; bring it online straight away to check the new password while the member is still there. The password is never returned or logged.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["password"],"properties":{"password":{"type":"string","minLength":1,"maxLength":256,"description":"The account's **trading** password, not the investor password.","example":"the-members-new-trading-password"},"server":{"type":"string","minLength":1,"maxLength":128,"description":"Optional: a corrected server name, exactly as MetaTrader shows it.","example":"VantageMarkets-Live"}}}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":["null","string"],"description":"Yours, for telling accounts apart."},"login":{"type":"string","description":"The MT5 account number."},"server":{"type":"string","description":"The broker server name, exactly as MetaTrader shows it."},"mode":{"type":"string","enum":["always_on","warm_on_demand","cold"]},"state":{"type":"string","enum":["created","provisioning","standby","starting","connecting","synchronizing","ready","executing","cooling","offline","degraded","reconnecting","invalid_credentials","trading_disabled","needs_2fa","needs_certificate","error"],"description":"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`."},"stateDetail":{"type":["null","string"],"description":"Why it is in that state, when there is more to say."},"stateChangedAt":{"type":"string","format":"date-time"},"problem":{"type":["null","object"],"description":"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.","properties":{"code":{"type":"string","enum":["LOGIN_REFUSED","TRADING_DISABLED","NEEDS_2FA","NEEDS_CERTIFICATE","CONNECTION_FAILED"]},"title":{"type":"string","examples":["The broker refused the login"]},"explanation":{"type":"string"},"detail":{"type":["null","string"],"description":"What the broker or terminal reported, verbatim."},"otherServers":{"type":"array","items":{"type":"string"},"examples":[["JustMarkets-Demo","JustMarkets-Demo2"]]},"actions":{"type":"array","description":"`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.","items":{"type":"object","properties":{"kind":{"type":"string","enum":["switch_server","replace_credentials","connect","contact_support"]},"server":{"type":"string"}},"required":["kind"]}}},"required":["code","title","explanation","detail","otherServers","actions"]},"currency":{"type":["null","string"]},"leverage":{"type":["null","integer"]},"marginMode":{"type":["null","string"]},"tradeAllowed":{"type":["null","boolean"]},"brokerName":{"type":["null","string"]},"environment":{"type":["null","string"],"enum":["demo","contest","live",null],"description":"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."},"tradingDisabled":{"type":"boolean","description":"Set by us or by the broker. No order is accepted while true."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/server":{"post":{"summary":"Move an account to another server","tags":["Accounts"],"description":"For a login refused because it was added under the wrong server name: keeps the stored password and tries it on `server` instead, so the password is not sent again. The broker's likely servers are in the account's `problem.otherServers`. With `connect: true` (the default) the account is brought online straight away, so the answer comes back in seconds — watch `state`, or the account's events.\n\n`409 ACCOUNT_EXISTS` when that login is already connected on that server here; `409 NO_PASSWORD` when no password is stored (send one to `/password` instead).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["server"],"properties":{"server":{"type":"string","minLength":1,"maxLength":128,"description":"Exactly as MetaTrader shows it.","example":"JustMarkets-Demo"},"connect":{"type":"boolean","default":true}}}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":["null","string"],"description":"Yours, for telling accounts apart."},"login":{"type":"string","description":"The MT5 account number."},"server":{"type":"string","description":"The broker server name, exactly as MetaTrader shows it."},"mode":{"type":"string","enum":["always_on","warm_on_demand","cold"]},"state":{"type":"string","enum":["created","provisioning","standby","starting","connecting","synchronizing","ready","executing","cooling","offline","degraded","reconnecting","invalid_credentials","trading_disabled","needs_2fa","needs_certificate","error"],"description":"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`."},"stateDetail":{"type":["null","string"],"description":"Why it is in that state, when there is more to say."},"stateChangedAt":{"type":"string","format":"date-time"},"problem":{"type":["null","object"],"description":"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.","properties":{"code":{"type":"string","enum":["LOGIN_REFUSED","TRADING_DISABLED","NEEDS_2FA","NEEDS_CERTIFICATE","CONNECTION_FAILED"]},"title":{"type":"string","examples":["The broker refused the login"]},"explanation":{"type":"string"},"detail":{"type":["null","string"],"description":"What the broker or terminal reported, verbatim."},"otherServers":{"type":"array","items":{"type":"string"},"examples":[["JustMarkets-Demo","JustMarkets-Demo2"]]},"actions":{"type":"array","description":"`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.","items":{"type":"object","properties":{"kind":{"type":"string","enum":["switch_server","replace_credentials","connect","contact_support"]},"server":{"type":"string"}},"required":["kind"]}}},"required":["code","title","explanation","detail","otherServers","actions"]},"currency":{"type":["null","string"]},"leverage":{"type":["null","integer"]},"marginMode":{"type":["null","string"]},"tradeAllowed":{"type":["null","boolean"]},"brokerName":{"type":["null","string"]},"environment":{"type":["null","string"],"enum":["demo","contest","live",null],"description":"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."},"tradingDisabled":{"type":"boolean","description":"Set by us or by the broker. No order is accepted while true."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/events":{"get":{"summary":"What happened to an account","tags":["Accounts"],"description":"The account's history in words, newest first: added, logging in, refused by the broker, online, moved to another server, taken offline. The same record the console shows as the account's activity.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"in":"query","name":"limit","required":false},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"at":{"type":"string","format":"date-time"},"tone":{"type":"string","enum":["success","info","warning","danger"]},"title":{"type":"string","example":"The broker refused the login"},"detail":{"type":["null","string"]},"by":{"type":"string","enum":["key","member","staff","system"]},"action":{"type":"string"}},"required":["id","at","tone","title","detail","by","action"]}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/warm":{"post":{"summary":"Bring an account online","tags":["Lifecycle"],"description":"Starts connecting the account and returns **202** immediately — the broker login is still in progress. Poll `pollUrl` until `state` is `ready`.\n\nCalling this for an account that is already online is harmless and returns `alreadyRunning: true`, so a client that is unsure can simply call it.\n\nReturns 409 when the account needs a human first (a wrong password, 2FA, a certificate, trading disabled at the broker). Retrying will not fix those, and repeated failed logins are how a broker locks an account.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"202":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"runtimeId":{"type":"string","format":"uuid"},"alreadyRunning":{"type":"boolean","description":"True when the account was already online or connecting; asking again is harmless."},"state":{"type":"string","enum":["created","provisioning","standby","starting","connecting","synchronizing","ready","executing","cooling","offline","degraded","reconnecting","invalid_credentials","trading_disabled","needs_2fa","needs_certificate","error"]},"pollUrl":{"type":"string","description":"Poll here until `state` is `ready`."}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/prepare":{"post":{"summary":"Bring several accounts online at once","tags":["Lifecycle"],"description":"Brings every account listed online and returns **202** with a result for each — the broker logins are still in progress. Built for a signal: call it when the signal goes out, and by the time people act on it their accounts are online, so the order goes straight through instead of waiting for a login.\n\nAn account already online is reported as `already_running`; one that needs a human first (`needs_operator`) is not retried. `warm_on_demand` accounts go offline again by themselves after the idle window with no orders.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountIds"],"additionalProperties":false,"properties":{"accountIds":{"type":"array","minItems":1,"maxItems":200,"uniqueItems":true,"items":{"type":"string","format":"uuid"}}}}}}},"responses":{"202":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","required":["accountId","result"],"properties":{"accountId":{"type":"string","format":"uuid"},"result":{"type":"string","enum":["starting","already_running","not_found","leased_elsewhere","needs_operator","no_secret","failed"],"description":"`starting`: connecting now. `already_running`: already online or connecting. `leased_elsewhere`: busy with another request; retry in a moment. `needs_operator`: needs a human first — a wrong login, 2FA or a certificate. `no_secret`: no credentials are stored; send them again. `failed`: could not be brought online; `message` says why."},"message":{"type":["null","string"]}}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/cool":{"post":{"summary":"Take an account offline","tags":["Lifecycle"],"description":"Takes the account offline and keeps it, with its stored password, in `standby` — ready to be brought online again. Open positions are untouched: a stop loss or take profit is held by the broker and keeps working while the account is offline.\n\nReturns 409 while an order is in flight. Going offline then would turn a known outcome into an unknown one, and a retry on top of that is a duplicate trade.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"stopped":{"type":"boolean","description":"False when the account was already offline."},"state":{"type":"string"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/restart":{"post":{"summary":"Restart the connection","tags":["Lifecycle"],"description":"For an account that is online but misbehaving — `degraded`, stale quotes, a stuck sync. Returns **202**; poll `pollUrl` until `state` is `ready`. Refused with 409 while an order is in flight, for the same reason as taking it offline.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"202":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"runtimeId":{"type":"string","format":"uuid"},"alreadyRunning":{"type":"boolean","description":"True when the account was already online or connecting; asking again is harmless."},"state":{"type":"string","enum":["created","provisioning","standby","starting","connecting","synchronizing","ready","executing","cooling","offline","degraded","reconnecting","invalid_credentials","trading_disabled","needs_2fa","needs_certificate","error"]},"pollUrl":{"type":"string","description":"Poll here until `state` is `ready`."}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/disconnect":{"post":{"summary":"Disconnect and erase the credential","tags":["Lifecycle"],"description":"Takes the account offline and **deletes the stored password**. The account record stays, with its history, in `offline`. Reconnecting means sending the password again.\n\nThis is the endpoint to call when a customer leaves. A disconnected account that still holds a usable password is a credential nobody is watching.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"state":{"type":"string"},"credentialsRemoved":{"type":"boolean"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/mode":{"post":{"summary":"Change how eagerly the account stays connected","tags":["Lifecycle"],"description":"`always_on`: stays connected. `warm_on_demand`: connects on demand (the first order, or a prepare) and goes offline by itself when idle. `cold`: connects only when you ask.\n\nTakes effect the next time the account is brought online, so the call stays fast and predictable. Switch to `always_on` and then bring the account online to apply it now.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["mode"],"properties":{"mode":{"type":"string","enum":["always_on","warm_on_demand","cold"]}}}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"mode":{"type":"string","enum":["always_on","warm_on_demand","cold"]},"restingState":{"type":"string","description":"Where the account sits when idle under this mode."}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/instruments":{"get":{"summary":"List the instruments a signal can name","tags":["Instruments"],"description":"The markets fxapis names once, whatever each broker calls them: currency pairs, metals, indices, energies and crypto. A signal that names one of these as `instrument` is traded on every account under that account's own broker symbol. Needs no account and no broker.","parameters":[{"schema":{"type":"string","enum":["forex","metals","indices","energies","crypto"]},"in":"query","name":"category","required":false,"description":"Only this category."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"instrument":{"type":"string","example":"XAUUSD"},"name":{"type":"string","example":"Gold vs US Dollar"},"category":{"type":"string","enum":["forex","metals","indices","energies","crypto"]}}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/symbols":{"get":{"summary":"List the symbols an account's broker offers","tags":["Instruments"],"description":"Every symbol the account's broker offers it, with its contract specification, as read from the broker when the account was last online — so it answers while the account is offline. Refreshed each time the account comes online and the list is a day old. `syncedAt` says when.\n\nReturns 409 `SYMBOLS_NOT_SYNCED` for an account that has never been online.","parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Only symbols whose name or description contains this."},{"schema":{"type":"string","enum":["true","false"]},"in":"query","name":"tradable","required":false,"description":"Only symbols this account can, or cannot, open positions in."},{"schema":{"type":"integer","minimum":1,"maximum":1000,"default":200},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"The `nextCursor` from the previous page."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"The broker's own name, exactly as an order must send it.","example":"XAUUSD.a"},"description":{"type":"string","example":"Gold vs US Dollar"},"path":{"type":"string","description":"The broker's folder for it.","example":"Metals\\XAUUSD.a"},"digits":{"type":["null","integer"],"example":2},"contractSize":{"type":["null","number"],"description":"Units of the underlying per 1.0 lot.","example":100},"volumeMin":{"type":["null","number"],"example":0.01},"volumeMax":{"type":["null","number"],"example":50},"volumeStep":{"type":["null","number"],"example":0.01},"tradable":{"type":"boolean","description":"Whether this account can open positions in it."},"sessions":{"type":["null","object"],"description":"The broker's own sessions, in its server time (see `meta.utcOffsetSeconds`). Null until read.","properties":{"trade":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","enum":["sunday","monday","tuesday","wednesday","thursday","friday","saturday"]},"open":{"type":"string","examples":["00:01"],"description":"HH:MM."},"close":{"type":"string","examples":["23:58"],"description":"HH:MM; `24:00` is the end of the day."}}},"description":"When orders can be placed."},"quote":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","enum":["sunday","monday","tuesday","wednesday","thursday","friday","saturday"]},"open":{"type":"string","examples":["00:01"],"description":"HH:MM."},"close":{"type":"string","examples":["23:58"],"description":"HH:MM; `24:00` is the end of the day."}}},"description":"When prices are quoted."}}},"currencyBase":{"type":"string"},"currencyProfit":{"type":"string"},"currencyMargin":{"type":"string"}}}},"meta":{"type":"object","properties":{"syncedAt":{"type":"string","format":"date-time","description":"When the list was read from the broker."},"server":{"type":"string"},"symbolCount":{"type":"integer"},"utcOffsetSeconds":{"type":["null","integer"],"description":"The broker's server clock minus UTC, in seconds, measured when the sessions were read.","example":10800},"sessionsSyncedAt":{"type":["null","string"],"format":"date-time","description":"When the sessions were read; null until they have been."}}},"page":{"type":"object","properties":{"hasMore":{"type":"boolean"},"nextCursor":{"type":["null","string"],"description":"Pass as `cursor` to continue."}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/instruments":{"get":{"summary":"See how each instrument maps onto an account's broker","tags":["Instruments"],"description":"For every instrument, the symbol an order naming it will trade on this account — or why it cannot: the broker has several plausible symbols (`ambiguous`, with `candidates`), or does not offer it (`missing`). Useful when a member connects, to tell them which signals their account can follow.\n\nA symbol is mapped automatically only when its name matches and, where the market has one standard contract, its contract size agrees: gold quoted per gram is never taken for gold per ounce.\n\nReturns 409 `SYMBOLS_NOT_SYNCED` for an account that has never been online.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"instrument":{"type":"string","example":"XAUUSD"},"name":{"type":"string"},"category":{"type":"string","enum":["forex","metals","indices","energies","crypto"]},"status":{"type":"string","enum":["mapped","ambiguous","missing"],"description":"`mapped`: orders naming the instrument trade `symbol`. `ambiguous`: the broker has more than one plausible symbol (in `candidates`), so an order must name the one it means. `missing`: the broker does not offer it to this account."},"symbol":{"type":["null","string"],"example":"XAUUSD.a"},"reason":{"type":["null","string"],"example":"its name once the broker's suffix is removed, contract size agrees"},"candidates":{"type":"array","items":{"type":"object","properties":{"symbol":{"type":"string"},"confidence":{"type":"number","description":"0 to 1."},"reason":{"type":"string"}}}}}}},"meta":{"type":"object","properties":{"syncedAt":{"type":"string","format":"date-time","description":"When the list was read from the broker."},"server":{"type":"string"},"symbolCount":{"type":"integer"},"utcOffsetSeconds":{"type":["null","integer"],"description":"The broker's server clock minus UTC, in seconds, measured when the sessions were read.","example":10800},"sessionsSyncedAt":{"type":["null","string"],"format":"date-time","description":"When the sessions were read; null until they have been."}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/sessions":{"get":{"summary":"Market hours for a symbol or instrument, from the account's broker","tags":["Instruments"],"description":"When the account's broker lets orders be placed in a symbol — or in this account's symbol for an instrument — as the broker configured it (MetaTrader's `SymbolInfoSessionTrade`), with whether it is open now and when that next changes.\n\n`trade` and `quote` are given in the broker's server time and in UTC; `utcOffsetSeconds` is the broker's clock as measured when the sessions were read. Read when the account comes online and refreshed daily, so it answers while the account is offline.\n\nHolidays a broker does not load into its schedule are not here: on such a day an order is still refused with `ORDER_REJECTED` (`Market closed`).","parameters":[{"schema":{"type":"string"},"in":"query","name":"symbol","required":false,"description":"A broker symbol, exactly as the broker spells it."},{"schema":{"type":"string"},"in":"query","name":"instrument","required":false,"description":"Or an instrument, e.g. `XAUUSD`: this account's symbol for it is used."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"symbol":{"type":"string","example":"XAUUSD"},"instrument":{"type":["null","string"],"example":"XAUUSD"},"server":{"type":"string"},"utcOffsetSeconds":{"type":"integer","example":10800},"sessionsSyncedAt":{"type":"string","format":"date-time"},"openNow":{"type":"boolean"},"nextOpen":{"type":["null","string"],"format":"date-time","description":"When it next opens (UTC), if closed."},"nextClose":{"type":["null","string"],"format":"date-time","description":"When it next closes (UTC), if open."},"trade":{"type":"object","properties":{"server":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","enum":["sunday","monday","tuesday","wednesday","thursday","friday","saturday"]},"open":{"type":"string","description":"HH:MM.","example":"00:01"},"close":{"type":"string","description":"HH:MM; `24:00` is the end of the day.","example":"23:58"}}},"description":"In the broker's server time."},"utc":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","enum":["sunday","monday","tuesday","wednesday","thursday","friday","saturday"]},"open":{"type":"string","description":"HH:MM.","example":"00:01"},"close":{"type":"string","description":"HH:MM; `24:00` is the end of the day.","example":"23:58"}}},"description":"In UTC."}}},"quote":{"type":"object","properties":{"server":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","enum":["sunday","monday","tuesday","wednesday","thursday","friday","saturday"]},"open":{"type":"string","description":"HH:MM.","example":"00:01"},"close":{"type":"string","description":"HH:MM; `24:00` is the end of the day.","example":"23:58"}}}},"utc":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","enum":["sunday","monday","tuesday","wednesday","thursday","friday","saturday"]},"open":{"type":"string","description":"HH:MM.","example":"00:01"},"close":{"type":"string","description":"HH:MM; `24:00` is the end of the day.","example":"23:58"}}}}}}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/symbols/sync":{"post":{"summary":"Read an account's symbols from its broker now","tags":["Instruments"],"description":"Reads the broker's symbol list again and remaps the instruments, for when the broker has added symbols. Needs the account online (`ready`); returns 409 `ACCOUNT_NOT_READY` otherwise. It happens on its own once a day while the account is online, so most integrations never call this.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"syncedAt":{"type":"string","format":"date-time","description":"When the list was read from the broker."},"server":{"type":"string"},"symbolCount":{"type":"integer"},"utcOffsetSeconds":{"type":["null","integer"],"description":"The broker's server clock minus UTC, in seconds, measured when the sessions were read.","example":10800},"sessionsSyncedAt":{"type":["null","string"],"format":"date-time","description":"When the sessions were read; null until they have been."}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/brokers/servers":{"get":{"summary":"Search broker servers","tags":["Accounts"],"description":"MT5 servers matching what someone typed — a broker's name (`vantage`), the start of a server name (`JustMarkets-De`), with or without dashes and spaces. Built for a typeahead in your connect form: call it as the person types (debounced, from 2 characters) and let them pick.\n\nServers accounts on fxapis have logged in to come first (`proven: true`), then names starting with what was typed, then the kind asked for (`demo`/`live`), then the broker's main server. With fewer than five matches for 3+ characters, the broker search is asked once and its servers added, so a broker nobody here has used yet is found too — that call can take a second or two.\n\n**A server that is not listed can still be connected**: always let people use exactly what they typed. Without `q`, the servers used most here.","parameters":[{"schema":{"type":"string","maxLength":64},"example":"justmarkets","in":"query","name":"q","required":false},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20},"in":"query","name":"limit","required":false}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","description":"Exactly as MetaTrader shows it — send this as `server`.","example":"JustMarkets-Demo"},"company":{"type":["null","string"],"description":"The broker's legal name, when known.","example":"JustMarkets Ltd"},"kind":{"type":"string","enum":["demo","live","contest","unknown"],"description":"From the server's name; `unknown` when the name does not say."},"proven":{"type":"boolean","description":"Accounts on fxapis have logged in to this server."}},"required":["name","company","kind","proven"]}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/orders/market":{"post":{"summary":"Place a market order","tags":["Trading"],"description":"Sends a market order and waits for the broker's answer.\n\n**Send an `Idempotency-Key` header.** Without one, a request that times out leaves you unable to retry safely: you cannot tell whether the order was placed, and guessing wrong opens a second position. With one, retrying is free — the same key returns the same answer and never places a second order.\n\nThree failures are worth telling apart, and the response distinguishes them:\n\n- **`SEND_FAILED` (503)** — the order never reached the broker. `retryable: true`. Safe to resend.\n- **`ORDER_REJECTED` (422)** — the broker refused it, with a reason and its own return code. `retryable` says whether the reason was transient (a requote, a moved price) or permanent (insufficient margin, a closed market).\n- **`ORDER_UNRESOLVED` (503)** — we do not know. The order may be live at the broker. It is in `unknown` while we confirm the result with the broker. **Do not resend it**; poll the order instead.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["side","volume"],"description":"Send `symbol` or `instrument`, not both.","properties":{"symbol":{"type":"string","minLength":1,"maxLength":32,"description":"As the broker names it, e.g. `EURUSD`.","example":"EURUSD"},"instrument":{"type":"string","minLength":1,"maxLength":32,"description":"Instead of `symbol`: an instrument from `GET /v1/instruments`, traded under this account's own broker symbol for it (`XAUUSD` may be `XAUUSD.a` or `GOLD` at the broker). The order records both. Refused with `INSTRUMENT_NOT_OFFERED` or `INSTRUMENT_AMBIGUOUS` when the account's broker has no single match.","example":"XAUUSD"},"side":{"type":"string","enum":["buy","sell"]},"volume":{"type":"string","pattern":"^\\d+(\\.\\d{1,8})?$","description":"Lots, **as a string** — `\"0.10\"`, not `0.1`. A JSON number is a double, and a volume that arrives as 0.30000000000000004 is rejected by the broker.","example":"0.01"},"stopLoss":{"type":"string","description":"Absolute price, not a distance. Must be below entry for a buy.","example":"1.12900"},"takeProfit":{"type":"string","description":"Absolute price, not a distance. Must be above entry for a buy.","example":"1.14200"},"deviationPoints":{"type":"integer","minimum":0,"maximum":10000,"description":"Maximum slippage in points. Too small and a fast market returns a requote instead of a fill.","example":20},"comment":{"type":"string","maxLength":120,"description":"Stored on the MT5 order after our 11-character reference, cut to fit MT5's limit: the first 17 characters, plain ASCII.","example":"signal 42"},"clientOrderId":{"type":"string","maxLength":120,"description":"Your reference. Not required to be unique.","example":"sig-42-user-7"}}}}},"description":"Send `symbol` or `instrument`, not both."},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true},{"schema":{"type":"string","maxLength":200},"example":"3f0c9a52-8a8e-4f7e-9b0e-6c1d2f5a7b10","in":"header","name":"idempotency-key","required":false,"description":"Any unique string, usually a UUID. A retry with the same key and body returns the first answer instead of placing a second order; the same key with a different body is refused."}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"accountId":{"type":"string","format":"uuid"},"clientOrderId":{"type":["null","string"],"description":"Your own reference, echoed back."},"symbol":{"type":"string","description":"The broker symbol traded."},"instrument":{"type":["null","string"],"description":"The instrument the order named, when it named one; `symbol` is what it was traded as.","example":"XAUUSD"},"side":{"type":"string","enum":["buy","sell"]},"type":{"type":"string","enum":["market","limit","stop","stop_limit"]},"intent":{"type":"string","enum":["open","close","modify","cancel"],"description":"What this order was for. A close is an order, with the same record and the same failed/unknown distinction as an open — `modify` covers moving a stop, which changes what the account risks."},"brokerPositionId":{"type":["null","string"],"description":"The position this acted on. Null on an opening order."},"volume":{"type":["null","string"],"description":"Requested volume, in lots."},"stopLoss":{"type":["null","string"],"description":"Absolute price, not a distance."},"takeProfit":{"type":["null","string"],"description":"Absolute price, not a distance."},"state":{"type":"string","enum":["accepted","validating","sending","working","completed","filled","partially_filled","rejected","failed","unknown","cancelled","expired"]},"stateDetail":{"type":["null","string"]},"needsReconciliation":{"type":"boolean","description":"True while we are confirming the result with the broker. Never resend such an order; poll it."},"retcode":{"type":["null","integer"],"description":"The broker's own MT5 return code, unmodified. 10009 is a completed request."},"retcodeText":{"type":["null","string"]},"brokerOrderId":{"type":["null","string"],"description":"The broker's ticket. What their statement shows."},"brokerDealId":{"type":["null","string"]},"filledVolume":{"type":["null","string"],"description":"What actually filled, which can be less than requested."},"filledPrice":{"type":["null","string"],"description":"What it actually filled at, which is rarely the requested price."},"sentAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time","description":"When an answer arrived."},"reconciledAt":{"type":["null","string"],"format":"date-time","description":"Set when a result was confirmed with the broker after the fact."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/positions/{positionId}/close":{"post":{"summary":"Close a position","tags":["Trading"],"description":"Closes a position in whole, or partly if you send a `volume`.\n\n**Send an `Idempotency-Key`.** It matters more here than on an opening order: a retried close does not close twice, it opens an opposing position, and the account ends up with exposure nobody chose.\n\nThe three failure modes are the same as for an opening order, and `ORDER_UNRESOLVED` means the same thing — **do not resend**, poll the order. An unresolved close is the case where you might believe you are flat and not be.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"volume":{"type":"string","pattern":"^\\d+(\\.\\d{1,8})?$","description":"Lots to close, as a string. Omit to close the whole position.","example":"0.01"},"deviationPoints":{"type":"integer","minimum":0,"maximum":10000,"example":20},"comment":{"type":"string","maxLength":120,"example":"take profit early"},"clientOrderId":{"type":"string","maxLength":120,"example":"sig-42-user-7-close"}}}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true},{"schema":{"type":"string"},"in":"path","name":"positionId","required":true,"description":"The broker's position ticket."},{"schema":{"type":"string","maxLength":200},"example":"3f0c9a52-8a8e-4f7e-9b0e-6c1d2f5a7b10","in":"header","name":"idempotency-key","required":false,"description":"Any unique string, usually a UUID. A retry with the same key and body returns the first answer instead of placing a second order; the same key with a different body is refused."}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"accountId":{"type":"string","format":"uuid"},"clientOrderId":{"type":["null","string"],"description":"Your own reference, echoed back."},"symbol":{"type":"string","description":"The broker symbol traded."},"instrument":{"type":["null","string"],"description":"The instrument the order named, when it named one; `symbol` is what it was traded as.","example":"XAUUSD"},"side":{"type":"string","enum":["buy","sell"]},"type":{"type":"string","enum":["market","limit","stop","stop_limit"]},"intent":{"type":"string","enum":["open","close","modify","cancel"],"description":"What this order was for. A close is an order, with the same record and the same failed/unknown distinction as an open — `modify` covers moving a stop, which changes what the account risks."},"brokerPositionId":{"type":["null","string"],"description":"The position this acted on. Null on an opening order."},"volume":{"type":["null","string"],"description":"Requested volume, in lots."},"stopLoss":{"type":["null","string"],"description":"Absolute price, not a distance."},"takeProfit":{"type":["null","string"],"description":"Absolute price, not a distance."},"state":{"type":"string","enum":["accepted","validating","sending","working","completed","filled","partially_filled","rejected","failed","unknown","cancelled","expired"]},"stateDetail":{"type":["null","string"]},"needsReconciliation":{"type":"boolean","description":"True while we are confirming the result with the broker. Never resend such an order; poll it."},"retcode":{"type":["null","integer"],"description":"The broker's own MT5 return code, unmodified. 10009 is a completed request."},"retcodeText":{"type":["null","string"]},"brokerOrderId":{"type":["null","string"],"description":"The broker's ticket. What their statement shows."},"brokerDealId":{"type":["null","string"]},"filledVolume":{"type":["null","string"],"description":"What actually filled, which can be less than requested."},"filledPrice":{"type":["null","string"],"description":"What it actually filled at, which is rarely the requested price."},"sentAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time","description":"When an answer arrived."},"reconciledAt":{"type":["null","string"],"format":"date-time","description":"Set when a result was confirmed with the broker after the fact."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/positions/{positionId}/modify":{"post":{"summary":"Move a position's stop loss or take profit","tags":["Trading"],"description":"**Send `null` to remove a level.** Omitting the field leaves it unchanged — an omitted field silently clearing a stop is how protection disappears without anybody choosing it.\n\nRecorded in the order history with intent `modify`, because widening a stop changes what the account risks and belongs beside the trade it protects.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"stopLoss":{"type":["string","null"],"description":"Absolute price. **Send null to remove it** — omitting the field leaves it unchanged.","example":"1.13100"},"takeProfit":{"type":["string","null"],"description":"Absolute price. Send null to remove it.","example":"1.14500"}}}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true},{"schema":{"type":"string"},"in":"path","name":"positionId","required":true,"description":"The broker's position ticket."}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"accountId":{"type":"string","format":"uuid"},"clientOrderId":{"type":["null","string"],"description":"Your own reference, echoed back."},"symbol":{"type":"string","description":"The broker symbol traded."},"instrument":{"type":["null","string"],"description":"The instrument the order named, when it named one; `symbol` is what it was traded as.","example":"XAUUSD"},"side":{"type":"string","enum":["buy","sell"]},"type":{"type":"string","enum":["market","limit","stop","stop_limit"]},"intent":{"type":"string","enum":["open","close","modify","cancel"],"description":"What this order was for. A close is an order, with the same record and the same failed/unknown distinction as an open — `modify` covers moving a stop, which changes what the account risks."},"brokerPositionId":{"type":["null","string"],"description":"The position this acted on. Null on an opening order."},"volume":{"type":["null","string"],"description":"Requested volume, in lots."},"stopLoss":{"type":["null","string"],"description":"Absolute price, not a distance."},"takeProfit":{"type":["null","string"],"description":"Absolute price, not a distance."},"state":{"type":"string","enum":["accepted","validating","sending","working","completed","filled","partially_filled","rejected","failed","unknown","cancelled","expired"]},"stateDetail":{"type":["null","string"]},"needsReconciliation":{"type":"boolean","description":"True while we are confirming the result with the broker. Never resend such an order; poll it."},"retcode":{"type":["null","integer"],"description":"The broker's own MT5 return code, unmodified. 10009 is a completed request."},"retcodeText":{"type":["null","string"]},"brokerOrderId":{"type":["null","string"],"description":"The broker's ticket. What their statement shows."},"brokerDealId":{"type":["null","string"]},"filledVolume":{"type":["null","string"],"description":"What actually filled, which can be less than requested."},"filledPrice":{"type":["null","string"],"description":"What it actually filled at, which is rarely the requested price."},"sentAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time","description":"When an answer arrived."},"reconciledAt":{"type":["null","string"],"format":"date-time","description":"Set when a result was confirmed with the broker after the fact."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/orders/pending":{"post":{"summary":"Place a limit, stop or stop-limit order","tags":["Trading"],"description":"A success here means **placed and waiting**, not filled — the broker answers `10008 PLACED` and the order is `working` until it triggers.\n\nA limit waits for a better price (buy below the market, sell above); a stop waits for a worse one and is how a breakout is traded (buy above, sell below). When fxapis has a recent price for the symbol on this account, the wrong side is refused before anything is sent, with a message naming the order you probably meant; otherwise the broker answers with its own `INVALID_PRICE`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["side","kind","volume","price"],"description":"Send `symbol` or `instrument`, not both.","properties":{"symbol":{"type":"string","minLength":1,"maxLength":32,"description":"As the broker names it.","example":"EURUSD"},"instrument":{"type":"string","minLength":1,"maxLength":32,"description":"Instead of `symbol`: an instrument from `GET /v1/instruments`, traded under this account's own broker symbol for it (`XAUUSD` may be `XAUUSD.a` or `GOLD` at the broker). The order records both. Refused with `INSTRUMENT_NOT_OFFERED` or `INSTRUMENT_AMBIGUOUS` when the account's broker has no single match.","example":"XAUUSD"},"side":{"type":"string","enum":["buy","sell"]},"kind":{"type":"string","enum":["limit","stop","stop_limit"],"description":"A **limit** waits for a better price: buy below the market, sell above it. A **stop** waits for a worse one and is how a breakout is traded: buy above, sell below. Getting these backwards is the commonest mistake here, so the wrong side is refused with a message saying which you meant."},"volume":{"type":"string","pattern":"^\\d+(\\.\\d{1,8})?$","example":"0.01"},"price":{"type":"string","description":"The price the order waits at.","example":"1.12800"},"stopLimitPrice":{"type":"string","description":"Required for stop_limit: the limit placed once the stop triggers.","example":"1.12780"},"stopLoss":{"type":"string","example":"1.12400"},"takeProfit":{"type":"string","example":"1.13600"},"expiresAt":{"type":"string","format":"date-time","description":"When the broker should drop it. Omit for good-till-cancelled."},"comment":{"type":"string","maxLength":120,"example":"breakout"},"clientOrderId":{"type":"string","maxLength":120,"example":"sig-43-user-7"}}}}},"description":"Send `symbol` or `instrument`, not both."},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true},{"schema":{"type":"string","maxLength":200},"example":"3f0c9a52-8a8e-4f7e-9b0e-6c1d2f5a7b10","in":"header","name":"idempotency-key","required":false,"description":"Any unique string, usually a UUID. A retry with the same key and body returns the first answer instead of placing a second order; the same key with a different body is refused."}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"accountId":{"type":"string","format":"uuid"},"clientOrderId":{"type":["null","string"],"description":"Your own reference, echoed back."},"symbol":{"type":"string","description":"The broker symbol traded."},"instrument":{"type":["null","string"],"description":"The instrument the order named, when it named one; `symbol` is what it was traded as.","example":"XAUUSD"},"side":{"type":"string","enum":["buy","sell"]},"type":{"type":"string","enum":["market","limit","stop","stop_limit"]},"intent":{"type":"string","enum":["open","close","modify","cancel"],"description":"What this order was for. A close is an order, with the same record and the same failed/unknown distinction as an open — `modify` covers moving a stop, which changes what the account risks."},"brokerPositionId":{"type":["null","string"],"description":"The position this acted on. Null on an opening order."},"volume":{"type":["null","string"],"description":"Requested volume, in lots."},"stopLoss":{"type":["null","string"],"description":"Absolute price, not a distance."},"takeProfit":{"type":["null","string"],"description":"Absolute price, not a distance."},"state":{"type":"string","enum":["accepted","validating","sending","working","completed","filled","partially_filled","rejected","failed","unknown","cancelled","expired"]},"stateDetail":{"type":["null","string"]},"needsReconciliation":{"type":"boolean","description":"True while we are confirming the result with the broker. Never resend such an order; poll it."},"retcode":{"type":["null","integer"],"description":"The broker's own MT5 return code, unmodified. 10009 is a completed request."},"retcodeText":{"type":["null","string"]},"brokerOrderId":{"type":["null","string"],"description":"The broker's ticket. What their statement shows."},"brokerDealId":{"type":["null","string"]},"filledVolume":{"type":["null","string"],"description":"What actually filled, which can be less than requested."},"filledPrice":{"type":["null","string"],"description":"What it actually filled at, which is rarely the requested price."},"sentAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time","description":"When an answer arrived."},"reconciledAt":{"type":["null","string"],"format":"date-time","description":"Set when a result was confirmed with the broker after the fact."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/orders/{id}/modify":{"post":{"summary":"Move a pending order's price or levels","tags":["Trading"],"description":"Keeps the order's ticket. Cancelling and re-placing loses its place in the broker's queue and leaves a window where the order does not exist at all — on a fast market that window is where the move happens.\n\nAn omitted field is left alone. Send `stopLoss: null` to clear a stop; omitting it keeps whatever is there.\n\nOnly an order in `working` can be moved. A `filled` order is a position — move its stop with `/positions/{id}/modify` instead.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"price":{"type":"string","description":"The new price the order waits at.","example":"1.12750"},"stopLoss":{"type":["string","null"],"description":"`null` clears it; omitting it keeps what is there.","example":"1.12350"},"takeProfit":{"type":["string","null"],"description":"`null` clears it; omitting it keeps what is there.","example":"1.13550"},"stopLimitPrice":{"type":"string","description":"For a stop-limit order.","example":"1.12730"},"expiresAt":{"type":"string","format":"date-time"}}}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"accountId":{"type":"string","format":"uuid"},"clientOrderId":{"type":["null","string"],"description":"Your own reference, echoed back."},"symbol":{"type":"string","description":"The broker symbol traded."},"instrument":{"type":["null","string"],"description":"The instrument the order named, when it named one; `symbol` is what it was traded as.","example":"XAUUSD"},"side":{"type":"string","enum":["buy","sell"]},"type":{"type":"string","enum":["market","limit","stop","stop_limit"]},"intent":{"type":"string","enum":["open","close","modify","cancel"],"description":"What this order was for. A close is an order, with the same record and the same failed/unknown distinction as an open — `modify` covers moving a stop, which changes what the account risks."},"brokerPositionId":{"type":["null","string"],"description":"The position this acted on. Null on an opening order."},"volume":{"type":["null","string"],"description":"Requested volume, in lots."},"stopLoss":{"type":["null","string"],"description":"Absolute price, not a distance."},"takeProfit":{"type":["null","string"],"description":"Absolute price, not a distance."},"state":{"type":"string","enum":["accepted","validating","sending","working","completed","filled","partially_filled","rejected","failed","unknown","cancelled","expired"]},"stateDetail":{"type":["null","string"]},"needsReconciliation":{"type":"boolean","description":"True while we are confirming the result with the broker. Never resend such an order; poll it."},"retcode":{"type":["null","integer"],"description":"The broker's own MT5 return code, unmodified. 10009 is a completed request."},"retcodeText":{"type":["null","string"]},"brokerOrderId":{"type":["null","string"],"description":"The broker's ticket. What their statement shows."},"brokerDealId":{"type":["null","string"]},"filledVolume":{"type":["null","string"],"description":"What actually filled, which can be less than requested."},"filledPrice":{"type":["null","string"],"description":"What it actually filled at, which is rarely the requested price."},"sentAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time","description":"When an answer arrived."},"reconciledAt":{"type":["null","string"],"format":"date-time","description":"Set when a result was confirmed with the broker after the fact."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/orders/{id}/cancel":{"post":{"summary":"Cancel a pending order","tags":["Trading"],"description":"Removes a pending order that has not triggered. If it already has, the broker refuses with `10035` — at that point there is a position, not an order, and what you want is a close.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"accountId":{"type":"string","format":"uuid"},"clientOrderId":{"type":["null","string"],"description":"Your own reference, echoed back."},"symbol":{"type":"string","description":"The broker symbol traded."},"instrument":{"type":["null","string"],"description":"The instrument the order named, when it named one; `symbol` is what it was traded as.","example":"XAUUSD"},"side":{"type":"string","enum":["buy","sell"]},"type":{"type":"string","enum":["market","limit","stop","stop_limit"]},"intent":{"type":"string","enum":["open","close","modify","cancel"],"description":"What this order was for. A close is an order, with the same record and the same failed/unknown distinction as an open — `modify` covers moving a stop, which changes what the account risks."},"brokerPositionId":{"type":["null","string"],"description":"The position this acted on. Null on an opening order."},"volume":{"type":["null","string"],"description":"Requested volume, in lots."},"stopLoss":{"type":["null","string"],"description":"Absolute price, not a distance."},"takeProfit":{"type":["null","string"],"description":"Absolute price, not a distance."},"state":{"type":"string","enum":["accepted","validating","sending","working","completed","filled","partially_filled","rejected","failed","unknown","cancelled","expired"]},"stateDetail":{"type":["null","string"]},"needsReconciliation":{"type":"boolean","description":"True while we are confirming the result with the broker. Never resend such an order; poll it."},"retcode":{"type":["null","integer"],"description":"The broker's own MT5 return code, unmodified. 10009 is a completed request."},"retcodeText":{"type":["null","string"]},"brokerOrderId":{"type":["null","string"],"description":"The broker's ticket. What their statement shows."},"brokerDealId":{"type":["null","string"]},"filledVolume":{"type":["null","string"],"description":"What actually filled, which can be less than requested."},"filledPrice":{"type":["null","string"],"description":"What it actually filled at, which is rarely the requested price."},"sentAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time","description":"When an answer arrived."},"reconciledAt":{"type":["null","string"],"format":"date-time","description":"Set when a result was confirmed with the broker after the fact."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/calculate":{"post":{"summary":"Margin required, or profit at a price","tags":["Trading"],"description":"Opens nothing and is safe to call freely. This is how you find out an order will be refused for margin *before* sending it, rather than collecting a `10019` from the broker.\n\nThe account must be online: an offline account is refused with 409 `NO_RUNTIME`. A null `value` means the broker would not answer, which is not the same as zero.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["kind","symbol","side","volume","price"],"properties":{"kind":{"type":"string","enum":["margin","profit"]},"symbol":{"type":"string","maxLength":32,"example":"EURUSD"},"side":{"type":"string","enum":["buy","sell"]},"volume":{"type":"string","pattern":"^\\d+(\\.\\d{1,8})?$","example":"0.10"},"price":{"type":"string","description":"The price the position opens at.","example":"1.13426"},"closePrice":{"type":"string","description":"Required for a profit calculation.","example":"1.13926"}}}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"kind":{"type":"string","enum":["margin","profit"]},"value":{"type":["null","string"],"description":"In the account's currency. Null means the broker would not answer — which is not the same as zero."}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/orders":{"get":{"summary":"List orders","tags":["History"],"description":"Every order this workspace has placed, newest first, across all accounts unless `accountId` narrows it. Filter by `state` to find what needs attention — `state=unknown` is the set whose result we are still confirming with the broker.\n\nPaginated by cursor rather than offset: an offset shifts as new orders arrive, so page two would silently skip rows.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"query","name":"accountId","required":false,"description":"Narrow to one account."},{"schema":{"type":"string","enum":["accepted","validating","sending","working","completed","filled","partially_filled","rejected","failed","unknown","cancelled","expired"]},"in":"query","name":"state","required":false,"description":"`unknown` is the set whose result we are still confirming with the broker."},{"schema":{"type":"string","maxLength":32},"in":"query","name":"symbol","required":false},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"since","required":false},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"until","required":false},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"The `nextCursor` from the previous page."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"accountId":{"type":"string","format":"uuid"},"clientOrderId":{"type":["null","string"],"description":"Your own reference, echoed back."},"symbol":{"type":"string","description":"The broker symbol traded."},"instrument":{"type":["null","string"],"description":"The instrument the order named, when it named one; `symbol` is what it was traded as.","example":"XAUUSD"},"side":{"type":"string","enum":["buy","sell"]},"type":{"type":"string","enum":["market","limit","stop","stop_limit"]},"intent":{"type":"string","enum":["open","close","modify","cancel"],"description":"What this order was for. A close is an order, with the same record and the same failed/unknown distinction as an open — `modify` covers moving a stop, which changes what the account risks."},"brokerPositionId":{"type":["null","string"],"description":"The position this acted on. Null on an opening order."},"volume":{"type":["null","string"],"description":"Requested volume, in lots."},"stopLoss":{"type":["null","string"],"description":"Absolute price, not a distance."},"takeProfit":{"type":["null","string"],"description":"Absolute price, not a distance."},"state":{"type":"string","enum":["accepted","validating","sending","working","completed","filled","partially_filled","rejected","failed","unknown","cancelled","expired"]},"stateDetail":{"type":["null","string"]},"needsReconciliation":{"type":"boolean","description":"True while we are confirming the result with the broker. Never resend such an order; poll it."},"retcode":{"type":["null","integer"],"description":"The broker's own MT5 return code, unmodified. 10009 is a completed request."},"retcodeText":{"type":["null","string"]},"brokerOrderId":{"type":["null","string"],"description":"The broker's ticket. What their statement shows."},"brokerDealId":{"type":["null","string"]},"filledVolume":{"type":["null","string"],"description":"What actually filled, which can be less than requested."},"filledPrice":{"type":["null","string"],"description":"What it actually filled at, which is rarely the requested price."},"sentAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time","description":"When an answer arrived."},"reconciledAt":{"type":["null","string"],"format":"date-time","description":"Set when a result was confirmed with the broker after the fact."},"createdAt":{"type":"string","format":"date-time"}}}},"page":{"type":"object","properties":{"hasMore":{"type":"boolean"},"nextCursor":{"type":["null","string"],"description":"Pass as `cursor` to continue."}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/orders/{id}":{"get":{"summary":"Fetch one order","tags":["History"],"description":"The authoritative record of one order: what was asked for, what the broker returned, and its own return code unmodified. Poll this after an `ORDER_UNRESOLVED` response — an opening order moves out of `unknown` as soon as we have confirmed the result with the broker; a close, stop change or cancel stays `unknown`, with a `stateDetail` saying what to check at the broker.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"accountId":{"type":"string","format":"uuid"},"clientOrderId":{"type":["null","string"],"description":"Your own reference, echoed back."},"symbol":{"type":"string","description":"The broker symbol traded."},"instrument":{"type":["null","string"],"description":"The instrument the order named, when it named one; `symbol` is what it was traded as.","example":"XAUUSD"},"side":{"type":"string","enum":["buy","sell"]},"type":{"type":"string","enum":["market","limit","stop","stop_limit"]},"intent":{"type":"string","enum":["open","close","modify","cancel"],"description":"What this order was for. A close is an order, with the same record and the same failed/unknown distinction as an open — `modify` covers moving a stop, which changes what the account risks."},"brokerPositionId":{"type":["null","string"],"description":"The position this acted on. Null on an opening order."},"volume":{"type":["null","string"],"description":"Requested volume, in lots."},"stopLoss":{"type":["null","string"],"description":"Absolute price, not a distance."},"takeProfit":{"type":["null","string"],"description":"Absolute price, not a distance."},"state":{"type":"string","enum":["accepted","validating","sending","working","completed","filled","partially_filled","rejected","failed","unknown","cancelled","expired"]},"stateDetail":{"type":["null","string"]},"needsReconciliation":{"type":"boolean","description":"True while we are confirming the result with the broker. Never resend such an order; poll it."},"retcode":{"type":["null","integer"],"description":"The broker's own MT5 return code, unmodified. 10009 is a completed request."},"retcodeText":{"type":["null","string"]},"brokerOrderId":{"type":["null","string"],"description":"The broker's ticket. What their statement shows."},"brokerDealId":{"type":["null","string"]},"filledVolume":{"type":["null","string"],"description":"What actually filled, which can be less than requested."},"filledPrice":{"type":["null","string"],"description":"What it actually filled at, which is rarely the requested price."},"sentAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time","description":"When an answer arrived."},"reconciledAt":{"type":["null","string"],"format":"date-time","description":"Set when a result was confirmed with the broker after the fact."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/orders/{id}/deals":{"get":{"summary":"Deals produced by one order","tags":["History"],"description":"One order can produce several deals — a partial fill leaves more than one. These are the broker's own records of money changing hands, which is what a statement is reconciled against.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"accountId":{"type":"string","format":"uuid"},"orderId":{"type":["null","string"],"format":"uuid","description":"Null when the broker did this without us — a stop firing, a swap, a manual trade."},"brokerDealId":{"type":"string","description":"The broker's deal ticket. The identity of this record."},"brokerOrderId":{"type":["null","string"]},"brokerPositionId":{"type":["null","string"]},"symbol":{"type":"string"},"dealType":{"type":"string","description":"buy, sell, balance, credit, commission, swap-adjacent charges and corrections."},"entry":{"type":["null","string"],"description":"in, out, inout or out_by — whether exposure opened or closed."},"volume":{"type":["null","string"],"description":"Lots."},"price":{"type":["null","string"],"description":"Execution price."},"commission":{"type":["null","string"],"description":"Account currency."},"swap":{"type":["null","string"],"description":"Account currency."},"profit":{"type":["null","string"],"description":"Realised, in account currency. Negative is a loss."},"fee":{"type":["null","string"],"description":"Account currency."},"dealtAt":{"type":"string","format":"date-time","description":"The broker's timestamp, not ours."},"comment":{"type":["null","string"]}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/deals":{"get":{"summary":"An account's full deal history","tags":["History"],"description":"Everything the broker recorded against this account, **including deals no order of yours caused** — a stop loss firing, a swap charge, a deposit, or somebody trading the same login from the MetaTrader desktop.\n\nThat inclusion is the point. A history containing only your own orders would show an account whose balance moves for no visible reason. Ordered by the broker's timestamp, not ours.","parameters":[{"schema":{"type":"string","maxLength":32},"in":"query","name":"symbol","required":false,"description":"Only deals on this symbol, as the broker names it."},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"since","required":false,"description":"Deals at or after this time (the broker's timestamp)."},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"until","required":false,"description":"Deals at or before this time."},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"The `nextCursor` from the previous page."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"accountId":{"type":"string","format":"uuid"},"orderId":{"type":["null","string"],"format":"uuid","description":"Null when the broker did this without us — a stop firing, a swap, a manual trade."},"brokerDealId":{"type":"string","description":"The broker's deal ticket. The identity of this record."},"brokerOrderId":{"type":["null","string"]},"brokerPositionId":{"type":["null","string"]},"symbol":{"type":"string"},"dealType":{"type":"string","description":"buy, sell, balance, credit, commission, swap-adjacent charges and corrections."},"entry":{"type":["null","string"],"description":"in, out, inout or out_by — whether exposure opened or closed."},"volume":{"type":["null","string"],"description":"Lots."},"price":{"type":["null","string"],"description":"Execution price."},"commission":{"type":["null","string"],"description":"Account currency."},"swap":{"type":["null","string"],"description":"Account currency."},"profit":{"type":["null","string"],"description":"Realised, in account currency. Negative is a loss."},"fee":{"type":["null","string"],"description":"Account currency."},"dealtAt":{"type":"string","format":"date-time","description":"The broker's timestamp, not ours."},"comment":{"type":["null","string"]}}}},"page":{"type":"object","properties":{"hasMore":{"type":"boolean"},"nextCursor":{"type":["null","string"],"description":"Pass as `cursor` to continue."}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/reconcile":{"post":{"summary":"Confirm pending results with the broker now","tags":["Trading"],"description":"Confirms the result of every opening order on this account still in `unknown`, and brings its deals and positions up to date with the broker. A close, stop change or cancel in `unknown` is not settled from deal history — its `stateDetail` says to check the position or order at the broker.\n\nThis happens automatically; call it when you do not want to wait. It is safe to call at any time and safe to call twice — nothing is recorded or settled twice.\n\n`ambiguous` counts orders whose result the broker's records do not settle unambiguously. Those are left in `unknown` on purpose: a wrong guess produces a history that looks settled and is wrong, which is worse than the gap. They need a human.\n\n`skipped` is `no-runtime` when the account is offline: bring it online and call again.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"examined":{"type":"integer","description":"Orders that were in `unknown`."},"resolved":{"type":"integer","description":"How many now have a confirmed result."},"stillUnknown":{"type":"integer","description":"Still unconfirmed, including the ambiguous ones."},"ambiguous":{"type":"integer","description":"Orders the broker's records do not settle unambiguously. Left alone deliberately — a wrong guess produces a history that looks settled and is wrong. These need a human."},"historyNotReady":{"type":"integer","description":"Orders left unconfirmed only because the broker's records were not available yet — usually for about half a minute after an account comes online. An empty answer is not treated as proof an order did not execute; they are confirmed on a later attempt."},"historyReady":{"type":["null","boolean"],"description":"Whether the broker's records were available for this check. Null when that could not be told."},"dealsIngested":{"type":"integer","description":"Broker deals recorded, including ones no order caused."},"positionsOpen":{"type":"integer"},"positionsClosed":{"type":"integer","description":"Positions the broker stopped reporting."},"skipped":{"type":["null","string"],"description":"`no-runtime` when the account is offline, so there was nothing to ask; `unreachable` when the broker would not answer."}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/accounts/{id}/positions":{"get":{"summary":"Positions on an account","tags":["Trading"],"description":"What we last saw, with `observedAt` saying when. The broker is authoritative and this is a snapshot, not a ledger — `observedAt` is here so you can tell a current view from a stale one rather than having to assume.\n\nOpen positions only, unless `includeClosed=true`.","parameters":[{"schema":{"type":"string","enum":["true","false"],"default":"false"},"in":"query","name":"includeClosed","required":false,"description":"`true` also returns positions we have seen closed, with `closedAt` set."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"accountId":{"type":"string","format":"uuid"},"brokerPositionId":{"type":"string"},"symbol":{"type":"string"},"side":{"type":"string","enum":["buy","sell"]},"volume":{"type":["null","string"],"description":"Lots."},"openPrice":{"type":["null","string"],"description":""},"currentPrice":{"type":["null","string"],"description":""},"stopLoss":{"type":["null","string"],"description":""},"takeProfit":{"type":["null","string"],"description":""},"swap":{"type":["null","string"],"description":""},"profit":{"type":["null","string"],"description":"Unrealised, at observedAt."},"openedAt":{"type":["null","string"],"format":"date-time"},"observedAt":{"type":"string","format":"date-time","description":"When this was last true. A snapshot without it would be worthless."},"closedAt":{"type":["null","string"],"format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/execution-waves":{"post":{"summary":"Place one trade on many accounts","tags":["Waves"],"description":"A multi-account order: one trade placed on many accounts at once. Every account is brought online first, then the orders are sent together — at `executeAt`, or as soon as every account is online.\n\n**A multi-account order is not all-or-nothing once sent, and cannot be.** There is no transaction across a hundred brokers: accounts fill at different prices, some are rejected for margin, some go unanswered. So it never reports a single success or failure — it reports a result for each account, and `summary` counts what landed. An account whose result is `unresolved` must not be resent; poll its order.\n\n`dispatchSpreadMs` is the gap between the first account's order being sent and the last. It is the number worth watching: as it grows, your accounts are getting different prices.\n\n**`barrierPolicy`** decides what happens when some accounts are not online in time:\n\n- `release-ready` — trade on the accounts that are online, skip the rest. A partial entry beats a late one.\n- `all-or-nothing` — trade on none unless all are online. Note this is about *sending*: a broker can still reject an account's order after it was sent.\n- `wait` — keep waiting past `executeAt` until every account is online, up to `expiresAt`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountIds","symbol","side","volume"],"properties":{"accountIds":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":1000,"description":"The accounts to trade on, one order each. An account listed twice is traded once."},"symbol":{"type":"string","minLength":1,"maxLength":32,"example":"EURUSD"},"side":{"type":"string","enum":["buy","sell"]},"volume":{"type":"string","pattern":"^\\d+(\\.\\d{1,8})?$","description":"Lots per account, unless a weight overrides it.","example":"0.01"},"weights":{"type":"object","additionalProperties":{"type":"string"},"description":"Per-account volume, keyed by account id. For accounts that differ in equity."},"stopLoss":{"type":"string","example":"1.12900"},"takeProfit":{"type":"string","example":"1.14200"},"comment":{"type":"string","maxLength":120,"example":"signal 42"},"label":{"type":"string","maxLength":120,"example":"London open — EURUSD long"},"clientWaveId":{"type":"string","maxLength":120,"example":"signal-42"},"barrierPolicy":{"type":"string","enum":["release-ready","all-or-nothing","wait"],"default":"release-ready","description":"What to do when some accounts are not online in time. `release-ready` trades on the ones that are; `all-or-nothing` trades on none unless all are; `wait` keeps waiting past executeAt until expiresAt."},"executeAt":{"type":"string","format":"date-time","description":"When the orders should be sent. Omit to send as soon as every account is online — accounts still logging in are waited for up to 60 seconds, then the barrier policy decides."},"expiresAt":{"type":"string","format":"date-time","description":"Stop waiting for accounts that are not online after this."}}}}}},"parameters":[{"schema":{"type":"string","maxLength":200},"example":"3f0c9a52-8a8e-4f7e-9b0e-6c1d2f5a7b10","in":"header","name":"idempotency-key","required":false,"description":"Any unique string, usually a UUID. A retry with the same key and body returns the first answer instead of placing a second order; the same key with a different body is refused."}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":["null","string"]},"clientWaveId":{"type":["null","string"]},"symbol":{"type":"string"},"side":{"type":"string","enum":["buy","sell"]},"baseVolume":{"type":["null","string"]},"state":{"type":"string","enum":["planned","preparing","armed","releasing","settled","cancelled","abandoned"]},"stateDetail":{"type":["null","string"]},"barrierPolicy":{"type":"string","enum":["release-ready","all-or-nothing","wait"]},"executeAt":{"type":["null","string"],"format":"date-time"},"expiresAt":{"type":["null","string"],"format":"date-time"},"preparedAt":{"type":["null","string"],"format":"date-time"},"releasedAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time"},"dispatchSpreadMs":{"type":["null","integer"],"description":"The gap between the first account's order being sent and the last, in milliseconds. As it grows, your accounts are getting different prices."},"summary":{"type":"object","description":"What landed. Deliberately not a success flag — a multi-account order is not all-or-nothing once sent.","properties":{"total":{"type":"integer"},"filled":{"type":"integer"},"rejected":{"type":"integer"},"skipped":{"type":"integer"},"unresolved":{"type":"integer","description":"Accounts whose result we are still confirming with the broker. Do not resend these."}}},"legs":{"type":"array","description":"One entry per account: the order placed there and how it went.","items":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"orderId":{"type":["null","string"],"format":"uuid","description":"The ordinary order placed on this account. Query it like any other."},"volume":{"type":["null","string"]},"state":{"type":"string","enum":["pending","preparing","ready","dispatched","filled","rejected","skipped","unresolved"],"description":"`pending`/`preparing`: being brought online. `ready`: online and waiting. `dispatched`: sent, awaiting the broker. `filled`, `rejected`: the broker's answer. `skipped`: never sent. `unresolved`: sent, and we are confirming the result with the broker — do not resend."},"stateDetail":{"type":["null","string"]},"sentAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time"}}}},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}},"get":{"summary":"List multi-account orders","tags":["Waves"],"description":"Multi-account orders in this workspace, newest first, with each one's state, symbol, side, number of accounts and summary of results.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":["null","string"]},"clientWaveId":{"type":["null","string"]},"symbol":{"type":"string"},"side":{"type":"string","enum":["buy","sell"]},"baseVolume":{"type":["null","string"]},"state":{"type":"string","enum":["planned","preparing","armed","releasing","settled","cancelled","abandoned"]},"stateDetail":{"type":["null","string"]},"barrierPolicy":{"type":"string","enum":["release-ready","all-or-nothing","wait"]},"executeAt":{"type":["null","string"],"format":"date-time"},"expiresAt":{"type":["null","string"],"format":"date-time"},"preparedAt":{"type":["null","string"],"format":"date-time"},"releasedAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time"},"dispatchSpreadMs":{"type":["null","integer"],"description":"The gap between the first account's order being sent and the last, in milliseconds. As it grows, your accounts are getting different prices."},"summary":{"type":"object","description":"What landed. Deliberately not a success flag — a multi-account order is not all-or-nothing once sent.","properties":{"total":{"type":"integer"},"filled":{"type":"integer"},"rejected":{"type":"integer"},"skipped":{"type":"integer"},"unresolved":{"type":"integer","description":"Accounts whose result we are still confirming with the broker. Do not resend these."}}},"legs":{"type":"array","description":"One entry per account: the order placed there and how it went.","items":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"orderId":{"type":["null","string"],"format":"uuid","description":"The ordinary order placed on this account. Query it like any other."},"volume":{"type":["null","string"]},"state":{"type":"string","enum":["pending","preparing","ready","dispatched","filled","rejected","skipped","unresolved"],"description":"`pending`/`preparing`: being brought online. `ready`: online and waiting. `dispatched`: sent, awaiting the broker. `filled`, `rejected`: the broker's answer. `skipped`: never sent. `unresolved`: sent, and we are confirming the result with the broker — do not resend."},"stateDetail":{"type":["null","string"]},"sentAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time"}}}},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/execution-waves/{id}":{"get":{"summary":"Follow a multi-account order","tags":["Waves"],"description":"Poll this after creating a multi-account order. `state` moves `planned → preparing → armed → releasing → settled`: accepted, bringing accounts online, waiting for `executeAt`, sending, and every account has a result. `cancelled` and `abandoned` mean nothing was sent.\n\nEach account in `legs` carries its own state and its own order id — an account's order is an ordinary order, confirmed with the broker and audited like any other.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":["null","string"]},"clientWaveId":{"type":["null","string"]},"symbol":{"type":"string"},"side":{"type":"string","enum":["buy","sell"]},"baseVolume":{"type":["null","string"]},"state":{"type":"string","enum":["planned","preparing","armed","releasing","settled","cancelled","abandoned"]},"stateDetail":{"type":["null","string"]},"barrierPolicy":{"type":"string","enum":["release-ready","all-or-nothing","wait"]},"executeAt":{"type":["null","string"],"format":"date-time"},"expiresAt":{"type":["null","string"],"format":"date-time"},"preparedAt":{"type":["null","string"],"format":"date-time"},"releasedAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time"},"dispatchSpreadMs":{"type":["null","integer"],"description":"The gap between the first account's order being sent and the last, in milliseconds. As it grows, your accounts are getting different prices."},"summary":{"type":"object","description":"What landed. Deliberately not a success flag — a multi-account order is not all-or-nothing once sent.","properties":{"total":{"type":"integer"},"filled":{"type":"integer"},"rejected":{"type":"integer"},"skipped":{"type":"integer"},"unresolved":{"type":"integer","description":"Accounts whose result we are still confirming with the broker. Do not resend these."}}},"legs":{"type":"array","description":"One entry per account: the order placed there and how it went.","items":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"orderId":{"type":["null","string"],"format":"uuid","description":"The ordinary order placed on this account. Query it like any other."},"volume":{"type":["null","string"]},"state":{"type":"string","enum":["pending","preparing","ready","dispatched","filled","rejected","skipped","unresolved"],"description":"`pending`/`preparing`: being brought online. `ready`: online and waiting. `dispatched`: sent, awaiting the broker. `filled`, `rejected`: the broker's answer. `skipped`: never sent. `unresolved`: sent, and we are confirming the result with the broker — do not resend."},"stateDetail":{"type":["null","string"]},"sentAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time"}}}},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/execution-waves/{id}/cancel":{"post":{"summary":"Cancel a multi-account order before it is sent","tags":["Waves"],"description":"Only while nothing has been sent. Once orders are going out there is no cancelling them — `cancelled` would claim nothing was sent, and that is exactly the promise we can no longer make.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"label":{"type":["null","string"]},"clientWaveId":{"type":["null","string"]},"symbol":{"type":"string"},"side":{"type":"string","enum":["buy","sell"]},"baseVolume":{"type":["null","string"]},"state":{"type":"string","enum":["planned","preparing","armed","releasing","settled","cancelled","abandoned"]},"stateDetail":{"type":["null","string"]},"barrierPolicy":{"type":"string","enum":["release-ready","all-or-nothing","wait"]},"executeAt":{"type":["null","string"],"format":"date-time"},"expiresAt":{"type":["null","string"],"format":"date-time"},"preparedAt":{"type":["null","string"],"format":"date-time"},"releasedAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time"},"dispatchSpreadMs":{"type":["null","integer"],"description":"The gap between the first account's order being sent and the last, in milliseconds. As it grows, your accounts are getting different prices."},"summary":{"type":"object","description":"What landed. Deliberately not a success flag — a multi-account order is not all-or-nothing once sent.","properties":{"total":{"type":"integer"},"filled":{"type":"integer"},"rejected":{"type":"integer"},"skipped":{"type":"integer"},"unresolved":{"type":"integer","description":"Accounts whose result we are still confirming with the broker. Do not resend these."}}},"legs":{"type":"array","description":"One entry per account: the order placed there and how it went.","items":{"type":"object","properties":{"accountId":{"type":"string","format":"uuid"},"orderId":{"type":["null","string"],"format":"uuid","description":"The ordinary order placed on this account. Query it like any other."},"volume":{"type":["null","string"]},"state":{"type":"string","enum":["pending","preparing","ready","dispatched","filled","rejected","skipped","unresolved"],"description":"`pending`/`preparing`: being brought online. `ready`: online and waiting. `dispatched`: sent, awaiting the broker. `filled`, `rejected`: the broker's answer. `skipped`: never sent. `unresolved`: sent, and we are confirming the result with the broker — do not resend."},"stateDetail":{"type":["null","string"]},"sentAt":{"type":["null","string"],"format":"date-time"},"settledAt":{"type":["null","string"],"format":"date-time"}}}},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/plans":{"get":{"summary":"The available plans","tags":["Billing"],"description":"The plans on offer now: what each includes and what it costs. Prices are in minor units — `9900` is $99.00, never a float.\n\n`accounts` is a capacity limit: you cannot exceed it and be billed for the excess. The monthly allowances can run over where the plan allows it, up to twice the allowance, after which orders are refused — a runaway strategy should not be able to generate an unbounded invoice.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"annualPrice":{"type":["null","integer"],"description":"Minor units a year, billed yearly. Null: monthly only."},"pricing":{"type":"object","description":"How the plan charges. `bundle`: its price buys a fixed allowance. `usage`: its price includes `includedAccounts`, then each account past them costs the band's `unitPrice` a month, always-on accounts `alwaysOnPrice` a month, and opening executions past `executionsPerAccount` × the accounts paid for cost `overagePer1000` per 1,000. `freeDemoAccounts` demo accounts are not charged. Minor units throughout.","properties":{"model":{"type":"string","enum":["bundle","usage"]},"includedAccounts":{"type":"integer"},"accountTiers":{"type":"array","items":{"type":"object","properties":{"upTo":{"type":"integer"},"unitPrice":{"type":"integer"}}}},"alwaysOnPrice":{"type":["null","integer"]},"executionsPerAccount":{"type":"integer"},"overagePer1000":{"type":"integer"},"freeDemoAccounts":{"type":"integer"},"trialDays":{"type":["null","integer"]},"demoOnly":{"type":"boolean"}}},"monthlyPrice":{"type":["null","integer"],"description":"Minor units. 9900 is $99.00 — never a float. Null for a plan priced by contract."},"currency":{"type":"string"},"selfServe":{"type":"boolean","description":"False for a plan arranged with us rather than chosen in the dashboard."},"overagePerOrder":{"type":"integer","description":"Minor units per order beyond the allowance."},"features":{"type":"object","description":"What the plan switches on. A feature a plan lacks is refused with `402 FEATURE_NOT_IN_PLAN` when used to open something; closing, cancelling and modifying what already exists are always allowed.","properties":{"executionWaves":{"type":"boolean","description":"`POST /execution-waves`."},"pendingOrders":{"type":"boolean","description":"`POST /accounts/{id}/orders/pending`."},"alwaysOn":{"type":"boolean","description":"The `always_on` account mode."},"webhooks":{"type":"boolean","description":"Reserved for event delivery to your endpoints. Not available yet."}}},"entitlements":{"type":"object","properties":{"accounts":{"type":"integer","description":"A capacity limit, not a monthly allowance: you cannot exceed it and be billed."},"ordersPerMonth":{"type":"integer"},"wavesPerMonth":{"type":"integer"},"legsPerWave":{"type":"integer","description":"Accounts in one multi-account order."},"apiCallsPerMonth":{"type":"integer"},"allowOverage":{"type":"boolean","description":"Whether the monthly allowances may be exceeded and billed, up to twice the allowance."}}}}}}}}}}}}}},"/v1/billing/usage":{"get":{"summary":"This month's usage and what it would cost","tags":["Billing"],"description":"Counted as it happens rather than derived at the end of the month, so this is the same number the invoice will use.\n\n**Over quota, opening is refused and closing is always allowed.** A billing problem must never hold you in a position you cannot exit — an order to close comes back `201` however far over the plan you are, and only opening returns `402 QUOTA_EXCEEDED`.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"plan":{"type":"string"},"planName":{"type":"string"},"currency":{"type":"string"},"subtotal":{"type":["null","integer"],"description":"The subscription, in minor units. Null on a contract-priced plan."},"overage":{"type":"integer","description":"Charged on opening orders only — never on API calls or on getting flat."},"total":{"type":["null","integer"]},"entitlements":{"type":"object","properties":{"accounts":{"type":"integer","description":"Accounts holding credentials at once. A capacity limit, not a monthly allowance: you cannot exceed it and be billed."},"ordersPerMonth":{"type":"integer","description":"Opening orders. Closing, cancelling and moving stops are never counted."},"wavesPerMonth":{"type":"integer"},"legsPerWave":{"type":"integer","description":"Accounts in one multi-account order."},"apiCallsPerMonth":{"type":"integer"},"allowOverage":{"type":"boolean","description":"Whether the monthly allowances may be exceeded and billed, up to twice the allowance."}}},"features":{"type":"object","description":"What the plan switches on. A feature a plan lacks is refused with `402 FEATURE_NOT_IN_PLAN` when used to open something; closing, cancelling and modifying what already exists are always allowed.","properties":{"executionWaves":{"type":"boolean","description":"`POST /execution-waves`."},"pendingOrders":{"type":"boolean","description":"`POST /accounts/{id}/orders/pending`."},"alwaysOn":{"type":"boolean","description":"The `always_on` account mode."},"webhooks":{"type":"boolean","description":"Reserved for event delivery to your endpoints. Not available yet."}}},"pricing":{"type":"object","description":"How the plan charges. `bundle`: its price buys a fixed allowance. `usage`: its price includes `includedAccounts`, then each account past them costs the band's `unitPrice` a month, always-on accounts `alwaysOnPrice` a month, and opening executions past `executionsPerAccount` × the accounts paid for cost `overagePer1000` per 1,000. `freeDemoAccounts` demo accounts are not charged. Minor units throughout.","properties":{"model":{"type":"string","enum":["bundle","usage"]},"includedAccounts":{"type":"integer"},"accountTiers":{"type":"array","items":{"type":"object","properties":{"upTo":{"type":"integer"},"unitPrice":{"type":"integer"}}}},"alwaysOnPrice":{"type":["null","integer"]},"executionsPerAccount":{"type":"integer"},"overagePer1000":{"type":"integer"},"freeDemoAccounts":{"type":"integer"},"trialDays":{"type":["null","integer"]},"demoOnly":{"type":"boolean"}}},"trialEndsAt":{"type":["null","string"],"format":"date-time","description":"While on the free trial: when it ends."},"usage":{"type":"object","properties":{"orders":{"type":"integer"},"waves":{"type":"integer"},"api_calls":{"type":"integer"},"accounts":{"type":"integer","description":"Connected right now, not a monthly total."}}},"usageCharges":{"type":["null","object"],"description":"On a per-account plan: what this month has used so far and what it would add to the plan's price if the month ended now. Charged after the month ends — to the card the plan renews on, or with the next crypto payment.","properties":{"month":{"type":"string"},"total":{"type":"integer"},"paidAccounts":{"type":"integer"},"lines":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"quantity":{"type":"number"},"unitAmount":{"type":["null","integer"],"description":"Minor units each, where the line has a unit price."},"amount":{"type":"integer","description":"Minor units."}}}},"measured":{"type":"object","properties":{"liveAccounts":{"type":"integer"},"demoAccounts":{"type":"integer"},"alwaysOnDays":{"type":"integer"},"executions":{"type":"integer"}}}}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/billing/usage/daily":{"get":{"summary":"Usage broken down by day","tags":["Billing"],"description":"For a chart, or for checking an invoice line against the day it came from.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"day":{"type":"string","description":"UTC date, as YYYY-MM-DD."},"metric":{"type":"string"},"count":{"type":"integer"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/billing/subscription":{"get":{"summary":"What is paying for the plan","tags":["Billing"],"description":"The workspace's subscription, if it has one: plan, card or crypto, status, the current paid period and whether it ends at period end. Null when nothing is being paid for.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":["null","object"],"properties":{"id":{"type":"string","format":"uuid"},"plan":{"type":"string"},"method":{"type":"string","enum":["card","crypto","transfer"]},"interval":{"type":"string","enum":["month","year"]},"agreement":{"type":"boolean","description":"Pays for the workspace's enterprise agreement rather than a plan from the price list."},"status":{"type":"string","enum":["pending","active","past_due","ended"],"description":"`past_due`: a card renewal failed and is being retried; the plan is kept meanwhile. When paying stops the workspace moves to Free — opening is then refused, and closing never is."},"currentPeriodEnd":{"type":["null","string"],"format":"date-time"},"cancelAtPeriodEnd":{"type":"boolean"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/billing/invoices":{"get":{"summary":"Invoices, newest first","tags":["Billing"],"description":"Every invoice for this workspace, newest first, with its number, amount, status, provider and any refunds. Amounts are in minor units.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"number":{"type":"string","description":"Sequential, e.g. FX-2026-000123. Never reused. Invoices issued before the fxapis name keep their OW- numbers."},"plan":{"type":"string"},"method":{"type":"string","enum":["card","crypto","transfer"]},"status":{"type":"string","enum":["open","paid","void","uncollectible"]},"currency":{"type":"string"},"amount":{"type":"integer","description":"Minor units. 9900 is $99.00."},"amountRefunded":{"type":"integer","description":"Minor units."},"periodStart":{"type":["null","string"],"format":"date-time"},"periodEnd":{"type":["null","string"],"format":"date-time"},"crypto":{"type":["null","object"],"description":"Crypto only. While the invoice is open: send exactly `amount` of `coin` on `network` to `address`, with `extraId` as the memo or tag when one is given — without it the payment cannot be matched.","properties":{"coin":{"type":["null","string"]},"network":{"type":["null","string"]},"address":{"type":["null","string"]},"amount":{"type":["null","string"],"description":"Exact, as quoted. A string, never a float."},"extraId":{"type":["null","string"]},"expiresAt":{"type":["null","string"],"format":"date-time"},"providerStatus":{"type":["null","string"],"description":"waiting, confirming, confirmed, sending, partially_paid, finished, failed, expired."},"amountReceived":{"type":["null","string"]}}},"note":{"type":["null","string"]},"paidAt":{"type":["null","string"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/billing/crypto/coins":{"get":{"summary":"Coins accepted for crypto payment","tags":["Billing"],"description":"Each with the network it must be sent on. Sending on another network loses the payment.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"ticker":{"type":"string"},"label":{"type":"string"},"network":{"type":"string","description":"The chain it must be sent on."},"stable":{"type":"boolean"},"note":{"type":"string"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/billing/invoices/{id}":{"get":{"summary":"One invoice","tags":["Billing"],"description":"One invoice by id, with its lines, payment status and refunds. Another workspace's invoice is 404.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"number":{"type":"string","description":"Sequential, e.g. FX-2026-000123. Never reused. Invoices issued before the fxapis name keep their OW- numbers."},"plan":{"type":"string"},"method":{"type":"string","enum":["card","crypto","transfer"]},"status":{"type":"string","enum":["open","paid","void","uncollectible"]},"currency":{"type":"string"},"amount":{"type":"integer","description":"Minor units. 9900 is $99.00."},"amountRefunded":{"type":"integer","description":"Minor units."},"periodStart":{"type":["null","string"],"format":"date-time"},"periodEnd":{"type":["null","string"],"format":"date-time"},"crypto":{"type":["null","object"],"description":"Crypto only. While the invoice is open: send exactly `amount` of `coin` on `network` to `address`, with `extraId` as the memo or tag when one is given — without it the payment cannot be matched.","properties":{"coin":{"type":["null","string"]},"network":{"type":["null","string"]},"address":{"type":["null","string"]},"amount":{"type":["null","string"],"description":"Exact, as quoted. A string, never a float."},"extraId":{"type":["null","string"]},"expiresAt":{"type":["null","string"],"format":"date-time"},"providerStatus":{"type":["null","string"],"description":"waiting, confirming, confirmed, sending, partially_paid, finished, failed, expired."},"amountReceived":{"type":["null","string"]}}},"note":{"type":["null","string"]},"paidAt":{"type":["null","string"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/api-keys":{"get":{"summary":"List this workspace's keys","tags":["API keys"],"description":"Newest first, revoked keys included — a revocation is history worth seeing.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"publicId":{"type":"string","description":"The key's public half. Safe to log and to show."},"hint":{"type":"string","description":"The key with its secret elided, e.g. `fx_live_7f3a9c21_…`, for telling keys apart."},"environment":{"type":"string","enum":["live","test"]},"scopes":{"type":"array","items":{"type":"string"}},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"To the minute. Null if it has never been used."},"expiresAt":{"type":["null","string"],"format":"date-time"},"revokedAt":{"type":["null","string"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}},"post":{"summary":"Create a key","tags":["API keys"],"description":"Returns the key in `key`, **once**. We cannot show a key again after creation, or recover it. A lost key is replaced, not recovered.\n\n`admin` and `keys:manage` cannot be granted here. Issue narrow keys: an integration that only reads positions should hold `trading:read` and nothing else.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","scopes"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":80,"example":"Production trading server"},"scopes":{"type":"array","minItems":1,"uniqueItems":true,"items":{"type":"string","enum":["accounts:read","accounts:write","trading:read","trading:reduce","trading:execute","history:read","webhooks:write"]},"description":"`admin` and `keys:manage` cannot be granted to a key through the API."},"environment":{"type":"string","enum":["live","test"],"default":"live"},"expiresAt":{"type":"string","format":"date-time","description":"Optional. Must be in the future."}}}}}},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"publicId":{"type":"string","description":"The key's public half. Safe to log and to show."},"hint":{"type":"string","description":"The key with its secret elided, e.g. `fx_live_7f3a9c21_…`, for telling keys apart."},"environment":{"type":"string","enum":["live","test"]},"scopes":{"type":"array","items":{"type":"string"}},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"To the minute. Null if it has never been used."},"expiresAt":{"type":["null","string"],"format":"date-time"},"revokedAt":{"type":["null","string"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"key":{"type":"string","description":"The whole key. Shown here and never again — store it now. We cannot show it again after creation."}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/api-keys/{id}":{"get":{"summary":"Read one key","tags":["API keys"],"description":"A key's name, scopes, environment label, hint and when it was last used — never the key itself, which is shown only once, when it is created.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"publicId":{"type":"string","description":"The key's public half. Safe to log and to show."},"hint":{"type":"string","description":"The key with its secret elided, e.g. `fx_live_7f3a9c21_…`, for telling keys apart."},"environment":{"type":"string","enum":["live","test"]},"scopes":{"type":"array","items":{"type":"string"}},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"To the minute. Null if it has never been used."},"expiresAt":{"type":["null","string"],"format":"date-time"},"revokedAt":{"type":["null","string"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}},"patch":{"summary":"Rename or re-scope a key","tags":["API keys"],"description":"New scopes replace the old ones and apply from the key's next request. The key itself does not change, so nothing using it needs redeploying. A revoked key cannot be changed.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":80,"example":"Production trading server"},"scopes":{"type":"array","minItems":1,"uniqueItems":true,"items":{"type":"string","enum":["accounts:read","accounts:write","trading:read","trading:reduce","trading:execute","history:read","webhooks:write"]},"description":"Replaces the key's scopes. Takes effect on its next request."}}}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"publicId":{"type":"string","description":"The key's public half. Safe to log and to show."},"hint":{"type":"string","description":"The key with its secret elided, e.g. `fx_live_7f3a9c21_…`, for telling keys apart."},"environment":{"type":"string","enum":["live","test"]},"scopes":{"type":"array","items":{"type":"string"}},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"To the minute. Null if it has never been used."},"expiresAt":{"type":["null","string"],"format":"date-time"},"revokedAt":{"type":["null","string"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/api-keys/{id}/revoke":{"post":{"summary":"Revoke a key","tags":["API keys"],"description":"Refused from its very next request — there is no cache to wait for. Revoking an already-revoked key succeeds and changes nothing, so a retried revoke is safe.\n\nA key may revoke itself. Anything it was doing stops with it.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"publicId":{"type":"string","description":"The key's public half. Safe to log and to show."},"hint":{"type":"string","description":"The key with its secret elided, e.g. `fx_live_7f3a9c21_…`, for telling keys apart."},"environment":{"type":"string","enum":["live","test"]},"scopes":{"type":"array","items":{"type":"string"}},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"To the minute. Null if it has never been used."},"expiresAt":{"type":["null","string"],"format":"date-time"},"revokedAt":{"type":["null","string"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/workspace":{"get":{"summary":"The workspace this credential belongs to","tags":["Workspace"],"description":"Its plan, and whether trading is switched off. Our staff switch trading off for a whole workspace only during an incident; this is where to see it.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","required":["id","name","plan","planName","planAssigned","tradingDisabled"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"plan":{"type":"string","description":"The plan in force. `none` when the workspace pays for nothing and no free plan is offered: choose a plan to connect accounts and open trades."},"planName":{"type":"string"},"planAssigned":{"type":"boolean","description":"The plan was arranged with us rather than paid for, and is changed by talking to us."},"tradingDisabled":{"type":"boolean","description":"Trading is switched off for the whole workspace. While it is, every order is refused with `409 TRADING_DISABLED` — closes included."}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/alert-hooks":{"get":{"summary":"List TradingView alert hooks","tags":["Alerts"],"description":"Newest first. Deleted hooks are not listed. The URLs are shown only as hints — the secret is not stored.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"accountIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"One account places an ordinary order; several place a multi-account order."},"defaults":{"type":"object","properties":{"volume":{"type":"string","description":"Lots, used when an alert does not send `volume`.","example":"0.10"},"deviationPoints":{"type":["null","integer"],"description":"Maximum slippage in points. Null leaves it to the terminal.","example":20},"symbolMap":{"type":"object","additionalProperties":{"type":"string"},"description":"TradingView symbol (after the exchange prefix is removed) → your broker's symbol. Checked before the suffix.","example":{"XAUUSD":"XAUUSD.a","US30":"DJ30"}},"symbolSuffix":{"type":"string","description":"Appended to symbols the map does not name — for brokers that decorate every symbol, like `EURUSD.a`.","example":".a"},"stripExchangePrefix":{"type":"boolean","description":"Turn `OANDA:XAUUSD` into `XAUUSD`. On by default."},"allowClose":{"type":"boolean","description":"Whether `close`, `flat` and `close_all` alerts are acted on. On by default."},"onlyTradingViewIps":{"type":"boolean","description":"Refuse alerts that do not come from TradingView's published webhook addresses. On by default."}}},"enabled":{"type":"boolean"},"urlHint":{"type":"string","description":"The URL with its secret elided, for telling hooks apart. The full URL is returned only by create and rotate.","example":"https://api.fxapis.com/hooks/tradingview/…Qx4w"},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"When an alert last arrived, to the minute."},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}},"post":{"summary":"Create a TradingView alert hook","tags":["Alerts"],"description":"Returns a secret `url` to paste into a TradingView alert's **Webhook URL**. Every alert sent to it becomes an order on the hook's accounts: one account places an ordinary order, several place a multi-account order.\n\n**The URL is returned once**, here, and is a credential: anyone who has it can trade these accounts. We store only a hash of it. Lost or leaked, rotate it.\n\n`defaults` fill in what an alert leaves out and translate TradingView's symbols to your broker's. See the TradingView guide for the message format.\n\nSeveral accounts need a plan with multi-account orders; that is checked here, and again on every alert.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","accountIds"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":80,"example":"Gold breakout strategy"},"accountIds":{"type":"array","minItems":1,"maxItems":500,"uniqueItems":true,"items":{"type":"string","format":"uuid"},"example":["2b0c7c1e-5d0b-4d8e-9a53-0e6f3b1c9a10"]},"defaults":{"type":"object","properties":{"volume":{"type":"string","description":"Lots, used when an alert does not send `volume`.","pattern":"^\\d+(\\.\\d{1,8})?$","example":"0.10"},"deviationPoints":{"type":["null","integer"],"description":"Maximum slippage in points. Null leaves it to the terminal.","minimum":0,"maximum":10000,"example":20},"symbolMap":{"type":"object","additionalProperties":{"type":"string"},"description":"TradingView symbol (after the exchange prefix is removed) → your broker's symbol. Checked before the suffix.","example":{"XAUUSD":"XAUUSD.a","US30":"DJ30"}},"symbolSuffix":{"type":"string","description":"Appended to symbols the map does not name — for brokers that decorate every symbol, like `EURUSD.a`.","maxLength":16,"example":".a"},"stripExchangePrefix":{"type":"boolean","description":"Turn `OANDA:XAUUSD` into `XAUUSD`. On by default."},"allowClose":{"type":"boolean","description":"Whether `close`, `flat` and `close_all` alerts are acted on. On by default."},"onlyTradingViewIps":{"type":"boolean","description":"Refuse alerts that do not come from TradingView's published webhook addresses. On by default."}},"additionalProperties":false}}}}}},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"accountIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"One account places an ordinary order; several place a multi-account order."},"defaults":{"type":"object","properties":{"volume":{"type":"string","description":"Lots, used when an alert does not send `volume`.","example":"0.10"},"deviationPoints":{"type":["null","integer"],"description":"Maximum slippage in points. Null leaves it to the terminal.","example":20},"symbolMap":{"type":"object","additionalProperties":{"type":"string"},"description":"TradingView symbol (after the exchange prefix is removed) → your broker's symbol. Checked before the suffix.","example":{"XAUUSD":"XAUUSD.a","US30":"DJ30"}},"symbolSuffix":{"type":"string","description":"Appended to symbols the map does not name — for brokers that decorate every symbol, like `EURUSD.a`.","example":".a"},"stripExchangePrefix":{"type":"boolean","description":"Turn `OANDA:XAUUSD` into `XAUUSD`. On by default."},"allowClose":{"type":"boolean","description":"Whether `close`, `flat` and `close_all` alerts are acted on. On by default."},"onlyTradingViewIps":{"type":"boolean","description":"Refuse alerts that do not come from TradingView's published webhook addresses. On by default."}}},"enabled":{"type":"boolean"},"urlHint":{"type":"string","description":"The URL with its secret elided, for telling hooks apart. The full URL is returned only by create and rotate.","example":"https://api.fxapis.com/hooks/tradingview/…Qx4w"},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"When an alert last arrived, to the minute."},"createdAt":{"type":"string","format":"date-time"},"url":{"type":"string","description":"Paste this into the alert's Webhook URL. Shown here and never again — anyone holding it can trade the hook's accounts. Lost or leaked: rotate.","example":"https://api.fxapis.com/hooks/tradingview/3q2-7ZkT0d8m1sQe9yVbW4nX6pLr5aHcUgJf0oKxQx4w"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/alert-hooks/{id}":{"get":{"summary":"Read one alert hook","tags":["Alerts"],"description":"One alert hook: its name, accounts, defaults, whether it is enabled and when it was last used. The secret URL is never returned again — rotate the hook for a new one.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"accountIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"One account places an ordinary order; several place a multi-account order."},"defaults":{"type":"object","properties":{"volume":{"type":"string","description":"Lots, used when an alert does not send `volume`.","example":"0.10"},"deviationPoints":{"type":["null","integer"],"description":"Maximum slippage in points. Null leaves it to the terminal.","example":20},"symbolMap":{"type":"object","additionalProperties":{"type":"string"},"description":"TradingView symbol (after the exchange prefix is removed) → your broker's symbol. Checked before the suffix.","example":{"XAUUSD":"XAUUSD.a","US30":"DJ30"}},"symbolSuffix":{"type":"string","description":"Appended to symbols the map does not name — for brokers that decorate every symbol, like `EURUSD.a`.","example":".a"},"stripExchangePrefix":{"type":"boolean","description":"Turn `OANDA:XAUUSD` into `XAUUSD`. On by default."},"allowClose":{"type":"boolean","description":"Whether `close`, `flat` and `close_all` alerts are acted on. On by default."},"onlyTradingViewIps":{"type":"boolean","description":"Refuse alerts that do not come from TradingView's published webhook addresses. On by default."}}},"enabled":{"type":"boolean"},"urlHint":{"type":"string","description":"The URL with its secret elided, for telling hooks apart. The full URL is returned only by create and rotate.","example":"https://api.fxapis.com/hooks/tradingview/…Qx4w"},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"When an alert last arrived, to the minute."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}},"patch":{"summary":"Change an alert hook's name, accounts or defaults","tags":["Alerts"],"description":"The URL does not change, so nothing needs editing in TradingView. `defaults` fields you send replace those fields; the rest stay as they are. `symbolMap`, when sent, replaces the whole map.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"minProperties":1,"properties":{"name":{"type":"string","minLength":1,"maxLength":80,"example":"Gold breakout strategy"},"accountIds":{"type":"array","minItems":1,"maxItems":500,"uniqueItems":true,"items":{"type":"string","format":"uuid"},"example":["2b0c7c1e-5d0b-4d8e-9a53-0e6f3b1c9a10"]},"defaults":{"type":"object","properties":{"volume":{"type":"string","description":"Lots, used when an alert does not send `volume`.","pattern":"^\\d+(\\.\\d{1,8})?$","example":"0.10"},"deviationPoints":{"type":["null","integer"],"description":"Maximum slippage in points. Null leaves it to the terminal.","minimum":0,"maximum":10000,"example":20},"symbolMap":{"type":"object","additionalProperties":{"type":"string"},"description":"TradingView symbol (after the exchange prefix is removed) → your broker's symbol. Checked before the suffix.","example":{"XAUUSD":"XAUUSD.a","US30":"DJ30"}},"symbolSuffix":{"type":"string","description":"Appended to symbols the map does not name — for brokers that decorate every symbol, like `EURUSD.a`.","maxLength":16,"example":".a"},"stripExchangePrefix":{"type":"boolean","description":"Turn `OANDA:XAUUSD` into `XAUUSD`. On by default."},"allowClose":{"type":"boolean","description":"Whether `close`, `flat` and `close_all` alerts are acted on. On by default."},"onlyTradingViewIps":{"type":"boolean","description":"Refuse alerts that do not come from TradingView's published webhook addresses. On by default."}},"additionalProperties":false}}}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"accountIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"One account places an ordinary order; several place a multi-account order."},"defaults":{"type":"object","properties":{"volume":{"type":"string","description":"Lots, used when an alert does not send `volume`.","example":"0.10"},"deviationPoints":{"type":["null","integer"],"description":"Maximum slippage in points. Null leaves it to the terminal.","example":20},"symbolMap":{"type":"object","additionalProperties":{"type":"string"},"description":"TradingView symbol (after the exchange prefix is removed) → your broker's symbol. Checked before the suffix.","example":{"XAUUSD":"XAUUSD.a","US30":"DJ30"}},"symbolSuffix":{"type":"string","description":"Appended to symbols the map does not name — for brokers that decorate every symbol, like `EURUSD.a`.","example":".a"},"stripExchangePrefix":{"type":"boolean","description":"Turn `OANDA:XAUUSD` into `XAUUSD`. On by default."},"allowClose":{"type":"boolean","description":"Whether `close`, `flat` and `close_all` alerts are acted on. On by default."},"onlyTradingViewIps":{"type":"boolean","description":"Refuse alerts that do not come from TradingView's published webhook addresses. On by default."}}},"enabled":{"type":"boolean"},"urlHint":{"type":"string","description":"The URL with its secret elided, for telling hooks apart. The full URL is returned only by create and rotate.","example":"https://api.fxapis.com/hooks/tradingview/…Qx4w"},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"When an alert last arrived, to the minute."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}},"delete":{"summary":"Delete an alert hook","tags":["Alerts"],"description":"Its URL stops working at once and cannot be brought back. Orders it placed stay in the history, with the alert that caused them in `clientOrderId`.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"accountIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"One account places an ordinary order; several place a multi-account order."},"defaults":{"type":"object","properties":{"volume":{"type":"string","description":"Lots, used when an alert does not send `volume`.","example":"0.10"},"deviationPoints":{"type":["null","integer"],"description":"Maximum slippage in points. Null leaves it to the terminal.","example":20},"symbolMap":{"type":"object","additionalProperties":{"type":"string"},"description":"TradingView symbol (after the exchange prefix is removed) → your broker's symbol. Checked before the suffix.","example":{"XAUUSD":"XAUUSD.a","US30":"DJ30"}},"symbolSuffix":{"type":"string","description":"Appended to symbols the map does not name — for brokers that decorate every symbol, like `EURUSD.a`.","example":".a"},"stripExchangePrefix":{"type":"boolean","description":"Turn `OANDA:XAUUSD` into `XAUUSD`. On by default."},"allowClose":{"type":"boolean","description":"Whether `close`, `flat` and `close_all` alerts are acted on. On by default."},"onlyTradingViewIps":{"type":"boolean","description":"Refuse alerts that do not come from TradingView's published webhook addresses. On by default."}}},"enabled":{"type":"boolean"},"urlHint":{"type":"string","description":"The URL with its secret elided, for telling hooks apart. The full URL is returned only by create and rotate.","example":"https://api.fxapis.com/hooks/tradingview/…Qx4w"},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"When an alert last arrived, to the minute."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/alert-hooks/{id}/rotate":{"post":{"summary":"Replace an alert hook's URL","tags":["Alerts"],"description":"Issues a new secret URL and retires the old one at once: alerts still pointing at it are refused from now on. Update every TradingView alert that uses it. The new `url` is returned **once**.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"accountIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"One account places an ordinary order; several place a multi-account order."},"defaults":{"type":"object","properties":{"volume":{"type":"string","description":"Lots, used when an alert does not send `volume`.","example":"0.10"},"deviationPoints":{"type":["null","integer"],"description":"Maximum slippage in points. Null leaves it to the terminal.","example":20},"symbolMap":{"type":"object","additionalProperties":{"type":"string"},"description":"TradingView symbol (after the exchange prefix is removed) → your broker's symbol. Checked before the suffix.","example":{"XAUUSD":"XAUUSD.a","US30":"DJ30"}},"symbolSuffix":{"type":"string","description":"Appended to symbols the map does not name — for brokers that decorate every symbol, like `EURUSD.a`.","example":".a"},"stripExchangePrefix":{"type":"boolean","description":"Turn `OANDA:XAUUSD` into `XAUUSD`. On by default."},"allowClose":{"type":"boolean","description":"Whether `close`, `flat` and `close_all` alerts are acted on. On by default."},"onlyTradingViewIps":{"type":"boolean","description":"Refuse alerts that do not come from TradingView's published webhook addresses. On by default."}}},"enabled":{"type":"boolean"},"urlHint":{"type":"string","description":"The URL with its secret elided, for telling hooks apart. The full URL is returned only by create and rotate.","example":"https://api.fxapis.com/hooks/tradingview/…Qx4w"},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"When an alert last arrived, to the minute."},"createdAt":{"type":"string","format":"date-time"},"url":{"type":"string","description":"Paste this into the alert's Webhook URL. Shown here and never again — anyone holding it can trade the hook's accounts. Lost or leaked: rotate.","example":"https://api.fxapis.com/hooks/tradingview/3q2-7ZkT0d8m1sQe9yVbW4nX6pLr5aHcUgJf0oKxQx4w"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/alert-hooks/{id}/enable":{"post":{"summary":"Enable an alert hook","tags":["Alerts"],"description":"Alerts are traded again from the next one. Safe to repeat.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"accountIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"One account places an ordinary order; several place a multi-account order."},"defaults":{"type":"object","properties":{"volume":{"type":"string","description":"Lots, used when an alert does not send `volume`.","example":"0.10"},"deviationPoints":{"type":["null","integer"],"description":"Maximum slippage in points. Null leaves it to the terminal.","example":20},"symbolMap":{"type":"object","additionalProperties":{"type":"string"},"description":"TradingView symbol (after the exchange prefix is removed) → your broker's symbol. Checked before the suffix.","example":{"XAUUSD":"XAUUSD.a","US30":"DJ30"}},"symbolSuffix":{"type":"string","description":"Appended to symbols the map does not name — for brokers that decorate every symbol, like `EURUSD.a`.","example":".a"},"stripExchangePrefix":{"type":"boolean","description":"Turn `OANDA:XAUUSD` into `XAUUSD`. On by default."},"allowClose":{"type":"boolean","description":"Whether `close`, `flat` and `close_all` alerts are acted on. On by default."},"onlyTradingViewIps":{"type":"boolean","description":"Refuse alerts that do not come from TradingView's published webhook addresses. On by default."}}},"enabled":{"type":"boolean"},"urlHint":{"type":"string","description":"The URL with its secret elided, for telling hooks apart. The full URL is returned only by create and rotate.","example":"https://api.fxapis.com/hooks/tradingview/…Qx4w"},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"When an alert last arrived, to the minute."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/alert-hooks/{id}/disable":{"post":{"summary":"Disable an alert hook","tags":["Alerts"],"description":"Alerts are refused — answered 409 and recorded as `rejected` — until it is enabled again. The URL stays the same, so nothing changes in TradingView. Safe to repeat.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"accountIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"One account places an ordinary order; several place a multi-account order."},"defaults":{"type":"object","properties":{"volume":{"type":"string","description":"Lots, used when an alert does not send `volume`.","example":"0.10"},"deviationPoints":{"type":["null","integer"],"description":"Maximum slippage in points. Null leaves it to the terminal.","example":20},"symbolMap":{"type":"object","additionalProperties":{"type":"string"},"description":"TradingView symbol (after the exchange prefix is removed) → your broker's symbol. Checked before the suffix.","example":{"XAUUSD":"XAUUSD.a","US30":"DJ30"}},"symbolSuffix":{"type":"string","description":"Appended to symbols the map does not name — for brokers that decorate every symbol, like `EURUSD.a`.","example":".a"},"stripExchangePrefix":{"type":"boolean","description":"Turn `OANDA:XAUUSD` into `XAUUSD`. On by default."},"allowClose":{"type":"boolean","description":"Whether `close`, `flat` and `close_all` alerts are acted on. On by default."},"onlyTradingViewIps":{"type":"boolean","description":"Refuse alerts that do not come from TradingView's published webhook addresses. On by default."}}},"enabled":{"type":"boolean"},"urlHint":{"type":"string","description":"The URL with its secret elided, for telling hooks apart. The full URL is returned only by create and rotate.","example":"https://api.fxapis.com/hooks/tradingview/…Qx4w"},"lastUsedAt":{"type":["null","string"],"format":"date-time","description":"When an alert last arrived, to the minute."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/alert-hooks/{id}/deliveries":{"get":{"summary":"Alerts a hook received, and what became of each","tags":["Alerts"],"description":"Newest first, kept for 30 days. The first place to look when an alert did not trade: every alert that reached a hook is here — refused, ignored and duplicate ones included — with the reason in words.\n\nA hook takes at most 30 alerts a minute; past that, one row records the refusal and the rest of that minute's alerts are not recorded.","parameters":[{"schema":{"type":"string","enum":["pending","accepted","rejected","duplicate","ignored"]},"in":"query","name":"status","required":false},{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"in":"query","name":"limit","required":false},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"cursor","required":false,"description":"The previous page's `nextCursor`."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"receivedAt":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["pending","accepted","rejected","duplicate","ignored"],"description":"`pending`: taken, being sent. `accepted`: at least one order reached the broker — see `orderIds` for how each went. `rejected`: nothing was sent, and `reason` says why. `duplicate`: a repeat of an alert already taken. `ignored`: understood, and deliberately not traded (a partial exit, nothing to close, closing switched off)."},"reason":{"type":["null","string"]},"action":{"type":["null","string"],"example":"buy"},"symbol":{"type":["null","string"],"description":"The broker symbol it resolved to.","example":"XAUUSD.a"},"payload":{"type":["null","string"],"description":"The alert's message as received, up to 2 KB."},"orderIds":{"type":"array","items":{"type":"string","format":"uuid"}},"waveId":{"type":["null","string"],"format":"uuid","description":"Set when the alert became a multi-account order."},"completedAt":{"type":["null","string"],"format":"date-time"}}}},"page":{"type":"object","properties":{"hasMore":{"type":"boolean"},"nextCursor":{"type":["null","string"]}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/members":{"get":{"summary":"List this workspace's members","tags":["Members"],"description":"Everyone in this workspace, with their role and when they joined. Removed members are not listed.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","enum":["owner","admin","member"]},"you":{"type":"boolean","description":"True for the member making the request."},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/members/{id}":{"patch":{"summary":"Change a member's role","tags":["Members"],"description":"Only the owner changes roles, and the owner's own role cannot be changed here. Takes effect on the member's next request.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["role"],"additionalProperties":false,"properties":{"role":{"type":"string","enum":["admin","member"]}}}}}},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","enum":["owner","admin","member"]},"you":{"type":"boolean","description":"True for the member making the request."},"createdAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/members/{id}/remove":{"post":{"summary":"Remove a member","tags":["Members"],"description":"Signs them out everywhere at once and deletes their password. What they did stays attributed to them. Keys they created belong to the workspace and are not revoked — revoke them separately if they should stop too.\n\nThe owner cannot be removed. An admin may remove plain members only.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/members/invitations":{"get":{"summary":"List open invitations","tags":["Members"],"description":"Unaccepted, unrevoked and unexpired.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"type":"string","enum":["admin","member"]},"url":{"type":"string","description":"The link to send them. The same link every time it is asked for, until it is accepted, revoked or expires."},"invitedBy":{"type":["null","string"],"description":"Name of the member who sent it."},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}},"post":{"summary":"Invite someone","tags":["Members"],"description":"Returns a link to send them; there is no email yet. An address that already has an open invitation gets that invitation back — the same link, not a new one — with `handedBack: true`. To change the role on it, revoke it and invite again.\n\nThe owner may invite admins and members; an admin may invite members.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","role"],"additionalProperties":false,"properties":{"email":{"type":"string","format":"email","maxLength":254},"role":{"type":"string","enum":["admin","member"]}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"type":"string","enum":["admin","member"]},"url":{"type":"string","description":"The link to send them. The same link every time it is asked for, until it is accepted, revoked or expires."},"invitedBy":{"type":["null","string"],"description":"Name of the member who sent it."},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"handedBack":{"type":"boolean","description":"True when this address already had an open invitation and that one was returned instead."}}}}}}}},"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"role":{"type":"string","enum":["admin","member"]},"url":{"type":"string","description":"The link to send them. The same link every time it is asked for, until it is accepted, revoked or expires."},"invitedBy":{"type":["null","string"],"description":"Name of the member who sent it."},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"handedBack":{"type":"boolean","description":"True when this address already had an open invitation and that one was returned instead."}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/members/invitations/{id}/revoke":{"post":{"summary":"Withdraw an invitation","tags":["Members"],"description":"Its link stops working immediately. Safe to repeat.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}},"/v1/members/invitations/{id}/resend":{"post":{"summary":"Send an invitation again","tags":["Members"],"description":"The same link, emailed again — for one that was not received. At most once a minute per invitation.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"sentTo":{"type":"string"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable. Match on this, not on the message."},"message":{"type":"string","description":"For a human. May change between releases."},"details":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["code","message"]},"requestId":{"type":"string","description":"Also on every response. Quote it in a support request and the whole call can be found."}}}}}}}}}},"servers":[{"url":"https://api.fxapis.com","description":"Production"}],"security":[{"apiKey":[]}],"tags":[{"name":"Accounts","description":"Connecting MT5 accounts and reading their state."},{"name":"Lifecycle","description":"Bringing an account online, taking it offline, and changing how it stays connected."},{"name":"Instruments","description":"Markets named once — `XAUUSD`, `US30`, `BTCUSD` — and how each maps onto an account's broker symbols. An order can name an `instrument` instead of a `symbol`, and trades that account's own symbol for it."},{"name":"Trading","description":"Placing orders and reading positions. The endpoints that move money."},{"name":"History","description":"The durable record: every order, every deal the broker recorded, and what it returned. Includes deals no order of yours caused."},{"name":"Waves","description":"Multi-account orders: one trade placed on many accounts at once, with a result for each account. For signals that should reach every follower at the same moment."},{"name":"Alerts","description":"TradingView alert hooks: a secret URL that turns TradingView alerts into orders on your accounts, with no EA and no VPS. The URL is returned once, when a hook is created or rotated."},{"name":"Workspace","description":"The workspace a credential belongs to: its plan, and whether trading is switched off."},{"name":"Billing","description":"Plans, usage, what the month would cost, invoices, and paying for a plan."},{"name":"Members","description":"Who is in this workspace, who has been invited, and what each may do. Managed by a signed-in owner or admin from the dashboard; API keys, `admin` included, are refused."},{"name":"API keys","description":"Issuing, renaming, re-scoping and revoking this workspace's keys. A key's secret is returned once, by the request that creates it, and never again. Needs `keys:manage`."},{"name":"Health","description":"Liveness and readiness. No key required."}]}