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

# Receive and Verify Real-Time Call Data via Webhooks

> Configure VoiceInfra webhooks to receive POST requests with call data when calls complete. HMAC-SHA256 signatures verify every payload.

When a VoiceInfra call completes, your configured webhook endpoint receives a POST request containing the full call record — transcript, recording URL, AI summary, outcome, duration, and metadata. Use this data to update your CRM, feed your analytics pipeline, trigger post-call workflows, or archive records in your own system. Every payload is signed with HMAC-SHA256 so you can verify authenticity before processing.

## What You Receive

Every webhook delivery contains the following fields:

| Field              | Type     | Description                                      |
| ------------------ | -------- | ------------------------------------------------ |
| `call_id`          | string   | Unique identifier for the call                   |
| `from_number`      | string   | Caller's phone number in E.164 format            |
| `to_number`        | string   | The number that was called                       |
| `agent_id`         | string   | ID of the AI agent that handled the call         |
| `duration_seconds` | integer  | Total call duration in seconds                   |
| `start_time`       | ISO 8601 | Timestamp when the call started                  |
| `end_time`         | ISO 8601 | Timestamp when the call ended                    |
| `recording_url`    | string   | URL to the call recording audio file             |
| `transcript`       | string   | Full conversation transcript with speaker labels |
| `call_outcome`     | string   | `answered`, `voicemail`, or `failed`             |
| `summary`          | string   | AI-generated summary of the call                 |

## Configuring a Webhook

<Steps>
  <Step title="Go to Settings → Webhooks → Add Webhook">
    Open your VoiceInfra dashboard, navigate to **Settings → Webhooks**, and click **Add Webhook**.
  </Step>

  <Step title="Enter your endpoint URL">
    Paste the URL of your server endpoint. The endpoint must be publicly accessible over HTTPS and respond with an HTTP `200` status code within the timeout window.
  </Step>

  <Step title="Set a webhook secret (recommended)">
    Enter a secret string of your choice. VoiceInfra uses this secret to sign every payload with HMAC-SHA256 and sends the signature in the `X-VoiceInfra-Signature` header. Verify this signature in your handler to confirm the request is authentic.
  </Step>

  <Step title="Test the webhook">
    Click **Test** to send a sample payload to your endpoint immediately. Check your server logs to confirm it received the request and returned `200`. Fix any connectivity issues before enabling.
  </Step>

  <Step title="Enable and save">
    Toggle the webhook to **Enabled** and click **Save**. Your endpoint starts receiving POST requests as soon as the next call completes.
  </Step>
</Steps>

<Warning>
  Your endpoint must be publicly accessible and return a `200` status code within the timeout window. Endpoints that time out or return non-2xx responses are treated as failed deliveries and trigger automatic retries.
</Warning>

## Verifying Webhook Signatures

Always verify the `X-VoiceInfra-Signature` header before processing a payload. This ensures the request came from VoiceInfra and was not tampered with in transit.

```python theme={null}
import hmac
import hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

# In your webhook handler:
# signature = request.headers.get('X-VoiceInfra-Signature')
# is_valid = verify_webhook(request.body, signature, YOUR_SECRET)
```

<Note>
  Use `hmac.compare_digest` instead of `==` to prevent timing attacks when comparing signature strings.
</Note>

## Example Webhook Payload

```json theme={null}
{
  "call_id": "call_01HXYZ123456",
  "from_number": "+14155550100",
  "to_number": "+18005551234",
  "agent_id": "agent_abc123",
  "duration_seconds": 147,
  "start_time": "2025-01-15T14:23:00Z",
  "end_time": "2025-01-15T14:25:27Z",
  "recording_url": "https://recordings.voiceinfra.ai/call_01HXYZ123456.mp3",
  "call_outcome": "answered",
  "summary": "Customer called to inquire about January 15 appointment. Confirmed appointment at 2pm. No changes requested."
}
```

## Delivery Logs

Every webhook delivery is recorded in your dashboard. Access the logs at **Settings → Webhooks → View Logs** to see:

* **Timestamp** — exact time the delivery was attempted
* **HTTP status code** — the response code returned by your endpoint
* **Response time** — how long your endpoint took to respond
* **Full payload** — the complete JSON body that was sent
* **Response body** — your endpoint's response (useful for debugging)

Failed deliveries are retried automatically with exponential back-off. Check the logs to confirm delivery after fixing an endpoint issue — you don't need to retrigger the call.

## Multiple Endpoints

Configure as many webhook endpoints as you need — one per system is a common pattern:

* **CRM endpoint** — receives call data and logs Activities in Salesforce or HubSpot
* **Analytics endpoint** — feeds call metadata into your data warehouse or BI tool
* **Notification endpoint** — posts a summary to Slack or Teams when calls complete

Each endpoint receives the same payload independently. Manage all endpoints from **Settings → Webhooks**.

***

## Frequently Asked Questions

<AccordionGroup>
  <Accordion title="When exactly is the webhook triggered?">
    The webhook fires when the call completes — that is, when both parties have hung up. Post-call processing (transcript generation, AI summary) happens in the seconds immediately after hang-up, and the webhook is sent once that processing is complete.
  </Accordion>

  <Accordion title="Is the webhook secret required?">
    No, but it is strongly recommended. Without a secret, you cannot verify that a request came from VoiceInfra. Any party that discovers your endpoint URL could send fake payloads. Set a secret and always validate the signature before acting on a payload.
  </Accordion>

  <Accordion title="Can I have multiple webhook endpoints?">
    Yes. Add as many endpoints as you need in **Settings → Webhooks**. Each endpoint receives every call payload independently.
  </Accordion>

  <Accordion title="What happens if my endpoint is down when a call completes?">
    VoiceInfra retries failed deliveries automatically. Check the delivery logs in your dashboard to see retry status. Once your endpoint recovers and returns `200`, the delivery is marked successful.
  </Accordion>

  <Accordion title="Does the transcript include both sides of the conversation?">
    Yes. The transcript field contains the full conversation with speaker labels — both the caller's words and the AI agent's responses are included.
  </Accordion>

  <Accordion title="Can I disable a webhook without deleting it?">
    Yes. Toggle the webhook to **Disabled** in the dashboard. Your configuration is saved and no payloads are sent while disabled. Re-enable it at any time to resume delivery.
  </Accordion>
</AccordionGroup>
