Connect Two Numbers (Click-to-Call)

Click-to-Call lets you programmatically connect two phone numbers — for example, linking a sales agent with a customer — by initiating Outbound Calls from your application.

👍

This is a powerful tool for CRMs, lead forms, support desks, or any system that needs to trigger calls automatically.

⚙️ How It Works

This Click-to-Call scenario creates two outbound calls and bridges them together:

  1. Leg A: The scenario first dials the first target ($targetA) using dial@v1. This could be an internal user, agent, or operator.
  2. If leg A answers, the call enters the answered branch.
  3. Leg B: In that branch, it then dials the second target ($targetB) using a second dial@v1 call.
  4. If both calls are successful, the scenario uses bridge@v1 to connect the two legs together in real time.
  5. Throughout the process, call statuses are tracked with custom variables ($statusA, $statusB), and a full status object is sent to your server using fetch@v2.

You can configure different Caller IDs for each leg using $cliA and $cliB, which must either be numbers assigned to your account or pre-approved as Caller IDs.

description: Two outbound calls

compat:
  version: 2025-09-01

defaults:
  language: en-US

variables:
  # Targets A and B
  $targetA: "+33639980041"
  $targetB: "+33639980042"

  # CallerIDs
  # these numbers must be either:
  # - assigned numbers on your account
  # - callerids approved on your account
  $cliA: "+33199001234"
  $cliB: "+33199006789"

  # Dial statuses
  $dialA: null
  $dialB: null

  # We will store the status of each leg
  $statusA: "nodial"
  $statusB: "nodial"

branches:
  api-initiated:
    actions:
      # Dial A
      - action: javascript@v1
        params:
          code: |
            $statusA = 'dialing'

      # The dial action is blocking until the call is hung up
      - action: dial@v1
        params:
          cli: ${{ $cliA }}
          targets:
            - number: ${{ $targetA }}
              timeout: 30
          answerOnBranch: answered
        result: $dialA

      - if: $statusA === 'dialing'
        action: javascript@v1
        params:
          code: $statusA = $dialA.status

      - action: javascript@v1
        params:
          code: |
            return {
              run: run,
              dial: {
                A: $dialA,
                B: $dialB,
              },
              status: {
                A: $statusA,
                B: $statusB
              }
            }
        result: $body

      # Push the call statuses to your server
      - action: fetch@v2
        params:
          url: https://api.example.com/call-logs
          method: POST
          body: ${{ JSON.stringify($body) }}
          headers:
            Content-Type: application/json

  # The answered branch defines the action for the first leg of the call (A)
  answered:
    actions:
      # Update variables
      - action: javascript@v1
        params:
          code: |
            $statusA = 'answered'
            $statusB = 'dialing'

      # Call leg B now
      - action: dial@v1
        params:
          cli: ${{ $cliB }}
          answerOnBranch: legB
          targets:
            - number: ${{ $targetB }}
              timeout: 30
        result: $dialB

      - if: "!$dialB.ok"
        then:
          - action: javascript@v1
            params:
              code: $statusB = $dialB.status
          - action: say@v2
            params:
              what: Sorry, we could not reach an agent. Please try again later.
          - action: hangup@v1

  legB:
    actions:
      - action: javascript@v1
        params:
          code: |
            $statusA = 'bridged'
            $statusB = 'bridged'
      - action: bridge@v1
      - action: hangup@v1

🚀 Trigger via API

Here's how to trigger this flow using curl and your API key:

curl --request POST \
     --url https://api.callr.com/v2.0/actions/<your-scenario-sid>/runs \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'x-api-key: <your-callr-api-key>' \
     --data '
{
  "variables": {
    "$targetA": "<target-a>",
    "$targetB": "<target-b>"
  }
}
'

Replace:

  • <your-scenario-sid> with the SID of the Callr Actions scenario
  • <your-callr-api-key> with your actual API key
  • <target-a> with the first number to call
  • <target-b> with the second number to call

📘

More examples

You can view the full documentation of this method here.


📝 Notes

  • You can use this approach for call tracking, lead follow-up, or agent-customer handoffs.
  • Both legs of the call are visible in your call logs, and full CDR data is available.
  • You can enhance the flow with say@v2, or fetch@v2 to collect and store context.

🔒

Reminder

If you're in Build Mode, you can only call Testing Numbers — phone numbers you own and have verified.
Make sure to add your personal number as a Testing Number in the Callr Portal.


✅ Use Cases

  • 💼 Sales: Connect reps with leads as soon as they fill out a form
  • 🛠️ Support: Let agents instantly follow up on ticket updates
  • 📊 Tracking: Log call metadata for analytics and reporting