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

# Post Call Webhooks

> Receive call data on your server when a call ends, and test your webhook for inbound and outbound calls.

## What are Post-Call Webhooks?

Post-call webhooks are HTTP notifications that Bland AI automatically sends to your server after a phone call completes. Think of them as real-time alerts that deliver call data directly to your application, enabling you to:

* **Process call outcomes immediately** - Trigger follow-up actions based on call results
* **Integrate with your CRM or database** - Automatically update customer records with call transcripts and extracted data
* **Build custom analytics** - Track call performance and agent effectiveness
* **Create automated workflows** - Send emails, create tickets, or update dashboards based on call data
* **Access rich call data** - Get complete transcripts, extracted variables, call duration, and more

Webhooks make it easy to integrate with Bland, so your system can react to call completions right away, no need to keep polling our API.

## About This Tutorial

This tutorial will help you set up and test your Bland AI webhooks for both inbound and outbound phone calls.

## Step 1: Create your test webhook

For testing purposes, we'll use [Webhook.site](https://webhook.site/) to create a temporary webhook endpoint. Webhook.site generates instant webhook URLs with no setup required and captures all incoming requests so you can see webhook deliveries in real-time.

When you visit Webhook.site, it automatically provides you a unique webhook URL that will capture any HTTP requests sent to it. This is perfect for testing before you implement your own webhook endpoint.

