# Webhook Events

Description: Minimal event-selection guide for agents implementing Surge webhooks.
Related: /docs/receiving, /docs/receiving/two-way, /docs/sending/track-delivery, /docs/registration/api-walkthrough, /api-reference/webhooks

Use this page to decide which Surge webhook events matter for your workflow and which state transitions they imply.

## Event Families

- `message.sent`
- `message.delivered`
- `message.failed`
- `message.received`
- `contact.opted_in`
- `contact.opted_out`
- `conversation.created`
- `campaign.approved`
- `phone_number.attached_to_campaign`
- `link.followed`
- `call.ended`
- `recording.completed`
- `voicemail.received`

Voice events are feature-gated and only appear on accounts with voice enabled.

## Recommended Priority Order

Implement these first for most apps:

1. `message.received`
2. `contact.opted_out`
3. `message.failed`
4. `message.delivered`
5. `campaign.approved`
6. `phone_number.attached_to_campaign`

## High-Value Semantics

- `message.received` is the core inbound SMS trigger.
- `message.delivered` is best-effort; some carriers do not send delivery receipts.
- `message.failed` includes `failure_reason`; persist it for support and retries.
- `contact.opted_out` is per conversation, not a global contact ban across every number.
- `campaign.approved` means the campaign is approved, but a specific number still needs `phone_number.attached_to_campaign`.
- `phone_number.attached_to_campaign` is the production-ready signal for that number.

## Implementation Advice

- dispatch by `type`
- keep handlers idempotent
- ignore unneeded events rather than failing the entire webhook
- log enough metadata to trace event timing and retries

## Verification Checklist

- one inbound message triggers exactly one `message.received` side effect
- opt-out stops future sends on the opted-out thread
- delivery dashboards use `message.delivered` when available but tolerate missing receipts
- registration automation waits for `phone_number.attached_to_campaign` before declaring a number live
