Errors & Limits

Error frames

Errors come in two shapes depending on scope.

Connection-scope errors arrive as a standalone frame and may close the connection:

{ "type": "error", "code": "internal_error", "message": "..." }

Command-scope errors are returned against the command that caused them (the success: false ack):

{
  "method": "subscribe",
  "success": false,
  "error": { "code": "unknown_symbol", "message": "Unsupported symbol XAU/USD" },
  "req_id": 1
}

Error codes

Code Scope Meaning
auth_failed connection API key missing/invalid/expired, IP mismatch, account deactivated, or credential revoked mid-connection. Connection closes.
unknown_symbol command Subscribed to a pair that isn't supported.
rate_limited connection Dropped as a slow consumer (your client wasn't reading fast enough).
invalid_message connection or command Malformed JSON arrives as a standalone connection-scope frame ({ "type": "error", "code": "invalid_message" }); an unknown method arrives as a command-scope ack (success: false) against the offending command. Neither closes the connection.

Server-side faults are not surfaced as a frame on an open connection — they are logged server-side. If the connection closes unexpectedly, reconnect with backoff (see Connecting). Faults during the connection upgrade surface as an HTTP 500 on the upgrade response (see below).

Upgrade rejection (HTTP)

Auth and quota failures happen before the WebSocket opens, so they surface as HTTP status codes on the upgrade response, not as frames:

Status Reason
401 Missing/invalid X-Api-Key, IP mismatch, or deactivated account
429 Rate limit exceeded (see below)
500 Server-side fault while handling the upgrade. Retry with backoff.

Rate limits

Limit Default
Concurrent connections per account 5
Connection attempts per minute 60

Exceeding either rejects the upgrade with 429. If you need higher limits, contact support.

The concurrent-connection cap is enforced per server instance, so during scale-out an account may briefly hold more than the listed number across instances. The connection-attempt limit is enforced globally. Don't rely on the connection cap as a hard ceiling — size your client to the listed value.

Mid-connection revocation

Credentials are re-checked periodically while connected. If your API key is revoked or your account is deactivated, the connection is closed with auth_failed within ~25 seconds — you do not need to reconnect to pick up a revocation.

Slow consumers

If your client stops reading and the server's send buffer for your connection backs up beyond its limit for more than a few seconds, the connection is dropped with rate_limited. Read frames promptly (and reply to pings) to avoid this. On a drop, reconnect with backoff and re-subscribe.

Versioning

The feed is versioned in the URL path (/v1/rates). /v1 is stable; any breaking change ships under a new version.