onCallHoldstableOn hold
Fires whenever a "Place caller on hold" step runs. Use it to start a wait-time timer, send a Slack ping, or kick off any side-task that should run while t…
What it does
Fires every time a Place caller on hold (holdCall) node runs. The
worker has already started the hold music, marked the call as held, and
written a row to the call_holds table by the time your chain runs — the
trigger is a side-chain for the work that should happen alongside the
hold, not for managing the hold itself.
The chain runs in an isolated state branch and shares the call's vars,
so it sees vars.transferTo (set if the hold is part of a transfer
flow), vars._queueName (set when the caller is being parked into a
queue), and anything else the main flow has stamped. That makes it a
natural fit for "the customer is now waiting" notifications, started-at
timestamps you'll later read on unholdCall, or wait-time analytics.
When to use it
- Send a Slack ping to
#opswhen a customer is placed on hold so the team can keep an eye on long waits. - Stamp
vars.heldAtwith the current timestamp, then read it afterunholdCallto compute hold duration. - Fire an HTTP webhook to your own dashboard so the live agent view can highlight calls currently parked.
- Increment a counter in your CRM tracking how many holds happen per customer per day.
If you need to play music or audio during the hold, that's
already handled by the holdCall node's own configuration — pass a
holdMusicUrl there instead of trying to start audio from this trigger.
Configuration
_label and _note are author-only metadata; this trigger has no runtime
configuration of its own.
Fires whenever a "Place caller on hold" step runs. Use it to start a wait-time timer, send a Slack ping, or kick off any side-task that should run while the caller is on hold.
| Field | Label | Type | Required | Default | Notes |
|---|---|---|---|---|---|
_label | Trigger label | text | Optional | — | |
_note | Internal note | textarea | Optional | — |
Outgoing events: triggered
Examples
Slack ping when a customer goes on hold
{
"id": "hold-trigger",
"type": "onCallHold",
"config": { "_label": "Notify ops on hold" },
"on": { "triggered": "slack-ping" }
}
[onCallHold] ──► [httpCall POST hooks.slack.com/...
body: { text: "Caller {{event.from}} is on hold" }] ──► [end]
The main flow runs holdCall to actually park the caller; this trigger
fires alongside it.
[holdCall holdMusicUrl=...] ──► [enqueue queue=support] ──► ...
│
└──► (onCallHold trigger fires here, in parallel)
Gotchas
- Fires only via
holdCall, not on every Telnyx hold event. If the caller's leg goes on hold for some other reason (carrier-side hold,unholdCall->holdCallcycles from a parallel sub-flow), this trigger may not fire. Wire it toholdCallsemantics, not "any hold". - The hold is already in progress when the trigger runs. The
playbackStartfor the hold music and thecall_holdsinsert both happen beforerunTriggerChains('onCallHold')is called. Don't try to stop or modify the hold from inside the chain — use a separateunholdCallnode from the main flow if you need to lift it. - Side-chain runs in an isolated state branch. Shares
varswith the main flow, but cannot move the flow position.vars._onHoldis set totrueby the worker before the chain runs, and back tofalsebyunholdCall. - Reason inference is implicit. The hold reason written to
call_holds.reasonis determined by the worker:"transfer"ifvars.transferTois set,"queue"ifvars._queueNameis set, else"manual". Your chain can read these flags offvarsto branch on why the hold happened.
