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

# Webhooks

> Receive real-time event notifications from Indigenius on your own endpoint.

## Overview

Webhooks let your backend receive push notifications when key actions happen on your account — a call ends, a dubbing job completes, a workflow runs, and so on. Indigenius sends an HTTP `POST` to your configured endpoint with a JSON payload describing the event.

Configure your webhook URL when creating an API key (`callbackUrl`) or when creating a workflow (`webhook.url`).

***

## Delivery model

* Events are delivered via HTTP `POST` to your endpoint.
* Your endpoint must return a `2xx` status code within **10 seconds**. If it times out or returns a non-2xx, delivery is retried with backoff.
* Process events **asynchronously** — do your actual work in a background job, not in the request handler.

***

## Event payload shape

Every webhook delivery shares the same outer envelope:

```json theme={null}
{
  "event": "call.completed",
  "timestamp": "2026-06-05T14:32:00.000Z",
  "organizationId": "665e4a34c65bb95f2f2d72e0",
  "data": {}
}
```

| Field            | Type              | Description                       |
| ---------------- | ----------------- | --------------------------------- |
| `event`          | `string`          | The event type (see table below). |
| `timestamp`      | `ISO 8601 string` | When the event was emitted.       |
| `organizationId` | `string`          | Your organization ID.             |
| `data`           | `object`          | Event-specific payload.           |

***

## Event types

### `call.completed`

Fired when a web or phone call ends.

```json theme={null}
{
  "event": "call.completed",
  "timestamp": "2026-06-05T14:32:00.000Z",
  "organizationId": "665e4a34c65bb95f2f2d72e0",
  "data": {
    "callId": "665e4a34c65bb95f2f2d72e1",
    "assistantId": "665e4a34c65bb95f2f2d72e2",
    "type": "web",
    "durationSeconds": 142,
    "status": "completed"
  }
}
```

### `call.failed`

Fired when a call fails before completing.

```json theme={null}
{
  "event": "call.failed",
  "timestamp": "2026-06-05T14:32:00.000Z",
  "organizationId": "665e4a34c65bb95f2f2d72e0",
  "data": {
    "callId": "665e4a34c65bb95f2f2d72e1",
    "assistantId": "665e4a34c65bb95f2f2d72e2",
    "reason": "connection_timeout"
  }
}
```

### `workflow.completed`

Fired when a workflow execution finishes successfully.

```json theme={null}
{
  "event": "workflow.completed",
  "timestamp": "2026-06-05T14:35:00.000Z",
  "organizationId": "665e4a34c65bb95f2f2d72e0",
  "data": {
    "workflowId": "665e4a34c65bb95f2f2d72e3",
    "jobId": "job_01hxyz",
    "status": "completed"
  }
}
```

### `dubbing.completed`

Fired when a dubbing job finishes and media is ready to download.

```json theme={null}
{
  "event": "dubbing.completed",
  "timestamp": "2026-06-05T14:40:00.000Z",
  "organizationId": "665e4a34c65bb95f2f2d72e0",
  "data": {
    "dubbingId": "665e4a34c65bb95f2f2d72e7",
    "projectName": "Product explainer dub",
    "targetLanguage": "French",
    "status": "completed"
  }
}
```

### `dubbing.failed`

Fired when a dubbing job fails during processing.

```json theme={null}
{
  "event": "dubbing.failed",
  "timestamp": "2026-06-05T14:40:00.000Z",
  "organizationId": "665e4a34c65bb95f2f2d72e0",
  "data": {
    "dubbingId": "665e4a34c65bb95f2f2d72e7",
    "reason": "source_video_unreachable"
  }
}
```

### `tts.completed`

Fired when a text-to-speech job finishes.

```json theme={null}
{
  "event": "tts.completed",
  "timestamp": "2026-06-05T14:38:00.000Z",
  "organizationId": "665e4a34c65bb95f2f2d72e0",
  "data": {
    "jobId": "665e4a34c65bb95f2f2d72e8",
    "status": "completed"
  }
}
```

***

## Receiver checklist

<Steps>
  <Step title="Use HTTPS">
    Indigenius only delivers to `https://` endpoints. Plain HTTP URLs are
    rejected.
  </Step>

  <Step title="Respond quickly">
    Return `200 OK` (or any `2xx`) as soon as you receive and validate the
    payload. Do not block the response while processing.
  </Step>

  <Step title="Make handlers idempotent">
    Deliveries can be retried. Always check whether you have already processed
    an event before acting on it — use `data.callId` or `data.jobId` as your
    deduplication key.
  </Step>

  <Step title="Log event IDs">
    Log the event type, timestamp, and relevant IDs on every delivery. This
    makes it easy to cross-reference against [Webhook
    History](/webhook-history).
  </Step>
</Steps>

***

## Example receiver (Node/Express)

```javascript theme={null}
import express from 'express';

const app = express();
app.use(express.json());

app.post('/hooks/indigenius', (req, res) => {
  // Acknowledge immediately
  res.sendStatus(200);

  // Process asynchronously
  const { event, data } = req.body;
  processEvent(event, data).catch(console.error);
});

async function processEvent(event, data) {
  switch (event) {
    case 'call.completed':
      await handleCallCompleted(data);
      break;
    case 'dubbing.completed':
      await handleDubbingCompleted(data);
      break;
    default:
      console.log('Unhandled event type:', event);
  }
}
```

***

## Retry behaviour

If your endpoint returns a non-`2xx` status or times out, Indigenius retries delivery with exponential backoff. You can inspect all delivery attempts — successful and failed — in [Webhook History](/webhook-history).
