onCallUnholdstableOn unhold
Fires whenever a "Resume caller from hold" step runs. Use it to stop a wait-time timer, log the hold duration to a CRM, or kick off any side-task that sho…
What it does
Fires every time a Resume caller from hold (unholdCall) node runs.
The worker has already stopped the hold music, closed the open row in
the call_holds table (stamping endedAt and computing durationSecs),
and flipped vars._onHold back to false by the time your chain runs —
the trigger is a side-chain for the work that should happen alongside
the resume, not for managing the unhold itself.
The chain runs in an isolated state branch and shares the call's vars,
so it sees anything the main flow stamped during the hold (for example
vars.heldAt if you set a started-at timestamp from onCallHold). That
makes it a natural fit for "the customer is back" notifications, hold
duration analytics, or CRM updates that should land the moment the
caller is brought back.
When to use it
- Send a Slack ping to
#opswhen a long-held customer is finally picked back up so the team can stand down. - Compute hold duration by reading a
vars.heldAtstamped fromonCallHoldand postingnow - vars.heldAtto your dashboard. - Fire an HTTP webhook to your own analytics so the live agent view can clear the "currently parked" highlight.
- Increment a counter in your CRM tracking how many resume events happen per customer per day.
If you need to play a "thanks for waiting" prompt after the resume,
that's better wired into the main flow as a say or playAudio after
the unholdCall node, so it cleanly gates forward progress instead of
racing against the side-chain.
Configuration
_label and _note are author-only metadata; this trigger has no runtime
configuration of its own.
Fires whenever a "Resume caller from hold" step runs. Use it to stop a wait-time timer, log the hold duration to a CRM, or kick off any side-task that should run when a held caller is brought back.
| 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 comes off hold
{
"id": "unhold-trigger",
"type": "onCallUnhold",
"config": { "_label": "Notify ops on resume" },
"on": { "triggered": "slack-ping" }
}
[onCallUnhold] ──► [httpCall POST hooks.slack.com/...
body: { text: "Caller {{event.from}} resumed" }] ──► [end]
The main flow runs unholdCall to actually resume the caller; this
trigger fires alongside it.
[unholdCall] ──► [bridge agent=...] ──► ...
│
└──► (onCallUnhold trigger fires here, in parallel)
Gotchas
- Fires only via
unholdCall, not on every Telnyx unhold event. If the caller's leg comes off hold for some other reason (carrier-side resume, hangup-during-hold cleanup), this trigger may not fire. Wire it tounholdCallsemantics, not "any unhold". - The resume is already in progress when the trigger runs. The
playbackStopand thecall_holdsclose both happen beforerunTriggerChains('onCallUnhold')is called. Don't try to re-hold or modify playback from inside the chain — use a freshholdCallnode from the main flow if you need to park the caller again. - Side-chain runs in an isolated state branch. Shares
varswith the main flow, but cannot move the flow position.vars._onHoldis set tofalseby the worker before the chain runs. - No
unholdCallupstream is fine. IfunholdCallruns without a matching open hold row (the caller wasn't actually on hold), the close is a no-op but this trigger still fires. Guard inside the chain if you only want to act on real resumes. - Caller-initiated hangup during hold won't fire this. If the caller
hangs up while on hold, the worker's hangup path closes the open hold
row directly —
unholdCallnever runs, so neither does this trigger. UseonCallEndfor that case.