![Webhook.site page showing a unique webhook URL](https://mintcdn.com/blandai/hxL-_fou7-aXv059/tutorials/tutorials-assets/webhooksite.jpeg?fit=max\&auto=format\&n=hxL-_fou7-aXv059\&q=85\&s=f819f73bcf9f3623949df4c53e3c8e68)

Copy your unique webhook URL - you'll need it in the next step.

## Step 2: Configure webhook for inbound calls

Inbound calls report to the webhook set on the phone number they arrive on.

### Open your phone number

1. Open the [Bland dashboard](https://app.bland.ai) and set the selector at the top of the sidebar to **All agents**
2. Under Dispatch, open **Phone numbers**
3. Press Configure on your number's row

### Add your webhook

1. **Open Call configuration**: it holds the webhook and events settings for the number
2. **Paste your webhook URL**: use the Webhook.site URL from Step 1
3. **Save**: under **Review and save**, tick the confirmation and press **Save**

The same Call configuration is available inside an agent, from the number on its Channels page. See [Dispatch](https://docs.bland.ai/agents/dispatch.md#configure-a-number) for the full sheet.

**Need live events during the call?** The webhook sends data after the call completes. To receive events during the call (like when the call starts, transfers, or ends), see the `webhook_events` parameter in [Send Call with an Agent](https://docs.bland.ai/api-v1/post/calls-agent.md#param-webhook-events).

## Step 3: Test with a live phone call

Now test with an actual phone call:

1. **Call your inbound phone number** and have a conversation with your agent
2. **End the call** completely
3. **Return to Webhook.site**. A new request appears in the list with the complete call data
4. **Inspect the payload** to see the full transcript, call duration, and other call metadata

![Webhook.site showing a received webhook request](https://mintcdn.com/blandai/hxL-_fou7-aXv059/tutorials/tutorials-assets/webhooksite-result.jpeg?fit=max\&auto=format\&n=hxL-_fou7-aXv059\&q=85\&s=abe3d9b9ed0ff271c779f4ca08595856)

**If nothing arrives:**

* Double-check that you saved the correct URL
* Make sure there are no extra spaces or characters
* Confirm the number is attached to your agent and the agent is published to production

If issues persist, reach out in our [Discord community](https://discord.gg/QvxDz8zcKe) or ask for technical support from [support@bland.ai](mailto:support@bland.ai).

## Step 4: Configure webhooks for outbound calls

For outbound calls, include the `webhook` parameter when you send the call with your agent:

```json theme={null}
{
  "agent_id": "41282230-dd13-4546-8785-0afa19b708c0",
  "phone_number": "+15551234567",
  "webhook": "https://webhook.site/your-unique-id"
}
```

The webhook URL must start with `https://`. See [Send Call with an Agent](https://docs.bland.ai/api-v1/post/calls-agent.md) for complete request details.

### Testing your outbound webhook

1. **Send a test call** using the API with your webhook URL
2. **Wait for the call to complete**
3. **Check Webhook.site** for the incoming webhook payload
4. **Verify the payload** contains your outbound call data

If you encounter any issues, reach out in our [Discord community](https://discord.gg/QvxDz8zcKe) for support.

***

## Webhook Payload Examples

Understanding the structure of webhook payloads helps you build better integrations. Here are examples of the actual data your webhook endpoint will receive:

### Standard Post-Call Webhook

This is the immediate webhook sent right after a call completes. This example comes from a call that ran a pathway, so it includes pathway fields such as `pathway_id`, `pathway_logs`, and `pathway_tags`. For field definitions, see [Call details](https://docs.bland.ai/api-v1/get/calls-id.md).

> [accordion] View Standard Post-Call Webhook Payload
>
> ```json theme={null}
> {
>   "call_id": "12345678-1234-1234-1234-123456789012",
>   "c_id": "12345678-1234-1234-1234-123456789012",
>   "call_length": 0.183333333333333,
>   "batch_id": "7c42b56e-3a1d-4f8f-9a37-1ce89d29f204",
>   "to": "+15551234567",
>   "from": "+15559876543",
>   "completed": true,
>   "created_at": "2025-09-12T20:39:03.168+00:00",
>   "inbound": false,
>   "queue_status": "complete",
>   "max_duration": 12,
>   "error_message": "Account not allowed to call +12345678901",
>   "variables": {
>     "now": "Friday, September 12, 2025 1:39 PM",
>     "now_utc": "Friday, September 12, 2025 8:39 PM",
>     "short_from": "5559876543",
>     "short_to": "5551234567",
>     "from": "+15559876543",
>     "to": "+15551234567",
>     "call_id": "12345678-1234-1234-1234-123456789012",
>     "phone_number": "+15551234567",
>     "country": "US",
>     "state": "CA",
>     "language": "English",
>     "timestamp": "2025-09-12T13:39:11-07:00",
>     "timezone": "America/Los_Angeles"
>   },
>   "answered_by": "human",
>   "record": true,
>   "recording_url": "https://api.twilio.com/2010-04-01/Accounts/ACexample123/Recordings/REexample456",
>   "metadata": {
>     "campaign_type": "test_calls",
>     "environment": "production",
>     "call_purpose": "system_test"
>   },
>   "summary": "The call was a brief test call from Bland, during which the assistant confirmed the connection and exchanged polite pleasantries with the user before ending the call.",
>   "price": 0.017,
>   "started_at": "2025-09-12T20:39:03.168Z",
>   "local_dialing": false,
>   "call_ended_by": "ASSISTANT",
>   "pathway_logs": [
>     {
>       "tag": {
>         "name": "Intro Node",
>         "color": "#862727"
>       },
>       "role": "user",
>       "text": "<Call Connected>",
>       "decision": "{\"Global Prompt\":\"\",\"Current Node Prompt/Text\":\"This is a test call from Bland.\"}",
>       "created_at": "2025-09-12T20:39:03.168Z",
>       "pathway_info": "{\"Request Data\":{\"phone_number\":\"+15551234567\",\"task\":\"This is a test call from Bland.\"}}",
>       "chosen_node_id": "1"
>     },
>     {
>       "tag": null,
>       "role": "assistant",
>       "text": "This is a test call from Bland.",
>       "decision": null,
>       "created_at": "2025-09-12T20:39:13.566Z",
>       "pathway_info": null,
>       "chosen_node_id": "a7b3c9d2-8e4f-4a5b-9c7d-2e8f6a9b4c7d"
>     }
>   ],
>   "transferred_to": "+12345678909",
>   "pre_transfer_duration": 0.3955,
>   "post_transfer_duration": 0.571166666666667,
>   "pathway_tags": [
>     "Intro Node",
>     "Call Completion"
>   ],
>   "recording_expiration": "2030-10-15T17:20:55.779Z",
>   "status": "completed",
>   "pathway_id": "b71c4c5c-33e3-496b-a5f4-91b7e8e6a931",
>   "is_proxy_agent_call": false,
>   "is_canary": false,
>   "citation_schema_ids": [],
>   "warm_transfer_call": {
>     "proxy_agent_calls": [
>       {
>         "state": "MERGED",
>         "call_id": "a35d88f2-cafe-4a32-8640-90cc2118bed7",
>         "phone_number": "+17079311009"
>       }
>     ],
>     "state": "MERGED"
>   },
>   "concatenated_transcript": "user: Hello?  \n assistant: This is a test call from Bland. \n user: Cool. Thank you very much. \n assistant: You're welcome, have a great day, goodbye. \n agent-action: Ended call \n ",
>   "transcripts": [
>     {
>       "id": 123456789,
>       "user": "user",
>       "text": "Hello? ",
>       "created_at": "2025-09-12T20:39:13.173+00:00"
>     },
>     {
>       "id": 123456790,
>       "user": "assistant",
>       "text": "This is a test call from Bland.",
>       "created_at": "2025-09-12T20:39:13.566+00:00"
>     },
>     {
>       "id": 123456791,
>       "user": "user",
>       "text": "Cool. Thank you very much.",
>       "created_at": "2025-09-12T20:39:17.748+00:00"
>     },
>     {
>       "id": 123456792,
>       "user": "assistant",
>       "text": "You're welcome, have a great day, goodbye.",
>       "created_at": "2025-09-12T20:39:19.186+00:00"
>     },
>     {
>       "id": 123456793,
>       "user": "agent-action",
>       "text": "Ended call",
>       "created_at": "2025-09-12T20:39:20.53+00:00"
>     }
>   ],
>   "corrected_duration": "11",
>   "end_at": "2025-09-12T20:39:21.000Z",
>   "disposition_tag": "COMPLETED_ACTION"
> }
> ```

### Disposition results

If your agent runs [dispositions](https://docs.bland.ai/agents/dispositions.md), their results arrive on this webhook under `agent_dispositions`. The disposition's **Webhook behavior** setting decides how they arrive:

* **Follow-up event**: the call webhook fires as usual. A second event with `event_type` set to `dispositions` follows once the disposition finishes
* **Hold original webhook**: Bland waits for the disposition, then sends one combined webhook with `agent_dispositions` on the call payload. This adds up to 30 minutes of latency

See [Read the results](https://docs.bland.ai/agents/dispositions.md#read-the-results) for the payload shape.

### Legacy: delayed webhook with citations

> [!NOTE]
>
> Citations are a legacy feature. [Dispositions](https://docs.bland.ai/agents/dispositions.md) replace citations and outcomes. On an agent still running V1 citations, the call webhook waits for citations, and a disposition set to Hold original webhook falls back to Follow-up event.

With legacy citation extraction, you can delay the post-call webhook until citations are processed. The combined webhook includes all call data plus citations and a corrected transcript. It needs both of these:

1. `citations` in the call's `webhook_events`
2. The "Delay post call webhook" toggle in your citation settings

For details, see the [Citations documentation](https://docs.bland.ai/enterprise-features/citations.md#option-2%3A-delayed-post-call-webhook-with-citations).

> [accordion] View Delayed Webhook with Citations Payload
>
> ```json theme={null}
> {
>   "to": "+447931841239",
>   "c_id": "8a9620f6-d634-4b92-8d75-93280a894a71",
>   "from": "+14159438185",
>   "price": 0.029,
>   "end_at": "2025-09-19T18:22:31.000Z",
>   "record": true,
>   "status": "completed",
>   "call_id": "8a9620f6-d634-4b92-8d75-93280a894a71",
>   "inbound": false,
>   "summary": "The call was a brief confirmation from Jean at Nutriva Health to a client named James, verifying his attendance at an upcoming appointment scheduled for the next day at 10:00 AM. James confirmed his ability to attend, and the call was promptly ended.",
>   "batch_id": "7c42b56e-3a1d-4f8f-9a37-1ce89d29f204",
>   "metadata": {
>     "unitID": 58392739240,
>     "agentName": "alex"
>   },
>   "completed": true,
>   "variables": {
>     "to": "+447931841239",
>     "now": "Friday, September 19, 2025 11:22 AM",
>     "from": "+14159438185",
>     "call_id": "8a9620f6-d634-4b92-8d75-93280a894a71",
>     "country": "GB",
>     "now_utc": "Friday, September 19, 2025 6:22 PM",
>     "language": "English",
>     "short_to": "7931841239",
>     "timezone": "America/Los_Angeles",
>     "timestamp": "2025-09-19T11:22:13-07:00",
>     "short_from": "4159438185",
>     "phone_number": "+447931841239"
>   },
>   "created_at": "2025-09-19T18:22:06.984+00:00",
>   "pathway_id": "b71c4c5c-33e3-496b-a5f4-91b7e8e6a931",
>   "started_at": "2025-09-19T18:22:06.984Z",
>   "answered_by": "human",
>   "call_length": 0.316666666666667,
>   "transcripts": [
>     {
>       "id": 174,
>       "text": "Hey, this is Jean from Nutriva Health. Could you confirm your name for me?",
>       "user": "assistant",
>       "created_at": "2025-09-19T18:22:15.893+00:00"
>     },
>     {
>       "id": 175,
>       "text": "Yeah. My name is James.",
>       "user": "user",
>       "created_at": "2025-09-19T18:22:20.579+00:00"
>     },
>     {
>       "id": 176,
>       "text": "Hey James, great to meet you! I just wanted to confirm that you'll be able to attend your upcoming appointment tomorrow at ten A M?",
>       "user": "assistant",
>       "created_at": "2025-09-19T18:22:22.375+00:00"
>     },
>     {
>       "id": 177,
>       "text": "Yeah. I will be able to. Goodbye.",
>       "user": "user",
>       "created_at": "2025-09-19T18:22:31.061+00:00"
>     }
>   ],
>   "max_duration": 12,
>   "pathway_logs": [
>     {
>       "tag": {
>         "name": "Appointment Confirmation",
>         "color": "#4287f5"
>       },
>       "role": null,
>       "text": null,
>       "decision": null,
>       "created_at": "2025-09-19T18:22:06.984Z",
>       "pathway_info": "{\"Request Data\":{\"phone_number\":\"+447931841239\",\"task\":\"Confirm appointment attendance for James\"}}",
>       "chosen_node_id": "1"
>     },
>     {
>       "tag": null,
>       "role": "assistant",
>       "text": "Hey, this is Jean from Nutriva Health. Could you confirm your name for me?",
>       "decision": "{\"Global Prompt\":\"\",\"Current Node Prompt/Text\":\"Hey, this is Jean from Nutriva Health.\",\"Current Node Name\":\"Identity Verification\"}",
>       "created_at": "2025-09-19T18:22:15.893Z",
>       "pathway_info": null,
>       "chosen_node_id": "f2d8e9a3-6c4b-4e7f-8a1d-3c5e7b9f2a8c"
>     }
>   ],
>   "pathway_tags": [
>     "Appointment Confirmation",
>     "Appointment Details",
>     "Call Completion"
>   ],
>   "queue_status": "complete",
>   "call_ended_by": "USER",
>   "error_message": "Account not allowed to call +12345678901",
>   "local_dialing": false,
>   "recording_url": "https://akalocaldev.internal.bland.ai/v1/recordings/8a9620f6-d634-4b92-8d75-93280a894a71:24847607-ce61-4488-be8f-8e63d548b13e",
>   "transferred_at": "2025-10-16T17:10:28.301Z",
>   "transferred_to": "+12345678901",
>   "disposition_tag": "COMPLETED_ACTION",
>   "corrected_duration": "19",
>   "citation_schema_ids": [
>     "b0477cba-1c97-4105-8ac9-46cb8eae5cf1"
>   ],
>   "is_proxy_agent_call": false,
>   "is_canary": false,
>   "warm_transfer_call": {
>     "proxy_agent_calls": [
>       {
>         "state": "MERGED",
>         "call_id": "1f8a3c2d-75e9-4b32-bb19-73a672e9e22a",
>         "phone_number": "+12345678901"
>       }
>     ],
>     "state": "MERGED"
>   },
>   "recording_expiration": "2025-10-19T18:22:36.641+00:00",
>   "pre_transfer_duration": 0.3955,
>   "post_transfer_duration": 0.571166666666667,
>   "concatenated_transcript": "assistant: Hey, this is Jean from Nutriva Health. Could you confirm your name for me? \n user: Yeah. My name is James. \n assistant: Hey James, great to meet you! I just wanted to confirm that you'll be able to attend your upcoming appointment tomorrow at ten A M? \n user: Yeah. I will be able to. Goodbye. \n ",
>   "citations": [
>     {
>       "call_id": "8a9620f6-d634-4b92-8d75-93280a894a71",
>       "variable_name": "firstName",
>       "variable_type": "string",
>       "value": "James",
>       "cited_utterances": [
>         {
>           "id": "8a9620f6-d634-4b92-8d75-93280a894a71_1",
>           "idx": 1,
>           "start_time": 5.056,
>           "end_time": 6.176,
>           "confidence": 0.115,
>           "channel": 1,
>           "transcript": "- Yeah, my name is James.",
>           "speaker_id": "SPEAKER_1_0",
>           "speaker_name": "James (Customer)",
>           "speaker_description": "The customer being called to confirm his appointment.",
>           "topics": [
>             "identity_confirmation"
>           ],
>           "topics_meta": "{\"identity_confirmation\":\"The customer confirms his name is James.\"}",
>           "utterance_type": "answer"
>         },
>         {
>           "id": "8a9620f6-d634-4b92-8d75-93280a894a71_2",
>           "idx": 2,
>           "start_time": 8.704,
>           "end_time": 14.848,
>           "confidence": 0.7174999999999999,
>           "channel": 0,
>           "transcript": "Hey, James. Great to meet you. I just wanted to confirm that you'll be able to attend your upcoming appointment tomorrow at 10 a.m.",
>           "speaker_id": "SPEAKER_0_0",
>           "speaker_name": "Jean (Agent)",
>           "speaker_description": "An agent from Nutriva Health calling to confirm an appointment.",
>           "topics": [
>             "greeting",
>             "appointment_confirmation"
>           ],
>           "topics_meta": "{\"appointment_confirmation\":\"The agent asks the customer to confirm his attendance for an appointment at a specific date and time.\",\"greeting\":\"The agent greets the customer by name.\"}",
>           "utterance_type": "question"
>         }
>       ],
>       "schema_id": "b0477cba-1c97-4105-8ac9-46cb8eae5cf1"
>     }
>   ],
>   "corrected_transcript": [
>     {
>       "start": 0.384,
>       "end": 4.096,
>       "speaker": 2,
>       "speaker_label": "assistant",
>       "text": "Hey, this is Jean from Nutriva Health. Could you confirm your name for me?",
>       "confidence": 0.713
>     },
>     {
>       "start": 5.056,
>       "end": 6.176,
>       "speaker": 1,
>       "speaker_label": "user",
>       "text": "Yeah, my name is James.",
>       "confidence": 0.115
>     },
>     {
>       "start": 8.704,
>       "end": 14.848,
>       "speaker": 2,
>       "speaker_label": "assistant",
>       "text": "Hey James, great to meet you! I just wanted to confirm that you'll be able to attend your upcoming appointment tomorrow at ten A M?",
>       "confidence": 0.717
>     },
>     {
>       "start": 16.224,
>       "end": 18.464,
>       "speaker": 1,
>       "speaker_label": "user",
>       "text": "Yeah. I will be able to. Goodbye.",
>       "confidence": 0.432
>     }
>   ]
> }
> ```

> [!NOTE]
>
> **Understanding Warm Transfer States**: The example above shows a warm transfer with `"state": "MERGED"` and `"call_ended_by": "USER"`. For complete state definitions, see the [Warm Transfer documentation](https://docs.bland.ai/tutorials/warm-transfer.md#warm-transfer-state-definitions).

Compared with the standard webhook, the delayed citations webhook:

* Is sent after post-call processing, 30 to 60 seconds later
* Includes `corrected_transcript`, with speaker labels and confidence scores
* Contains a `citations` array with extracted variables linked to specific utterances

When the delay is off, the post-call webhook fires immediately and citations are sent in a separate webhook.

### Post-Transfer Transcript

> [!NOTE]
>
> The post-transfer transcript is in limited rollout. If it is not enabled for your organization, these properties are absent.

To receive the post-transfer transcript, subscribe by including `"post_transfer_transcript"` in the call's `webhook_events`. No citation schema is needed. Subscribing requires call recording: `record` is enabled automatically when unset, and passing `record: false` alongside the subscription returns a 400. Both cold and warm transfers are covered.

Subscribed calls that were transferred to a human carry two additional properties on the post-processing webhook (in both the standalone and delayed delivery modes):

* `transfer_offset_seconds`: seconds from the start of the call to the transfer.
* `post_transfer_transcript`: the conversation after the transfer, as speaker-attributed segments. The transferred-to human is `speaker: 2` / `"representative"`; the caller is `speaker: 1` / `"user"`. Timestamps are seconds from the start of the transferred conversation. The `corrected_transcript` continues to contain only the pre-transfer portion of the call.

```json theme={null}
{
  "transfer_offset_seconds": 9.573,
  "post_transfer_transcript": [
    {
      "start": 9.544,
      "end": 17.804,
      "speaker": 2,
      "speaker_label": "representative",
      "text": "Hi, this is Sam with support. How can I help you today?",
      "confidence": 0.7
    },
    {
      "start": 18.912,
      "end": 21.952,
      "speaker": 1,
      "speaker_label": "user",
      "text": "I was calling about my appointment on Thursday.",
      "confidence": 0.49
    }
  ]
}
```

For subscribed calls, the post-processing webhook also labels what it contains. When the payload carries exactly one enrichment, `event_type` names it (for example `"post_transfer_transcript"` or `"citations"`). When it carries more than one, `event_type` is `"multiple"` and a `contents` array lists what is present, in a fixed order:

```json theme={null}
{
  "event_type": "multiple",
  "contents": ["citations", "post_transfer_transcript"]
}
```

`contents` can list `citations`, `corrected_transcript`, `dispositions`, `post_transfer_transcript`, and `live_translation_transcript`. Calls without the `post_transfer_transcript` subscription are unaffected: their payloads are unchanged.

The same segment format is available live during the transferred conversation via the [Post-Transfer Transcript Stream](https://docs.bland.ai/api-v1/post/calls-id-transcript-stream.md) WebSocket. The live stream is enabled separately with [`stream_post_transfer_transcript: true`](https://docs.bland.ai/api-v1/post/calls#param-stream-post-transfer-transcript); it does not require the webhook subscription, and the webhook subscription does not require the stream.

***

## SMS Conversation Webhooks

SMS conversations fire webhooks with the same structure as voice calls, so you can use a single webhook endpoint for both channels.

### Message Webhooks

Every time a message is sent or received, a webhook fires with the message details and full chat history. The payload includes:

* `conversation_id`, `phone_number`, `agent_number`, `channel` (`"sms"`, `"rcs"`, or `"whatsapp"`)
* `pathway_id`, `pathway_version`
* `message`, `sender` (`"USER"`, `"AGENT"`, or `"HUMAN"` for a rep replying during a [human handoff](https://docs.bland.ai/api-v1/post/sms-conversations-handoff.md))
* `chat_history`: the full conversation so far
* `variables`: pathway variables collected during the conversation
* `metadata`: custom metadata passed when the conversation was created
* `pathway_tags`: tags from pathway nodes visited during the conversation

### Status Webhooks

When a conversation ends (via timeout, end-call node, or opt-out), a status webhook fires with the complete conversation context. In addition to the fields above, the status payload includes:

* `status`: `"ended"`, `"timeout"`, `"blacklisted"`, `"inactive"`, `"human_handoff"`, `"human_handoff_ended"`, `"read"`, or `"link_clicked"`
* `message_count`: total messages in the conversation
* `concatenated_transcript`: the full conversation as a single string
* `summary`: AI-generated summary (when a summary prompt is configured)
* `citations`: extracted citation variables, when legacy citation schemas are configured
* `dispositions`: outcome run results, when legacy outcomes are configured

SMS also supports `read` and `link_clicked` status events for RCS and WhatsApp channels, which fire when a recipient reads a message or taps an action button link.

`human_handoff` fires once when a human takes over a thread (via the API or the **Transfer to Human** pathway node) and `human_handoff_ended` when the agent gets it back. A thread [ended](https://docs.bland.ai/api-v1/post/sms-conversations-end.md) during a handoff fires `ended` instead, with `metadata.last_human_handoff` recording the takeover. While a handoff is active, message webhooks keep firing for every inbound message, `metadata.human_handoff` carries the reason, source, and any metadata passed at handoff, and no per-message status webhooks are sent.

### Configuring SMS Webhooks

You can set a webhook URL in three ways:

1. **On the SMS number**: set the number's **Webhook** under Channels, on the Messages tab, inside the agent ([Dispatch](https://docs.bland.ai/agents/dispatch.md#per-number-messaging-settings)), or use the [Update SMS Webhook](https://docs.bland.ai/api-v1/post/sms-webhook-update) endpoint
2. **Per request**: pass a `webhook` parameter in [Send SMS](https://docs.bland.ai/api-v1/post/sms-send.md) to override the number's configured webhook
3. **Per batch**: pass a `webhook` in the `global` object of [Send SMS Batch](https://docs.bland.ai/api-v1/post/sms-batch.md)

***

## Error Message Reference

All possible values for the `error_message` field in post-call webhooks. Note that webhook delivery uses HTTP status codes separately from call outcome errors.

### Webhook HTTP Status Codes

**Successful Webhook Delivery:**

* `200` - Webhook delivered successfully (regardless of call outcome)
* `2xx` - Any 2xx status indicates successful webhook delivery

**Webhook Delivery Failures:**

* `4xx` - Client errors (invalid webhook URL, authentication issues)
* `429` - Rate limiting (webhook endpoint receiving too many requests)
* `5xx` - Server errors (webhook endpoint unavailable or internal errors)

*Webhook delivery failures will trigger automatic retries based on the response code.*

### Call Error Messages

The following error messages appear in the `error_message` field within successfully delivered webhook payloads:

### Successful Calls

* `null` - Call completed successfully

### Call Connection Failures

**HTTP Status: 200** *(All call failures result in successful webhook delivery with error details in the payload)*

* `"Call failed."` - Base failure message
* `"Call failed. The number you dialed is not found."` - Invalid/disconnected number (SIP 404)
* `"Call failed. The number you dialed is temporarily unavailable."` - Network/carrier issues (SIP 480)
* `"Call failed. The number you dialed is busy. Please try again later."` - Line busy (SIP 486)
* `"Call failed. Service Provider Blocked Call due to Spam or Number Reputation. Try a different number."` - Carrier blocked (SIP 608)

### System Errors

**HTTP Status: 200** *(System errors result in successful webhook delivery with error details in the payload)*

* `"A database error occurred. Please contact support."` - Internal database error
* `"Unable to start call. Check the call details error_message for more details."` - Call dispatch failure
* `"unknown"` - Fallback error message

### Important Notes

* **Webhook Delivery vs Call Outcome**: HTTP status codes indicate webhook delivery success (200 = delivered), while call errors are embedded in the payload
* **SIP Mapping**: Call connection failures map from SIP response codes to user-friendly error messages
* **Error Handling**: Your webhook endpoint should return 2xx status codes to confirm receipt, regardless of how you process the call data

***

Docs for agents: [llms.txt](https://docs.bland.ai/llms.txt)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.