There is a feature that almost every product manager has requested at least once: a "Call Me Back" button.
The user fills in their phone number, hits the button, and within seconds — an agent calls them back.
The problem? Traditionally this meant integrating with a call center, managing agents, paying per-seat licensing, and hoping someone picks up at 2am.
With an AI agent backed by VoIPBin, you can build this entire flow yourself — triggered from a simple API call, available 24/7, no human required.
This post walks through the full implementation.
What We Are Building
User clicks "Call Me Back" on your website
↓
Your backend calls VoIPBin API → outbound call placed
↓
User picks up → AI agent speaks greeting
↓
STT captures user voice → your webhook receives transcript
↓
You run logic (answer questions, qualify lead, collect info)
↓
TTS responds → conversation continues until resolved
Your server handles only text. VoIPBin handles the call, audio codec negotiation, STT, TTS, and everything telephony-related.
Step 1: Get Your API Key
No credit card required to start. Sign up with a single request:
curl -s -X POST https://api.voipbin.net/v1.0/auth/signup \
-H "Content-Type: application/json" \
-d '{
"username": "yourname",
"password": "yourpassword",
"email": "you@example.com"
}'
The response includes accesskey.token — that is your API key.
Step 2: The Frontend Button
A minimal "Call Me Back" form in plain HTML:
<form id="callback-form">
<label for="phone">Your phone number</label>
<input type="tel" id="phone" name="phone"
placeholder="+1 415 555 0100" required />
<button type="submit">Call Me Back</button>
</form>
<script>
document.getElementById("callback-form").addEventListener("submit", async (e) => {
e.preventDefault();
const phone = document.getElementById("phone").value;
const res = await fetch("/api/callback", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ phone })
});
const data = await res.json();
if (data.ok) {
alert("Calling you now!");
}
});
</script>
Step 3: Backend — Place the Outbound Call
Your /api/callback endpoint receives the user's phone number and triggers an outbound call via VoIPBin.
Here is a Node.js/Express example:
const express = require("express");
const app = express();
app.use(express.json());
const VOIPBIN_TOKEN = process.env.VOIPBIN_TOKEN;
const YOUR_CALLER_ID = "+15550001234"; // your VoIPBin number
const WEBHOOK_URL = "https://yourapp.com/api/voice-webhook";
app.post("/api/callback", async (req, res) => {
const { phone } = req.body;
const response = await fetch("https://api.voipbin.net/v1.0/calls", {
method: "POST",
headers: {
"Authorization": `Bearer ${VOIPBIN_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
source: { type: "tel", target: YOUR_CALLER_ID },
destinations: [{ type: "tel", target: phone }],
flow_id: null,
webhook: { url: WEBHOOK_URL }
})
});
const call = await response.json();
console.log("Call placed:", call.id);
res.json({ ok: true, call_id: call.id });
});
app.listen(3000);
Once the user picks up, VoIPBin fires events to your webhook.
Step 4: The AI Agent — Webhook Handler
When the call connects, VoIPBin sends a call.started event. You respond with instructions: speak a greeting, then listen for input.
app.post("/api/voice-webhook", async (req, res) => {
const event = req.body;
if (event.type === "call.started") {
return res.json({
actions: [
{
type: "talk",
text: "Hi! Thanks for requesting a callback from Acme. What can I help you with today?"
},
{
type: "listen",
timeout: 8,
max_duration: 15
}
]
});
}
if (event.type === "call.transcription") {
const userSaid = event.transcript;
const aiReply = await getAIReply(userSaid);
return res.json({
actions: [
{
type: "talk",
text: aiReply
},
{
type: "listen",
timeout: 8,
max_duration: 20
}
]
});
}
if (event.type === "call.ended") {
console.log("Callback call completed:", event.call_id);
return res.json({ ok: true });
}
res.json({});
});
Step 5: Connect an LLM
The getAIReply function is where your product logic lives. A minimal example using OpenAI:
const { OpenAI } = require("openai");
const openai = new OpenAI();
async function getAIReply(userMessage) {
const completion = await openai.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{
role: "system",
content: "You are a helpful support agent for Acme Corp. Answer questions about our product concisely. If the user wants to speak to a human, say: I will transfer you now. Keep responses under 2 sentences for phone clarity."
},
{ role: "user", content: userMessage }
]
});
return completion.choices[0].message.content;
}
Swap OpenAI for Anthropic Claude, Google Gemini, or any LLM — the interface stays the same.
What You Just Built
With roughly 80 lines of code, you have:
- A working "Call Me Back" button any website can embed
- Outbound calls triggered by your backend
- AI agent that greets and converses with callers
- STT to LLM to TTS pipeline, fully managed by VoIPBin
- No telephony infrastructure to operate
Your team never picks up the phone. The AI handles the first touch, qualifies the question, or resolves it entirely.
Extensions Worth Building
Escalate to a human when needed:
if (aiReply.includes("transfer you now")) {
return res.json({
actions: [
{ type: "talk", text: "Connecting you to our team." },
{ type: "transfer", destination: { type: "tel", target: "+15559998888" } }
]
});
}
Log every callback to a CRM:
if (event.type === "call.ended") {
await crm.createTicket({
phone: event.caller,
summary: conversationSummary,
resolved: !escalated
});
}
Respect business hours — schedule the call for later:
if (!isBusinessHours()) {
const scheduledAt = nextBusinessHourTimestamp();
body.scheduled_at = scheduledAt;
}
Try It
- Docs and API reference: https://voipbin.net
- Golang SDK:
go get github.com/voipbin/voipbin-go - MCP server (use from Claude Code or Cursor):
uvx voipbin-mcp
Signup takes one API call. No OTP, no waiting, no approval queue.
If you build something interesting with this, drop it in the comments.
Top comments (0)