HCC Docs

Voicemail

onVoicemail is all it takes to leave a message. On the flow target, *onVoicemail(c) with yield* c.play(url) and yield* c.hangup(). On the campaign, .onVoicemail((call) => call.play(url).hangup()).

It runs when the greeting has ended, usually at the beep, so the recording isn't talking over it. The audio is yours, at a URL you host. There's nothing to turn on, and it works the same on a flow target and a queue target. The lead moves on to the next step, as for any machine, and goals and exits still run.

A flow with neither treats a voicemail as a real conversation. It's never told about machines, so a call an answering machine picks up counts as answered, the lead leaves as exit, and nobody tries it again. If your flow can reach voicemail, add onVoicemail to the flow or the campaign: a machine then moves the lead to the next step.

When we look for a machine

We look when a rep is held, or when onVoicemail would use the answer: the flow target's own, or the campaign's for a flow with none.

With a rep held, we always look, without making the lead wait. When the carrier says a machine answered, the rep comes off with no wrap-up, the call doesn't count against them, and onVoicemail says what's next, or we hang up.

That's a few seconds of greeting for the rep; with onVoicemail the carrier reports machines when the greeting ends, so a message lands and the rep hears the whole greeting. A person gets the rep just as fast either way: the rep joins at the answer, and no verdict is waited for.

What's recorded

  • A hook that plays or says something leaves the call with outcome: 'voicemail_left', and afterCall, .goal and .exit see that outcome. It says the message started; we can't tell if your URL could be fetched, or how much the machine kept.
  • One that only hangs up stays a plain machine.
  • A greeting past about 30 seconds comes back unknown, so no message is left, and it counts as a conversation.

Where it doesn't run

  • An onAnswer that enters a flow, on a queue target, only gets this if the campaign has onVoicemail too. Otherwise detection was asked for the earliest answer, and the entered flow's own onVoicemail runs at the start of the greeting.
  • .call(offer(queue)) has no detection, so onVoicemail doesn't run on it.

A prerecorded message on a consumer's phone can need their prior written consent, under the TCPA and some states' laws. Text to speech may count too. A grant here is what you told us, not a legal opinion. It's your campaign and your list: ask your lawyer before this reaches real leads.

  • A voice on a machine needs a grant on file. If your hook plays or says anything and the number has no prerecorded grant, or connects an AI agent and it has neither an ai_voice nor a prerecorded grant, we hang up instead, and dial_attempts says voicemail_no_consent.
  • Hand-offs need none. A hand-off (enqueue, dial, connect, a transfer to a person, enterFlow), record and sendDigits need no grant, so a person detection took for a machine still reaches your rep.
  • The same goes for later instructions on that call. Once a call is known to be on a machine, hcc.calls.update with that voice and no grant is refused with 422 no_consent, and a call.custom handler's answer isn't applied (applied: false). The call stays as it was.
  • onAnswer isn't gated. With no voicemail handler and no rep held, no detection is asked for, so we don't know a machine answered. A say or play in onAnswer reaches whoever or whatever picked up, grant or not. That's your call to make until counsel has answered.

The local test harness doesn't simulate this. See Consent.