{"openapi": "3.0.3", "info": {"title": "Financial Data WebSocket API", "description": "Market data updates on **`api.financialdata.online`** (11 feed(s) enabled). Use the same API host as REST (`https://api.financialdata.online`). Authenticate with a JWT, open a feed path with **`wss://`**, subscribe to tickers, and receive JSON updates documented per feed.\n\n## Guides\n\n- [Overview](https://financialdata.online/api/docs/websocket/#overview)\n- [Authentication](https://financialdata.online/api/docs/websocket/#authentication)\n\n## Quick example\n\n```\nwss://api.financialdata.online/ws/stocks/AM/\nAuthorization: Bearer YOUR_JWT_ACCESS\n```\n\n```json\n{\"action\": \"subscribe\", \"tickers\": [\"AAPL\"]}\n```\n\n## Close codes\n\n| Code | Meaning |\n|---|---|\n| `1000` | Normal closure |\n| `4400` | Unknown or disabled feed |\n| `4401` | Authentication failed (after JSON `authentication_failed` error) |\n", "version": "1.0.0", "contact": {"name": "API Support", "url": "https://financialdata.online"}}, "servers": [{"url": "https://api.financialdata.online", "description": "API host \u2014 WebSocket paths use `wss://` on this hostname"}], "tags": [{"name": "Crypto", "description": "Crypto market updates over WebSocket on **api.financialdata.online**. Enabled feeds: `/ws/crypto/XA/`, `/ws/crypto/XAS/`, `/ws/crypto/XQ/`, `/ws/crypto/XT/`."}, {"name": "Forex", "description": "Forex market updates over WebSocket on **api.financialdata.online**. Enabled feeds: `/ws/forex/C/`, `/ws/forex/CA/`, `/ws/forex/CAS/`."}, {"name": "Stocks", "description": "Stocks market updates over WebSocket on **api.financialdata.online**. Enabled feeds: `/ws/stocks/A/`, `/ws/stocks/AM/`, `/ws/stocks/Q/`, `/ws/stocks/T/`."}], "paths": {"/ws/crypto/XA/": {"get": {"summary": "Crypto OHLCV updates", "description": "Pushes OHLCV updates for subscribed crypto pairs on this connection.\n\n### Plan access\n\n- **Minimum plan:** `Premium`\n- **Premium latency:** `realtime`\n- **Pro:** not available on this feed (Premium only)\n\n### Connection\n\nOpen a **WebSocket** to this service (not an HTTP GET on the path below):\n\n```\nwss://api.financialdata.online/ws/crypto/XA/\n```\n\n### Authentication\n\nSend **`Authorization: Bearer <JWT>`** on the upgrade request. Obtain an access token with **`POST /api/token/`** and use the JSON field **`access`**. CLI clients (wscat, Postman, many scripts) must also send **`Origin: https://api.financialdata.online`** \u2014 without it the handshake fails with **HTTP 403**. Browsers set `Origin` automatically. On auth failure you receive a JSON error frame first, then close code **`4401`** with a short `reason`.\n\n### Subscribe and unsubscribe\n\nAfter the connection is open, send UTF-8 JSON text frames:\n\n```json\n{\"action\": \"subscribe\", \"tickers\": [\"BTCUSD\"]}\n```\n\n```json\n{\"action\": \"unsubscribe\", \"tickers\": [\"BTCUSD\"]}\n```\n\nTicker symbols are normalized to **uppercase**. Subscription state is **per connection** and **per feed path** (this endpoint is **Crypto OHLCV updates**).\n\n### Control messages (server \u2192 client)\n\n#### Subscription acknowledgements\n\n| Field | Description |\n|---|---|\n| `type` | Always `subscribed` or `unsubscribed`. |\n| `tickers` | Tickers affected by the last action (full set after subscribe; removed set after unsubscribe). |\n\n#### Errors (JSON frame, then connection close)\n\n| Field | Description |\n|---|---|\n| `code` | Machine-readable code (e.g. `authentication_failed`, `protocol_error`, `unknown_feed`). Errors do **not** use a `type` field. |\n| `message` | Human-readable explanation. Authentication failures close with **`4401`** after this frame. |\n\n### Market data (server \u2192 client)\n\nMarket updates are **single JSON objects** with the response fields below. They do **not** include a `type` property. The event code field **`ev`** is **`XA`** for this feed. Only fields listed in the schema are sent on this feed.\n\n### Limits\n\n- Up to **50** tickers per WebSocket connection.\n- One connection per feed path per session is recommended.\n\n[WebSocket authentication guide](https://financialdata.online/api/docs/websocket/#authentication) \u00b7 [WebSocket overview](https://financialdata.online/api/docs/websocket/#overview)", "operationId": "ws_crypto_XA", "tags": ["Crypto"], "x-wsEntitlement": {"minPlan": "Premium", "premiumLatencyTier": "realtime"}, "parameters": [{"name": "Authorization", "in": "header", "required": true, "description": "JWT access token from `POST /api/token/` as `Bearer <access>`.", "schema": {"type": "string"}, "example": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}, {"name": "Origin", "in": "header", "required": false, "description": "Required for CLI clients that do not send Origin by default (wscat, Postman). Use `https://api.financialdata.online`. Missing or disallowed Origin \u2192 HTTP **403** on handshake. Browsers send this automatically.", "schema": {"type": "string"}, "example": "https://api.financialdata.online"}], "responses": {"101": {"description": "WebSocket established. Server sends JSON text frames (control and market data).", "content": {"application/json": {"schema": {"oneOf": [{"type": "object", "title": "Subscription confirmation", "properties": {"type": {"type": "string", "enum": ["subscribed", "unsubscribed"]}, "tickers": {"type": "array", "items": {"type": "string"}, "description": "Tickers confirmed for the last subscribe or removed by the last unsubscribe."}}, "required": ["type", "tickers"]}, {"type": "object", "title": "Crypto OHLCV updates", "description": "Market data update (no `type` field).", "properties": {"ev": {"type": "string", "description": "Event code for this feed (constant on every message for a given path)."}, "pair": {"type": "string", "description": "Instrument pair or symbol (format depends on asset class)."}, "o": {"type": "number", "description": "Opening price for the update."}, "c": {"type": "number", "description": "Closing / last price for the update."}, "h": {"type": "number", "description": "High price for the update."}, "l": {"type": "number", "description": "Low price for the update."}, "v": {"type": "integer", "description": "Reported volume for the update."}, "s": {"type": "integer", "description": "Update start time (Unix milliseconds, UTC)."}, "e": {"type": "integer", "description": "Update end time (Unix milliseconds, UTC)."}}}, {"type": "object", "title": "Error", "description": "Protocol or auth error (no `type` field).", "properties": {"code": {"type": "string", "description": "Machine-readable error code (e.g. authentication_failed, unknown_feed, protocol_error)."}, "message": {"type": "string"}}, "required": ["code", "message"]}]}, "examples": {"subscribed": {"summary": "Subscription confirmation", "value": {"type": "subscribed", "tickers": ["BTCUSD"]}}, "unsubscribed": {"summary": "Unsubscription confirmation", "value": {"type": "unsubscribed", "tickers": ["BTCUSD"]}}, "data": {"summary": "Market data update", "value": {"ev": "XA", "pair": "BTCUSD", "o": 182.63, "c": 182.63, "h": 182.63, "l": 182.63, "v": 1500, "s": 1709312400000, "e": 1709312400000}}, "error": {"summary": "Client protocol error", "value": {"code": "protocol_error", "message": "'tickers' must be a non-empty list of strings."}}, "auth_error": {"summary": "Authentication failed (before close 4401)", "value": {"code": "authentication_failed", "message": "JWT is invalid or expired. Obtain a new access token via POST /api/token/."}}}}}}, "403": {"description": "Handshake rejected. Common cause: missing or disallowed `Origin` header (CLI clients must send `Origin: https://api.financialdata.online`). Distinct from post-connect close code `4401` (authentication failed after accept)."}}, "x-codeSamples": [{"lang": "Shell", "label": "wscat", "source": "wscat -c \"wss://api.financialdata.online/ws/crypto/XA/\" \\\n  -H \"Authorization: Bearer YOUR_JWT_ACCESS\" \\\n  -H \"Origin: https://api.financialdata.online\""}, {"lang": "Python", "label": "Python (websockets)", "source": "import asyncio, json, websockets\n\nasync def main():\n    uri = \"wss://api.financialdata.online/ws/crypto/XA/\"\n    headers = {\n        \"Authorization\": \"Bearer YOUR_JWT_ACCESS\",\n        \"Origin\": \"https://api.financialdata.online\",\n    }\n    async with websockets.connect(uri, additional_headers=headers) as ws:\n        await ws.send(json.dumps({\"action\": \"subscribe\", \"tickers\": [\"BTCUSD\"]}))\n        async for msg in ws:\n            print(json.loads(msg))\n\nasyncio.run(main())"}]}}, "/ws/crypto/XAS/": {"get": {"summary": "Crypto OHLCV updates", "description": "Pushes OHLCV updates for subscribed crypto pairs on this connection.\n\n### Plan access\n\n- **Minimum plan:** `Premium`\n- **Premium latency:** `realtime`\n- **Pro:** not available on this feed (Premium only)\n\n### Connection\n\nOpen a **WebSocket** to this service (not an HTTP GET on the path below):\n\n```\nwss://api.financialdata.online/ws/crypto/XAS/\n```\n\n### Authentication\n\nSend **`Authorization: Bearer <JWT>`** on the upgrade request. Obtain an access token with **`POST /api/token/`** and use the JSON field **`access`**. CLI clients (wscat, Postman, many scripts) must also send **`Origin: https://api.financialdata.online`** \u2014 without it the handshake fails with **HTTP 403**. Browsers set `Origin` automatically. On auth failure you receive a JSON error frame first, then close code **`4401`** with a short `reason`.\n\n### Subscribe and unsubscribe\n\nAfter the connection is open, send UTF-8 JSON text frames:\n\n```json\n{\"action\": \"subscribe\", \"tickers\": [\"BTCUSD\"]}\n```\n\n```json\n{\"action\": \"unsubscribe\", \"tickers\": [\"BTCUSD\"]}\n```\n\nTicker symbols are normalized to **uppercase**. Subscription state is **per connection** and **per feed path** (this endpoint is **Crypto OHLCV updates**).\n\n### Control messages (server \u2192 client)\n\n#### Subscription acknowledgements\n\n| Field | Description |\n|---|---|\n| `type` | Always `subscribed` or `unsubscribed`. |\n| `tickers` | Tickers affected by the last action (full set after subscribe; removed set after unsubscribe). |\n\n#### Errors (JSON frame, then connection close)\n\n| Field | Description |\n|---|---|\n| `code` | Machine-readable code (e.g. `authentication_failed`, `protocol_error`, `unknown_feed`). Errors do **not** use a `type` field. |\n| `message` | Human-readable explanation. Authentication failures close with **`4401`** after this frame. |\n\n### Market data (server \u2192 client)\n\nMarket updates are **single JSON objects** with the response fields below. They do **not** include a `type` property. The event code field **`ev`** is **`XAS`** for this feed. Only fields listed in the schema are sent on this feed.\n\n### Limits\n\n- Up to **50** tickers per WebSocket connection.\n- One connection per feed path per session is recommended.\n\n[WebSocket authentication guide](https://financialdata.online/api/docs/websocket/#authentication) \u00b7 [WebSocket overview](https://financialdata.online/api/docs/websocket/#overview)", "operationId": "ws_crypto_XAS", "tags": ["Crypto"], "x-wsEntitlement": {"minPlan": "Premium", "premiumLatencyTier": "realtime"}, "parameters": [{"name": "Authorization", "in": "header", "required": true, "description": "JWT access token from `POST /api/token/` as `Bearer <access>`.", "schema": {"type": "string"}, "example": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}, {"name": "Origin", "in": "header", "required": false, "description": "Required for CLI clients that do not send Origin by default (wscat, Postman). Use `https://api.financialdata.online`. Missing or disallowed Origin \u2192 HTTP **403** on handshake. Browsers send this automatically.", "schema": {"type": "string"}, "example": "https://api.financialdata.online"}], "responses": {"101": {"description": "WebSocket established. Server sends JSON text frames (control and market data).", "content": {"application/json": {"schema": {"oneOf": [{"type": "object", "title": "Subscription confirmation", "properties": {"type": {"type": "string", "enum": ["subscribed", "unsubscribed"]}, "tickers": {"type": "array", "items": {"type": "string"}, "description": "Tickers confirmed for the last subscribe or removed by the last unsubscribe."}}, "required": ["type", "tickers"]}, {"type": "object", "title": "Crypto OHLCV updates", "description": "Market data update (no `type` field).", "properties": {"ev": {"type": "string", "description": "Event code for this feed (constant on every message for a given path)."}, "pair": {"type": "string", "description": "Instrument pair or symbol (format depends on asset class)."}, "o": {"type": "number", "description": "Opening price for the update."}, "c": {"type": "number", "description": "Closing / last price for the update."}, "h": {"type": "number", "description": "High price for the update."}, "l": {"type": "number", "description": "Low price for the update."}, "v": {"type": "integer", "description": "Reported volume for the update."}, "s": {"type": "integer", "description": "Update start time (Unix milliseconds, UTC)."}, "e": {"type": "integer", "description": "Update end time (Unix milliseconds, UTC)."}}}, {"type": "object", "title": "Error", "description": "Protocol or auth error (no `type` field).", "properties": {"code": {"type": "string", "description": "Machine-readable error code (e.g. authentication_failed, unknown_feed, protocol_error)."}, "message": {"type": "string"}}, "required": ["code", "message"]}]}, "examples": {"subscribed": {"summary": "Subscription confirmation", "value": {"type": "subscribed", "tickers": ["BTCUSD"]}}, "unsubscribed": {"summary": "Unsubscription confirmation", "value": {"type": "unsubscribed", "tickers": ["BTCUSD"]}}, "data": {"summary": "Market data update", "value": {"ev": "XAS", "pair": "BTCUSD", "o": 182.63, "c": 182.63, "h": 182.63, "l": 182.63, "v": 1500, "s": 1709312400000, "e": 1709312400000}}, "error": {"summary": "Client protocol error", "value": {"code": "protocol_error", "message": "'tickers' must be a non-empty list of strings."}}, "auth_error": {"summary": "Authentication failed (before close 4401)", "value": {"code": "authentication_failed", "message": "JWT is invalid or expired. Obtain a new access token via POST /api/token/."}}}}}}, "403": {"description": "Handshake rejected. Common cause: missing or disallowed `Origin` header (CLI clients must send `Origin: https://api.financialdata.online`). Distinct from post-connect close code `4401` (authentication failed after accept)."}}, "x-codeSamples": [{"lang": "Shell", "label": "wscat", "source": "wscat -c \"wss://api.financialdata.online/ws/crypto/XAS/\" \\\n  -H \"Authorization: Bearer YOUR_JWT_ACCESS\" \\\n  -H \"Origin: https://api.financialdata.online\""}, {"lang": "Python", "label": "Python (websockets)", "source": "import asyncio, json, websockets\n\nasync def main():\n    uri = \"wss://api.financialdata.online/ws/crypto/XAS/\"\n    headers = {\n        \"Authorization\": \"Bearer YOUR_JWT_ACCESS\",\n        \"Origin\": \"https://api.financialdata.online\",\n    }\n    async with websockets.connect(uri, additional_headers=headers) as ws:\n        await ws.send(json.dumps({\"action\": \"subscribe\", \"tickers\": [\"BTCUSD\"]}))\n        async for msg in ws:\n            print(json.loads(msg))\n\nasyncio.run(main())"}]}}, "/ws/crypto/XQ/": {"get": {"summary": "Crypto quotes", "description": "Pushes quote updates for subscribed crypto pairs on this connection.\n\n### Plan access\n\n- **Minimum plan:** `Premium`\n- **Premium latency:** `realtime`\n- **Pro:** not available on this feed (Premium only)\n\n### Connection\n\nOpen a **WebSocket** to this service (not an HTTP GET on the path below):\n\n```\nwss://api.financialdata.online/ws/crypto/XQ/\n```\n\n### Authentication\n\nSend **`Authorization: Bearer <JWT>`** on the upgrade request. Obtain an access token with **`POST /api/token/`** and use the JSON field **`access`**. CLI clients (wscat, Postman, many scripts) must also send **`Origin: https://api.financialdata.online`** \u2014 without it the handshake fails with **HTTP 403**. Browsers set `Origin` automatically. On auth failure you receive a JSON error frame first, then close code **`4401`** with a short `reason`.\n\n### Subscribe and unsubscribe\n\nAfter the connection is open, send UTF-8 JSON text frames:\n\n```json\n{\"action\": \"subscribe\", \"tickers\": [\"BTCUSD\"]}\n```\n\n```json\n{\"action\": \"unsubscribe\", \"tickers\": [\"BTCUSD\"]}\n```\n\nTicker symbols are normalized to **uppercase**. Subscription state is **per connection** and **per feed path** (this endpoint is **Crypto quotes**).\n\n### Control messages (server \u2192 client)\n\n#### Subscription acknowledgements\n\n| Field | Description |\n|---|---|\n| `type` | Always `subscribed` or `unsubscribed`. |\n| `tickers` | Tickers affected by the last action (full set after subscribe; removed set after unsubscribe). |\n\n#### Errors (JSON frame, then connection close)\n\n| Field | Description |\n|---|---|\n| `code` | Machine-readable code (e.g. `authentication_failed`, `protocol_error`, `unknown_feed`). Errors do **not** use a `type` field. |\n| `message` | Human-readable explanation. Authentication failures close with **`4401`** after this frame. |\n\n### Market data (server \u2192 client)\n\nMarket updates are **single JSON objects** with the response fields below. They do **not** include a `type` property. The event code field **`ev`** is **`XQ`** for this feed. Only fields listed in the schema are sent on this feed.\n\n### Limits\n\n- Up to **50** tickers per WebSocket connection.\n- One connection per feed path per session is recommended.\n\n[WebSocket authentication guide](https://financialdata.online/api/docs/websocket/#authentication) \u00b7 [WebSocket overview](https://financialdata.online/api/docs/websocket/#overview)", "operationId": "ws_crypto_XQ", "tags": ["Crypto"], "x-wsEntitlement": {"minPlan": "Premium", "premiumLatencyTier": "realtime"}, "parameters": [{"name": "Authorization", "in": "header", "required": true, "description": "JWT access token from `POST /api/token/` as `Bearer <access>`.", "schema": {"type": "string"}, "example": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}, {"name": "Origin", "in": "header", "required": false, "description": "Required for CLI clients that do not send Origin by default (wscat, Postman). Use `https://api.financialdata.online`. Missing or disallowed Origin \u2192 HTTP **403** on handshake. Browsers send this automatically.", "schema": {"type": "string"}, "example": "https://api.financialdata.online"}], "responses": {"101": {"description": "WebSocket established. Server sends JSON text frames (control and market data).", "content": {"application/json": {"schema": {"oneOf": [{"type": "object", "title": "Subscription confirmation", "properties": {"type": {"type": "string", "enum": ["subscribed", "unsubscribed"]}, "tickers": {"type": "array", "items": {"type": "string"}, "description": "Tickers confirmed for the last subscribe or removed by the last unsubscribe."}}, "required": ["type", "tickers"]}, {"type": "object", "title": "Crypto quotes", "description": "Market data update (no `type` field).", "properties": {"ev": {"type": "string", "description": "Event code for this feed (constant on every message for a given path)."}, "pair": {"type": "string", "description": "Instrument pair or symbol (format depends on asset class)."}, "bp": {"type": "number", "description": "Bid price on this update."}, "ap": {"type": "number", "description": "Ask price on this update."}, "t": {"type": "integer", "description": "Event time (Unix milliseconds, UTC)."}}}, {"type": "object", "title": "Error", "description": "Protocol or auth error (no `type` field).", "properties": {"code": {"type": "string", "description": "Machine-readable error code (e.g. authentication_failed, unknown_feed, protocol_error)."}, "message": {"type": "string"}}, "required": ["code", "message"]}]}, "examples": {"subscribed": {"summary": "Subscription confirmation", "value": {"type": "subscribed", "tickers": ["BTCUSD"]}}, "unsubscribed": {"summary": "Unsubscription confirmation", "value": {"type": "unsubscribed", "tickers": ["BTCUSD"]}}, "data": {"summary": "Market data update", "value": {"ev": "XQ", "pair": "BTCUSD", "bp": 182.63, "ap": 182.63, "t": 1709312400000}}, "error": {"summary": "Client protocol error", "value": {"code": "protocol_error", "message": "'tickers' must be a non-empty list of strings."}}, "auth_error": {"summary": "Authentication failed (before close 4401)", "value": {"code": "authentication_failed", "message": "JWT is invalid or expired. Obtain a new access token via POST /api/token/."}}}}}}, "403": {"description": "Handshake rejected. Common cause: missing or disallowed `Origin` header (CLI clients must send `Origin: https://api.financialdata.online`). Distinct from post-connect close code `4401` (authentication failed after accept)."}}, "x-codeSamples": [{"lang": "Shell", "label": "wscat", "source": "wscat -c \"wss://api.financialdata.online/ws/crypto/XQ/\" \\\n  -H \"Authorization: Bearer YOUR_JWT_ACCESS\" \\\n  -H \"Origin: https://api.financialdata.online\""}, {"lang": "Python", "label": "Python (websockets)", "source": "import asyncio, json, websockets\n\nasync def main():\n    uri = \"wss://api.financialdata.online/ws/crypto/XQ/\"\n    headers = {\n        \"Authorization\": \"Bearer YOUR_JWT_ACCESS\",\n        \"Origin\": \"https://api.financialdata.online\",\n    }\n    async with websockets.connect(uri, additional_headers=headers) as ws:\n        await ws.send(json.dumps({\"action\": \"subscribe\", \"tickers\": [\"BTCUSD\"]}))\n        async for msg in ws:\n            print(json.loads(msg))\n\nasyncio.run(main())"}]}}, "/ws/crypto/XT/": {"get": {"summary": "Crypto trade prices", "description": "Pushes trade price updates for subscribed crypto pairs on this connection.\n\n### Plan access\n\n- **Minimum plan:** `Premium`\n- **Premium latency:** `realtime`\n- **Pro:** not available on this feed (Premium only)\n\n### Connection\n\nOpen a **WebSocket** to this service (not an HTTP GET on the path below):\n\n```\nwss://api.financialdata.online/ws/crypto/XT/\n```\n\n### Authentication\n\nSend **`Authorization: Bearer <JWT>`** on the upgrade request. Obtain an access token with **`POST /api/token/`** and use the JSON field **`access`**. CLI clients (wscat, Postman, many scripts) must also send **`Origin: https://api.financialdata.online`** \u2014 without it the handshake fails with **HTTP 403**. Browsers set `Origin` automatically. On auth failure you receive a JSON error frame first, then close code **`4401`** with a short `reason`.\n\n### Subscribe and unsubscribe\n\nAfter the connection is open, send UTF-8 JSON text frames:\n\n```json\n{\"action\": \"subscribe\", \"tickers\": [\"BTCUSD\"]}\n```\n\n```json\n{\"action\": \"unsubscribe\", \"tickers\": [\"BTCUSD\"]}\n```\n\nTicker symbols are normalized to **uppercase**. Subscription state is **per connection** and **per feed path** (this endpoint is **Crypto trade prices**).\n\n### Control messages (server \u2192 client)\n\n#### Subscription acknowledgements\n\n| Field | Description |\n|---|---|\n| `type` | Always `subscribed` or `unsubscribed`. |\n| `tickers` | Tickers affected by the last action (full set after subscribe; removed set after unsubscribe). |\n\n#### Errors (JSON frame, then connection close)\n\n| Field | Description |\n|---|---|\n| `code` | Machine-readable code (e.g. `authentication_failed`, `protocol_error`, `unknown_feed`). Errors do **not** use a `type` field. |\n| `message` | Human-readable explanation. Authentication failures close with **`4401`** after this frame. |\n\n### Market data (server \u2192 client)\n\nMarket updates are **single JSON objects** with the response fields below. They do **not** include a `type` property. The event code field **`ev`** is **`XT`** for this feed. Only fields listed in the schema are sent on this feed.\n\n### Limits\n\n- Up to **50** tickers per WebSocket connection.\n- One connection per feed path per session is recommended.\n\n[WebSocket authentication guide](https://financialdata.online/api/docs/websocket/#authentication) \u00b7 [WebSocket overview](https://financialdata.online/api/docs/websocket/#overview)", "operationId": "ws_crypto_XT", "tags": ["Crypto"], "x-wsEntitlement": {"minPlan": "Premium", "premiumLatencyTier": "realtime"}, "parameters": [{"name": "Authorization", "in": "header", "required": true, "description": "JWT access token from `POST /api/token/` as `Bearer <access>`.", "schema": {"type": "string"}, "example": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}, {"name": "Origin", "in": "header", "required": false, "description": "Required for CLI clients that do not send Origin by default (wscat, Postman). Use `https://api.financialdata.online`. Missing or disallowed Origin \u2192 HTTP **403** on handshake. Browsers send this automatically.", "schema": {"type": "string"}, "example": "https://api.financialdata.online"}], "responses": {"101": {"description": "WebSocket established. Server sends JSON text frames (control and market data).", "content": {"application/json": {"schema": {"oneOf": [{"type": "object", "title": "Subscription confirmation", "properties": {"type": {"type": "string", "enum": ["subscribed", "unsubscribed"]}, "tickers": {"type": "array", "items": {"type": "string"}, "description": "Tickers confirmed for the last subscribe or removed by the last unsubscribe."}}, "required": ["type", "tickers"]}, {"type": "object", "title": "Crypto trade prices", "description": "Market data update (no `type` field).", "properties": {"ev": {"type": "string", "description": "Event code for this feed (constant on every message for a given path)."}, "pair": {"type": "string", "description": "Instrument pair or symbol (format depends on asset class)."}, "p": {"type": "number", "description": "Last trade price."}, "t": {"type": "integer", "description": "Event time (Unix milliseconds, UTC)."}, "s": {"type": "integer", "description": "Size associated with the update (shares/contracts when provided)."}}}, {"type": "object", "title": "Error", "description": "Protocol or auth error (no `type` field).", "properties": {"code": {"type": "string", "description": "Machine-readable error code (e.g. authentication_failed, unknown_feed, protocol_error)."}, "message": {"type": "string"}}, "required": ["code", "message"]}]}, "examples": {"subscribed": {"summary": "Subscription confirmation", "value": {"type": "subscribed", "tickers": ["BTCUSD"]}}, "unsubscribed": {"summary": "Unsubscription confirmation", "value": {"type": "unsubscribed", "tickers": ["BTCUSD"]}}, "data": {"summary": "Market data update", "value": {"ev": "XT", "pair": "BTCUSD", "p": 182.63, "t": 1709312400000, "s": 1500}}, "error": {"summary": "Client protocol error", "value": {"code": "protocol_error", "message": "'tickers' must be a non-empty list of strings."}}, "auth_error": {"summary": "Authentication failed (before close 4401)", "value": {"code": "authentication_failed", "message": "JWT is invalid or expired. Obtain a new access token via POST /api/token/."}}}}}}, "403": {"description": "Handshake rejected. Common cause: missing or disallowed `Origin` header (CLI clients must send `Origin: https://api.financialdata.online`). Distinct from post-connect close code `4401` (authentication failed after accept)."}}, "x-codeSamples": [{"lang": "Shell", "label": "wscat", "source": "wscat -c \"wss://api.financialdata.online/ws/crypto/XT/\" \\\n  -H \"Authorization: Bearer YOUR_JWT_ACCESS\" \\\n  -H \"Origin: https://api.financialdata.online\""}, {"lang": "Python", "label": "Python (websockets)", "source": "import asyncio, json, websockets\n\nasync def main():\n    uri = \"wss://api.financialdata.online/ws/crypto/XT/\"\n    headers = {\n        \"Authorization\": \"Bearer YOUR_JWT_ACCESS\",\n        \"Origin\": \"https://api.financialdata.online\",\n    }\n    async with websockets.connect(uri, additional_headers=headers) as ws:\n        await ws.send(json.dumps({\"action\": \"subscribe\", \"tickers\": [\"BTCUSD\"]}))\n        async for msg in ws:\n            print(json.loads(msg))\n\nasyncio.run(main())"}]}}, "/ws/forex/C/": {"get": {"summary": "Forex quotes", "description": "Pushes quote updates for subscribed currency pairs on this connection.\n\n### Plan access\n\n- **Minimum plan:** `Premium`\n- **Premium latency:** `realtime`\n- **Pro:** not available on this feed (Premium only)\n\n### Connection\n\nOpen a **WebSocket** to this service (not an HTTP GET on the path below):\n\n```\nwss://api.financialdata.online/ws/forex/C/\n```\n\n### Authentication\n\nSend **`Authorization: Bearer <JWT>`** on the upgrade request. Obtain an access token with **`POST /api/token/`** and use the JSON field **`access`**. CLI clients (wscat, Postman, many scripts) must also send **`Origin: https://api.financialdata.online`** \u2014 without it the handshake fails with **HTTP 403**. Browsers set `Origin` automatically. On auth failure you receive a JSON error frame first, then close code **`4401`** with a short `reason`.\n\n### Subscribe and unsubscribe\n\nAfter the connection is open, send UTF-8 JSON text frames:\n\n```json\n{\"action\": \"subscribe\", \"tickers\": [\"EURUSD\"]}\n```\n\n```json\n{\"action\": \"unsubscribe\", \"tickers\": [\"EURUSD\"]}\n```\n\nTicker symbols are normalized to **uppercase**. Subscription state is **per connection** and **per feed path** (this endpoint is **Forex quotes**).\n\n### Control messages (server \u2192 client)\n\n#### Subscription acknowledgements\n\n| Field | Description |\n|---|---|\n| `type` | Always `subscribed` or `unsubscribed`. |\n| `tickers` | Tickers affected by the last action (full set after subscribe; removed set after unsubscribe). |\n\n#### Errors (JSON frame, then connection close)\n\n| Field | Description |\n|---|---|\n| `code` | Machine-readable code (e.g. `authentication_failed`, `protocol_error`, `unknown_feed`). Errors do **not** use a `type` field. |\n| `message` | Human-readable explanation. Authentication failures close with **`4401`** after this frame. |\n\n### Market data (server \u2192 client)\n\nMarket updates are **single JSON objects** with the response fields below. They do **not** include a `type` property. The event code field **`ev`** is **`C`** for this feed. Only fields listed in the schema are sent on this feed.\n\n### Limits\n\n- Up to **50** tickers per WebSocket connection.\n- One connection per feed path per session is recommended.\n\n[WebSocket authentication guide](https://financialdata.online/api/docs/websocket/#authentication) \u00b7 [WebSocket overview](https://financialdata.online/api/docs/websocket/#overview)", "operationId": "ws_forex_C", "tags": ["Forex"], "x-wsEntitlement": {"minPlan": "Premium", "premiumLatencyTier": "realtime"}, "parameters": [{"name": "Authorization", "in": "header", "required": true, "description": "JWT access token from `POST /api/token/` as `Bearer <access>`.", "schema": {"type": "string"}, "example": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}, {"name": "Origin", "in": "header", "required": false, "description": "Required for CLI clients that do not send Origin by default (wscat, Postman). Use `https://api.financialdata.online`. Missing or disallowed Origin \u2192 HTTP **403** on handshake. Browsers send this automatically.", "schema": {"type": "string"}, "example": "https://api.financialdata.online"}], "responses": {"101": {"description": "WebSocket established. Server sends JSON text frames (control and market data).", "content": {"application/json": {"schema": {"oneOf": [{"type": "object", "title": "Subscription confirmation", "properties": {"type": {"type": "string", "enum": ["subscribed", "unsubscribed"]}, "tickers": {"type": "array", "items": {"type": "string"}, "description": "Tickers confirmed for the last subscribe or removed by the last unsubscribe."}}, "required": ["type", "tickers"]}, {"type": "object", "title": "Forex quotes", "description": "Market data update (no `type` field).", "properties": {"ev": {"type": "string", "description": "Event code for this feed (constant on every message for a given path)."}, "p": {"type": "string", "description": "Instrument pair or symbol (format depends on asset class)."}, "a": {"type": "number", "description": "Ask price (forex)."}, "b": {"type": "number", "description": "Bid price (forex)."}, "t": {"type": "integer", "description": "Event time (Unix milliseconds, UTC)."}}}, {"type": "object", "title": "Error", "description": "Protocol or auth error (no `type` field).", "properties": {"code": {"type": "string", "description": "Machine-readable error code (e.g. authentication_failed, unknown_feed, protocol_error)."}, "message": {"type": "string"}}, "required": ["code", "message"]}]}, "examples": {"subscribed": {"summary": "Subscription confirmation", "value": {"type": "subscribed", "tickers": ["EURUSD"]}}, "unsubscribed": {"summary": "Unsubscription confirmation", "value": {"type": "unsubscribed", "tickers": ["EURUSD"]}}, "data": {"summary": "Market data update", "value": {"ev": "C", "p": "EURUSD", "a": 182.63, "b": 182.63, "t": 1709312400000}}, "error": {"summary": "Client protocol error", "value": {"code": "protocol_error", "message": "'tickers' must be a non-empty list of strings."}}, "auth_error": {"summary": "Authentication failed (before close 4401)", "value": {"code": "authentication_failed", "message": "JWT is invalid or expired. Obtain a new access token via POST /api/token/."}}}}}}, "403": {"description": "Handshake rejected. Common cause: missing or disallowed `Origin` header (CLI clients must send `Origin: https://api.financialdata.online`). Distinct from post-connect close code `4401` (authentication failed after accept)."}}, "x-codeSamples": [{"lang": "Shell", "label": "wscat", "source": "wscat -c \"wss://api.financialdata.online/ws/forex/C/\" \\\n  -H \"Authorization: Bearer YOUR_JWT_ACCESS\" \\\n  -H \"Origin: https://api.financialdata.online\""}, {"lang": "Python", "label": "Python (websockets)", "source": "import asyncio, json, websockets\n\nasync def main():\n    uri = \"wss://api.financialdata.online/ws/forex/C/\"\n    headers = {\n        \"Authorization\": \"Bearer YOUR_JWT_ACCESS\",\n        \"Origin\": \"https://api.financialdata.online\",\n    }\n    async with websockets.connect(uri, additional_headers=headers) as ws:\n        await ws.send(json.dumps({\"action\": \"subscribe\", \"tickers\": [\"EURUSD\"]}))\n        async for msg in ws:\n            print(json.loads(msg))\n\nasyncio.run(main())"}]}}, "/ws/forex/CA/": {"get": {"summary": "Forex OHLC updates", "description": "Pushes OHLC updates for subscribed currency pairs on this connection.\n\n### Plan access\n\n- **Minimum plan:** `Premium`\n- **Premium latency:** `realtime`\n- **Pro:** not available on this feed (Premium only)\n\n### Connection\n\nOpen a **WebSocket** to this service (not an HTTP GET on the path below):\n\n```\nwss://api.financialdata.online/ws/forex/CA/\n```\n\n### Authentication\n\nSend **`Authorization: Bearer <JWT>`** on the upgrade request. Obtain an access token with **`POST /api/token/`** and use the JSON field **`access`**. CLI clients (wscat, Postman, many scripts) must also send **`Origin: https://api.financialdata.online`** \u2014 without it the handshake fails with **HTTP 403**. Browsers set `Origin` automatically. On auth failure you receive a JSON error frame first, then close code **`4401`** with a short `reason`.\n\n### Subscribe and unsubscribe\n\nAfter the connection is open, send UTF-8 JSON text frames:\n\n```json\n{\"action\": \"subscribe\", \"tickers\": [\"EURUSD\"]}\n```\n\n```json\n{\"action\": \"unsubscribe\", \"tickers\": [\"EURUSD\"]}\n```\n\nTicker symbols are normalized to **uppercase**. Subscription state is **per connection** and **per feed path** (this endpoint is **Forex OHLC updates**).\n\n### Control messages (server \u2192 client)\n\n#### Subscription acknowledgements\n\n| Field | Description |\n|---|---|\n| `type` | Always `subscribed` or `unsubscribed`. |\n| `tickers` | Tickers affected by the last action (full set after subscribe; removed set after unsubscribe). |\n\n#### Errors (JSON frame, then connection close)\n\n| Field | Description |\n|---|---|\n| `code` | Machine-readable code (e.g. `authentication_failed`, `protocol_error`, `unknown_feed`). Errors do **not** use a `type` field. |\n| `message` | Human-readable explanation. Authentication failures close with **`4401`** after this frame. |\n\n### Market data (server \u2192 client)\n\nMarket updates are **single JSON objects** with the response fields below. They do **not** include a `type` property. The event code field **`ev`** is **`CA`** for this feed. Only fields listed in the schema are sent on this feed.\n\n### Limits\n\n- Up to **50** tickers per WebSocket connection.\n- One connection per feed path per session is recommended.\n\n[WebSocket authentication guide](https://financialdata.online/api/docs/websocket/#authentication) \u00b7 [WebSocket overview](https://financialdata.online/api/docs/websocket/#overview)", "operationId": "ws_forex_CA", "tags": ["Forex"], "x-wsEntitlement": {"minPlan": "Premium", "premiumLatencyTier": "realtime"}, "parameters": [{"name": "Authorization", "in": "header", "required": true, "description": "JWT access token from `POST /api/token/` as `Bearer <access>`.", "schema": {"type": "string"}, "example": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}, {"name": "Origin", "in": "header", "required": false, "description": "Required for CLI clients that do not send Origin by default (wscat, Postman). Use `https://api.financialdata.online`. Missing or disallowed Origin \u2192 HTTP **403** on handshake. Browsers send this automatically.", "schema": {"type": "string"}, "example": "https://api.financialdata.online"}], "responses": {"101": {"description": "WebSocket established. Server sends JSON text frames (control and market data).", "content": {"application/json": {"schema": {"oneOf": [{"type": "object", "title": "Subscription confirmation", "properties": {"type": {"type": "string", "enum": ["subscribed", "unsubscribed"]}, "tickers": {"type": "array", "items": {"type": "string"}, "description": "Tickers confirmed for the last subscribe or removed by the last unsubscribe."}}, "required": ["type", "tickers"]}, {"type": "object", "title": "Forex OHLC updates", "description": "Market data update (no `type` field).", "properties": {"ev": {"type": "string", "description": "Event code for this feed (constant on every message for a given path)."}, "pair": {"type": "string", "description": "Instrument pair or symbol (format depends on asset class)."}, "o": {"type": "number", "description": "Opening price for the update."}, "c": {"type": "number", "description": "Closing / last price for the update."}, "h": {"type": "number", "description": "High price for the update."}, "l": {"type": "number", "description": "Low price for the update."}, "v": {"type": "integer", "description": "Reported volume for the update."}, "s": {"type": "integer", "description": "Update start time (Unix milliseconds, UTC)."}, "e": {"type": "integer", "description": "Update end time (Unix milliseconds, UTC)."}}}, {"type": "object", "title": "Error", "description": "Protocol or auth error (no `type` field).", "properties": {"code": {"type": "string", "description": "Machine-readable error code (e.g. authentication_failed, unknown_feed, protocol_error)."}, "message": {"type": "string"}}, "required": ["code", "message"]}]}, "examples": {"subscribed": {"summary": "Subscription confirmation", "value": {"type": "subscribed", "tickers": ["EURUSD"]}}, "unsubscribed": {"summary": "Unsubscription confirmation", "value": {"type": "unsubscribed", "tickers": ["EURUSD"]}}, "data": {"summary": "Market data update", "value": {"ev": "CA", "pair": "EURUSD", "o": 182.63, "c": 182.63, "h": 182.63, "l": 182.63, "v": 1500, "s": 1709312400000, "e": 1709312400000}}, "error": {"summary": "Client protocol error", "value": {"code": "protocol_error", "message": "'tickers' must be a non-empty list of strings."}}, "auth_error": {"summary": "Authentication failed (before close 4401)", "value": {"code": "authentication_failed", "message": "JWT is invalid or expired. Obtain a new access token via POST /api/token/."}}}}}}, "403": {"description": "Handshake rejected. Common cause: missing or disallowed `Origin` header (CLI clients must send `Origin: https://api.financialdata.online`). Distinct from post-connect close code `4401` (authentication failed after accept)."}}, "x-codeSamples": [{"lang": "Shell", "label": "wscat", "source": "wscat -c \"wss://api.financialdata.online/ws/forex/CA/\" \\\n  -H \"Authorization: Bearer YOUR_JWT_ACCESS\" \\\n  -H \"Origin: https://api.financialdata.online\""}, {"lang": "Python", "label": "Python (websockets)", "source": "import asyncio, json, websockets\n\nasync def main():\n    uri = \"wss://api.financialdata.online/ws/forex/CA/\"\n    headers = {\n        \"Authorization\": \"Bearer YOUR_JWT_ACCESS\",\n        \"Origin\": \"https://api.financialdata.online\",\n    }\n    async with websockets.connect(uri, additional_headers=headers) as ws:\n        await ws.send(json.dumps({\"action\": \"subscribe\", \"tickers\": [\"EURUSD\"]}))\n        async for msg in ws:\n            print(json.loads(msg))\n\nasyncio.run(main())"}]}}, "/ws/forex/CAS/": {"get": {"summary": "Forex OHLC updates", "description": "Pushes OHLC updates for subscribed currency pairs on this connection.\n\n### Plan access\n\n- **Minimum plan:** `Premium`\n- **Premium latency:** `realtime`\n- **Pro:** not available on this feed (Premium only)\n\n### Connection\n\nOpen a **WebSocket** to this service (not an HTTP GET on the path below):\n\n```\nwss://api.financialdata.online/ws/forex/CAS/\n```\n\n### Authentication\n\nSend **`Authorization: Bearer <JWT>`** on the upgrade request. Obtain an access token with **`POST /api/token/`** and use the JSON field **`access`**. CLI clients (wscat, Postman, many scripts) must also send **`Origin: https://api.financialdata.online`** \u2014 without it the handshake fails with **HTTP 403**. Browsers set `Origin` automatically. On auth failure you receive a JSON error frame first, then close code **`4401`** with a short `reason`.\n\n### Subscribe and unsubscribe\n\nAfter the connection is open, send UTF-8 JSON text frames:\n\n```json\n{\"action\": \"subscribe\", \"tickers\": [\"EURUSD\"]}\n```\n\n```json\n{\"action\": \"unsubscribe\", \"tickers\": [\"EURUSD\"]}\n```\n\nTicker symbols are normalized to **uppercase**. Subscription state is **per connection** and **per feed path** (this endpoint is **Forex OHLC updates**).\n\n### Control messages (server \u2192 client)\n\n#### Subscription acknowledgements\n\n| Field | Description |\n|---|---|\n| `type` | Always `subscribed` or `unsubscribed`. |\n| `tickers` | Tickers affected by the last action (full set after subscribe; removed set after unsubscribe). |\n\n#### Errors (JSON frame, then connection close)\n\n| Field | Description |\n|---|---|\n| `code` | Machine-readable code (e.g. `authentication_failed`, `protocol_error`, `unknown_feed`). Errors do **not** use a `type` field. |\n| `message` | Human-readable explanation. Authentication failures close with **`4401`** after this frame. |\n\n### Market data (server \u2192 client)\n\nMarket updates are **single JSON objects** with the response fields below. They do **not** include a `type` property. The event code field **`ev`** is **`CAS`** for this feed. Only fields listed in the schema are sent on this feed.\n\n### Limits\n\n- Up to **50** tickers per WebSocket connection.\n- One connection per feed path per session is recommended.\n\n[WebSocket authentication guide](https://financialdata.online/api/docs/websocket/#authentication) \u00b7 [WebSocket overview](https://financialdata.online/api/docs/websocket/#overview)", "operationId": "ws_forex_CAS", "tags": ["Forex"], "x-wsEntitlement": {"minPlan": "Premium", "premiumLatencyTier": "realtime"}, "parameters": [{"name": "Authorization", "in": "header", "required": true, "description": "JWT access token from `POST /api/token/` as `Bearer <access>`.", "schema": {"type": "string"}, "example": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}, {"name": "Origin", "in": "header", "required": false, "description": "Required for CLI clients that do not send Origin by default (wscat, Postman). Use `https://api.financialdata.online`. Missing or disallowed Origin \u2192 HTTP **403** on handshake. Browsers send this automatically.", "schema": {"type": "string"}, "example": "https://api.financialdata.online"}], "responses": {"101": {"description": "WebSocket established. Server sends JSON text frames (control and market data).", "content": {"application/json": {"schema": {"oneOf": [{"type": "object", "title": "Subscription confirmation", "properties": {"type": {"type": "string", "enum": ["subscribed", "unsubscribed"]}, "tickers": {"type": "array", "items": {"type": "string"}, "description": "Tickers confirmed for the last subscribe or removed by the last unsubscribe."}}, "required": ["type", "tickers"]}, {"type": "object", "title": "Forex OHLC updates", "description": "Market data update (no `type` field).", "properties": {"ev": {"type": "string", "description": "Event code for this feed (constant on every message for a given path)."}, "pair": {"type": "string", "description": "Instrument pair or symbol (format depends on asset class)."}, "o": {"type": "number", "description": "Opening price for the update."}, "c": {"type": "number", "description": "Closing / last price for the update."}, "h": {"type": "number", "description": "High price for the update."}, "l": {"type": "number", "description": "Low price for the update."}, "v": {"type": "integer", "description": "Reported volume for the update."}, "s": {"type": "integer", "description": "Update start time (Unix milliseconds, UTC)."}, "e": {"type": "integer", "description": "Update end time (Unix milliseconds, UTC)."}}}, {"type": "object", "title": "Error", "description": "Protocol or auth error (no `type` field).", "properties": {"code": {"type": "string", "description": "Machine-readable error code (e.g. authentication_failed, unknown_feed, protocol_error)."}, "message": {"type": "string"}}, "required": ["code", "message"]}]}, "examples": {"subscribed": {"summary": "Subscription confirmation", "value": {"type": "subscribed", "tickers": ["EURUSD"]}}, "unsubscribed": {"summary": "Unsubscription confirmation", "value": {"type": "unsubscribed", "tickers": ["EURUSD"]}}, "data": {"summary": "Market data update", "value": {"ev": "CAS", "pair": "EURUSD", "o": 182.63, "c": 182.63, "h": 182.63, "l": 182.63, "v": 1500, "s": 1709312400000, "e": 1709312400000}}, "error": {"summary": "Client protocol error", "value": {"code": "protocol_error", "message": "'tickers' must be a non-empty list of strings."}}, "auth_error": {"summary": "Authentication failed (before close 4401)", "value": {"code": "authentication_failed", "message": "JWT is invalid or expired. Obtain a new access token via POST /api/token/."}}}}}}, "403": {"description": "Handshake rejected. Common cause: missing or disallowed `Origin` header (CLI clients must send `Origin: https://api.financialdata.online`). Distinct from post-connect close code `4401` (authentication failed after accept)."}}, "x-codeSamples": [{"lang": "Shell", "label": "wscat", "source": "wscat -c \"wss://api.financialdata.online/ws/forex/CAS/\" \\\n  -H \"Authorization: Bearer YOUR_JWT_ACCESS\" \\\n  -H \"Origin: https://api.financialdata.online\""}, {"lang": "Python", "label": "Python (websockets)", "source": "import asyncio, json, websockets\n\nasync def main():\n    uri = \"wss://api.financialdata.online/ws/forex/CAS/\"\n    headers = {\n        \"Authorization\": \"Bearer YOUR_JWT_ACCESS\",\n        \"Origin\": \"https://api.financialdata.online\",\n    }\n    async with websockets.connect(uri, additional_headers=headers) as ws:\n        await ws.send(json.dumps({\"action\": \"subscribe\", \"tickers\": [\"EURUSD\"]}))\n        async for msg in ws:\n            print(json.loads(msg))\n\nasyncio.run(main())"}]}}, "/ws/stocks/A/": {"get": {"summary": "Stock OHLCV updates", "description": "Pushes session OHLCV updates (open, high, low, close, volume) for subscribed US equity tickers. **Pro** receives ~15-minute delayed updates; **Premium** receives current updates.\n\n### Plan access\n\n- **Minimum plan:** `Pro`\n- **Premium latency:** `realtime`\n- **Pro latency (this feed):** `delayed` (~15 minutes behind current updates)\n\n### Connection\n\nOpen a **WebSocket** to this service (not an HTTP GET on the path below):\n\n```\nwss://api.financialdata.online/ws/stocks/A/\n```\n\n### Authentication\n\nSend **`Authorization: Bearer <JWT>`** on the upgrade request. Obtain an access token with **`POST /api/token/`** and use the JSON field **`access`**. CLI clients (wscat, Postman, many scripts) must also send **`Origin: https://api.financialdata.online`** \u2014 without it the handshake fails with **HTTP 403**. Browsers set `Origin` automatically. On auth failure you receive a JSON error frame first, then close code **`4401`** with a short `reason`.\n\n### Subscribe and unsubscribe\n\nAfter the connection is open, send UTF-8 JSON text frames:\n\n```json\n{\"action\": \"subscribe\", \"tickers\": [\"AAPL\"]}\n```\n\n```json\n{\"action\": \"unsubscribe\", \"tickers\": [\"AAPL\"]}\n```\n\nTicker symbols are normalized to **uppercase**. Subscription state is **per connection** and **per feed path** (this endpoint is **Stock OHLCV updates**).\n\n### Control messages (server \u2192 client)\n\n#### Subscription acknowledgements\n\n| Field | Description |\n|---|---|\n| `type` | Always `subscribed` or `unsubscribed`. |\n| `tickers` | Tickers affected by the last action (full set after subscribe; removed set after unsubscribe). |\n\n#### Errors (JSON frame, then connection close)\n\n| Field | Description |\n|---|---|\n| `code` | Machine-readable code (e.g. `authentication_failed`, `protocol_error`, `unknown_feed`). Errors do **not** use a `type` field. |\n| `message` | Human-readable explanation. Authentication failures close with **`4401`** after this frame. |\n\n### Market data (server \u2192 client)\n\nMarket updates are **single JSON objects** with the response fields below. They do **not** include a `type` property. The event code field **`ev`** is **`A`** for this feed. Only fields listed in the schema are sent on this feed.\n\n### Limits\n\n- Up to **50** tickers per WebSocket connection.\n- One connection per feed path per session is recommended.\n\n[WebSocket authentication guide](https://financialdata.online/api/docs/websocket/#authentication) \u00b7 [WebSocket overview](https://financialdata.online/api/docs/websocket/#overview)", "operationId": "ws_stocks_A", "tags": ["Stocks"], "x-wsEntitlement": {"minPlan": "Pro", "premiumLatencyTier": "realtime", "proLatencyTier": "delayed"}, "parameters": [{"name": "Authorization", "in": "header", "required": true, "description": "JWT access token from `POST /api/token/` as `Bearer <access>`.", "schema": {"type": "string"}, "example": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}, {"name": "Origin", "in": "header", "required": false, "description": "Required for CLI clients that do not send Origin by default (wscat, Postman). Use `https://api.financialdata.online`. Missing or disallowed Origin \u2192 HTTP **403** on handshake. Browsers send this automatically.", "schema": {"type": "string"}, "example": "https://api.financialdata.online"}], "responses": {"101": {"description": "WebSocket established. Server sends JSON text frames (control and market data).", "content": {"application/json": {"schema": {"oneOf": [{"type": "object", "title": "Subscription confirmation", "properties": {"type": {"type": "string", "enum": ["subscribed", "unsubscribed"]}, "tickers": {"type": "array", "items": {"type": "string"}, "description": "Tickers confirmed for the last subscribe or removed by the last unsubscribe."}}, "required": ["type", "tickers"]}, {"type": "object", "title": "Stock OHLCV updates", "description": "Market data update (no `type` field).", "properties": {"ev": {"type": "string", "description": "Event code for this feed (constant on every message for a given path)."}, "sym": {"type": "string", "description": "Listed ticker symbol (US stocks: e.g. `AAPL`)."}, "v": {"type": "integer", "description": "Reported volume for the update."}, "o": {"type": "number", "description": "Opening price for the update."}, "c": {"type": "number", "description": "Closing / last price for the update."}, "h": {"type": "number", "description": "High price for the update."}, "l": {"type": "number", "description": "Low price for the update."}, "s": {"type": "integer", "description": "Update start time (Unix milliseconds, UTC)."}, "e": {"type": "integer", "description": "Update end time (Unix milliseconds, UTC)."}}}, {"type": "object", "title": "Error", "description": "Protocol or auth error (no `type` field).", "properties": {"code": {"type": "string", "description": "Machine-readable error code (e.g. authentication_failed, unknown_feed, protocol_error)."}, "message": {"type": "string"}}, "required": ["code", "message"]}]}, "examples": {"subscribed": {"summary": "Subscription confirmation", "value": {"type": "subscribed", "tickers": ["AAPL"]}}, "unsubscribed": {"summary": "Unsubscription confirmation", "value": {"type": "unsubscribed", "tickers": ["AAPL"]}}, "data": {"summary": "Market data update", "value": {"ev": "A", "sym": "AAPL", "v": 1500, "o": 182.63, "c": 182.63, "h": 182.63, "l": 182.63, "s": 1709312400000, "e": 1709312400000}}, "error": {"summary": "Client protocol error", "value": {"code": "protocol_error", "message": "'tickers' must be a non-empty list of strings."}}, "auth_error": {"summary": "Authentication failed (before close 4401)", "value": {"code": "authentication_failed", "message": "JWT is invalid or expired. Obtain a new access token via POST /api/token/."}}}}}}, "403": {"description": "Handshake rejected. Common cause: missing or disallowed `Origin` header (CLI clients must send `Origin: https://api.financialdata.online`). Distinct from post-connect close code `4401` (authentication failed after accept)."}}, "x-codeSamples": [{"lang": "Shell", "label": "wscat", "source": "wscat -c \"wss://api.financialdata.online/ws/stocks/A/\" \\\n  -H \"Authorization: Bearer YOUR_JWT_ACCESS\" \\\n  -H \"Origin: https://api.financialdata.online\""}, {"lang": "Python", "label": "Python (websockets)", "source": "import asyncio, json, websockets\n\nasync def main():\n    uri = \"wss://api.financialdata.online/ws/stocks/A/\"\n    headers = {\n        \"Authorization\": \"Bearer YOUR_JWT_ACCESS\",\n        \"Origin\": \"https://api.financialdata.online\",\n    }\n    async with websockets.connect(uri, additional_headers=headers) as ws:\n        await ws.send(json.dumps({\"action\": \"subscribe\", \"tickers\": [\"AAPL\"]}))\n        async for msg in ws:\n            print(json.loads(msg))\n\nasyncio.run(main())"}]}}, "/ws/stocks/AM/": {"get": {"summary": "Stock OHLCV updates", "description": "Pushes session OHLCV updates (open, high, low, close, volume) for subscribed US equity tickers. **Pro** receives ~15-minute delayed updates; **Premium** receives current updates.\n\n### Plan access\n\n- **Minimum plan:** `Pro`\n- **Premium latency:** `realtime`\n- **Pro latency (this feed):** `delayed` (~15 minutes behind current updates)\n\n### Connection\n\nOpen a **WebSocket** to this service (not an HTTP GET on the path below):\n\n```\nwss://api.financialdata.online/ws/stocks/AM/\n```\n\n### Authentication\n\nSend **`Authorization: Bearer <JWT>`** on the upgrade request. Obtain an access token with **`POST /api/token/`** and use the JSON field **`access`**. CLI clients (wscat, Postman, many scripts) must also send **`Origin: https://api.financialdata.online`** \u2014 without it the handshake fails with **HTTP 403**. Browsers set `Origin` automatically. On auth failure you receive a JSON error frame first, then close code **`4401`** with a short `reason`.\n\n### Subscribe and unsubscribe\n\nAfter the connection is open, send UTF-8 JSON text frames:\n\n```json\n{\"action\": \"subscribe\", \"tickers\": [\"AAPL\"]}\n```\n\n```json\n{\"action\": \"unsubscribe\", \"tickers\": [\"AAPL\"]}\n```\n\nTicker symbols are normalized to **uppercase**. Subscription state is **per connection** and **per feed path** (this endpoint is **Stock OHLCV updates**).\n\n### Control messages (server \u2192 client)\n\n#### Subscription acknowledgements\n\n| Field | Description |\n|---|---|\n| `type` | Always `subscribed` or `unsubscribed`. |\n| `tickers` | Tickers affected by the last action (full set after subscribe; removed set after unsubscribe). |\n\n#### Errors (JSON frame, then connection close)\n\n| Field | Description |\n|---|---|\n| `code` | Machine-readable code (e.g. `authentication_failed`, `protocol_error`, `unknown_feed`). Errors do **not** use a `type` field. |\n| `message` | Human-readable explanation. Authentication failures close with **`4401`** after this frame. |\n\n### Market data (server \u2192 client)\n\nMarket updates are **single JSON objects** with the response fields below. They do **not** include a `type` property. The event code field **`ev`** is **`AM`** for this feed. Only fields listed in the schema are sent on this feed.\n\n### Limits\n\n- Up to **50** tickers per WebSocket connection.\n- One connection per feed path per session is recommended.\n\n[WebSocket authentication guide](https://financialdata.online/api/docs/websocket/#authentication) \u00b7 [WebSocket overview](https://financialdata.online/api/docs/websocket/#overview)", "operationId": "ws_stocks_AM", "tags": ["Stocks"], "x-wsEntitlement": {"minPlan": "Pro", "premiumLatencyTier": "realtime", "proLatencyTier": "delayed"}, "parameters": [{"name": "Authorization", "in": "header", "required": true, "description": "JWT access token from `POST /api/token/` as `Bearer <access>`.", "schema": {"type": "string"}, "example": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}, {"name": "Origin", "in": "header", "required": false, "description": "Required for CLI clients that do not send Origin by default (wscat, Postman). Use `https://api.financialdata.online`. Missing or disallowed Origin \u2192 HTTP **403** on handshake. Browsers send this automatically.", "schema": {"type": "string"}, "example": "https://api.financialdata.online"}], "responses": {"101": {"description": "WebSocket established. Server sends JSON text frames (control and market data).", "content": {"application/json": {"schema": {"oneOf": [{"type": "object", "title": "Subscription confirmation", "properties": {"type": {"type": "string", "enum": ["subscribed", "unsubscribed"]}, "tickers": {"type": "array", "items": {"type": "string"}, "description": "Tickers confirmed for the last subscribe or removed by the last unsubscribe."}}, "required": ["type", "tickers"]}, {"type": "object", "title": "Stock OHLCV updates", "description": "Market data update (no `type` field).", "properties": {"ev": {"type": "string", "description": "Event code for this feed (constant on every message for a given path)."}, "sym": {"type": "string", "description": "Listed ticker symbol (US stocks: e.g. `AAPL`)."}, "v": {"type": "integer", "description": "Reported volume for the update."}, "o": {"type": "number", "description": "Opening price for the update."}, "c": {"type": "number", "description": "Closing / last price for the update."}, "h": {"type": "number", "description": "High price for the update."}, "l": {"type": "number", "description": "Low price for the update."}, "s": {"type": "integer", "description": "Update start time (Unix milliseconds, UTC)."}, "e": {"type": "integer", "description": "Update end time (Unix milliseconds, UTC)."}}}, {"type": "object", "title": "Error", "description": "Protocol or auth error (no `type` field).", "properties": {"code": {"type": "string", "description": "Machine-readable error code (e.g. authentication_failed, unknown_feed, protocol_error)."}, "message": {"type": "string"}}, "required": ["code", "message"]}]}, "examples": {"subscribed": {"summary": "Subscription confirmation", "value": {"type": "subscribed", "tickers": ["AAPL"]}}, "unsubscribed": {"summary": "Unsubscription confirmation", "value": {"type": "unsubscribed", "tickers": ["AAPL"]}}, "data": {"summary": "Market data update", "value": {"ev": "AM", "sym": "AAPL", "v": 1500, "o": 182.63, "c": 182.63, "h": 182.63, "l": 182.63, "s": 1709312400000, "e": 1709312400000}}, "error": {"summary": "Client protocol error", "value": {"code": "protocol_error", "message": "'tickers' must be a non-empty list of strings."}}, "auth_error": {"summary": "Authentication failed (before close 4401)", "value": {"code": "authentication_failed", "message": "JWT is invalid or expired. Obtain a new access token via POST /api/token/."}}}}}}, "403": {"description": "Handshake rejected. Common cause: missing or disallowed `Origin` header (CLI clients must send `Origin: https://api.financialdata.online`). Distinct from post-connect close code `4401` (authentication failed after accept)."}}, "x-codeSamples": [{"lang": "Shell", "label": "wscat", "source": "wscat -c \"wss://api.financialdata.online/ws/stocks/AM/\" \\\n  -H \"Authorization: Bearer YOUR_JWT_ACCESS\" \\\n  -H \"Origin: https://api.financialdata.online\""}, {"lang": "Python", "label": "Python (websockets)", "source": "import asyncio, json, websockets\n\nasync def main():\n    uri = \"wss://api.financialdata.online/ws/stocks/AM/\"\n    headers = {\n        \"Authorization\": \"Bearer YOUR_JWT_ACCESS\",\n        \"Origin\": \"https://api.financialdata.online\",\n    }\n    async with websockets.connect(uri, additional_headers=headers) as ws:\n        await ws.send(json.dumps({\"action\": \"subscribe\", \"tickers\": [\"AAPL\"]}))\n        async for msg in ws:\n            print(json.loads(msg))\n\nasyncio.run(main())"}]}}, "/ws/stocks/Q/": {"get": {"summary": "Stock quotes", "description": "Pushes quote updates for subscribed US equity tickers on this connection.\n\n### Plan access\n\n- **Minimum plan:** `Premium`\n- **Premium latency:** `realtime`\n- **Pro:** not available on this feed (Premium only)\n\n### Connection\n\nOpen a **WebSocket** to this service (not an HTTP GET on the path below):\n\n```\nwss://api.financialdata.online/ws/stocks/Q/\n```\n\n### Authentication\n\nSend **`Authorization: Bearer <JWT>`** on the upgrade request. Obtain an access token with **`POST /api/token/`** and use the JSON field **`access`**. CLI clients (wscat, Postman, many scripts) must also send **`Origin: https://api.financialdata.online`** \u2014 without it the handshake fails with **HTTP 403**. Browsers set `Origin` automatically. On auth failure you receive a JSON error frame first, then close code **`4401`** with a short `reason`.\n\n### Subscribe and unsubscribe\n\nAfter the connection is open, send UTF-8 JSON text frames:\n\n```json\n{\"action\": \"subscribe\", \"tickers\": [\"AAPL\"]}\n```\n\n```json\n{\"action\": \"unsubscribe\", \"tickers\": [\"AAPL\"]}\n```\n\nTicker symbols are normalized to **uppercase**. Subscription state is **per connection** and **per feed path** (this endpoint is **Stock quotes**).\n\n### Control messages (server \u2192 client)\n\n#### Subscription acknowledgements\n\n| Field | Description |\n|---|---|\n| `type` | Always `subscribed` or `unsubscribed`. |\n| `tickers` | Tickers affected by the last action (full set after subscribe; removed set after unsubscribe). |\n\n#### Errors (JSON frame, then connection close)\n\n| Field | Description |\n|---|---|\n| `code` | Machine-readable code (e.g. `authentication_failed`, `protocol_error`, `unknown_feed`). Errors do **not** use a `type` field. |\n| `message` | Human-readable explanation. Authentication failures close with **`4401`** after this frame. |\n\n### Market data (server \u2192 client)\n\nMarket updates are **single JSON objects** with the response fields below. They do **not** include a `type` property. The event code field **`ev`** is **`Q`** for this feed. Only fields listed in the schema are sent on this feed.\n\n### Limits\n\n- Up to **50** tickers per WebSocket connection.\n- One connection per feed path per session is recommended.\n\n[WebSocket authentication guide](https://financialdata.online/api/docs/websocket/#authentication) \u00b7 [WebSocket overview](https://financialdata.online/api/docs/websocket/#overview)", "operationId": "ws_stocks_Q", "tags": ["Stocks"], "x-wsEntitlement": {"minPlan": "Premium", "premiumLatencyTier": "realtime"}, "parameters": [{"name": "Authorization", "in": "header", "required": true, "description": "JWT access token from `POST /api/token/` as `Bearer <access>`.", "schema": {"type": "string"}, "example": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}, {"name": "Origin", "in": "header", "required": false, "description": "Required for CLI clients that do not send Origin by default (wscat, Postman). Use `https://api.financialdata.online`. Missing or disallowed Origin \u2192 HTTP **403** on handshake. Browsers send this automatically.", "schema": {"type": "string"}, "example": "https://api.financialdata.online"}], "responses": {"101": {"description": "WebSocket established. Server sends JSON text frames (control and market data).", "content": {"application/json": {"schema": {"oneOf": [{"type": "object", "title": "Subscription confirmation", "properties": {"type": {"type": "string", "enum": ["subscribed", "unsubscribed"]}, "tickers": {"type": "array", "items": {"type": "string"}, "description": "Tickers confirmed for the last subscribe or removed by the last unsubscribe."}}, "required": ["type", "tickers"]}, {"type": "object", "title": "Stock quotes", "description": "Market data update (no `type` field).", "properties": {"ev": {"type": "string", "description": "Event code for this feed (constant on every message for a given path)."}, "sym": {"type": "string", "description": "Listed ticker symbol (US stocks: e.g. `AAPL`)."}, "bp": {"type": "number", "description": "Bid price on this update."}, "ap": {"type": "number", "description": "Ask price on this update."}, "t": {"type": "integer", "description": "Event time (Unix milliseconds, UTC)."}}}, {"type": "object", "title": "Error", "description": "Protocol or auth error (no `type` field).", "properties": {"code": {"type": "string", "description": "Machine-readable error code (e.g. authentication_failed, unknown_feed, protocol_error)."}, "message": {"type": "string"}}, "required": ["code", "message"]}]}, "examples": {"subscribed": {"summary": "Subscription confirmation", "value": {"type": "subscribed", "tickers": ["AAPL"]}}, "unsubscribed": {"summary": "Unsubscription confirmation", "value": {"type": "unsubscribed", "tickers": ["AAPL"]}}, "data": {"summary": "Market data update", "value": {"ev": "Q", "sym": "AAPL", "bp": 182.63, "ap": 182.63, "t": 1709312400000}}, "error": {"summary": "Client protocol error", "value": {"code": "protocol_error", "message": "'tickers' must be a non-empty list of strings."}}, "auth_error": {"summary": "Authentication failed (before close 4401)", "value": {"code": "authentication_failed", "message": "JWT is invalid or expired. Obtain a new access token via POST /api/token/."}}}}}}, "403": {"description": "Handshake rejected. Common cause: missing or disallowed `Origin` header (CLI clients must send `Origin: https://api.financialdata.online`). Distinct from post-connect close code `4401` (authentication failed after accept)."}}, "x-codeSamples": [{"lang": "Shell", "label": "wscat", "source": "wscat -c \"wss://api.financialdata.online/ws/stocks/Q/\" \\\n  -H \"Authorization: Bearer YOUR_JWT_ACCESS\" \\\n  -H \"Origin: https://api.financialdata.online\""}, {"lang": "Python", "label": "Python (websockets)", "source": "import asyncio, json, websockets\n\nasync def main():\n    uri = \"wss://api.financialdata.online/ws/stocks/Q/\"\n    headers = {\n        \"Authorization\": \"Bearer YOUR_JWT_ACCESS\",\n        \"Origin\": \"https://api.financialdata.online\",\n    }\n    async with websockets.connect(uri, additional_headers=headers) as ws:\n        await ws.send(json.dumps({\"action\": \"subscribe\", \"tickers\": [\"AAPL\"]}))\n        async for msg in ws:\n            print(json.loads(msg))\n\nasyncio.run(main())"}]}}, "/ws/stocks/T/": {"get": {"summary": "Stock trade prices", "description": "Pushes trade price updates for subscribed US equity tickers on this connection.\n\n### Plan access\n\n- **Minimum plan:** `Premium`\n- **Premium latency:** `realtime`\n- **Pro:** not available on this feed (Premium only)\n\n### Connection\n\nOpen a **WebSocket** to this service (not an HTTP GET on the path below):\n\n```\nwss://api.financialdata.online/ws/stocks/T/\n```\n\n### Authentication\n\nSend **`Authorization: Bearer <JWT>`** on the upgrade request. Obtain an access token with **`POST /api/token/`** and use the JSON field **`access`**. CLI clients (wscat, Postman, many scripts) must also send **`Origin: https://api.financialdata.online`** \u2014 without it the handshake fails with **HTTP 403**. Browsers set `Origin` automatically. On auth failure you receive a JSON error frame first, then close code **`4401`** with a short `reason`.\n\n### Subscribe and unsubscribe\n\nAfter the connection is open, send UTF-8 JSON text frames:\n\n```json\n{\"action\": \"subscribe\", \"tickers\": [\"AAPL\"]}\n```\n\n```json\n{\"action\": \"unsubscribe\", \"tickers\": [\"AAPL\"]}\n```\n\nTicker symbols are normalized to **uppercase**. Subscription state is **per connection** and **per feed path** (this endpoint is **Stock trade prices**).\n\n### Control messages (server \u2192 client)\n\n#### Subscription acknowledgements\n\n| Field | Description |\n|---|---|\n| `type` | Always `subscribed` or `unsubscribed`. |\n| `tickers` | Tickers affected by the last action (full set after subscribe; removed set after unsubscribe). |\n\n#### Errors (JSON frame, then connection close)\n\n| Field | Description |\n|---|---|\n| `code` | Machine-readable code (e.g. `authentication_failed`, `protocol_error`, `unknown_feed`). Errors do **not** use a `type` field. |\n| `message` | Human-readable explanation. Authentication failures close with **`4401`** after this frame. |\n\n### Market data (server \u2192 client)\n\nMarket updates are **single JSON objects** with the response fields below. They do **not** include a `type` property. The event code field **`ev`** is **`T`** for this feed. Only fields listed in the schema are sent on this feed.\n\n### Limits\n\n- Up to **50** tickers per WebSocket connection.\n- One connection per feed path per session is recommended.\n\n[WebSocket authentication guide](https://financialdata.online/api/docs/websocket/#authentication) \u00b7 [WebSocket overview](https://financialdata.online/api/docs/websocket/#overview)", "operationId": "ws_stocks_T", "tags": ["Stocks"], "x-wsEntitlement": {"minPlan": "Premium", "premiumLatencyTier": "realtime"}, "parameters": [{"name": "Authorization", "in": "header", "required": true, "description": "JWT access token from `POST /api/token/` as `Bearer <access>`.", "schema": {"type": "string"}, "example": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}, {"name": "Origin", "in": "header", "required": false, "description": "Required for CLI clients that do not send Origin by default (wscat, Postman). Use `https://api.financialdata.online`. Missing or disallowed Origin \u2192 HTTP **403** on handshake. Browsers send this automatically.", "schema": {"type": "string"}, "example": "https://api.financialdata.online"}], "responses": {"101": {"description": "WebSocket established. Server sends JSON text frames (control and market data).", "content": {"application/json": {"schema": {"oneOf": [{"type": "object", "title": "Subscription confirmation", "properties": {"type": {"type": "string", "enum": ["subscribed", "unsubscribed"]}, "tickers": {"type": "array", "items": {"type": "string"}, "description": "Tickers confirmed for the last subscribe or removed by the last unsubscribe."}}, "required": ["type", "tickers"]}, {"type": "object", "title": "Stock trade prices", "description": "Market data update (no `type` field).", "properties": {"ev": {"type": "string", "description": "Event code for this feed (constant on every message for a given path)."}, "sym": {"type": "string", "description": "Listed ticker symbol (US stocks: e.g. `AAPL`)."}, "p": {"type": "number", "description": "Last trade price."}, "s": {"type": "integer", "description": "Size associated with the update (shares/contracts when provided)."}, "t": {"type": "integer", "description": "Event time (Unix milliseconds, UTC)."}}}, {"type": "object", "title": "Error", "description": "Protocol or auth error (no `type` field).", "properties": {"code": {"type": "string", "description": "Machine-readable error code (e.g. authentication_failed, unknown_feed, protocol_error)."}, "message": {"type": "string"}}, "required": ["code", "message"]}]}, "examples": {"subscribed": {"summary": "Subscription confirmation", "value": {"type": "subscribed", "tickers": ["AAPL"]}}, "unsubscribed": {"summary": "Unsubscription confirmation", "value": {"type": "unsubscribed", "tickers": ["AAPL"]}}, "data": {"summary": "Market data update", "value": {"ev": "T", "sym": "AAPL", "p": 182.63, "s": 1500, "t": 1709312400000}}, "error": {"summary": "Client protocol error", "value": {"code": "protocol_error", "message": "'tickers' must be a non-empty list of strings."}}, "auth_error": {"summary": "Authentication failed (before close 4401)", "value": {"code": "authentication_failed", "message": "JWT is invalid or expired. Obtain a new access token via POST /api/token/."}}}}}}, "403": {"description": "Handshake rejected. Common cause: missing or disallowed `Origin` header (CLI clients must send `Origin: https://api.financialdata.online`). Distinct from post-connect close code `4401` (authentication failed after accept)."}}, "x-codeSamples": [{"lang": "Shell", "label": "wscat", "source": "wscat -c \"wss://api.financialdata.online/ws/stocks/T/\" \\\n  -H \"Authorization: Bearer YOUR_JWT_ACCESS\" \\\n  -H \"Origin: https://api.financialdata.online\""}, {"lang": "Python", "label": "Python (websockets)", "source": "import asyncio, json, websockets\n\nasync def main():\n    uri = \"wss://api.financialdata.online/ws/stocks/T/\"\n    headers = {\n        \"Authorization\": \"Bearer YOUR_JWT_ACCESS\",\n        \"Origin\": \"https://api.financialdata.online\",\n    }\n    async with websockets.connect(uri, additional_headers=headers) as ws:\n        await ws.send(json.dumps({\"action\": \"subscribe\", \"tickers\": [\"AAPL\"]}))\n        async for msg in ws:\n            print(json.loads(msg))\n\nasyncio.run(main())"}]}}}, "components": {"securitySchemes": {"BearerJWT": {"type": "http", "scheme": "bearer", "bearerFormat": "JWT", "description": "JWT access token from `POST /api/token/`. Send as `Authorization: Bearer <access>` on the WebSocket handshake."}}}, "security": [{"BearerJWT": []}]}