The most likely issue is how you’re using the WebSocket subprotocol for auth.
Deepgram expects the Sec-WebSocket-Protocol header to contain two separate subprotocol values:
Sec-WebSocket-Protocol: token, YOUR_DEEPGRAM_API_KEY
i.e., one subprotocol is token, the other is the API key. [Sec-WebSocket-Protocol; TTS example]
In your code:
authorizationHeader = String("token, ") + DEEPGRAM_API_KEY;
websocket_cfg.subprotocol = authorizationHeader.c_str();
you’re passing a single string "token, <API_KEY>" as the subprotocol. Whether this works depends entirely on how esp_websocket_client serializes subprotocol:
- If it sends exactly
Sec-WebSocket-Protocol: token, <API_KEY>, you’re fine.
- If it treats
subprotocol as a single token and does not insert the comma/space correctly (or escapes it), the server will see one invalid subprotocol and reject auth, which can manifest as a 404/failed upgrade.
Deepgram’s own examples that use subprotocols (e.g., Python websockets.connect(..., subprotocols=["token", api_key])) rely on the library to send two values in the header, not one concatenated string. [Flutter discussion; Twilio agent example]
Other things to double‑check against the docs:
-
Endpoint URL
For Voice Agent v1, the WebSocket URL must be:
wss://agent.deepgram.com/v1/agent/converse
The reference explicitly documents this path. [Voice agent ref]