Skip to main content

Webhooks Overview

Webhooks are HTTP callbacks that Superfone sends to your server when specific call events occur. They enable real-time communication between Superfone and your application, allowing you to respond dynamically to call events.

How Webhooks Work

When a call event occurs (e.g., call answered, call ended), Superfone makes an HTTP request to your configured webhook URL with a JSON payload containing event details. Your server processes the payload and responds accordingly.

Webhook Types

SFVoPI supports three types of webhooks:

WebhookWhen CalledResponse RequiredTimeout
Answer WebhookWhen call is answered (callee picks up)Yes — must return Stream JSON10 seconds (with fallback)
Hangup WebhookWhen call ends (any reason)No — response ignored5 seconds (fire-and-forget)
Ring WebhookWhen phone starts ringing (optional)No — response ignored5 seconds (fire-and-forget)
info

The Answer Webhook is the most critical webhook — it MUST return a valid Stream JSON response within 10 seconds, or the call will fail. The Hangup Webhook is fire-and-forget and does not require a response.

Configuring Webhooks

Webhooks are configured at two levels:

1. App-Level Webhooks (Default)

When you create a SFVoPI app, you specify default webhook URLs that apply to all calls handled by that app:

{
"name": "My Voice App",
"answer_url": "https://your-server.com/webhook/answer",
"answer_method": "POST",
"hangup_url": "https://your-server.com/webhook/hangup",
"hangup_method": "POST",
"fallback_answer_url": "https://backup-server.com/webhook/answer",
"fallback_answer_method": "POST"
}

See: Create App API

2. Call-Level Webhooks (Override)

When initiating an outbound call, you can override the app's default webhooks for that specific call:

{
"from": "+918000000003",
"to": "+918000000001",
"answer_url": "https://custom-server.com/webhook/answer",
"answer_method": "POST",
"ring_url": "https://custom-server.com/webhook/ring",
"ring_method": "POST",
"hangup_url": "https://custom-server.com/webhook/hangup",
"hangup_method": "POST"
}

See: Initiate Call API

HTTP Methods

Webhooks support two HTTP methods:

  • POST (recommended): Payload sent in request body as JSON
  • GET: Payload sent as URL query parameters
tip

Use POST for webhooks to avoid URL length limits and ensure proper JSON encoding. GET is provided for compatibility with legacy systems.

Webhook Timeouts

WebhookTimeoutFallback Behavior
Answer Webhook10 secondsIf primary answer_url fails or times out, Superfone tries fallback_answer_url (if configured) with 5-second timeout
Hangup Webhook5 secondsFire-and-forget — errors logged but do not affect call
Ring Webhook5 secondsFire-and-forget — errors logged but do not affect call
warning

If both answer_url and fallback_answer_url fail or time out, the call will be terminated with a failure status.

Webhook Security

HTTPS Required

All webhook URLs must use HTTPS in production. HTTP is only allowed for local development (e.g., http://localhost:3000).

Restrict webhook endpoint access to Superfone's IP addresses:

# Superfone webhook source IPs (example)
203.0.113.10
203.0.113.11
203.0.113.12

Contact Superfone support for the current list of webhook source IPs.

Request Validation

Validate incoming webhook requests:

  1. Check Content-Type: Ensure Content-Type: application/json for POST requests
  2. Validate Payload Schema: Use JSON schema validation to ensure payload structure matches expected format
  3. Check Required Fields: Verify all required fields are present (e.g., call_uuid, from, to)
info

Webhook signature verification (HMAC-based authentication) is not currently implemented but may be added in future releases.

Webhook Reliability

Idempotency

Webhooks are not guaranteed to be delivered exactly once. Your server should handle duplicate webhook deliveries gracefully:

  • Use call_uuid or request_uuid as idempotency key
  • Check if event already processed before taking action
  • Store processed event IDs in database or cache
const processedEvents = new Set();

app.post('/webhook/hangup', (req, res) => {
const { call_uuid } = req.body;

// Check if already processed
if (processedEvents.has(call_uuid)) {
console.log(`Duplicate hangup webhook for call ${call_uuid}`);
return res.json({ received: true });
}

// Process event
processedEvents.add(call_uuid);
// ... handle hangup logic

res.json({ received: true });
});

Retry Logic

Superfone does not automatically retry failed webhook deliveries. If your server is temporarily unavailable:

  • Answer Webhook: Superfone tries fallback_answer_url (if configured), then fails the call
  • Hangup Webhook: Event is lost (fire-and-forget)
  • Ring Webhook: Event is lost (fire-and-forget)
tip

Ensure your webhook endpoints have high availability (99.9%+ uptime) and fast response times (<1 second).

Response Requirements

Answer Webhook

MUST return HTTP 200 with valid Stream JSON:

{
"stream": {
"url": "wss://your-server.com/ws",
"codec": "PCMU",
"sample_rate": 8000,
"direction": "BOTH",
"stream_timeout": 86400,
"extra_headers": { "X-Session-Id": "abc123" }
}
}

See: Answer Webhook

Hangup Webhook

Response is ignored — return any HTTP 2xx status to acknowledge receipt:

{
"received": true
}

See: Hangup Webhook

Ring Webhook

Response is ignored — return any HTTP 2xx status to acknowledge receipt:

{
"received": true
}

Error Handling

Answer Webhook Errors

If your answer webhook fails (timeout, non-200 status, invalid JSON), Superfone:

  1. Tries fallback_answer_url (if configured)
  2. If fallback also fails, terminates call with FAILED status
  3. Sends hangup webhook with call_status: "FAILED"

Hangup Webhook Errors

Errors are logged but do not affect call processing (fire-and-forget).

Common Error Scenarios

ErrorCauseSolution
TimeoutServer response took >10s (answer) or >5s (hangup)Optimize webhook handler, return response quickly
Connection refusedServer not reachable at webhook URLCheck firewall, DNS, server status
Invalid JSONResponse body is not valid JSONValidate JSON before sending response
Schema validation failedStream JSON missing required fieldsEnsure all required fields present (url, codec, sample_rate, direction)

Testing Webhooks

Local Development with ngrok

Use ngrok to expose your local server for webhook testing:

# Start your server
npm run dev

# In another terminal, expose port 3000
ngrok http 3000

# Copy the HTTPS URL (e.g., https://abc123.ngrok.io)
# Use this URL in your SFVoPI app configuration

Webhook Testing Tools

  • Postman: Simulate webhook requests with custom payloads
  • RequestBin: Capture and inspect webhook requests
  • ngrok Inspector: View webhook requests in real-time at http://localhost:4040

Example Test Payload

curl -X POST https://your-server.com/webhook/answer \
-H "Content-Type: application/json" \
-d '{
"call_uuid": "test-uuid-12345",
"request_uuid": "sfv_ob_req_test123",
"from": "+918000000003",
"to": "+918000000001",
"direction": "OUTBOUND",
"call_status": "IN_PROGRESS",
"answered_at": "2026-02-02T10:00:00.000Z"
}'

Next Steps