Skip to main content
The old Omni v2 chat URL was discontinued on August 13, 2026. Connections to that URL now return 404. Move every Omni client to:
This is a URL and handshake migration for clients that were working on the old URL immediately before discontinuation. The audio and control protocol remains the native Omni binary protocol described below. Clients that still send an old query alias, auth parameter, bare audio, or text control frame need the corresponding updates in this guide.

Migration checklist

1. Replace the URL and query parameters

session_label is an opaque, optional tag. It can also be a managed Agent profile id. Values must be no more than 256 characters and safe to place in an HTTP header. Do not send agent, agent_id, access_token, or model to /v1/omni. The route rejects agent and agent_id with 400 unsupported_parameter; access_token is not an auth mechanism; model is outside the canonical Omni contract. Keep format and rate explicit. Use pcm16 and 24000 for a browser or 24 kHz audio pipeline. Use the actual negotiated rate if your telephony pipeline is 16 kHz or 8 kHz.

2. Use a supported auth mechanism

For browser clients, send the API key as a WebSocket subprotocol:
For server-side clients, use one of:
If your WebSocket library cannot set headers, append api_key to the URL. Do not place the key in access_token or another query parameter. The key needs the omni:session scope.

3. Send configure after the socket opens

Send one 0x03-prefixed binary control frame. Its JSON body is keyed on type, not event:
If you use a managed Agent profile through session_label, you can omit fields already stored on that profile. An inline configure value overrides the stored value for the session.

4. Keep native Omni binary framing

Every WebSocket message uses a one-byte type prefix: Prefix every caller-audio chunk with 0x01. Prefix client controls such as configure, dtmf, and tool_result with 0x03. Client controls use a type key. Server control payloads use an event key; transcript payloads are plain text.
Do not send bare PCM or bare text JSON. Do not treat every binary message as audio. Strip and inspect the first byte before decoding the payload.

Error and close behavior

Handshake failures happen before a WebSocket session exists: After a successful upgrade, handle these WebSocket closes: Do not rely on every auth or parameter failure arriving as a WebSocket close. The canonical edge can reject the HTTP upgrade first. A reconnect starts a new session and requires a fresh configure frame.

Troubleshooting

  • 404 during connect: the URL still points at the discontinued route.
  • 400 unsupported_parameter: copy an agent or agent_id value into session_label, then remove the old parameter.
  • The socket opens but the agent hears nothing: caller audio is missing the 0x01 prefix, is not PCM16 little-endian, or does not match the URL rate.
  • The socket opens but the persona is ignored: the outbound configure body uses event: "configure" instead of type: "configure", or it was sent as text instead of a 0x03 binary frame.
  • Control data sounds like an audio glitch: demultiplex 0x02 transcript and 0x03 control frames instead of sending them to audio playback.
  • 401 or 4401: use a valid PyAI key through a supported auth mechanism.
  • 403 or 4403: add the omni:session scope to the key.
For the complete event catalog and current configure fields, see the Omni wire protocol. If you need help validating a client, contact support@pyai.com with the request id and close code. Never send an API key.