This project implements an automated appointment confirmation system using the 8x8 Voice API. It allows you to simulate outbound calls to customers to confirm their appointments using an Interactive Voice Response (IVR) system.
- Common Use Cases
- Features
- Prerequisites
- Setup Guide
- Making Test Calls
- API Documentation
- Additional Information
- Walkthrough Videos
This system can be adapted for various scenarios, including:
- Medical appointments and healthcare consultations
- Restaurant reservations and dining bookings
- Salon and spa services
- Vehicle service appointments and maintenance
- Professional consultations (legal, financial, real estate)
Each use case can be implemented by customizing the voice prompts and workflow in the application configuration.
- Outbound calls to confirm appointments or reservations
- Interactive voice menu for customers to confirm or cancel
- Real-time webhook handling for call events
- Session tracking for call state management
- Detailed logging for debugging and monitoring
🔑 Required accounts and resources
- Docker and Docker Compose
- 8x8 Connect Account with:
- API Key
- Subaccount ID
- Virtual Number (for outbound calls)
- Ngrok account with authtoken and a static domain for local testing
🔄 Setting Up Ngrok
This project requires ngrok with a static domain for webhook handling:
- Ngrok account: Sign up at ngrok.com
- Static domain: Head over to https://dashboard.ngrok.com/domains to create a static domain (Limited to 1 static url for free ngrok accounts)
- Authtoken: Go to https://dashboard.ngrok.com/authtokens to create an authtoken
While there are alternatives to ngrok, such as:
- Deploying to a cloud provider (AWS, GCP, Azure)
- Using other tunneling services like Cloudflare Tunnel
- Setting up your own reverse proxy with a static IP
Please note that this project's Docker configuration, scripts, and overall implementation are specifically designed for ngrok. Using any alternative would require significant changes to the Docker setup, configuration files, and possibly the application code.
🐳 Quick Start with Docker (Recommended)
-
Clone the repository:
git clone https://github.com/8x8/cpaas_voice_ivr.git cd cpaas_voice_ivr -
Set up environment variables:
cp .env.example .env
Edit
.envand fill in your credentials:EIGHT_X_EIGHT_API_KEY=your_api_key_from_connect_portal EIGHT_X_EIGHT_SUBACCOUNT_ID=your_subaccount_id OUTBOUND_PHONE_NUMBER=your_virtual_number # Must be in international format e.g for SG +6591234567 WEBHOOK_AUTH_TOKEN=your_randomly_generated_webhook_auth_token WEBHOOK_BASE_URL=your_static_ngrok_domain # e.g., https://your-domain.ngrok-free.app NGROK_AUTHTOKEN=your_ngrok_authtokenNote: The
OUTBOUND_PHONE_NUMBERis used as the source number for all outbound calls. It must be a valid 8x8 virtual number configured in your account. Reach out to cpaas-support@8x8.com or your account manager if unsure. -
Configure your static ngrok domain:
- Go to https://dashboard.ngrok.com/domains to find your static ngrok domain or create one if you haven't already.
- Update
WEBHOOK_BASE_URLin your.envfile with your static ngrok domain. - Edit the
docker-compose.ymlfile and update the--domainparameter in theNGROK_OPTSenvironment variable with your static domain:- 'NGROK_OPTS=--log=stdout --domain=your-domain.ngrok-free.app'
Note: The ngrok configuration is automatically generated inside the container, so you don't need to manually create or edit an ngrok.yml file.
-
Configure webhooks in 8x8 Connect console or via API:
- VCA Webhook URL:
{WEBHOOK_BASE_URL}/api/webhooks/vca - VSS Webhook URL:
{WEBHOOK_BASE_URL}/api/webhooks/vss
- VCA Webhook URL:
-
Start the application:
# For first time setup, use --build flag docker-compose up -d --build # For subsequent starts docker-compose up -d
To check the status of your services:
docker ps
To view the ngrok tunnel URL:
curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"[^"]*' | grep -o 'http[^"]*'
To stop the services:
docker-compose down
The application is now ready to handle calls!
⚙️ Manual Installation (Alternative)
If you prefer not to use Docker, you can install the application manually:
-
Clone the repository:
git clone https://github.com/8x8/cpaas_voice_ivr.git cd cpaas_voice_ivr -
Create and activate a virtual environment:
python -m venv venv source venv/bin/activate # On Windows, use: venv\Scripts\activate
-
Install dependencies:
pip install -r requirements.txt
-
Set up environment variables:
cp .env.example .env
Edit
.envand fill in your credentials:EIGHT_X_EIGHT_API_KEY=your_api_key_from_connect_portal EIGHT_X_EIGHT_SUBACCOUNT_ID=your_subaccount_id OUTBOUND_PHONE_NUMBER=your_virtual_number # Must be in international format e.g for SG +6591234567 WEBHOOK_AUTH_TOKEN=your_randomly_generated_webhook_auth_token WEBHOOK_BASE_URL=your_static_ngrok_domain # e.g., https://your-domain.ngrok-free.app NGROK_AUTHTOKEN=your_ngrok_authtokenNote: The
OUTBOUND_PHONE_NUMBERis used as the source number for all outbound calls. It must be a valid 8x8 virtual number configured in your account. -
Configure your static ngrok domain:
- Go to https://dashboard.ngrok.com/domains to find your static ngrok domain or create one if you haven't already.
- Update
WEBHOOK_BASE_URLin your.envfile with your static ngrok domain.
-
Configure webhooks in 8x8 Connect console:
- VCA Webhook URL:
{WEBHOOK_BASE_URL}/api/webhooks/vca - VSS Webhook URL:
{WEBHOOK_BASE_URL}/api/webhooks/vss
Configure authentication as described in the Docker setup section (step 4).
- VCA Webhook URL:
-
Set up ngrok configuration: Create a file named
ngrok.ymlwith the following content, or simply copy ngrok.yml.example:version: 2 authtoken: your_ngrok_authtoken web_addr: 0.0.0.0:4040 tunnels: http: addr: 5678 proto: http domain: your-static-domain.ngrok-free.app # Use your static domain here basic_auth: - "admin:your_webhook_auth_token" # Same as WEBHOOK_AUTH_TOKEN in .env
-
Start ngrok to create a tunnel for webhooks:
# Start ngrok with the configuration file ngrok start --config ngrok.yml httpThis command starts the tunnel named "http" defined in your configuration file.
Verify that ngrok is using your static domain by checking the output. You should see a line like:
started tunnel http -> http://localhost:5678 url: https://your-static-domain.ngrok-free.app -
Start the FastAPI server:
python -m uvicorn main:app --reload --port 5678
🧪 Testing with cURL
Use curl or any API client to make a test call. First, create a Base64 encoded string of admin:your_webhook_auth_token:
# On Mac/Linux
echo -n "admin:your_webhook_auth_token" | base64
# On Windows PowerShell
[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("admin:your_webhook_auth_token"))Then use the encoded string in your API call:
curl --location 'http://localhost:5678/api/make-call' \
--header 'Authorization: Basic YOUR_BASE64_ENCODED_STRING' \
--header 'Content-Type: application/json' \
--data '{
"orderId": "APT123",
"customerPhone": "+6591234567",
"businessName": "Business Name",
"appointmentTime": "2025-04-20T19:30:00Z"
}'Example:
- If your
WEBHOOK_AUTH_TOKENissecret123 - Base64 encode
admin:secret123→YWRtaW46c2VjcmV0MTIz - Use
Authorization: Basic YWRtaW46c2VjcmV0MTIzin the header
Note: The call will be made from the OUTBOUND_PHONE_NUMBER specified in your .env file
🔌 Available Endpoints
-
POST /api/make-call- Makes an outbound call to confirm an appointment
- Uses OUTBOUND_PHONE_NUMBER from .env as the source number
- Requires Basic Auth (admin:WEBHOOK_AUTH_TOKEN encoded in Base64)
- Request body example:
{ "orderId": "APT123", "customerPhone": "+6591234567", "businessName": "Ana's Dental Clinic", "appointmentTime": "2025-04-20T19:30:00Z" }
-
POST /api/webhooks/vca- Handles Voice Call Action webhooks from 8x8
-
POST /api/webhooks/vss- Handles Voice Session Summary webhooks from 8x8
🔄 Call Flow
- System makes an outbound call to the customer
- Plays a message with appointment details
- Customer inputs DTMF:
- Press 1 to confirm
- Press 0 to cancel
- System responds with confirmation/cancellation message
- Call ends with appropriate status
📝 Logging
You can view logs of inbound/outbound API requests via ngrok's Traffic Inspector by going to:
- http://localhost:4040/ (legacy but cleaner interface)
- https://dashboard.ngrok.com/ → "Traffic Inspector" in the left menu