> ## Documentation Index
> Fetch the complete documentation index at: https://docs.open.cx/llms.txt
> Use this file to discover all available pages before exploring further.

# Phone follow-up workflows and callbacks

> Build outcome-based WhatsApp follow-ups, schedule a one-time AI callback, and pass call details to CRM automation with explicit result checks.

Use separate workflows to start calls and react to their results. Start with a tested [outbound agent](/phone/outbound-calls), permission to edit and activate workflows, and the [Call Finished fields](/phone/call-outcomes) available in your workspace.

## No answer, busy, or voicemail → WhatsApp

You need a connected WhatsApp number, an approved template, and an OpenCX contact with a phone number.

<Steps>
  <Step title="Filter the finished call">
    Create a workflow with **Call Finished**. Add conditions requiring **Direction = Outbound** and **Disposition** equal to `no_answer`, `busy`, or `voicemail`. Keep `unknown`, `failed`, `declined`, and `canceled` on separate branches so their handling is deliberate.
  </Step>

  <Step title="Send the template">
    Add **Send WhatsApp Template**. Set **Contact ID** from `trigger.call.ticket.contact.id`, choose your sending **Phone Number** and **WhatsApp Template**, and fill **Template Variables** in placeholder order: header, body, then buttons. Route a missing contact ID to review instead of sending.
  </Step>

  <Step title="Check the action result">
    Branch on the action's **Sent** output. If false, record or surface **Error** for follow-up. Expected send failures can return `sent: false` without failing the whole workflow, so a completed run alone does not prove a message was sent. A successful send returns a **WhatsApp Message ID**; it does not prove delivery or that the recipient read it.
  </Step>

  <Step title="Test and activate">
    Test each branch with a contact you control. Confirm the recipient, template variables, message in the session, and action result. Check other active workflows and sequences so they do not also send the same follow-up for that attempt.
  </Step>
</Steps>

## Schedule one callback at a chosen time

For an individually configured callback, combine **Cron Trigger** with **Make phone call**:

1. Create a separate workflow for the callback and choose **Cron Trigger**.
2. Set **Cron Expression** for the intended date and time. Set **Run Limit** to `1` so the workflow deactivates after its one scheduled fire.
3. Add **Make phone call**. Set **AI Agent**, the customer's **Contact Number** in international format, and **Extra Instructions** explaining the callback purpose.
4. Confirm the next occurrence before activation, then activate the workflow. Configure result handling in a separate **Call Finished** workflow.

For example, `30 14 25 9 *` means September 25 at 14:30 in the schedule's timezone. Cron configuration without an explicit timezone uses **UTC**; do not assume the browser or customer's local timezone. Convert the agreed customer time before entering the expression. This expression has no year: if the date has passed, its next occurrence is the following year. Always confirm the upcoming occurrence is the one intended.

**Run Limit counts scheduled fires, not successful answers.** A failed or unanswered call does not automatically re-arm this one-time workflow. Choose an explicit retry policy based on the finished call.

To cancel a callback before it fires, deactivate its workflow. To reschedule a pending callback, deactivate it, change the schedule, then reactivate it after checking the new time. Deactivation does not stop a call that has already started. For another callback after the one-shot workflow has fired, create a new workflow; editing the old schedule does not reset its fired count.

For many customers with changing appointment times, keep the schedule and cancellation state in your CRM or scheduling system and invoke the [Make Outbound Call API](/api-reference/phone/make_outbound_call) when each callback is due. Store the returned session reference with the appointment. This is a configured integration; OpenCX does not infer a callback appointment from call feedback alone.

## Delays and session follow-ups

A **Wait** step pauses a workflow for an elapsed duration and supports up to **30 days** per step. It is useful for a relative delay, but has no customer appointment date/time field. A session's scheduled AI follow-up resumes session handling; scheduling one does not itself guarantee an outbound phone dial. Add an explicit **Make phone call** step in the flow that should dial.

