← Back to Documentation

Webhooks Configuration

Set up inbound webhooks from Twilio, Stripe, and HubSpot to power real-time lead capture, billing, and CRM sync.

🔔 Required Webhook Endpoints

1

Twilio SMS Webhook

Receives inbound SMS replies and delivery status updates

Endpoint:/api/webhooks/twilio/sms
Configure in:Twilio Console → Messaging → Settings → Webhook URL
Events to enable:
  • Inbound SMS (lead replies)
  • Delivery receipts (sent/delivered/failed)
Verification:X-Twilio-Signature header validated using Auth Token
Example Payload
{
  "MessageSid": "SMxxxxxxxxxxxx",
  "From": "+12145550132",
  "To": "+12145550199",
  "Body": "Yes, I need service tomorrow",
  "MessageStatus": "received",
  "ApiVersion": "2010-04-01"
}
2

Twilio Voice Webhook

Receives missed call notifications and AI voice callback events

Endpoint:/api/webhooks/twilio/voice
Configure in:Twilio Console → Voice → Settings → Webhook URL
Events to enable:
  • Incoming call (no-answer, busy, failed)
  • Call completed (for AI voice callbacks)
  • Recording/transcription ready
Verification:X-Twilio-Signature header validated using Auth Token
Example Payload
{
  "CallSid": "CAxxxxxxxxxxxx",
  "From": "+12145550132",
  "To": "+12145550199",
  "CallStatus": "no-answer",
  "Direction": "inbound",
  "CallerName": "Marcus T.",
  "ForwardedFrom": "+12145550199"
}
3

Stripe Webhook

Handles subscription lifecycle, payments, and billing events

Endpoint:/api/webhooks/stripe
Configure in:Stripe Dashboard → Developers → Webhooks → Add Endpoint
Events to enable:
  • customer.subscription.created/updated/deleted
  • invoice.payment_succeeded/failed
  • checkout.session.completed
  • customer.updated
Verification:Stripe-Signature header validated using Webhook Secret
Example Payload
{
  "id": "evt_xxxxxxxxxxxx",
  "type": "customer.subscription.updated",
  "data": {
    "object": {
      "id": "sub_xxxxxxxxxxxx",
      "customer": "cus_xxxxxxxxxxxx",
      "status": "past_due",
      "current_period_end": 1704931200
    }
  }
}
4

HubSpot Webhook

Receives contact/deal updates from HubSpot for two-way sync

Endpoint:/api/webhooks/hubspot
Configure in:HubSpot Settings → Integrations → Webhooks
Events to enable:
  • Contact property changes
  • Deal stage changes
  • New contact/deal created
Verification:X-HubSpot-Signature header validated using Client Secret
Example Payload
{
  "subscriptionType": "contact.propertyChange",
  "objectId": 12345,
  "propertyName": "phone",
  "propertyValue": "+12145550132",
  "changeSource": "CRM_UI"
}

📋 Setup Checklist

1

Get Your Ringback Webhook URLs

All webhook endpoints are under /api/webhooks/. Note the full URLs (e.g., https://yourapp.com/api/webhooks/twilio/sms).

2

Configure in Provider Dashboard

Paste each URL into the corresponding provider's webhook settings. See table above for exact locations.

3

Enable Required Events

Select only the events listed above. Extra events increase noise and processing time.

4

Set Signature Secrets

Twilio: Copy Auth Token from Console. Stripe: Copy Webhook Signing Secret. HubSpot: Copy Client Secret.

5

Test Each Webhook

Use provider's 'Test Webhook' button or trigger a real event (missed call, SMS reply, subscription change).

6

Verify in Ringback

Check Supabase ring_webhook_event table — each received webhook logs with processed_at timestamp.

🛠️ Local Development Testing

  • Use ngrok/cloudflared for local tunnel: ngrok http 3000
  • Update webhook URLs in provider dashboards to https://xxx.ngrok.io/api/webhooks/...
  • Set env vars: TWILIO_AUTH_TOKEN, STRIPE_WEBHOOK_SECRET, HUBSPOT_CLIENT_SECRET
  • Trigger test events: Twilio 'Test Webhook', Stripe CLI 'stripe trigger', HubSpot test button
  • Check terminal logs for webhook receipt and processing

🔧 Troubleshooting

Webhook not receiving requests

  • URL is publicly accessible (no localhost, no auth, no VPN)
  • HTTPS with valid cert (Let's Encrypt OK)
  • Provider firewall/IP allowlist includes your domain
  • Correct HTTP method (POST) and path

Signature verification fails

  • Twilio: Using Auth Token (not Account SID) from correct project
  • Stripe: Using Webhook Signing Secret (whsec_...) from Stripe Dashboard
  • HubSpot: Using Client Secret from App settings
  • Raw request body used for verification (no middleware parsing before validation)

Webhook received but lead not created

  • Check ring_webhook_event table — status=processed means Ringback handled it
  • Verify phone_number_id exists and is verified
  • Check ring_lead table for new records
  • Twilio: Ensure CallStatus is 'no-answer', 'busy', or 'failed' (not 'completed')

Duplicate webhook processing

  • ring_webhook_event.idempotency_key prevents duplicates
  • Key format: {provider}:{event_type}:{resource_id}
  • If duplicates persist, check provider retry settings (disable if possible)

Stripe webhook: subscription not updating

  • Event type is customer.subscription.updated (not invoice.payment_succeeded)
  • Customer metadata has ringback_user_id linked
  • Check ring_crm_sync_log for sync errors

🔑 Idempotency & Retries

All webhooks are idempotent. Ringback stores idempotency_key in ring_webhook_event table.

Key format: provider:event_type:resource_id
Example: twilio:sms:SMxxxxxxxxxxxx

Retries: If your endpoint returns 5xx or times out (over 10s), provider retries with exponential backoff. Ringback processes each unique key only once — safe to retry.

Manual replay: In Supabase, find the event in ring_webhook_event, copy payload, POST to webhook URL with same signature.