Genesys AudioHook is 8 kHz µ-law, and there is nowhere to stand
The Genesys Cloud AudioHook protocol pins its sample rate in the type system: MediaRate is the literal 8000, and 16000 appears nowhere in the specification. AudioHook Monitor is a one-way tap whose server output is explicitly discarded; Audio Connector can play audio back, but it is a bot fork inside the IVR that pauses the flow and never reaches an agent. A spec-by-spec reading of what a third party can and cannot do in that media path, with the four things we could not confirm named as unconfirmed.
Every specification claim below is quoted from Genesys' own published documentation and linked. Where we could not confirm something, it is listed as unconfirmed rather than filled in — there is a section for that near the end. If any of this is wrong or changes, tell us and we will correct it with a date.
Contact centres are where voice AI meets actual revenue, and Genesys Cloud is one of the largest of them. So the question that matters for anyone selling audio processing is narrow and answerable: what does the media path look like, and is there a place in it where a third party can stand?
The Genesys answer is unusually legible, because they publish the protocol rather than describing it. Here is the whole sample-rate question, as it appears in their type definitions:
type MediaFormat = 'PCMU';
type MediaRate = 8000;
Not a default. Not a recommendation. A literal type. The protocol reference restates it in prose — "Sample rate of the media format in Hertz. The Genesys Cloud client currently only supports 8000Hz" — and the string 16000 does not appear anywhere in the AudioHook specification.
That is the wedge this whole site is about, stated by the platform itself. Every third party integrating audio into Genesys Cloud through the documented protocol receives narrowband G.711 µ-law, and essentially every speech enhancement model on the market is trained wideband.
The transport, briefly
AudioHook inverts the roles you might expect. Genesys is the WebSocket client; your service is the server.
"The AudioHook protocol uses WebSockets over TLS as the transport and is designed to make it easy to implement servers that accept it." — introduction
Concretely, from the security page and the session walkthrough:
| Property | Value |
|---|---|
| Port | 443, and only 443 |
| TLS | 1.2 and 1.3; certificates must be signed by a public CA (no self-signed) |
| Framing | JSON in text frames, raw audio in binary frames |
| Maximum message size | 64,000 bytes, text and binary alike |
| Open / ping / close timeouts | 5,000 ms / 5,000 ms / 10,000 ms |
| Application ping interval | every 5 seconds per connection |
| Auth | X-API-KEY header, plus optional HMAC-SHA256 request signing with a mandatory nonce |
| Retries | up to 5, exponential backoff |
Two details worth pulling out because they bite implementers.
The ping is not the WebSocket ping. These are application-level ping/pong JSON messages — "a protocol feature distinct from the WebSocket ping/pong messages (which are not used)" — and an unsolicited pong is a protocol error. You have five seconds to answer, every five seconds, or Genesys may treat the connection as lost and re-establish it.
There is no WebSocket subprotocol. We looked for one specifically. The documented handshake carries Audiohook-Organization-Id, Audiohook-Correlation-Id, Audiohook-Session-Id and X-API-KEY headers, and no Sec-WebSocket-Protocol at all; the string does not appear on any AudioHook specification page. If you were planning to route by subprotocol, route by path instead.
The media negotiation, and what the two channels actually are
The open message carries an offer and your opened response picks from it, SDP-style. The rule is strict:
"The server must choose exactly one of the entries offered and must not modify an offered media format (including the channels and their order). This is similar to the offer-answer exchange of an SIP/SDP media negotiation, just simpler." — session walkthrough
A typical offer is three entries, all PCMU at 8000 Hz, differing only in channels: ["external", "internal"], ["external"], ["internal"].
The channel names are the part people get wrong, and they are not "caller" and "agent". AudioHook follows a participant, not a leg:
"Currently, two values are supported:
external, which represents what the party represented by they participant speaks andinternal, which represents what they hear." — protocol reference
So internal is everything that participant hears — which can be IVR prompts, ACD hold music, or, in a conference, a mix. Genesys says so explicitly: "the audio of the 'internal' channel in our AudioHook represents a mix of the audio from both agents." If you are building anything that assumes one voice per channel, that assumption fails on a warm transfer. In a stereo answer, left is index 0 and right is index 1.
Frame sizes: there aren't any
This is the single most likely source of a bug in a first implementation, and the specification is blunt about it.
"The number of samples per frame is variable and is up to the client... The server must not make any assumptions about audio frame sizes and maintain a timeline of the audio stream by counting the samples." — session walkthrough
The only concrete number given is illustrative: a 100 ms frame of two-channel PCMU at 8000 Hz is 1600 bytes, headerless and interleaved. Your framing budget is the 64,000-byte message ceiling and the rate limits — 10 binary messages per second on average with a burst of 25, the same for text.
And the stream is not paced like a phone call. Genesys buffers:
"The client maintains a history buffer of at least 20 Seconds of audio... it will send the buffered audio to the server faster than real-time and then continue with the real-time stream. The rate at which the client 'catches up' is undefined."
So a session opens with a burst of history at an unspecified rate, then settles into real time. Anything you build with a fixed block size — which is every streaming enhancement model, ours included — needs its own re-framing buffer in front of it, and anything that measures real-time factor from wall-clock arrival will read nonsense for the first few seconds.
When the client cannot keep up it tells you, with a discarded message carrying start and discarded durations and the invariant position = start + discarded. That is a gap announcement, not a control command: "whenever there is a discontinuity in the audio stream due to unexpected loss of audio." Explicit pause and resume do not produce one. If you are counting samples to maintain a timeline — and the spec tells you to — discarded is how you learn your timeline just moved.
The question that decides everything: can you send audio back?
It depends entirely on which of the four AudioHook features you are implementing, and the answers are not similar to each other.
| Feature | Audio to your server | Audio back into the call | What you may return |
|---|---|---|---|
| AudioHook Monitor | Yes, external and/or internal | No | Nothing in band |
| Audio Connector | Yes, external only | Yes — played to the caller | Audio, as bot prompts |
| Transcription Connector | Yes | No | transcript events |
| Bot Transcription Connector | Yes (PCMU or L16) | No | transcript and speech events |
AudioHook Monitor is a tap and says so. The features page does not leave room for interpretation:
"here the client will stream the conversation audio to the server but no in band data can be sent back to the client. Data returned by the server will be silently ignored and discarded."
Note silently. Not an error, not a warning — your processed audio disappears and the session looks healthy. The introduction frames the whole protocol the same way: "Think of this as 'taps' on the audio streams to and from participants' parties."
Audio Connector genuinely is bidirectional, and this is the one that looks, at first, like the opening:
"This feature supports bi-directional audio streaming... Any audio data sent to the client will be played to the caller. Only the
externalaudio channel is sent from the client to the server." — features
It has the machinery you would expect for that: playback-started and playback-completed client messages, a barge_in server event, a dtmf message. Server-to-client audio is capped at "no more than 64,000 bytes per message" and paced — "the server should not send audio more often than every 200ms".
There is one documented contradiction worth knowing about before you spend a day on it. The error table in the same protocol reference still says the opposite:
"
415Unsupported Media Type — The server sent a binary message to the client... sending audio from the server to the client is not supported."
Our reading is that 415 predates Audio Connector and applies to Monitor and Transcription Connector sessions, where binary from the server is indeed illegal; the changelog shows bidirectional audio, DTMF, playback and barge-in arriving in a later update. But the specification contains both statements today, and if you are building against it you should expect to discover which one applies to your session type empirically.
Why Audio Connector is still not an insertion point
Here is where the architecture, rather than the protocol, closes the door. Audio Connector is a bot turn, not an inline filter, and three properties of it are individually disqualifying for anyone trying to clean audio before someone else's bot:
"The Call Audio Connector action in Architect forks the voice stream, sends it to the configured URL, and then pauses the flow execution at this point, until the bi-directional stream ends... The bi-directional streaming session is active only in the IVR channel. It does not transfer to an agent." — Audio Connector overview
- The audio you send goes to the caller, not to the bot. You are being asked to be the voice on the other end. There is no "return the cleaned caller audio and let the platform's speech recogniser hear it instead" direction, because the direction that exists points at the human.
- It is a fork with a blocking flow. Execution stops at the action and resumes when your session ends. That is a dialog turn, not a pipeline stage.
- It never reaches an agent. IVR only.
Plus the smaller constraints, all documented on the same page: one bidirectional stream, external channel only, 300 concurrent Audio Connector calls and a 900-second per-call ceiling, and no support under BYOC Premises.
So the honest conclusion, checked surface by surface: Genesys Cloud documents audio egress, audio dialog in the IVR leg, and metadata return. It documents no way for a third party to receive audio, process it, and have the processed audio be what the platform's own downstream consumers hear. We checked Monitor, Audio Connector, Transcription Connector, Bot Transcription Connector, Genesys Agent Assist (a knowledge-surfacing feature with no audio path at all), Genesys Bot Connector (text and intents, message flows only), and Bring Your Own Interactions (post-hoc ingestion, not live media).
Where you can stand, and it is exactly one place
There is a real insertion point, and it is not the one people look for.
If you are the speech recogniser, you can clean the audio before your own recogniser. The Bot Transcription Connector exists precisely to let a third party be the STT engine — "allows audio to be streamed to the AudioHook-based server that will serve as an STT engine" — and Genesys' own help centre describes it as the way to "integrate third-party ASR engines using the Genesys AudioHook protocol". That path receives PCMU, and uniquely also offers L16, and returns transcript and speech-start events rather than audio.
Which relocates the question rather than answering it. Inside that boundary you own the whole chain: 8 kHz µ-law in, your processing, your recogniser, transcript out. Nothing in the platform stops you from putting a filter there. What stops you is that on our own measurements, that filter is currently a bad idea: across our seven telephony conditions no engine we tested produced a meaningful improvement over the unprocessed audio, several degraded it by five to ten points of word error rate, and our own model did worse than all of them. The place to stand exists. The thing worth standing there with does not exist yet, and that is the entire reason this company is building one.
The second-order consequence is worth stating for anyone doing platform selection. On AudioHook, the audio-quality decision for your highest-volume channel is made upstream of you and cannot be changed by you. You get 8 kHz µ-law and whatever the carrier leg did to it, and the only lever you have is what you do after it arrives.
What we could not confirm
Named explicitly, because a developer-facing post that quietly fills gaps is worth nothing.
- Genesys' own transcription sample rate. We could not find any Genesys statement of what rate their own speech-to-text runs at, and no 8 kHz versus 16 kHz comparison anywhere. Their engines are vendor-backed (Google, Microsoft Azure, AWS Transcribe, a Genesys native engine, Deepgram) and no rate is published for any of them. Trunk codecs can include G.722 and Opus, so the carrier leg is not necessarily narrowband — but what reaches the transcriber is undocumented. The 8000 Hz figure in this post is the AudioHook third-party path only. Do not extend it to Genesys' own pipeline on our say-so.
- Any supported way to insert an SBC or media server into a BYOC SIP path to modify audio. BYOC Cloud lets you define SIP trunks to third-party carriers, and trunk codecs are configurable. We found no Genesys document that endorses, describes or forbids putting a processing element in that path. Absence of documentation is not permission and it is not prohibition.
- A maximum number of concurrent AudioHook Monitor connections. Only integration and monitor counts are published — five AudioHook Monitor integrations, up to 20 integration installations, up to 500 configured monitors, ten Transcription Connector integrations. Audio Connector's 300 concurrent calls is the only concurrency figure we found.
- The wire format of server-to-client audio in Audio Connector. The specification gives the cadence (no more often than 200 ms) and the size ceiling (64,000 bytes) but never restates the format. It is presumably the negotiated one. It does not say so.
- "AudioHook Media Service" does not appear to be a Genesys product name. We searched the developer centre's sitemap and the full help-centre article index and found nothing. If you have seen the term, it did not come from Genesys documentation.
We also note that Genesys publishes a reference server implementation in TypeScript with a client tool and a test suite, and a separate Audio Connector reference server whose source pins MediaFormat to 'PCMU' | 'L16', MediaRate to 8000 and the maximum binary message to 64000 — which is a second, independent confirmation of the numbers above, in code rather than prose.
If you are implementing this
- Count samples, do not count frames. The spec requires it and the catch-up burst punishes anything that doesn't.
- Buffer into your model's block size, and never take arrival timing as a proxy for audio timing during the first twenty seconds.
- Handle
discardedas a timeline event, not as an error to log and move on from. Your sample counter is wrong afterwards if you don't. - Answer
pingwithin five seconds, always, from a path that cannot be blocked by inference. If your model and your control plane share an event loop, a slow block eats your connection. - Decide which feature you are before you design anything. Monitor and Audio Connector look like the same protocol and are opposite architectures, and the error table will not stop you from building the wrong one.
- Note the PCI boundary. AudioHook adheres to PCI DSS compliance when secure pause runs during secure flows, and you cannot use it to stream audio during a secure flow. Whatever you build has a hole in it by design, and that hole is deliberate.
The companion post covering Amazon Connect, Twilio, NICE CXone and Avaya reads the same question against the other four platforms — and one of them turns out to document something Genesys does not.