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', andafterCall,.goaland.exitsee 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
onAnswerthat enters a flow, on a queue target, only gets this if the campaign hasonVoicemailtoo. Otherwise detection was asked for the earliest answer, and the entered flow's ownonVoicemailruns at the start of the greeting. .call(offer(queue))has no detection, soonVoicemaildoesn't run on it.
Consent for a voice on a machine
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
prerecordedgrant, or connects an AI agent and it has neither anai_voicenor aprerecordedgrant, we hang up instead, anddial_attemptssaysvoicemail_no_consent. - Hand-offs need none. A hand-off (
enqueue,dial,connect, a transfer to a person,enterFlow),recordandsendDigitsneed 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.updatewith that voice and no grant is refused with 422no_consent, and acall.customhandler's answer isn't applied (applied: false). The call stays as it was. onAnswerisn't gated. With no voicemail handler and no rep held, no detection is asked for, so we don't know a machine answered. AsayorplayinonAnswerreaches 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.