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

# Webhooks & Callbacks

> Receive task completion notifications via webhook callbacks

When creating tasks, you can provide a `callback_url` to receive webhook notifications when the task completes or fails. This avoids polling and lets you integrate with your backend asynchronously.

## Enabling Callbacks

Pass `callback_url` at the top level of your request (outside the `input` object):

```bash theme={null}
curl -X POST https://api.unifically.com/v1/tasks \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "model": "google/veo-3.1-fast",
    "input": {
      "prompt": "A cat walking on the beach at sunset"
    },
    "callback_url": "https://your-server.com/webhook"
  }'
```

<ParamField body="callback_url" type="string">
  Optional webhook URL. When provided, the API sends a POST request to this URL when the task completes or fails.
</ParamField>

## Webhook Payload Format

The API sends a POST request to your `callback_url` with a JSON body. The payload structure depends on whether the task succeeded or failed.

### Success Payload

When the task completes successfully:

```json theme={null}
{
  "task_id": "abc123def456",
  "status": "completed",
  "data": {
    "video_url": "https://cdn.unifically.com/outputs/abc123.mp4"
  }
}
```

The `data` object contains the output URL(s) based on the task type:

| Task Type | Output Field | Description                |
| --------- | ------------ | -------------------------- |
| Video     | `video_url`  | URL to the generated video |
| Image     | `image_url`  | URL to the generated image |
| Audio     | `audio_url`  | URL to the generated audio |

Some models may return additional fields. For example, multi-output models might include `image_urls` or `audio_urls` as arrays.

### Failure Payload

When the task fails:

```json theme={null}
{
  "task_id": "abc123def456",
  "status": "failed",
  "error_message": "Description of what went wrong"
}
```

| Field           | Type   | Description                      |
| --------------- | ------ | -------------------------------- |
| `task_id`       | string | The task ID                      |
| `status`        | string | `"failed"`                       |
| `error_message` | string | Human-readable error description |

## Request Details

* **Method:** POST
* **Content-Type:** `application/json`
* **Body:** JSON payload as shown above

## Best Practices

1. **Respond quickly** — Return a 2xx status code within a few seconds to acknowledge receipt. Process the payload asynchronously if needed.
2. **Verify webhook origin** — Use HTTPS and consider validating requests (e.g., via a shared secret or signature if supported in the future).
3. **Handle duplicates** — The same webhook may be delivered more than once; use `task_id` to deduplicate.
4. **Validate URLs** — Ensure your callback URL is publicly accessible and accepts POST requests.

## Example Handler

```javascript theme={null}
// Express.js example
app.post('/webhook', (req, res) => {
  const { task_id, status, data, error_message } = req.body;

  // Acknowledge immediately
  res.status(200).send('OK');

  if (status === 'completed') {
    const url = data.video_url || data.image_url || data.audio_url;
    console.log(`Task ${task_id} completed: ${url}`);
    // Process the completed task...
  } else if (status === 'failed') {
    console.error(`Task ${task_id} failed: ${error_message}`);
    // Handle the failure...
  }
});
```
