Click-to-Call Integration
Add AI-powered outbound calling to your website with YourGPT's Phone AI Agent API
What is Click-to-Call?
Click-to-Call enables you to add a "Call Me" or "Get a Call" button to your website that triggers an AI-powered outbound phone call. When users click the button and provide their phone number, YourGPT's Phone AI Agent automatically calls them to qualify leads, book appointments, provide support, or any other use case you configure.
This feature turns passive website visitors into engaged leads through personalized voice conversations powered by AI.
Use Cases
Click-to-Call is perfect for:
- Healthcare: Schedule doctor appointments, send appointment reminders
- Travel & Hospitality: Trip planning consultations, booking assistance
- Sales & CRM: Lead qualification, customer outreach, follow-ups
- E-commerce: Order confirmations, delivery updates
- Professional Services: Consultation scheduling, service inquiries
Prerequisites
Before implementing Click-to-Call, you need:
- A YourGPT account with a configured chatbot
- A Phone AI Agent set up and configured (see Phone AI Integration guide)
- Your Agent ID (found in Phone AI settings)
- An API Key (generated from Integration settings)
API Endpoint
Click-to-Call uses the makeOutboundCall endpoint. For complete API documentation, see the Make Outbound Call API Reference.
Endpoint:
POST https://api.yourgpt.ai/chatbot/v1/makeOutboundCallHeaders:
{
"Content-Type": "application/json",
"api-key": "your_api_key_here"
}Request Body:
{
"agent_id": "your_agent_id",
"call_to": "+1234567890",
"extra_data": {
"contact_data": {
"name": "John Doe",
"phone": "+1234567890"
}
}
}Phone Number Format
Phone numbers must be in E.164 format (starting with + followed by country code and number). Example: +1234567890
Implementation Examples
Basic React/Next.js Example
Here's a simple form-based implementation:
"use client";
import { useState } from "react";
import { toast } from "sonner"; // or your preferred toast library
export default function CallMeForm() {
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [loading, setLoading] = useState(false);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
// Validation
if (!name || !phone) {
toast.error("Please fill in all fields");
return;
}
if (!phone.startsWith("+")) {
toast.error("Phone number must start with + (e.g., +1234567890)");
return;
}
try {
setLoading(true);
const response = await fetch("https://api.yourgpt.ai/chatbot/v1/makeOutboundCall", {
method: "POST",
headers: {
"Content-Type": "application/json",
"api-key": process.env.NEXT_PUBLIC_API_KEY!,
},
body: JSON.stringify({
agent_id: process.env.NEXT_PUBLIC_AGENT_ID!,
call_to: phone,
extra_data: {
contact_data: {
name: name,
phone: phone,
},
},
}),
});
const result = await response.json();
if (result.type === "RXSUCCESS") {
toast.success("Call initiated! You'll receive a call shortly.");
setName("");
setPhone("");
} else {
toast.error("Failed to initiate call. Please try again.");
}
} catch (error) {
console.error("Error:", error);
toast.error("Something went wrong. Please try again.");
} finally {
setLoading(false);
}
}
return (
<form onSubmit={handleSubmit} className="flex flex-col gap-4 max-w-md">
<h2 className="text-2xl font-bold">Get a Call from Our AI Assistant</h2>
<input
type="text"
placeholder="Your Name"
value={name}
onChange={(e) => setName(e.target.value)}
className="px-4 py-2 border rounded-md"
/>
<input
type="tel"
placeholder="Phone (e.g., +1234567890)"
value={phone}
onChange={(e) => setPhone(e.target.value)}
className="px-4 py-2 border rounded-md"
/>
<button
type="submit"
disabled={loading}
className="bg-blue-500 text-white px-6 py-3 rounded-md hover:bg-blue-600 disabled:opacity-50"
>
{loading ? "Initiating Call..." : "Call Me Now"}
</button>
</form>
);
}Environment Variables
Create a .env.local file in your project:
NEXT_PUBLIC_API_KEY=your_api_key_here
NEXT_PUBLIC_AGENT_ID=your_agent_id_hereSecurity Note
For production applications, consider creating a backend API route that handles the call initiation to keep your API key secure. The examples above use NEXT_PUBLIC_ variables for simplicity, but API keys should ideally be kept server-side.
Server-Side Implementation (Recommended)
For better security, create an API route in your Next.js app:
app/api/initiate-call/route.ts:
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
try {
const { name, phone } = await request.json();
// Validate input
if (!name || !phone) {
return NextResponse.json(
{ error: "Name and phone are required" },
{ status: 400 }
);
}
if (!phone.startsWith("+")) {
return NextResponse.json(
{ error: "Phone number must be in E.164 format" },
{ status: 400 }
);
}
// Call YourGPT API (API key is kept server-side)
const response = await fetch(
"https://api.yourgpt.ai/chatbot/v1/makeOutboundCall",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"api-key": process.env.YOURGPT_API_KEY!,
},
body: JSON.stringify({
agent_id: process.env.YOURGPT_AGENT_ID!,
call_to: phone,
extra_data: {
contact_data: {
name: name,
phone: phone,
},
},
}),
}
);
const result = await response.json();
if (!response.ok) {
return NextResponse.json(
{ error: result.message || "Failed to initiate call" },
{ status: response.status }
);
}
return NextResponse.json(result);
} catch (error) {
console.error("Error initiating call:", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 }
);
}
}Client-side code:
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setLoading(true);
try {
const response = await fetch("/api/initiate-call", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, phone }),
});
const result = await response.json();
if (response.ok && result.type === "RXSUCCESS") {
toast.success("Call initiated successfully!");
setName("");
setPhone("");
} else {
toast.error(result.error || "Failed to initiate call");
}
} catch (error) {
toast.error("Something went wrong");
} finally {
setLoading(false);
}
}Best Practices
Phone Number Validation
Always validate phone numbers before making API calls:
function validatePhoneNumber(phone: string): boolean {
// Must start with +
if (!phone.startsWith("+")) {
return false;
}
// Remove + and check if remaining chars are digits
const digits = phone.slice(1);
if (!/^\d+$/.test(digits)) {
return false;
}
// Length should be between 8 and 15 digits (E.164 format)
if (digits.length < 8 || digits.length > 15) {
return false;
}
return true;
}Error Handling
Handle different error scenarios gracefully:
const response = await fetch("https://api.yourgpt.ai/chatbot/v1/makeOutboundCall", {
// ... your config
});
const result = await response.json();
if (result.type === "RXERROR") {
switch (response.status) {
case 400:
toast.error("Invalid phone number format");
break;
case 401:
toast.error("Authentication failed");
break;
case 404:
toast.error("Agent not found");
break;
default:
toast.error(result.message || "Failed to initiate call");
}
}Rate Limiting
Consider implementing rate limiting to prevent abuse:
// Simple client-side rate limiting
const COOLDOWN_MS = 60000; // 1 minute
let lastCallTime = 0;
function canInitiateCall(): boolean {
const now = Date.now();
if (now - lastCallTime < COOLDOWN_MS) {
return false;
}
lastCallTime = now;
return true;
}User Experience
- Loading States: Always show loading indicators during API calls
- Clear Instructions: Explain the phone number format to users
- Confirmation: Show a success message after initiating the call
- Error Messages: Provide helpful error messages for different failure scenarios
Demo Repository
Check out our complete Click-to-Call Demo Repository on GitHub featuring:
- Doctor appointment booking
- Trip planning consultation
- CRM customer outreach
- Website development inquiry
- Multiple UI patterns (forms, modals, etc.)
Next Steps
Need Help?
Join our Discord Community for support and feedback.