Skip to main content
POST
/
api
/
v1
/
voice
/
webhook
Voice Webhook
curl --request POST \
  --url https://api.example.com/api/v1/voice/webhook \
  --header 'Content-Type: application/json' \
  --data '
{
  "sessionId": "<string>",
  "phoneNumber": "<string>",
  "recordingUrl": "<string>",
  "duration": 123,
  "status": "<string>"
}
'
{
  "status": "<string>",
  "session_id": "<string>",
  "error": "<string>"
}

Overview

This webhook endpoint receives real-time updates about voice conference calls from Africa’s Talking voice service. It automatically updates recording status and stores recording URLs when calls complete.
This endpoint is called automatically by Africa’s Talking. You don’t need to call it manually. Configure this URL in your Africa’s Talking voice dashboard.

Webhook Configuration

In your Africa’s Talking dashboard:
  1. Navigate to Voice > Settings
  2. Set callback URL to: https://api.voicepact.com/api/v1/voice/webhook
  3. Enable POST method
  4. Save configuration

Request Format

Africa’s Talking sends form-encoded data with the following fields:
sessionId
string
Unique identifier for the voice session (matches conference_id)
phoneNumber
string
Phone number of the party in E.164 format
recordingUrl
string
URL where the call recording can be downloaded
duration
integer
Call duration in seconds
status
string
Call status: completed, failed, busy, no-answer

Example Webhook Payload

Successful Call Completion

POST /api/v1/voice/webhook HTTP/1.1
Host: api.voicepact.com
Content-Type: application/x-www-form-urlencoded

sessionId=ATVoice_a1b2c3d4e5f6&phoneNumber=%2B254712345678&recordingUrl=https%3A%2F%2Fvoice.africastalking.com%2Frecordings%2Fa1b2c3d4e5f6.mp3&duration=420&status=completed
Decoded values:
{
  "sessionId": "ATVoice_a1b2c3d4e5f6",
  "phoneNumber": "+254712345678",
  "recordingUrl": "https://voice.africastalking.com/recordings/a1b2c3d4e5f6.mp3",
  "duration": 420,
  "status": "completed"
}

Failed Call

POST /api/v1/voice/webhook HTTP/1.1
Host: api.voicepact.com
Content-Type: application/x-www-form-urlencoded

sessionId=ATVoice_x9y8z7w6v5u4&phoneNumber=%2B254787654321&status=no-answer
Decoded values:
{
  "sessionId": "ATVoice_x9y8z7w6v5u4",
  "phoneNumber": "+254787654321",
  "status": "no-answer"
}

Response

The endpoint returns a JSON response acknowledging receipt:
status
string
Processing result: webhook_processed or webhook_error
session_id
string
The session ID that was processed
error
string
Error message (only present if status is webhook_error)

Success Response

{
  "status": "webhook_processed",
  "session_id": "ATVoice_a1b2c3d4e5f6"
}

Error Response

{
  "status": "webhook_error",
  "error": "Database connection timeout"
}

Webhook Processing Flow

  1. Receive Webhook: Africa’s Talking sends call status
  2. Parse Data: Extract form fields from request
  3. Lookup Recording: Find voice recording by session ID
  4. Update Status: Save recording URL, duration, and status
  5. Commit Changes: Persist updates to database
  6. Return Acknowledgment: Send success response

Status Values

StatusDescriptionRecording Available
completedCall successfully completedYes
failedCall failed due to technical errorNo
busyCalled party was busyNo
no-answerCalled party didn’t answerNo
rejectedCalled party rejected the callNo

Database Updates

When a webhook is received, the following fields are updated in the VoiceRecording table:
  • recording_url: Set to the provided recording URL
  • duration: Set to call duration in seconds
  • processing_status: Set to the call status
  • processed_at: Set to current timestamp

Monitoring Webhooks

You can query the recording status using the GET endpoint:
curl -X GET https://api.voicepact.com/api/v1/voice/recordings/ATVoice_a1b2c3d4e5f6 \
  -H "Authorization: Bearer YOUR_API_KEY"
Response:
{
  "recording_id": "ATVoice_a1b2c3d4e5f6",
  "status": "completed",
  "duration": 420,
  "recording_url": "https://voice.africastalking.com/recordings/a1b2c3d4e5f6.mp3",
  "created_at": "2026-03-06T14:00:00Z",
  "processed_at": "2026-03-06T14:07:00Z"
}

Security Considerations

IP Whitelisting

Consider restricting webhook access to Africa’s Talking IP addresses:
  • 52.47.190.220
  • 3.127.102.70

Signature Verification

Implement webhook signature verification to ensure authenticity:
import hmac
import hashlib

def verify_webhook(payload, signature, secret):
    expected = hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

HTTPS Only

Always use HTTPS endpoints for webhook URLs to protect data in transit.

Troubleshooting

Webhook Not Received

  1. Check URL Configuration: Verify webhook URL in Africa’s Talking dashboard
  2. Test Connectivity: Ensure your server is accessible from internet
  3. Check Firewall: Whitelist Africa’s Talking IPs
  4. Review Logs: Check server logs for incoming requests

Recording URL Not Saved

  1. Verify Session ID: Ensure session ID matches conference ID
  2. Check Database: Confirm recording entry exists
  3. Review Webhook Logs: Look for error messages in application logs

Multiple Webhooks

Africa’s Talking may send multiple webhooks per call (one per participant). The system updates the same recording entry with each webhook.

Testing Webhooks

Use tools like ngrok for local testing:
# Start ngrok tunnel
ngrok http 8000

# Use the ngrok URL in Africa's Talking dashboard
https://abc123.ngrok.io/api/v1/voice/webhook
Manually trigger a test webhook:
curl -X POST http://localhost:8000/api/v1/voice/webhook \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "sessionId=test_session_123&phoneNumber=%2B254712345678&recordingUrl=https%3A%2F%2Fexample.com%2Ftest.mp3&duration=300&status=completed"

Best Practices

  • Idempotency: Handle duplicate webhooks gracefully
  • Async Processing: Don’t block webhook response with heavy operations
  • Error Logging: Log all webhook processing errors for debugging
  • Monitoring: Set up alerts for webhook failures
  • Retry Logic: Africa’s Talking retries failed webhooks automatically

Build docs developers (and LLMs) love