Avoid sending every failed callback straight back into the same call-starting flow. Store attempt limits and stop conditions in the system managing the journey so a no-answer result cannot create an endless retry loop.

## Log the result in your CRM

Use **Call Finished** to send the call ID, session ID, contact reference, outcome, disposition, and end time to your CRM automation. Configure the task or note creation explicitly. Connecting a CRM alone does not create a callback task for every call.

For **Send Webhook**, set the receiver URL, HTTP method, required authentication headers, and body fields. Check its **Is Success** and **Status Code** outputs. Your receiving integration must match the CRM contact and handle repeated delivery. See [HubSpot phone tasks and notes](/integrations/hubspot/channels/phone#callback-tasks-and-call-notes) for field mapping and verification.

## Verify the journey

| Scenario | Expected check |
| - | - |
| Human answers | No no-answer WhatsApp message is sent. |
| No answer / busy / voicemail | The intended branch runs once and records its result. |
| Unknown answer type | A deliberate fallback handles it. |
| Missing phone or rejected template | The failed send is visible through **Sent** and **Error**. |
| Callback due | One call-starting run occurs at the agreed time; its result is handled separately. |
| Callback canceled or moved | The old pending schedule does not dial. |
| CRM receives the result twice | It updates or reuses the saved activity instead of creating duplicates. |
| Final summary is delayed | The outcome is retained and summary enrichment waits for available text. |

## Skip a sequence call after a reply

A contact's reply exits them from a sequence. Use **Skip Sequence Step** before **Continue Sequence for Contact** to omit their next pending call while retaining their remaining WhatsApp and email outreach. The action works across sequences and supports all three channels.

You need permission to edit and activate workflows. API and MCP callers need `sequences:write`. Start with a **Sequence Replied** trigger and a condition that identifies “cannot talk now” replies.

1. Add **Skip Sequence Step**. Set **Sequence** to `{{trigger.sequence.id}}` and **Contact ID** to `{{trigger.contact.id}}`.
2. Set **Skip mode** to **Next pending step of a channel**, **Channel** to **Phone**, and **Reason** to `Customer cannot talk now`.
3. Continue only when its **Outcome** is `skipped` or `already_skipped`. For `dispatch_in_progress`, wait for that attempt's outcome before retrying. Other outcomes identify why nothing was skipped.
4. Add **Continue Sequence for Contact**, using the same sequence and contact references. Check its **Resumed** output; `nothing_to_continue` means no pending outreach remains.

Example action inputs after naming the first action `skipPhone`:

```json theme={"dark"}
{
  "sequenceId": "{{trigger.sequence.id}}",
  "contactId": "{{trigger.contact.id}}",
  "mode": "next_channel",
  "channel": "voice",
  "reason": "Customer cannot talk now"
}
```

The continuation action uses:

```json theme={"dark"}
{
  "sequenceId": "{{trigger.sequence.id}}",
  "contactId": "{{trigger.contact.id}}"
}
```

**Channel** appears only for the channel mode. Choose **A specific step** to show the selected sequence's **Step** picker; it stores a zero-based index. Sequence, contact, mode, channel, step index, and reason support workflow references. When the sequence is supplied dynamically, reference the intended step index too.

Changing **Sequence** clears a previously selected step. Choose the step again before saving. **Save** requires **Step** for **A specific step**, and **Channel** for **Next pending step of a channel**; references are accepted and resolved when the workflow runs.

Skipping preserves the original waiting time. A 30-minute wait before the omitted call plus a 60-minute wait before the next email remains a 90-minute gap. For a reply-exited contact, those waits start when **Continue Sequence for Contact** runs. Sending windows can push the schedule later. The skip alone leaves exited contacts exited and parked contacts parked; it never revives a completed, removed, or suppressed enrollment.

Review the contact's sequence journey for **Skipped**, the reason, and its timestamp. Workflow and operator attribution are retained in [contact events](/api-reference/sequences/get-contact-events). See the [skip operation](/api-reference/sequences/skip-step) for the full result and retry contract.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.