openapi: 3.1.0 info: title: MetaBridgeAPI version: 0.1.0 description: MetaBridgeAPI public API for MT4 and MT5 account data, trading and streaming. Live mode accepts Demo and Real master accounts with broker-defined symbol and volume rules. Key and broker-data responses prohibit caching. servers: - url: https://metabridgeapi.com/api/v1 - url: http://127.0.0.1:4000/api/v1 security: - bearerAuth: [] components: securitySchemes: bearerAuth: type: http scheme: bearer description: Paste your MetaBridgeAPI key without the Bearer prefix. Workspace administration requires a signed-in owner session. schemas: Error: type: object required: [error] properties: error: type: object required: [code, message, requestId] properties: code: { type: string } message: { type: string } requestId: { type: string, format: uuid } Account: type: object properties: id: { type: string, format: uuid } organization_id: { type: string, format: uuid } name: { type: string } platform: { type: string, enum: [mt4, mt5] } login: { type: string, description: Broker login represented as a string to preserve precision. } server: { type: string } broker_port: { type: [integer, 'null'], minimum: 1, maximum: 65535 } status: { type: string } created_at: { type: string, format: date-time } AccountInput: type: object additionalProperties: false required: [name, platform, login, server, password] properties: name: { type: string, maxLength: 100 } platform: { type: string, enum: [mt4, mt5] } login: { type: string, pattern: '^[0-9]+$' } server: { type: string } connectionMethod: { type: string, enum: [host_port, server_name], default: host_port, description: 'server_name resolves the exact broker server label for the selected platform to a public broker endpoint. Omit brokerPort in this mode.' } brokerPort: { type: integer, minimum: 1, maximum: 65535 } password: { type: string, format: password, writeOnly: true } AccountUpdateInput: type: object additionalProperties: false required: [name, platform, login, server] properties: name: { type: string, maxLength: 100 } platform: { type: string, enum: [mt4, mt5] } login: { type: string, pattern: '^[0-9]+$' } server: { type: string } connectionMethod: { type: string, enum: [host_port, server_name], default: host_port, description: 'server_name resolves the exact broker server label for the selected platform to a public broker endpoint. Omit brokerPort in this mode.' } brokerPort: { type: integer, minimum: 1, maximum: 65535 } password: { type: string, format: password, writeOnly: true } ApiKeyInput: type: object additionalProperties: false required: [name, scopes] properties: name: { type: string } scopes: type: array minItems: 1 items: { type: string, enum: ['accounts:read', 'accounts:write', 'market:read', 'trades:read', 'trades:write', 'streams:read'] } expiresAt: { type: string, format: date-time } accountIds: type: array items: { type: string, format: uuid } TradeInput: oneOf: - type: object additionalProperties: false required: - kind - request properties: kind: type: string const: send request: type: object additionalProperties: false required: - symbol - operation - volume - price - slippage - stoploss - takeprofit properties: symbol: type: string minLength: 1 maxLength: 100 operation: type: string enum: - Buy - Sell - BuyLimit - SellLimit - BuyStop - SellStop - BuyStopLimit - SellStopLimit volume: type: number exclusiveMinimum: 0 price: type: number minimum: 0 slippage: type: integer minimum: 0 maximum: 2147483647 stoploss: type: number minimum: 0 takeprofit: type: number minimum: 0 stopLimitPrice: type: number exclusiveMinimum: 0 - type: object additionalProperties: false required: - kind - request properties: kind: type: string const: modify request: type: object additionalProperties: false required: - ticket - price - stoploss - takeprofit properties: ticket: type: string pattern: ^[1-9][0-9]*$ targetCorrelation: type: object additionalProperties: false required: - comment - expertId properties: comment: type: string pattern: ^vnd[0-9a-f]{28}$ expertId: type: string pattern: ^[1-9][0-9]*$ price: type: number minimum: 0 stoploss: type: number minimum: 0 takeprofit: type: number minimum: 0 - type: object additionalProperties: false required: - kind - request properties: kind: type: string const: close request: type: object additionalProperties: false required: - ticket - lots - price - slippage properties: ticket: type: string pattern: ^[1-9][0-9]*$ targetCorrelation: type: object additionalProperties: false required: - comment - expertId properties: comment: type: string pattern: ^vnd[0-9a-f]{28}$ expertId: type: string pattern: ^[1-9][0-9]*$ lots: type: number exclusiveMinimum: 0 price: type: number minimum: 0 slippage: type: integer minimum: 0 maximum: 2147483647 - type: object additionalProperties: false required: - kind - request properties: kind: type: string const: cancel request: type: object additionalProperties: false required: - ticket properties: ticket: type: string pattern: ^[1-9][0-9]*$ targetCorrelation: type: object additionalProperties: false required: - comment - expertId properties: comment: type: string pattern: ^vnd[0-9a-f]{28}$ expertId: type: string pattern: ^[1-9][0-9]*$ description: MT4 supports Buy/Sell/BuyLimit/SellLimit/BuyStop/SellStop. MT5 additionally supports BuyStopLimit/SellStopLimit, requiring stopLimitPrice; other types reject it. Pending prices must be on the correct side of the fresh bid/ask, with positive protections when positive. Zero disables a protection when the broker permits it. Broker acceptance remains conditional. responses: Error: { description: Error response with request ID, content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } } paths: /organizations/{org}/billing: get: summary: Read workspace crypto invoices and paid access description: Workspace owner only; open Playground → Workspace management. API keys are denied. Returns configured/enforced flags, trialEnabled, trialDays, trial account and dates, mode, plans, invoices and grants. parameters: - {name: org, in: path, required: true, schema: {type: string, format: uuid}} responses: '200': {description: Billing status} '403': {description: Workspace owner access required} '503': {description: Billing storage unavailable} /organizations/{org}/billing/trial: post: summary: Start the one-account 14-day demo trial description: Workspace owner only; open Playground → Workspace management. Requires a connected broker-verified Demo account. One lifetime trial per owner; retries return the original expiry. Real accounts require paid access. Only available for workspaces under the trial/billing rollout. parameters: - {name: org, in: path, required: true, schema: {type: string, format: uuid}} requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [accountId] properties: accountId: {type: string, format: uuid} responses: '200': {description: Trial account_id, starts_at and expires_at} '402': {description: Live account requires paid access} '403': {description: Workspace owner access required} '404': {description: Account not found in workspace} '409': {description: Trial already used, account disconnected or connection changed} '503': {description: Broker account type or trial storage cannot be verified} /organizations/{org}/billing/checkout: post: summary: Create a NOWPayments hosted crypto invoice description: Workspace owner only; open Playground → Workspace management. Fixed USD price, manual renewal, 30-day access after fully paid verified finished notification. Reuse requestKey for the same intent; unknown provider outcomes need reconciliation. parameters: - {name: org, in: path, required: true, schema: {type: string, format: uuid}} requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [plan, requestKey] properties: plan: {type: string, enum: [single, builder, scale]} accountId: {type: string, format: uuid, description: Required for single; omitted for builder/scale} accountIds: {type: array, minItems: 1, maxItems: 20, uniqueItems: true, items: {type: string, format: uuid}, description: Required for builder/scale; up to5 for builder or20 for scale. Fixed invoice selection.} requestKey: {type: string, format: uuid} responses: '201': {description: Created invoice with validated provider invoice_url} '200': {description: Same stored invoice on replay} '400': {description: Invalid plan or account selection} '403': {description: Workspace owner access required} '409': {description: Conflicting or unconfirmed creation intent} '502': {description: Provider creation outcome not confirmed; do not blindly retry} '503': {description: Provider not configured or storage unavailable} /billing/nowpayments/ipn: post: security: [] summary: NOWPayments signed payment notification description: Provider only. HMAC-SHA512 of recursively sorted JSON, exact order/invoice/USD amount match, and full payment required. Database settlement grants access exactly once; refunds revoke the invoice grant. parameters: - {name: x-nowpayments-sig, in: header, required: true, schema: {type: string}} requestBody: required: true content: application/json: schema: {type: object, additionalProperties: true} responses: '200': {description: Notification persisted or idempotently ignored} '400': {description: Payment does not match invoice or invalid notification} '401': {description: Invalid signature} '503': {description: Transient storage/configuration error; retry required} /me: get: summary: Current authenticated principal responses: '200': { description: Principal details } '401': { $ref: '#/components/responses/Error' } /organizations: get: summary: List organizations for the current dashboard user description: Requires a Supabase dashboard session. responses: '200': { description: Organization membership list } post: summary: Create an organization description: Requires a Supabase dashboard session. requestBody: required: true content: { application/json: { schema: { type: object, required: [name], properties: { name: { type: string, minLength: 2, maxLength: 100 } } } } } responses: '201': { description: Organization created } /organizations/{org}/accounts: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } get: summary: List owned trading accounts description: Requires accounts:read for API keys. responses: '200': { description: Account list } '403': { $ref: '#/components/responses/Error' } post: summary: Save a trading account before connecting description: Requires accounts:write for API keys. This stores credentials but does not establish a broker connection. requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/AccountInput' } } } } responses: '201': { description: Account metadata created } '400': { $ref: '#/components/responses/Error' } /organizations/{org}/accounts/{id}: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } patch: summary: Correct a disconnected account's connection details description: Requires accounts:write and account access. Omit password to keep the saved credential. Connected/in-progress accounts cannot be edited. Broker identity cannot change after saved trading operations. A concurrent connection or duplicate account returns 409. requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/AccountUpdateInput' } } } } responses: '200': { description: Updated account metadata without credentials } '400': { $ref: '#/components/responses/Error' } '403': { $ref: '#/components/responses/Error' } '409': { $ref: '#/components/responses/Error' } delete: summary: Delete an account without trading history responses: '204': { description: Deleted } '409': { description: Account retained because operations reference it } /organizations/{org}/accounts/{id}/connect: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } post: summary: Connect an MT4 or MT5 broker account description: Requires accounts:write and an operator-allowed broker host and port. The connector verifies the broker login before the API records a private session. Both MT4 and MT5 are supported when configured. responses: '200': { description: Broker login verified and session recorded } '403': { description: Broker destination is not operator-allowed } '503': { description: Account connector unavailable } /organizations/{org}/accounts/{id}/summary: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read an MT4 or MT5 account summary description: Requires accounts:read. Broker login is reverified before returning balance, equity and margin data. responses: '200': { description: Account summary } '409': { description: Account is not connected } '503': { description: Account connector unavailable } /organizations/{org}/accounts/{id}/disconnect: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } post: summary: Disconnect an MT4 or MT5 account description: Requires accounts:write and a confirmed connector response. responses: '200': { description: Connector session removed } /organizations/{org}/accounts/{id}/trades: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } post: summary: Submit a trade within configured limits description: 'Requires trades:write and an active connected account. Executes trades on the selected demo or live broker account. MT4 supports market, limit and stop orders; MT5 also supports stop-limit orders. Use the same Idempotency-Key for the same request and read the returned operation before retrying an uncertain outcome.' parameters: - name: Idempotency-Key in: header required: true schema: { type: string, pattern: '^[A-Za-z0-9._:-]{1,200}$' } requestBody: required: true content: application/json: schema: { $ref: '#/components/schemas/TradeInput' } responses: '202': description: Persisted operation; poll its Location for the outcome headers: Location: { schema: { type: string }, description: Operation resource URL } '400': { description: Invalid payload or missing idempotency key } '403': { description: Scope or configured trading boundary denied } '409': { description: Idempotency conflict or order identity mismatch } '503': { $ref: '#/components/responses/Error' } /organizations/{org}/api-keys: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } get: summary: List API key metadata description: Organization owner only. Secrets are never returned. responses: '200': { description: Key metadata list } post: summary: Create a scoped API key description: Organization owner only. The token is returned once. requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ApiKeyInput' } } } } responses: '201': { description: Key created with one-time token } /organizations/{org}/api-keys/{id}: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } delete: summary: Revoke an API key description: Organization owner only. Revocation applies to subsequent requests. responses: '204': { description: Revoked } /organizations/{org}/audit: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Recent organization audit events description: Organization owner only. responses: '200': { description: Up to 100 recent events } /organizations/{org}/usage: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Request usage summary description: Organization owner only. Best-effort operational telemetry, not billing-grade metering. parameters: - { name: days, in: query, schema: { type: integer, minimum: 1, maximum: 30, default: 7 } } responses: '200': { description: Request count, error count and mean duration } /organizations/{org}/members: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } get: summary: List organization members description: Organization owner only. responses: '200': { description: Member IDs, roles and creation dates } post: summary: Add or update an existing user membership description: Organization owner only. The target user must already exist in Supabase Auth. requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [userId, role] properties: userId: { type: string, format: uuid } role: { type: string, enum: [owner, member] } responses: '200': { description: Membership updated } '409': { description: Change would remove the last owner } /organizations/{org}/members/{id}: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } delete: summary: Remove a member description: Organization owner only. The last owner cannot be removed. responses: '204': { description: Member removed } '409': { description: Change would remove the last owner } /organizations/{org}/accounts/{id}/details: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read MT4 or MT5 account details description: 'Requires accounts:read and access to this tenant account. Broker identity is reverified before reading. ' responses: '200': description: Broker read result in a data envelope content: application/json: schema: type: object required: [data] properties: data: {} '400': { description: Invalid or unexpected query parameters } '401': { description: Authentication required } '403': { description: Tenant, scope or account access denied } '404': { description: Account not found } '409': { description: Account is not connected } '502': { description: Broker account or response could not be validated } '503': { description: MT5 connector method unavailable } /organizations/{org}/accounts/{id}/symbols: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read available MT4 or MT5 symbols description: 'Requires market:read and access to this tenant account. Broker identity is reverified before reading. ' responses: '200': description: Broker read result in a data envelope content: application/json: schema: type: object required: [data] properties: data: {} '400': { description: Invalid or unexpected query parameters } '401': { description: Authentication required } '403': { description: Tenant, scope or account access denied } '404': { description: Account not found } '409': { description: Account is not connected } '502': { description: Broker account or response could not be validated } '503': { description: MT5 connector method unavailable } /organizations/{org}/accounts/{id}/quote: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read an MT4 or MT5 symbol quote description: 'Requires market:read and access to this tenant account. Broker identity is reverified before reading. ' parameters: - { name: symbol, in: query, required: true, schema: { type: string, minLength: 1, maxLength: 100 } } responses: '200': description: Broker read result in a data envelope content: application/json: schema: type: object required: [data] properties: data: {} '400': { description: Invalid or unexpected query parameters } '401': { description: Authentication required } '403': { description: Tenant, scope or account access denied } '404': { description: Account not found } '409': { description: Account is not connected } '502': { description: Broker account or response could not be validated } '503': { description: MT5 connector method unavailable } /organizations/{org}/accounts/{id}/price-history: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read MT5 price history description: 'Requires market:read and access to this tenant account. Broker identity is reverified before reading. timeFrame is a positive vendor integer, at most 43200; its unit has not been verified. Date range is limited to 31 days. The legacy connector downloads whole months, so the gateway filters returned bars to the requested range.' parameters: - { name: symbol, in: query, required: true, schema: { type: string, minLength: 1, maxLength: 100 } } - { name: from, in: query, required: true, schema: { type: string, format: date-time } } - { name: to, in: query, required: true, schema: { type: string, format: date-time } } - { name: timeFrame, in: query, required: true, schema: { type: integer, minimum: 1, maximum: 43200 } } responses: '200': description: Broker read result in a data envelope content: application/json: schema: type: object required: [data] properties: data: {} '400': { description: Invalid or unexpected query parameters } '401': { description: Authentication required } '403': { description: Tenant, scope or account access denied } '404': { description: Account not found } '409': { description: Account is not connected } '502': { description: Broker account or response could not be validated } '503': { description: MT5 connector method unavailable } /organizations/{org}/accounts/{id}/orders/open: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read MT4 or MT5 open orders description: 'Requires trades:read and access to this tenant account. Broker identity is reverified before reading. ' responses: '200': description: Broker read result in a data envelope content: application/json: schema: type: object required: [data] properties: data: {} '400': { description: Invalid or unexpected query parameters } '401': { description: Authentication required } '403': { description: Tenant, scope or account access denied } '404': { description: Account not found } '409': { description: Account is not connected } '502': { description: Broker account or response could not be validated } '503': { description: MT5 connector method unavailable } /organizations/{org}/accounts/{id}/orders/closed: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read latest MT4 or MT5 closed orders description: 'Requires trades:read and access to this tenant account. Broker identity is reverified before reading. Vendor coverage is limited to the latest 100 closed orders; this is not complete account history. Response includes meta.limit=100 and meta.coverage=latest.' responses: '200': description: Broker read result in a data envelope content: application/json: schema: type: object required: [data] properties: data: {} '400': { description: Invalid or unexpected query parameters } '401': { description: Authentication required } '403': { description: Tenant, scope or account access denied } '404': { description: Account not found } '409': { description: Account is not connected } '502': { description: Broker account or response could not be validated } '503': { description: MT5 connector method unavailable } /organizations/{org}/accounts/{id}/symbol-params: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read MT4 or MT5 symbol trading parameters description: 'Requires market:read and access to the tenant account. Broker identity is verified before the read. This read-only result does not enable trading.' parameters: - { name: symbol, in: query, required: true, schema: { type: string, minLength: 1, maxLength: 100 } } responses: '200': description: Verified read-only result in a data envelope content: application/json: schema: type: object required: [data] properties: data: { type: object } '400': { description: Invalid or unexpected query parameters } '401': { description: Authentication required } '403': { description: Tenant, scope or account access denied } '404': { description: Account not found } '409': { description: Account is not connected } '502': { description: Broker account or response could not be validated } '503': { description: MT5 preflight method unavailable } /organizations/{org}/accounts/{id}/investor-status: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read MT4 or MT5 investor login status description: 'Requires accounts:read and access to the tenant account. Broker identity is verified before the read. This read-only result does not enable trading.' responses: '200': description: Verified read-only result in a data envelope content: application/json: schema: type: object required: [data] properties: data: { type: boolean } '400': { description: Invalid or unexpected query parameters } '401': { description: Authentication required } '403': { description: Tenant, scope or account access denied } '404': { description: Account not found } '409': { description: Account is not connected } '502': { description: Broker account or response could not be validated } '503': { description: MT5 preflight method unavailable } /organizations/{org}/accounts/{id}/trade-session: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read MT5 symbol trading-session status description: 'Requires market:read and an owned connected account. Available for MT5. MT4 returns 503 because symbol trading-session lookup is not offered. An open session does not guarantee order acceptance.' parameters: - { name: symbol, in: query, required: true, schema: { type: string, minLength: 1, maxLength: 100 } } responses: '200': description: Verified read-only session status in a data envelope content: application/json: schema: type: object required: [data] properties: data: { type: boolean } '400': { description: Invalid or unexpected query parameters } '401': { description: Authentication required } '403': { description: Tenant, scope or account access denied } '404': { description: Account not found } '409': { description: Account is not connected } '502': { description: Broker account or response could not be validated } '503': { description: MT5 preflight method unavailable } /organizations/{org}/accounts/{id}/margin-estimate: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Estimate MT4 pre-trade margin description: 'Requires market:read and access to the tenant account. MT4 returns a pre-trade margin estimate. Broker acceptance depends on the account and existing positions. MT5 pre-trade estimates are not currently offered and return HTTP 503. Current broker margin is available through the account summary on both platforms.' parameters: - { name: symbol, in: query, required: true, schema: { type: string, minLength: 1, maxLength: 100 } } - { name: lots, in: query, required: true, schema: { type: number, exclusiveMinimum: 0 }, description: Finite positive lot volume } - { name: type, in: query, required: true, schema: { type: string, enum: [DealBuy, DealSell] } } - { name: price, in: query, required: true, schema: { type: number, minimum: 0 }, description: Finite nonnegative requested price } responses: '200': description: Read-only result only when a verified connector configuration explicitly supports this capability content: application/json: schema: type: object required: [data] properties: data: { type: number } '400': { description: Invalid or unexpected query parameters } '401': { description: Authentication required } '403': { description: Tenant, scope or account access denied } '404': { description: Account not found } '409': { description: Account is not connected } '502': { description: Broker account or response could not be validated } '503': { description: MT5 preflight method unavailable } /organizations/{org}/accounts/{id}/quotes: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } post: summary: Read a batch of MT4 or MT5 quotes description: 'Requires market:read. Read-only request with 1–50 unique exact broker symbols.' requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [symbols] properties: symbols: { type: array, minItems: 1, maxItems: 50, uniqueItems: true, items: { type: string, minLength: 1, maxLength: 100 } } responses: '200': { description: Quotes in a data array } '400': { description: Invalid symbols } '503': { description: Connector unavailable } /organizations/{org}/accounts/{id}/orders/history: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read closed orders for a date range description: 'Requires trades:read. Maximum 31 days. Returns broker history for the requested range. Refresh current orders and inspect the saved trade operation when confirming execution.' parameters: - { name: from, in: query, required: true, schema: { type: string, format: date-time } } - { name: to, in: query, required: true, schema: { type: string, format: date-time } } - { name: sort, in: query, schema: { type: string, enum: [OpenTime, CloseTime], default: CloseTime } } - { name: ascending, in: query, schema: { type: boolean, default: false } } responses: '200': { description: Order data and coverage metadata } '400': { description: Invalid date range } '503': { description: Connector unavailable } /organizations/{org}/accounts/{id}/operations: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read persisted trading operation outcomes description: 'Requires trades:read. Does not dispatch or retry an operation.' parameters: - { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 100, default: 25 } } responses: '200': { description: Latest operations in a data array } '404': { description: Account not found } /organizations/{org}/accounts/{id}/operations/{operationId}: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } - { name: operationId, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Read one persisted trading operation description: 'Requires trades:read and access to the owning account.' responses: '200': { description: Operation data } '404': { description: Account or operation not found } /organizations/{org}/accounts/{id}/recover-connection: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } post: summary: Recover a stranded connection with a known session description: 'Workspace owner only; open Playground → Workspace management. Confirm the old worker has stopped before requesting recovery. A stale timestamp alone cannot fence a live worker. Unknown remote sessions remain blocked for operator review.' requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: [confirmOldWorkerStopped] properties: confirmOldWorkerStopped: { type: boolean, const: true } responses: '200': { description: Known remote session disconnected and stored state recovered } '409': { description: Not stale or remote outcome requires operator review } /organizations/{org}/api-keys/{id}/rotate: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } post: summary: Atomically replace an API key and revoke the old key description: 'Owner session only. Old access stops immediately. Name, permissions, account restrictions and expiry are preserved unless a new future expiry is supplied. The new token is shown once. Creation, revocation and audit commit together.' requestBody: content: application/json: schema: type: object additionalProperties: false properties: expiresAt: { type: string, format: date-time } responses: '201': { description: Replacement key with one-time token } '400': { description: Expired key requires a new future expiry } '409': { description: Old key is revoked } /organizations/{org}/accounts/{id}/quotes/stream: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Stream MT4 or MT5 quotes over authenticated SSE description: 'Requires streams:read and account access. One quote stream per connector session (both platforms also permit one orders and one profits stream), up to 20 streams per API process, 10 minute lifetime. Quote data is sampled and has no replay guarantee. Session generation and authorization are checked before forwarding each quote and every 15 seconds while idle; in-flight authorization can race with revocation. Use an HTTP client with a Bearer header, not credentials in the URL. Slow consumers are disconnected.' parameters: - name: symbols in: query required: true schema: { type: string } description: Comma-separated list of 1–10 distinct exact broker symbols responses: '200': description: 'SSE quote events contain symbol, bid, ask and UTC time. A close event ends the stream; clients must explicitly reconnect and refresh their snapshot.' content: text/event-stream: schema: { type: string } '400': { description: Invalid symbols } '403': { description: Stream scope or account access denied } '503': { description: Connector unavailable or stream capacity reached } /organizations/{org}/accounts/{id}/orders/stream: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Stream MT4 or MT5 orders and account totals over authenticated SSE description: 'Requires streams:read and account access. MT4 and MT5. Same authorization, session fencing, capacity, backpressure and lifetime rules as quote streams. No query parameters. Tickets are decimal strings; private connector selectors are never returned. Refresh current orders after reconnect; events have no replay guarantee.' responses: '200': description: 'SSE orders event data contains balance, equity, margin, freeMargin, profit and an orders array. A close event ends the stream.' content: text/event-stream: schema: { type: string } '400': { description: Unexpected query parameters } '401': { description: Authentication required } '403': { description: Tenant, stream scope or account access denied } '503': { description: Connector unavailable or stream capacity reached } /organizations/{org}/accounts/{id}/profits/stream: parameters: - { name: org, in: path, required: true, schema: { type: string, format: uuid } } - { name: id, in: path, required: true, schema: { type: string, format: uuid } } get: summary: Stream MT4 or MT5 order profit over authenticated SSE description: 'Requires streams:read and account access. MT4 and MT5. Same authorization, session fencing, capacity, backpressure and lifetime rules as quote streams. No query parameters. Tickets are decimal strings. No replay guarantee.' responses: '200': description: 'SSE profits event data is an array of sanitized current orders with profit. An empty snapshot is valid. A close event ends the stream.' content: text/event-stream: schema: { type: string } '400': { description: Unexpected query parameters } '401': { description: Authentication required } '403': { description: Tenant, stream scope or account access denied } '503': { description: Connector unavailable or stream capacity reached } /organizations/{org}/accounts/{id}/capabilities: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid get: summary: Read configured platform capabilities description: Requires accounts:read. Available before connection. Lists available account features and their supported parameters. responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/connection: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid get: summary: Read verified broker connection status description: Requires accounts:read and a stored session. Returns data.connected after independently checking the broker login. This does not certify symbol trading hours. responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/client-info: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid get: summary: Read sanitized broker client metadata description: Requires accounts:read. Returns broker login as a decimal string, currency/company, server build, account type/leverage, timestamps and client timeout settings. Proxy credentials, private selectors, host/port and customer contact details are omitted. responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/server-timezone: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid get: summary: Read broker UTC offset description: Requires market:read. Integer UTC offset in minutes. Broker history timestamps can be broker-local. responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/orders/archive: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid get: summary: Read broker order-history archive description: Requires trades:read. MT4 OrderHistory and MT5 OrderHistory.orders. Broker internal deals/orders are not exposed. No pagination/completeness guarantee; archive means the vendor helper, not unlimited history. responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/analytics/equity: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid get: summary: Read connector-calculated equity history description: Requires trades:read. MT4 and MT5. from must be within the past 366 days. Max 10000 points; this is a broker calculation rather than an immutable ledger. parameters: - name: from in: query required: true schema: type: string format: date-time - name: timeframe in: query required: true schema: type: string enum: - H1 - D1 - W1 - MN1 - name: excludeSameBars in: query required: true schema: type: boolean responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/analytics/rules: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid get: summary: Read connector-calculated rule statistics description: Requires trades:read. MT4 and MT5. Percent inputs between 0 and 100. Values and flags are broker calculations, not authoritative prop-firm eligibility or broker rules. parameters: - name: dailyLossLimit in: query required: true schema: type: number minimum: 0 maximum: 100 - name: totalLossLimit in: query required: true schema: type: number minimum: 0 maximum: 100 - name: target in: query required: true schema: type: number minimum: 0 maximum: 100 - name: floatingRisk in: query required: true schema: type: number minimum: 0 maximum: 100 responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/analytics/daily-profit: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid get: summary: Read MT5 broker daily-profit statistics description: Requires trades:read. MT5 only; MT4 returns 503. Includes broker daily profit/loss counts and totals; calculations are not independently recomputed. responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/price-history/bars: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid get: summary: Read MT4 bars backward from an anchor description: Requires market:read. MT4 only; MT5 returns 503. Broker count-backward semantics. Maximum 2000 bars and response limit 10000 records. MT4 volume conversion may differ by broker; zero volume does not prove no ticks. parameters: - name: symbol in: query required: true schema: type: string minLength: 1 maxLength: 100 - name: from in: query required: true schema: type: string format: date-time - name: timeframe in: query required: true schema: type: string enum: - M1 - M5 - M15 - M30 - H1 - H4 - D1 - W1 - MN1 - name: count in: query required: true schema: type: integer minimum: 1 maximum: 2000 responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/price-history/month: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid get: summary: Read MT5 monthly-anchor history description: Requires market:read. MT5 only. The broker helper uses an anchor date and a broker window; it does not guarantee calendar-month completeness. Calendar day must exist. parameters: - name: symbol in: query required: true schema: type: string minLength: 1 maxLength: 100 - name: year in: query required: true schema: type: integer minimum: 2000 maximum: 2100 - name: month in: query required: true schema: type: integer minimum: 1 maximum: 12 - name: day in: query required: true schema: type: integer minimum: 1 maximum: 31 - name: timeFrame in: query required: true schema: type: integer minimum: 1 maximum: 43200 responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/price-history/today: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid get: summary: Read MT5 today history description: Requires market:read. MT5 only. Broker broker-day semantics and incomplete coverage possible. parameters: - name: symbol in: query required: true schema: type: string minLength: 1 maxLength: 100 - name: timeFrame in: query required: true schema: type: integer minimum: 1 maximum: 43200 responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/trade-sessions: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid post: summary: Read symbol trading-session flags in a batch description: "Requires market:read. MT5 only until the MT4 symbol-session helper\ \ is repaired. 1\u201320 unique symbols; results are {symbol,open}. A nonexistent\ \ symbol returns false." requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - symbols properties: symbols: type: array minItems: 1 maxItems: 20 uniqueItems: true items: type: string minLength: 1 maxLength: 100 responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/price-history/batch: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid post: summary: Read MT5 month or today history for multiple symbols description: "Requires market:read. MT5 only. 1\u20135 unique symbols. Sequential\ \ bounded reads; an upstream failure fails the whole HTTP response. Broker completeness\ \ is not guaranteed." requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - symbols - period - timeFrame properties: symbols: type: array minItems: 1 maxItems: 5 uniqueItems: true items: type: string minLength: 1 maxLength: 100 period: type: string enum: - month - today timeFrame: type: integer minimum: 1 maximum: 43200 year: type: integer minimum: 2000 maximum: 2100 month: type: integer minimum: 1 maximum: 12 day: type: integer minimum: 1 maximum: 31 description: month requires year/month/day; today rejects date fields. responses: '200': description: Requested account data wrapped in data '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable /organizations/{org}/accounts/{id}/trades/batch: parameters: - name: org in: path required: true schema: type: string format: uuid - name: id in: path required: true schema: type: string format: uuid post: summary: Submit a bounded sequential batch of durable trades description: 'Requires trades:write and the same configured identity/destination/symbol/volume boundaries as /trades. Maximum 20 explicit trades. Not atomic: every item has an operation. Stops on the first error or non-succeeded operation. Same original batch/key can be resumed; a changed batch conflicts before further dispatch. Read per-item outcomes even on 202. Bulk close/cancel requires an exact broker ticket for every item; targetCorrelation is optional in live mode.' requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - trades properties: trades: type: array minItems: 1 maxItems: 20 items: $ref: '#/components/schemas/TradeInput' responses: '400': description: Invalid or unexpected fields '401': description: Authentication required '403': description: Scope, organization or account denied '409': description: Account disconnected '502': description: Broker response could not be validated '503': description: Feature unavailable '202': description: data array of {index,operation} or {index,error}, plus meta.atomic=false, submitted,total,stoppedEarly. No batch-level Location; poll each operation id. parameters: - name: Idempotency-Key in: header required: true schema: type: string pattern: ^[A-Za-z0-9._:-]{1,160}$