Context: API Makeathon participant writing a zero-dependency Node client for /ws/modeling/commands.
The gap
The standard WebSocket API (browser and Node) cannot set an Authorization header on the upgrade request, so ?token=<tok> is the natural first guess — and it is silently ignored: the upgrade succeeds (101 with or without any credentials), the server nags auth_token_missing once per second, then hard-drops the socket (~4–5 s, close code 1006 with no close frame).
The actual protocol — which we only learned from the nag text itself — is a post-upgrade JSON frame:
{"type":"headers","headers":{"Authorization":"Bearer <token>"}}
Success is then signaled by a modeling_session_data response carrying an api_call_id. Note one auth_token_missing nag still races in before the auth frame is processed, so clients must not treat the first nag as fatal.
Asks
- A short "authenticating over the websocket" section in the modeling-websocket docs stating the
headers frame explicitly (it exists in the OpenAPI WebSocketRequest schema, but nothing narrative points at it).
- Ideally note that auth query params are not supported (or have the server reject them loudly instead of ignoring them).
- Minor, same page: a client-initiated
close(1000) is reported back as 1006 (no completed close handshake), which looks like an error to standard clients — worth a one-line note if that's expected behavior.
Happy to PR the docs section if that's welcome — the measured transcript is in hand.
Context: API Makeathon participant writing a zero-dependency Node client for
/ws/modeling/commands.The gap
The standard
WebSocketAPI (browser and Node) cannot set anAuthorizationheader on the upgrade request, so?token=<tok>is the natural first guess — and it is silently ignored: the upgrade succeeds (101 with or without any credentials), the server nagsauth_token_missingonce per second, then hard-drops the socket (~4–5 s, close code 1006 with no close frame).The actual protocol — which we only learned from the nag text itself — is a post-upgrade JSON frame:
{"type":"headers","headers":{"Authorization":"Bearer <token>"}}Success is then signaled by a
modeling_session_dataresponse carrying anapi_call_id. Note oneauth_token_missingnag still races in before the auth frame is processed, so clients must not treat the first nag as fatal.Asks
headersframe explicitly (it exists in the OpenAPIWebSocketRequestschema, but nothing narrative points at it).close(1000)is reported back as 1006 (no completed close handshake), which looks like an error to standard clients — worth a one-line note if that's expected behavior.Happy to PR the docs section if that's welcome — the measured transcript is in hand.