Skip to main content
Flows define what happens during a call. They’re the brains of your campaigns—controlling everything from the initial dial to the final hangup.

How flows work

A flow is a directed graph of nodes. Each node performs an action and then routes to the next node based on what happened. Execution starts at a designated start node and continues until it reaches a terminal node (usually a hangup).
┌─────────┐     ┌─────────┐     ┌─────────┐     ┌─────────┐
│  Dial   │────▶│  Play   │────▶│  DTMF   │────▶│ Hangup  │
└─────────┘     └─────────┘     └─────────┘     └─────────┘
     │                              │
     │ onBusy                       │ onTimeout
     ▼                              ▼
┌─────────┐                    ┌─────────┐
│ Hangup  │                    │ Hangup  │
└─────────┘                    └─────────┘

Node types

Gomobile supports these node types:
NodePurposeOutputs
DialPlaces the outbound callonAnswer, onVoicemail, onNoAnswer, onBusy, onRejected, onError, default
AnswerAnswers an inbound callonSuccess, onError, default
PlayPlays audio to the recipientonComplete, onError, default
DTMFCollects keypad inputbranches (by digit), onSuccess, onTimeout, onInvalid, onMaxRetries, onError, default
RecordRecords the recipient’s voiceonComplete, onTimeout, onError, default
ConditionBranches based on variablesonTrue, onFalse, onError
Set VariableStores a value for later useonSuccess, onError, default
HangupEnds the callNone (terminal node)

Creating a flow

Here’s a complete flow that plays a message and collects a response:
curl -X POST https://api.gomobile.ma/api/flows \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Payment Reminder",
    "description": "Reminds customers about pending payments",
    "graph": {
      "startNodeId": "dial-1",
      "nodes": [
        {
          "id": "dial-1",
          "type": "dial",
          "label": "Call Customer",
          "config": {
            "timeout": 30000,
            "enableAMD": true
          },
          "outputs": {
            "onAnswer": "play-greeting",
            "onVoicemail": "hangup-vm",
            "onNoAnswer": "hangup-na",
            "onBusy": "hangup-busy"
          }
        },
        {
          "id": "play-greeting",
          "type": "play",
          "label": "Play Reminder",
          "config": {
            "audioItems": [
              { "type": "audioFile", "audioId": "greeting-audio-id" }
            ]
          },
          "outputs": {
            "onComplete": "collect-response"
          }
        },
        {
          "id": "collect-response",
          "type": "dtmf",
          "label": "Get Response",
          "config": {
            "mode": "single_digit",
            "variable": "customerResponse",
            "timeout": 10000,
            "singleDigitConfig": {
              "allowedDigits": ["1", "2"]
            }
          },
          "outputs": {
            "branches": {
              "1": "play-confirmed",
              "2": "play-callback"
            },
            "onTimeout": "hangup-timeout"
          }
        },
        {
          "id": "play-confirmed",
          "type": "play",
          "label": "Confirm Payment",
          "config": {
            "audioItems": [
              { "type": "audioFile", "audioId": "confirmed-audio-id" }
            ]
          },
          "outputs": {
            "onComplete": "hangup-success"
          }
        },
        {
          "id": "play-callback",
          "type": "play",
          "label": "Schedule Callback",
          "config": {
            "audioItems": [
              { "type": "audioFile", "audioId": "callback-audio-id" }
            ]
          },
          "outputs": {
            "onComplete": "hangup-success"
          }
        },
        {
          "id": "hangup-success",
          "type": "hangup",
          "label": "End Call - Success",
          "config": { "reason": "completed", "hangupType": "normal" }
        },
        {
          "id": "hangup-vm",
          "type": "hangup",
          "label": "End Call - Voicemail",
          "config": { "reason": "voicemail", "hangupType": "voicemail" }
        },
        {
          "id": "hangup-na",
          "type": "hangup",
          "label": "End Call - No Answer",
          "config": { "reason": "no_answer", "hangupType": "no_answer" }
        },
        {
          "id": "hangup-busy",
          "type": "hangup",
          "label": "End Call - Busy",
          "config": { "reason": "busy", "hangupType": "busy" }
        },
        {
          "id": "hangup-timeout",
          "type": "hangup",
          "label": "End Call - Timeout",
          "config": { "reason": "dtmf_timeout", "hangupType": "timeout" }
        }
      ]
    }
  }'

Variables in flows

Flows can read and write variables during execution. Variables come from several sources:
SourceExampleDescription
Systemsys.callId, sys.contactPhoneAutomatically available
Contactcontact.firstName, contact.cityFrom the contact being called
Custom Attributecontact.customAttributes.balanceCustom fields on contacts
Flow VariablecustomerResponseSet during execution
Use variables in conditions or to personalize audio playback.

Answering Machine Detection (AMD)

When enableAMD is true on a dial node, Gomobile attempts to detect if a human or machine answered:
  • Human detected → Routes to onAnswer
  • Machine detected → Routes to onVoicemail
This helps you leave voicemail messages instead of playing interactive prompts to answering machines.

Audio playback options

The Play node supports several audio types:
{
  "audioItems": [
    { "type": "audioFile", "audioId": "welcome-message" },
    {
      "type": "number",
      "value": {
        "source": "customAttribute",
        "attributeName": "accountBalance"
      },
      "mode": "full",
      "language": "ar"
    },
    { "type": "audioFile", "audioId": "currency-mad" }
  ]
}
Types include:
  • audioFile - Pre-recorded audio
  • number - Dynamic number playback
  • date - Dynamic date playback
  • word - Dictionary-based word playback

Flow validation

Before saving, Gomobile validates your flow:
  • Every node must be reachable from the start node
  • All output references must point to existing nodes
  • Terminal nodes (hangup) shouldn’t have outputs
  • Required configuration must be present
You can validate without saving:
curl -X POST https://api.gomobile.ma/api/flows/validate \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "graph": { "startNodeId": "...", "nodes": [] } }'

Best practices

  • Start simple - Get a basic flow working before adding complexity
  • Handle all outcomes - Every dial result should route somewhere
  • Use descriptive labels - Makes debugging much easier
  • Test thoroughly - Use ad-hoc calls to test before launching campaigns
  • Version carefully - Changing a flow affects all programs using it

Call Flows Guide

Detailed node configuration.

Audio Management

Managing audio files.

Dictionaries

Dynamic audio for numbers and words.

Programs

Using flows in campaigns.