For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
HomeGet API key
DocumentationIntegrationsAPI Reference
DocumentationIntegrationsAPI Reference
  • Get Started
    • Welcome
  • Guides
    • Agents
    • Phone Numbers
    • Conversations
    • Calls
    • Webhooks
    • Agent Webhooks
    • Usage & Billing
  • Reference
    • Pagination
    • Error Handling
    • Messaging Rate Limits
    • Testing
    • Best Practices
    • Code Examples
    • FAQ
  • SDKs
    • TypeScript / JavaScript
    • Python
LogoLogo
HomeGet API key
On this page
  • Testing webhooks locally
  • Using ngrok
  • Using localtunnel
  • Test webhook endpoint
  • Mock webhook payloads
  • SMS payload
  • Voice payload
  • Testing with curl
  • Example test handlers
  • Python (Flask)
  • Node.js (Express)
  • Checking webhook deliveries
Reference

Testing

Was this page helpful?
Previous

Best Practices

Next
Built with

This guide covers how to test your AgentPhone integration during development, including local webhook testing and mock payloads.

Testing webhooks locally

To receive webhooks during development, you need to expose your local server to the internet. We recommend ngrok.

Using ngrok

1

Install ngrok

Download from ngrok.com, or install via Homebrew:

$brew install ngrok
2

Start your local server

$python app.py # or node server.js
3

Expose your local port

In a separate terminal:

$ngrok http 3000

Copy the HTTPS URL (e.g., https://abc123.ngrok.io).

4

Register the URL as your webhook

$curl -X POST "https://api.agentphone.ai/v1/webhooks" \
> -H "Authorization: Bearer YOUR_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{"url": "https://abc123.ngrok.io/webhook"}'
5

Send a test webhook

$curl -X POST "https://api.agentphone.ai/v1/webhooks/test" \
> -H "Authorization: Bearer YOUR_API_KEY"

Using localtunnel

$npm install -g localtunnel
$lt --port 3000

Use the provided URL as your webhook URL.

Free ngrok accounts have session limits. The tunnel will disconnect and you’ll need to restart ngrok and update your webhook URL. For persistent tunnels, consider a paid ngrok plan or deploying to a cloud service.

Test webhook endpoint

Use the test endpoint to verify your webhook handler is working correctly. This sends a sample agent.message payload to your configured URL:

$curl -X POST "https://api.agentphone.ai/v1/webhooks/test" \
> -H "Authorization: Bearer YOUR_API_KEY"
1{
2 "success": true,
3 "httpStatus": 200,
4 "errorMessage": null
5}

You can also test per-agent webhooks:

$curl -X POST "https://api.agentphone.ai/v1/agents/agt_abc123/webhook/test" \
> -H "Authorization: Bearer YOUR_API_KEY"

Mock webhook payloads

Use these sample payloads to test your webhook handler locally with curl or in your test suite.

SMS payload

1{
2 "event": "agent.message",
3 "channel": "sms",
4 "timestamp": "2025-12-03T10:05:00Z",
5 "agentId": "agent_123",
6 "data": {
7 "conversationId": "conv_test456",
8 "numberId": "num_abc",
9 "from": "+14155551234",
10 "to": "+18571234567",
11 "message": "Test message",
12 "direction": "inbound",
13 "receivedAt": "2025-12-03T10:05:00Z"
14 },
15 "conversationState": { "testMode": true },
16 "recentHistory": [
17 { "content": "Hello", "direction": "inbound", "channel": "sms", "at": "2025-12-03T10:04:00Z" }
18 ]
19}

Voice payload

1{
2 "event": "agent.message",
3 "channel": "voice",
4 "timestamp": "2025-12-03T10:05:00Z",
5 "agentId": "agent_123",
6 "data": {
7 "callId": "call_abc123",
8 "numberId": "num_abc",
9 "from": "+14155551234",
10 "to": "+18571234567",
11 "status": "in-progress",
12 "transcript": "I need help with my order",
13 "confidence": 0.95,
14 "direction": "inbound"
15 },
16 "conversationState": null,
17 "recentHistory": [
18 { "content": "Hello, how can I help?", "direction": "outbound", "channel": "voice", "at": "2025-12-03T10:04:30Z" }
19 ]
20}

Testing with curl

Send a mock payload to your local server:

$curl -X POST http://localhost:3000/webhook \
> -H "Content-Type: application/json" \
> -d '{
> "event": "agent.message",
> "channel": "voice",
> "agentId": "agent_123",
> "data": {
> "callId": "call_test",
> "from": "+14155551234",
> "to": "+18571234567",
> "transcript": "What are your hours?",
> "confidence": 0.95,
> "direction": "inbound"
> },
> "conversationState": null,
> "recentHistory": []
> }'

Example test handlers

Python (Flask)

1from flask import Flask, request, jsonify
2
3app = Flask(__name__)
4
5@app.route('/webhook', methods=['POST'])
6def webhook():
7 payload = request.json
8 channel = payload.get('channel')
9 data = payload.get('data', {})
10
11 if channel == 'sms':
12 print(f"SMS from {data['from']}: {data['message']}")
13 return jsonify({'status': 'ok'}), 200
14
15 if channel == 'voice':
16 print(f"Voice from {data['from']}: {data['transcript']}")
17 return jsonify({'text': f"I heard: {data['transcript']}"}), 200
18
19 return jsonify({'status': 'ok'}), 200
20
21if __name__ == '__main__':
22 app.run(port=3000)

Node.js (Express)

1const express = require('express');
2const app = express();
3app.use(express.json());
4
5app.post('/webhook', (req, res) => {
6 const { channel, data } = req.body;
7
8 if (channel === 'sms') {
9 console.log(`SMS from ${data.from}: ${data.message}`);
10 return res.status(200).json({ status: 'ok' });
11 }
12
13 if (channel === 'voice') {
14 console.log(`Voice from ${data.from}: ${data.transcript}`);
15 return res.status(200).json({ text: `I heard: ${data.transcript}` });
16 }
17
18 res.status(200).json({ status: 'ok' });
19});
20
21app.listen(3000, () => console.log('Webhook server on port 3000'));

Checking webhook deliveries

Monitor delivery status to debug issues:

$curl "https://api.agentphone.ai/v1/webhooks/deliveries?limit=10" \
> -H "Authorization: Bearer YOUR_API_KEY"

The response shows delivery attempts, HTTP status codes, error messages, and retry timestamps. Use this to verify your endpoint is receiving and acknowledging webhooks correctly.