Provider webhooks
Provider ingress is POST /hooks/comms.php?p={provider}. This is for provider consoles, not general client integrations.
Authentication
Section titled “Authentication”| Provider | Preferred verification | Fallback |
|---|---|---|
| Telnyx | Ed25519 using Telnyx-Signature-Ed25519, Telnyx-Timestamp, and TELNYX_PUBLIC_KEY; timestamp must be within 300 seconds | ?t= matching COMMS_WEBHOOK_TOKEN |
| Twilio | X-Twilio-Signature HMAC-SHA1 using TWILIO_AUTH_TOKEN; signed URL derives from PUBLIC_BASE_URL plus request URI | ?t= matching COMMS_WEBHOOK_TOKEN |
| SendGrid | None implemented | ?t= matching COMMS_WEBHOOK_TOKEN is required |
An empty shared-token configuration never authenticates. Failed/unknown provider requests return HTTP 403 {"error":"forbidden"}. Keep the token out of logs where possible; provider-native signatures are stronger because the fallback is a query secret.
Telnyx
Section titled “Telnyx”Configure:
https://app.dialdozer.com/hooks/comms.php?p=telnyxHandled events:
message.received: inbound SMS/MMS, including media URLs.message.sentandmessage.finalized: outbound delivery-state updates.- Other event types return
{"ok":true,"ignored":"event.name"}.
Duplicate provider message IDs are acknowledged with dup:true. An in-progress/failed idempotent claim returns HTTP 503 processing_failed so Telnyx can retry.
Twilio
Section titled “Twilio”Configure the exact public callback URL used in signature generation:
https://app.dialdozer.com/hooks/comms.php?p=twilioMessageStatus requests update outbound delivery. Requests with From and Body store inbound SMS/MMS (up to 10 MediaUrlN fields) and return empty TwiML. Signature validation fails if PUBLIC_BASE_URL does not match the externally signed scheme/host/path/query.
SendGrid
Section titled “SendGrid”Configure Event Webhook and Inbound Parse with a secret query token:
https://app.dialdozer.com/hooks/comms.php?p=sendgrid&t=YOUR_SHARED_TOKENThe Event Webhook handles open, click, delivered, bounce, dropped, and spamreport when each event includes npk_message_id. Bounce/drop/spam events mark the email channel opted out. Inbound Parse accepts multipart fields such as from, to, subject, text, html, and headers; it threads by sender address and uses RFC Message-ID when available for replay safety.
Shared behavior
Section titled “Shared behavior”Inbound phone messages match contact channels first, then VICIdial phone records; unknown senders become leads only when COMMS_INBOUND_LIST_ID is configured. Unknown email senders are not created. Provider identities are leased for five minutes to prevent concurrent duplicate effects. STOP-family keywords revoke SMS consent and send one confirmation; START/UNSTOP restores express consent; C/CONFIRM can confirm the nearest pending appointment within the current hour-to-48-hour window.