> ## Documentation Index
> Fetch the complete documentation index at: https://docs.revdesk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Subscribe to call, SMS, contact, number-lifecycle, and booking events delivered to your URL.

RevDesk POSTs an event to your URL whenever something happens in your workspace — a call ends, an SMS
is delivered, a number is provisioned. Subscribe once per event type; we deliver as the events occur.

## Subscribe

```bash theme={null}
curl -X POST https://api.revdesk.com/api/v1/webhook_subscriptions \
  -H "Authorization: Bearer $REVDESK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "webhook_url": "https://example.com/hooks/revdesk", "event_type": "call_completed" }'
# → { "id": "whk_…" }
```

| Field         | Required | Description                          |
| ------------- | -------- | ------------------------------------ |
| `webhook_url` | yes      | HTTPS URL that receives the `POST`.  |
| `event_type`  | yes      | One of the event types below.        |
| `workflow_id` | no       | Scope delivery to a single workflow. |
| `campaign_id` | no       | Scope delivery to a single campaign. |

## Unsubscribe

```bash theme={null}
curl -X DELETE https://api.revdesk.com/api/v1/webhook_subscriptions/whk_… \
  -H "Authorization: Bearer $REVDESK_API_KEY"
# → 204 No Content
```

## Event types

<Note>
  `call_completed` fires on every call end. The **disposition** events below fire *in addition*, only
  on the matching outcome — subscribe to them to branch (retry, SMS fallback) without parsing call
  records. Answered/successful calls emit no disposition event.
</Note>

| `event_type`                 | Fires when                                                |
| ---------------------------- | --------------------------------------------------------- |
| `new_call`                   | A call starts.                                            |
| `call_completed`             | A call ends (any outcome).                                |
| `call_no_answer`             | A call ended unanswered (rang out).                       |
| `call_voicemail`             | A call reached voicemail / an answering machine.          |
| `call_busy`                  | The destination was busy.                                 |
| `call_failed`                | A call failed (declined, unreachable, carrier rejection). |
| `contact_replied`            | An inbound SMS was received.                              |
| `sms_sent`                   | An outbound SMS was accepted by the carrier.              |
| `sms_delivered`              | An outbound SMS was delivered to the handset.             |
| `sms_failed`                 | An outbound SMS failed / was undelivered.                 |
| `contact_created`            | A new contact was created.                                |
| `number_purchased`           | A phone number finished provisioning and went active.     |
| `number_released`            | A phone number was released from your workspace.          |
| `new_appointment`            | A booking was created.                                    |
| `workflow_contact_completed` | A contact finished a workflow.                            |

## Delivery

Each event is a `POST` with a JSON body to your `webhook_url`. Delivery is fire-and-forget; return a
`2xx` quickly and do any heavy work asynchronously. Subscribe to the same event type multiple times
to fan out to multiple URLs.

### Payload examples

Call disposition (`call_no_answer`, `call_voicemail`, `call_busy`, `call_failed`):

```json theme={null}
{
  "id": "call_abc123",
  "from_number": "+15551234567",
  "to_number": "+15557654321",
  "direction": "outbound",
  "duration_seconds": 0,
  "status": "VOICEMAIL",
  "failure_code": "voicemail_reached",
  "failure_category": "voicemail",
  "disconnection_reason": null,
  "created_at": "2026-06-30T19:30:00.000Z"
}
```

Outbound SMS (`sms_sent`, `sms_delivered`, `sms_failed`):

```json theme={null}
{
  "id": "msg_uuid",
  "phone_number": "+15557654321",
  "from_number": "+15551234567",
  "direction": "outbound",
  "status": "delivered",
  "provider_id": "…",
  "error_message": null,
  "channel": "sms",
  "created_at": "2026-06-30T19:30:00.000Z"
}
```

Number lifecycle (`number_purchased`, `number_released`):

```json theme={null}
{
  "id": 4821,
  "phone_number": "+15551234567",
  "area_code": "555",
  "status": "ACTIVE",
  "organization_id": "…"
}
```
