TriggersafterCallstable

After the call ends

Runs once after the call is over, however it ended: the caller hung up, the flow hung up or finished, the call was transferred or answered by an agent, or…

What it does

Runs its chain once, after the call is over — however it ended: the caller hung up, a Hang up step ended it, the flow ran to its end, the call was transferred or answered by an agent, or the AI receptionist ended it.

Everything the call collected is still readable — {{vars.x}}, a step's result {{steps.<id>.ok}} — plus two values the trigger adds:

  • {{vars.callEndReason}} — caller_hangup, flow_hangup, transferred, completed or error.
  • {{vars.callDurationSecs}} — seconds from the answer to the hang-up.

Nobody is on the line any more, so only steps that need no caller can go below it: Call an API, Set variable, Branch, Business hours, Look up contact, Run sub-flow, Custom script, Notify agent and No-op. Anything that plays, listens, records, dials or transfers is refused there.

One per flow. It is never the flow's start.

When to use it

  • Log every call's outcome and length to your CRM or a webhook
  • Send a "missed you" follow-up when vars.callEndReason is caller_hangup before the caller reached anyone
  • Put whatever used to hang off a node's old "Caller hung up" path here — nodes on the call no longer have a hang-up path

Configuration

_label and _note are author-only metadata; the trigger has no runtime configuration of its own.

Runs once after the call is over, however it ended: the caller hung up, the flow hung up or finished, the call was transferred or answered by an agent, or the AI receptionist ended it. Everything the call collected is still readable ({{vars.x}}, {{steps.<id>.ok}}), plus why and how long: {{vars.callEndReason}} and {{vars.callDurationSecs}}. Nobody is on the line any more, so only steps that need no caller can go below it: Call an API, Set variable, Branch, Business hours, Look up contact, Run sub-flow, Custom script, Notify agent and No-op. One per flow.

FieldLabelTypeRequiredDefaultNotes
_labelTrigger labeltextOptional—Friendly name shown in the canvas and run logs. Optional.
_noteInternal notetextareaOptional—Notes for your team.

Outgoing events: triggered

Examples

Post the outcome to a webhook

{
  "id": "after-call",
  "type": "afterCall",
  "config": { "_label": "Log the call" },
  "on": { "triggered": "post-outcome" }
}
{
  "id": "post-outcome",
  "type": "apiCall",
  "config": {
    "mode": "http",
    "method": "POST",
    "url": "https://crm.example.com/calls",
    "body": "{ \"from\": \"{{event.from}}\", \"reason\": \"{{vars.callEndReason}}\", \"seconds\": {{vars.callDurationSecs}} }"
  }
}
[afterCall] ──► [apiCall POST crm.example.com/calls]

Gotchas

  • One per flow. The designer disables it in the palette once the flow has one; the validator reports a second as after_call_duplicate.
  • Never the start. A flow whose start is this trigger fails validation (after_call_is_start).
  • Only steps that need no caller below it. The designer offers only those when you add a step from the chain and refuses a wire to any other ("Say can't run after the call ends — nobody is on the line"); the validator reports one as after_call_node_not_allowed and the walker won't run it.
  • Nothing connects into it. It starts on its own when the call ends.
  • Old "Caller hung up" edges. Flows saved before this trigger existed may have call.hangup edges on Say, Gather, Play music and similar nodes. They never run. On save the server turns one into the node's normal next path when that path is free; otherwise it stays, flagged by the call_hangup_edge warning. Move that logic under this trigger.

See also