Webhooks
Receiving delivery status updates via webhook callbacks from messaging providers.
Overview
ATACA Connect receives delivery status updates from messaging providers via webhooks. When a message is sent, delivered, read, or fails, the provider sends a callback to your Connect instance.
Webhook endpoints
Connect exposes two webhook endpoints per channel:
GET /v1/incoming_webhooks/{channel} — provider verification (challenge-response)
POST /v1/incoming_webhooks/{channel} — delivery status events
Where {channel} is one of: whatsapp, viber, sinch_sms, plivo_sms, telegram. Organizations with their own credentials (BYOK) append ?tenant=<org> so the event is verified with their secret.
These endpoints are unauthenticated — they must be publicly accessible for providers to reach them. Signed channels are verified with the platform's secret by default. If you bring your own provider credentials, use the tenant-specific URL shown on the credentials page (?tenant=<org>) so events are verified with your secret instead.
Provider verification
Some providers verify your webhook URL before sending events.
WhatsApp sends a GET request with a challenge token. Connect responds with the token to confirm ownership. The verify token is configured in your WhatsApp credentials.
Meta signs every event POST with the app secret (X-Hub-Signature-256). Connect verifies the signature and rejects events that do not match. The app secret must be configured; without it every event is rejected.
Viber
Viber signs webhook payloads with HMAC-SHA256 using your auth token. Connect verifies the signature on each POST request and rejects invalid signatures.
Plivo
Plivo signs each delivery report with your auth token over the callback URL and a nonce (X-Plivo-Signature-V2). Connect verifies the signature against the configured callback URL and rejects reports that do not match.
Sinch
Sinch signs each delivery report with the HMAC secret configured for callbacks on your service plan: HMAC-SHA256 over the body, nonce, and timestamp (x-sinch-webhook-signature headers). Connect verifies the signature and rejects reports that do not match. The webhook secret must be configured; without it every report is rejected.
Telegram
Telegram sends the secret_token given to setWebhook in the X-Telegram-Bot-Api-Secret-Token header on every update. Connect compares it with the configured webhook secret and rejects updates that do not match.
Delivery status events
When a provider sends a status update, Connect parses the webhook payload and updates the corresponding delivery attempt. Status progression:
| Status | Meaning |
|---|---|
pending |
Message enqueued, not yet sent to provider |
sent |
Provider accepted the message for delivery |
delivered |
Message confirmed delivered to recipient |
read |
Recipient read the message (if supported) |
failed |
Delivery failed — check the delivery attempt for details |
Not all channels support all statuses. SMS providers typically confirm sent but may not confirm delivered. WhatsApp and Viber support delivered and read status.
Configuring webhooks
Set your Connect instance's public URL as the webhook URL in each provider's dashboard:
- WhatsApp — Meta Business Platform → WhatsApp → Configuration → Webhook URL
- Viber — Viber Admin Panel → Account settings → Webhook URL
- Sinch — Sinch Dashboard → SMS → Callback URL
- Plivo — Plivo Console → Messaging → Applications → Message URL
- Telegram — Set via Bot API
setWebhookmethod
The webhook URL format is:
https://connect.ataca.io/v1/incoming_webhooks/{channel}
Delivery attempts
Each delivery attempt is recorded with its status, provider response, and timestamps. View delivery attempts for a message in the dashboard under Messages → Message Detail.
When a delivery attempt fails or times out, the orchestrator cascades to the next channel step in your delivery policy. See Delivery Workflow for details.
Rail email events
Rail posts signed events to the existing POST /v1/incoming_webhooks/EMAIL endpoint.
Connect verifies Ed25519 signatures against the configured Rail server's HTTPS public-key endpoint.
Timestamps must fall within five minutes of Connect's clock.
Connect stores verified events before returning 204 and deduplicates them by webhook-id.
Storage or key-server failures return 503 so Rail can retry.
| Event | Connect behavior |
|---|---|
delivery |
Confirms recipient-server acceptance or reports a permanent delivery failure. |
open |
Records a pixel load and its client, proxy, prefetch, or unknown classification. |
bounce |
Marks the email attempt failed and blocks future email to that contact. |
complaint |
Marks the email attempt failed and blocks future email to that contact. |
reply |
Stores the message in the original message's organisation inbox. |
inbound |
Stores the message in the organisation mapped to its recipient address. |
Rail submissions stay SENT until a delivery webhook confirms them.
The delivery policy's timeout and cascade rules still apply.
Open events do not prove a person read the email and do not change delivery status.
View delivery and open events under Messages → Message Detail.
View inbound email and replies under Inbox. Message source is displayed as escaped text.
Map inbound mailboxes explicitly in Connect configuration:
email:
rail:
inbound_mailboxes:
[email protected]: your-organisation
Connect ignores a callback's tenant query parameter.
Replies and feedback use the stored Rail message ID to determine the organisation.
Unmatched events remain pending and retry every five minutes.
Mail addressed to multiple configured organisations remains pending to avoid exposing mail across organisations.
Raw inbound messages remain stored until an operator defines a retention policy.
Rail activation
Deploy the Rail release that adds delivery and open notifications before activating Connect's asynchronous email delivery.
Enable signing and open tracking in Rail. Opt the submitting certificate's CN into status events:
delivery:
status_webhook_clients: [connect]
tracking:
enabled: true
webhook_signing:
enabled: true
Use the actual certificate CN if it differs from connect.
These settings require a Rail restart.
Configure the callback with Rail's administrator CLI after deploying the receiver:
rail clients webhooks --set https://connect.ataca.io/v1/incoming_webhooks/EMAIL connect
--set replaces the client's webhook list. Include existing destinations as additional --set arguments when retaining them.
Wagon v0.3.0 can inspect identity and delivery status but cannot configure webhook destinations.
Rail's delivery and open notifications use the existing signed webhook retry queue.
They are opt-in per client and do not replay events that predate the Rail migration.