Agent-readable docs index: /llms.txt. Full docs in one file: /llms-full.txt. Download /docs.zip to grep all markdown files locally.

Errors and limits

Error envelope

Every error returns a stable machine code, a safe message, and the request ID:
{ "error": { "code": "account_disabled", "message": "The connected account is disabled", "requestId": "6c9e4a3e-..." } }
Keep the requestId when reporting a problem; it identifies the exact request on our side.

Error codes

CodeHTTP statusMeaning
invalid_request400; 404 for an unknown route or command; 413 for an oversized bodyMalformed body, parameters, cursor, or missing headers
invalid_api_key401The key is missing, malformed, revoked, or expired
insufficient_scope403The key lacks the scope this endpoint requires
subscription_required402The workspace does not have an active trial or subscription
account_not_found404No such account in your tenant
account_disabled409The account exists but reads are revoked
server_not_found422MT5 verified the server name does not resolve
broker_unreachable503The broker could not be reached; not a credential failure
credentials_rejected422The broker rejected the credentials; only used after a real broker response
capacity_exhausted503No worker capacity inside the request deadline
request_timeout504The request exceeded its deadline while being served
terminal_unhealthy503The MT5 terminal failed in a way that is not your fault
conflict409The request conflicts with concurrent state
control_plane_unavailable503The control plane was temporarily unavailable (reads are retried once first), or the data plane could not confirm its authority before contacting MT5
internal_error500; 502 for an oversized upstream data response; 503 for a failed strict history ingestUnexpected failure; safe to report with the request ID
account_slot_limit403The workspace has reached its connected account limit
execution_disabled409Trading is disabled for the account
execution_policy_violation403The order violates the configured execution policy
order_not_found404No such order in the connected account
position_not_found404No such position in the connected account
commit_unknown504 in an error envelopeThe gateway cannot confirm whether the operation committed
trade_rejected422The broker rejected the trading operation
account_warming202The account session is warming; retry the same request
rate_limit_exceeded429A request rate limit has been reached
cursor_expired410The cursor's cached page or pinned export window has expired
history_unsettled503Strict history coverage has not converged yet
history_offset_unavailable503The server clock offset required for strict history is unavailable
An error envelope with commit_unknown returns 504; a durable trading command with that outcome returns a pollable 202 command instead.
Two guarantees worth relying on: credentials_rejected is never used when FiveSocket failed to reach the broker, and server_not_found is never used for a transient terminal failure. A negative answer always means a verified negative. A single rejected login is never enough: credentials_rejected is returned only after two consecutive rejections of the same credentials on healthy workers, so a broker refusing a login burst is retried instead of reported as a wrong password.

Retries

  • capacity_exhausted returns 503 with a bounded Retry-After header. Honor it. Planned image rollouts keep resident sessions serving and create current-image overlap capacity only when authenticated migration or new-account demand needs it. The default physical peak is POOL_MAX_RUNTIMES + 1. Operators may raise POOL_ROLLOUT_MAX_SURGE_RUNTIMES only after measuring peak host fit, up to a maximum of POOL_MAX_RUNTIMES; the configurable physical maximum is twice the base runtime count. Migration reservations remain exclusive; new accounts use unreserved capacity, with at most one eligible oldest-idle eviction per admission at saturation or bounded backpressure. Accounts migrate directly to the current image using the request's credentials; idle sessions keep the existing five-minute TTL, spare-slot renewal, and six-hour cap. Current-image sessions on excess runtimes never migrate just to shrink the fleet. Placement fills base runtimes first. After the rollout, new accounts use only that base, and excess runtimes retire only when empty after normal closure or idle expiry. Requests for an existing excess account can prolong its residency. An empty stale runtime stays ready until a current-image successor is ready, except at an all-stale physical ceiling where full base readiness remains after retirement. Host refusal or the surge ceiling stalls progress and logs bounded deferrals while existing sessions keep serving. Creation retries use 5-to-60-second transient backoff or terminal 300-second re-probes. Readiness reports rollout progress separately, including surge state, optional current and maximum surge counts, waiting, and last failure class/time. It exposes no credentials, account identity, or target digest. Fresh-session replacement cancels its successor; shutdown aborts rollout work before releasing authority. Normal account capacity, admission bounds, serving/attaching protections, and first-service grace still apply.
  • rate_limit_exceeded returns 429 with Retry-After and the current rate-limit headers.
  • subscription_required returns 402; start or restore the subscription in the control surface.
  • control_plane_unavailable returns 503 with Retry-After for control-plane transport failures including a broken response body at any status, upstream timeouts, HTTP 429 or non-560 HTTP 5xx responses, and Convex service-unavailable responses. Structured ConvexError and other application failures stay application errors; unstructured Convex Server Error HTTP 560 retains its transient classification, and FiveSocket's own response deadline remains request_timeout. Convex 429 preserves a valid upstream Retry-After up to the shared 300-second API bound, otherwise the delay is one second. It is not retried internally. Other transport-failed reads are retried once internally first; trading and account mutations are not. No trading command was dispatched, so it is safe to repeat the same request with the same idempotency key. If a dispatch-marker, warming-defer, or execution-result write cannot be confirmed, or the command already owned by another dispatch attempt cannot be read, the response is a 202 command with outcome: commit_unknown instead, and the command resolves through the command poll.
  • A request that begins serving but exceeds its deadline returns 504. The worker session is fenced and destroyed, so the read either fully happened or fully did not.
  • Client mistakes return 4xx and are never worth retrying unchanged.

Idempotency

POST /v1/accounts and DELETE /v1/accounts/{accountId} require an Idempotency-Key header. Reuse the same key when retrying the same logical operation.

Pagination

GET /v1/accounts/{accountId}/trades, deals, and orders use opaque signed cursors. Pass the nextCursor value back verbatim; cursors are bound to the account and query window, and a tampered or foreign cursor is rejected as invalid_request.
Window rules:
  • initial reads require an explicit to; missing it returns 400 invalid_request
  • from defaults deterministically to 30 days before to
  • cursor requests omit from and to because the cursor carries both bounds
  • the window cannot exceed 90 days
  • limit is 1 to 1000, default 100

Limits

V1 enforces limits per tenant, API key, and connected account:
  • request rate and concurrent requests
  • concurrent logins per account
  • maximum trade-history interval and page size
  • maximum request deadline
  • request bodies over 32 KB are rejected
Limits protect the shared worker pool. They do not create freshness tiers; every read that succeeds is a live read.
The current per-minute policies are:
PlanAPI keyWorkspaceConnected MT5 account
Starter6012030
Plus12030030
Scale3001,00060
Every metered success includes RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset. The values describe the applicable bucket with the least remaining capacity. Cached history cursor pages do not consume the live MT5 account bucket.
A control-plane rate limit returns 503 control_plane_unavailable. Its Retry-After is at least one second and at most 300 seconds.