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:
- First leg: All of the user's registered devices (desk phones, softphones) ring simultaneously
- Answer: The user picks up any of their devices
- Second leg: The system dials the destination number
- 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
| Field | Type | Required | Description |
|---|---|---|---|
user_id | string | Yes | The user whose devices will ring first |
dial_string | string | Yes | The number to dial (see formats below) |
Dial String Formats
The dial_string parameter accepts several formats:
| Format | Example | Description |
|---|---|---|
| E.164 | +15551234567 | International format (recommended) |
| Local | 5551234567 | Normalized based on account region |
| Extension | 1001 | Internal extension dialing |
| Emergency | 911 | Emergency 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
| Status | Error | Description |
|---|---|---|
| 400 | user_id is required | Missing user_id in request |
| 400 | dial_string is required | Missing dial_string in request |
| 400 | Invalid user_id format | user_id is not a valid TypeID |
| 401 | Unauthorized | Invalid or missing API key/session |
| 404 | User not found | User 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:
- Use the Real-Time Events API to receive call status updates
- Query the Call Logs API to retrieve call history
Related Resources
- API Reference - Complete API documentation
- Real-Time Events - Receive call status updates
- Authentication - Authentication guide