{"templateId":"markdown","sharedDataIds":{},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"type":"markdown"},"seo":{"title":"Subscribing to Channels","description":"Write your own software to control Collective2","keywords":"documentation,api,automated trading,Collective2 API Documentation","lang":"en-US","siteUrl":"https://c2-api.redocly.app/","meta":[{"name":"charset","content":"utf-8"}],"llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"subscribing-to-channels","__idx":0},"children":["Subscribing to Channels"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"sending-a-subscription-request","__idx":1},"children":["Sending a Subscription Request"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To receive real-time signals, send a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["subscription.request"]}," message after the connection"," ","is established:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"msg_type\": \"subscription.request\",\n  \"request_id\": \"my-sub-001\",\n  \"timestamp\": \"2024-01-01T12:00:00Z\",\n  \"payload\": {\n    \"action\": \"subscribe\",\n    \"channel\": \"strategy.signal\",\n    \"strategy_id\": 12345678\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"payload-fields","__idx":2},"children":["Payload Fields"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Field"},"children":["Field"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Type"},"children":["Type"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Required"},"children":["Required"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["action"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["string"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"subscribe\""]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"unsubscribe\""]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["channel"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["string"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Channel to subscribe to. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"strategy.signal\""]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"strategy.positions\""]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["strategy_id"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["integer"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Yes"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The strategy to subscribe to. Must be a positive integer."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["resume_from"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["string"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["(",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"strategy.signal\""]}," channel only) Last ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["seq_id"]}," received. When set and greater than ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["0"]},", the server replays missed signals before starting live delivery. Omit or set to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["0"]}," to receive only signals published after this subscription is acknowledged. See ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/guides/websocket-gap-fill"},"children":["Gap Fill"]},"."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"envelope-fields","__idx":3},"children":["Envelope Fields"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Field"},"children":["Field"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Type"},"children":["Type"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Required"},"children":["Required"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["request_id"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["string"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Client-assigned correlation ID (max 50 characters). The server echoes it in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["subscription.ack"]}," envelope, useful when sending multiple subscriptions in quick succession."]}]}]}]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["timestamp"]}," field in your messages must be within 1 minute of UTC. Messages with a"," ","clock-skewed timestamp are rejected with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["INVALID_PARAMETER"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"using-websocat","__idx":4},"children":["Using websocat"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"websocat -H \"Authorization: Bearer YOUR_API_KEY\" wss://api4-general.collective2.com/ws \\\n  --text - <<< '{\"msg_type\":\"subscription.request\",\"timestamp\":\"2024-01-01T12:00:00Z\",\"payload\":{\"action\":\"subscribe\",\"channel\":\"strategy.signal\",\"strategy_id\":12345678}}'\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"using-python","__idx":5},"children":["Using Python"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"import asyncio\nimport json\nimport websockets\nfrom datetime import datetime, timezone\n\nAPI_KEY = \"YOUR_API_KEY\"\nWS_URL = \"wss://api4-general.collective2.com/ws\"\nSTRATEGY_ID = 12345678\n\nasync def subscribe():\n    headers = {\"Authorization\": f\"Bearer {API_KEY}\"}\n    async with websockets.connect(WS_URL, additional_headers=headers) as ws:\n        # Wait for connection.connected\n        await ws.recv()\n\n        # Send subscription request\n        request = {\n            \"msg_type\": \"subscription.request\",\n            \"request_id\": \"my-sub-001\",\n            \"timestamp\": datetime.now(timezone.utc).isoformat(),\n            \"payload\": {\n                \"action\": \"subscribe\",\n                \"channel\": \"strategy.signal\",\n                \"strategy_id\": STRATEGY_ID\n            }\n        }\n        await ws.send(json.dumps(request))\n\n        # Wait for subscription.ack\n        ack = json.loads(await ws.recv())\n        print(f\"Subscribed: {ack['msg_type']}\")\n\nasyncio.run(subscribe())\n","lang":"python"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"subscription-acknowledgement","__idx":6},"children":["Subscription Acknowledgement"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The server responds with a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["subscription.ack"]}," that echoes your full payload and"," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["request_id"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"msg_type\": \"subscription.ack\",\n  \"id\": \"msg_a1b2c3d4e5f6a1b2c3d4e5f6a7b8\",\n  \"request_id\": \"my-sub-001\",\n  \"timestamp\": \"2024-01-01T12:00:00Z\",\n  \"v\": 4,\n  \"payload\": {\n    \"action\": \"subscribe\",\n    \"channel\": \"strategy.signal\",\n    \"strategy_id\": 12345678,\n    \"resume_from\": null\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"receiving-positions","__idx":7},"children":["Receiving Positions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Once subscribed, position changes are pushed as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["strategy.positions"]}," messages. The message payload is ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://c2-api.redocly.app/apis/general/swagger/schemas/positiondto","target":"_blank"},"children":["PositionDTO"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"receiving-signals","__idx":8},"children":["Receiving Signals"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Once subscribed, new signals are pushed as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["strategy.signal"]}," messages:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"msg_type\": \"strategy.signal\",\n  \"id\": \"msg_a1b2c3d4e5f6a1b2c3d4e5f6a7b8\",\n  \"seq_id\": 98765,\n  \"timestamp\": \"2024-01-01T12:00:00Z\",\n  \"v\": 4,\n  \"payload\": {\n    \"Id\": 98765,\n    \"StrategyId\": 12345678,\n    \"SignalId\": 456789,\n    \"Side\": \"1\",\n    \"OpenClose\": \"O\",\n    \"OrderQuantity\": 100,\n    \"OrderType\": \"1\",\n    \"Stop\": null,\n    \"Limit\": null,\n    \"TIF\": \"Day\",\n    \"ParentSignalId\": null,\n    \"C2Symbol\": {\n      \"FullSymbol\": \"AAPL\",\n      \"SymbolType\": \"stock\",\n      \"Underlying\": null,\n      \"Expiry\": null,\n      \"PutOrCall\": null,\n      \"StrikePrice\": null,\n      \"Description\": \"Apple Inc.\"\n    },\n    \"ExchangeSymbol\": {\n      \"Symbol\": \"AAPL\",\n      \"Currency\": \"USD\",\n      \"SecurityExchange\": \"DEFAULT\",\n      \"SecurityType\": \"CS\",\n      \"MaturityMonthYear\": null,\n      \"PutOrCall\": null,\n      \"StrikePrice\": null,\n      \"PriceMultiplier\": 1\n    },\n    \"PostedDate\": \"2024-01-01T12:00:00Z\",\n    \"OrderStatus\": \"0\",\n    \"FilledQuantity\": 0,\n    \"SignalType\": 1\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Always store the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["seq_id"]}," from the last signal you receive. You will need it to resume"," ","after a disconnection — see ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/guides/websocket-gap-fill"},"children":["Gap Fill"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"signal-types-and-order-status","__idx":9},"children":["Signal Types and Order Status"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OrderStatus"]}," field in the payload indicates what kind of event the signal represents:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"OrderStatus` value"},"children":["OrderStatus` value"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Meaning"},"children":["Meaning"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["\"0\""]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Working"]}," — a new order has been placed and is active"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["\"2\""]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Filled"]}," — the order has been fully filled"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["\"4\""]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Canceled"]}," — the order has been canceled"]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Cancel signals"]}," carry only the identity fields — ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Id"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["StrategyId"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SignalId"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SignalType"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OrderStatus"]},". All order detail fields (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Side"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OpenClose"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OrderQuantity"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OrderType"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Stop"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Limit"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TIF"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["C2Symbol"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ExchangeSymbol"]},", etc.) are ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["null"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Fill signals"]}," mirror the original order signal but with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OrderStatus: \"2\""]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["FilledQuantity"]}," set to the filled quantity."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Working signals"]}," are the full order structure shown in the example above."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"unsubscribing","__idx":10},"children":["Unsubscribing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Send a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["subscription.request"]}," with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["action: \"unsubscribe\""]}," to stop receiving signals:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"msg_type\": \"subscription.request\",\n  \"timestamp\": \"2024-01-01T12:00:00Z\",\n  \"payload\": {\n    \"action\": \"unsubscribe\",\n    \"channel\": \"strategy.signal\",\n    \"strategy_id\": 12345678\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A successful unsubscribe returns a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["subscription.ack"]}," with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["action: \"unsubscribe\""]}," in the"," ","payload. Attempting to unsubscribe from a channel you are not subscribed to returns a"," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["NOT_FOUND"]}," error."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"subscription-errors","__idx":11},"children":["Subscription Errors"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Error"},"children":["Error"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Cause"},"children":["Cause"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["ALREADY_EXISTS"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Already subscribed to this channel and strategy"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["NOT_FOUND"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Tried to unsubscribe from a channel not currently subscribed"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["FORBIDDEN"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Not authorized to receive signals for this strategy. You must own or be subscribed to the strategy to receive its signals."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["TOO_MANY_SUBSCRIPTIONS"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Channel limit reached on this connection"]}]}]}]}]}]},"headings":[{"value":"Subscribing to Channels","id":"subscribing-to-channels","depth":1},{"value":"Sending a Subscription Request","id":"sending-a-subscription-request","depth":2},{"value":"Payload Fields","id":"payload-fields","depth":3},{"value":"Envelope Fields","id":"envelope-fields","depth":3},{"value":"Using websocat","id":"using-websocat","depth":3},{"value":"Using Python","id":"using-python","depth":3},{"value":"Subscription Acknowledgement","id":"subscription-acknowledgement","depth":2},{"value":"Receiving Positions","id":"receiving-positions","depth":2},{"value":"Receiving Signals","id":"receiving-signals","depth":2},{"value":"Signal Types and Order Status","id":"signal-types-and-order-status","depth":2},{"value":"Unsubscribing","id":"unsubscribing","depth":2},{"value":"Subscription Errors","id":"subscription-errors","depth":2}],"frontmatter":{"title":"Subscribing to Channels","description":"Subscribe to real-time strategy signals over WebSocket","seo":{"title":"Subscribing to Channels"}},"lastModified":"2026-04-16T16:08:40.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/websocket-subscribe","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}