Skip to main content

Click-to-Call

Click-to-call enables your application to initiate phone calls on behalf of users. When triggered, the system first calls the user's registered devices, then connects them to the destination number.

Overview

Click-to-call allows you to:

  • Add "Call" buttons next to customer phone numbers in your application
  • Enable one-click dialing from CRM records, support tickets, or contact lists
  • Track call activity through the call logs API

How It Works

When you initiate a click-to-call:

  1. First leg: All of the user's registered devices (desk phones, softphones) ring simultaneously
  2. Answer: The user picks up any of their devices
  3. Second leg: The system dials the destination number
  4. Bridge: Both calls are connected together

This "call-first" approach ensures the user is ready before the customer's phone rings, providing a professional experience.

Initiating a Call

Using the API

Make a POST request to /v1/calls with the user ID and dial string:

curl -X POST https://api.dialstack.ai/v1/calls \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: acct_01h2xcejqtf2nbrexx3vqjhp41" \
-H "Content-Type: application/json" \
-d '{
"user_id": "user_01h2xcejqtf2nbrexx3vqjhp42",
"dial_string": "+15551234567"
}'

The API returns 202 Accepted immediately. The call is processed asynchronously.

Using the SDK

import { loadDialStack } from '@dialstack/sdk';

const dialstack = await loadDialStack('pk_test_...', {
fetchClientSecret: async () => {
const response = await fetch('/api/dialstack/session');
return response.json();
},
});

// Initiate a call
await dialstack.calls.create({
userId: 'user_01h2xcejqtf2nbrexx3vqjhp42',
dialString: '+15551234567',
});

Request Parameters

FieldTypeRequiredDescription
user_idstringYesThe user whose devices will ring first
dial_stringstringYesThe number to dial (see formats below)

Dial String Formats

The dial_string parameter accepts several formats:

FormatExampleDescription
E.164+15551234567International format (recommended)
Local5551234567Normalized based on account region
Extension1001Internal extension dialing
Emergency911Emergency services

Server-Side Implementation

Here's how to implement a click-to-call endpoint in your backend:

Node.js / Express

import express from 'express';

const app = express();
app.use(express.json());

// Your platform's API key
const DIALSTACK_API_KEY = process.env.DIALSTACK_API_KEY;

app.post('/api/call', async (req, res) => {
const { userId, phoneNumber, accountId } = req.body;

try {
const response = await fetch('https://api.dialstack.ai/v1/calls', {
method: 'POST',
headers: {
Authorization: `Bearer ${DIALSTACK_API_KEY}`,
'DialStack-Account': accountId,
'Content-Type': 'application/json',
},
body: JSON.stringify({
user_id: userId,
dial_string: phoneNumber,
}),
});

if (response.status === 202) {
res.json({ success: true, message: 'Call initiated' });
} else {
const error = await response.json();
res.status(response.status).json(error);
}
} catch (error) {
res.status(500).json({ error: 'Failed to initiate call' });
}
});

Python / Flask

from flask import Flask, request, jsonify
import requests
import os

app = Flask(__name__)

DIALSTACK_API_KEY = os.environ.get('DIALSTACK_API_KEY')

@app.route('/api/call', methods=['POST'])
def initiate_call():
data = request.json

response = requests.post(
'https://api.dialstack.ai/v1/calls',
headers={
'Authorization': f'Bearer {DIALSTACK_API_KEY}',
'DialStack-Account': data['account_id'],
'Content-Type': 'application/json'
},
json={
'user_id': data['user_id'],
'dial_string': data['phone_number']
}
)

if response.status_code == 202:
return jsonify({'success': True, 'message': 'Call initiated'})
else:
return jsonify(response.json()), response.status_code

Frontend Integration

Add click-to-call buttons to your UI:

function CustomerCard({ customer, currentUser, accountId }) {
const [calling, setCalling] = useState(false);

async function handleCall() {
setCalling(true);
try {
const response = await fetch('/api/call', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
userId: currentUser.dialstackUserId,
phoneNumber: customer.phone,
accountId: accountId,
}),
});

if (response.ok) {
// Show "Calling..." indicator
showNotification('Calling ' + customer.name);
}
} finally {
setCalling(false);
}
}

return (
<div className="customer-card">
<h3>{customer.name}</h3>
<p>{customer.phone}</p>
<button onClick={handleCall} disabled={calling}>
{calling ? 'Calling...' : 'Call'}
</button>
</div>
);
}

Error Handling

StatusErrorDescription
400user_id is requiredMissing user_id in request
400dial_string is requiredMissing dial_string in request
400Invalid user_id formatuser_id is not a valid TypeID
401UnauthorizedInvalid or missing API key/session
404User not foundUser doesn't exist in the account

Best Practices

DO

  • Validate phone numbers before sending to the API
  • Show a loading state while the call is being initiated
  • Use E.164 format for phone numbers when possible
  • Log call attempts for troubleshooting

DON'T

  • Don't expose your platform API key in client-side code
  • Don't allow arbitrary dial strings from user input without validation
  • Don't retry failed calls automatically (let the user decide)

Monitoring Calls

After initiating a call, you can track its progress: