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:

  1. A YourGPT account with a configured chatbot
  2. A Phone AI Agent set up and configured (see Phone AI Integration guide)
  3. Your Agent ID (found in Phone AI settings)
  4. 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/makeOutboundCall

Headers:

{
  "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_here

Security 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.


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

  1. Loading States: Always show loading indicators during API calls
  2. Clear Instructions: Explain the phone number format to users
  3. Confirmation: Show a success message after initiating the call
  4. 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.

On this page