Skip to content
dhanu docs
Browse pages

Webhooks

Events

Every webhook event Dhanu can send, with the shape of its data, rendered from the same catalogue the server uses.

Subscribe to any of these when you create an endpoint. Each example below is a complete envelope; data is the part that differs per event.

task.message.created

An assistant or staff member finished a reply on a task. The message text is in `data.message.text`.

{
  "id": "evt_…",
  "type": "task.message.created",
  "createdAt": "2026-09-17T10:16:40.000Z",
  "workspaceId": "ws_…",
  "data": {
    "task": {
      "id": "3f2c…",
      "title": "Stand-up minutes"
    },
    "message": {
      "id": "9b1e…",
      "role": "assistant",
      "text": "Here are the minutes…",
      "createdAt": "2026-09-17T10:16:40.000Z"
    },
    "staffId": "stf_…"
  }
}

task.completed

A staff member finished the work it was given on a task, the reply that closes a trigger.

{
  "id": "evt_…",
  "type": "task.completed",
  "createdAt": "2026-09-17T10:16:40.000Z",
  "workspaceId": "ws_…",
  "data": {
    "task": {
      "id": "3f2c…",
      "title": "Stand-up minutes"
    },
    "message": {
      "id": "9b1e…",
      "role": "assistant",
      "text": "Here are the minutes…",
      "createdAt": "2026-09-17T10:16:40.000Z"
    },
    "staffId": "stf_…"
  }
}

job.succeeded

A background job started from the API finished; `data.job.result` holds its output.

{
  "id": "evt_…",
  "type": "job.succeeded",
  "createdAt": "2026-09-17T10:16:40.000Z",
  "workspaceId": "ws_…",
  "data": {
    "job": {
      "id": "7d0a…",
      "type": "video.generate",
      "status": "succeeded",
      "result": {
        "videoId": "c4e1…"
      },
      "error": null,
      "createdAt": "…",
      "completedAt": "…"
    }
  }
}

job.failed

A background job started from the API failed; `data.job.error` says why.

{
  "id": "evt_…",
  "type": "job.failed",
  "createdAt": "2026-09-17T10:16:40.000Z",
  "workspaceId": "ws_…",
  "data": {
    "job": {
      "id": "7d0a…",
      "type": "video.generate",
      "status": "failed",
      "result": null,
      "error": {
        "code": "provider_error",
        "message": "…"
      },
      "createdAt": "…",
      "completedAt": "…"
    }
  }
}

video.ready

A video finished rendering and can be fetched.

{
  "id": "evt_…",
  "type": "video.ready",
  "createdAt": "2026-09-17T10:16:40.000Z",
  "workspaceId": "ws_…",
  "data": {
    "video": {
      "id": "c4e1…",
      "taskId": "3f2c…",
      "title": "Product teaser",
      "durationSeconds": 8,
      "status": "ready"
    }
  }
}

credits.low

The workspace crossed a low-credit threshold.

{
  "id": "evt_…",
  "type": "credits.low",
  "createdAt": "2026-09-17T10:16:40.000Z",
  "workspaceId": "ws_…",
  "data": {
    "level": "low",
    "balance": 95000,
    "balanceLabel": "950 credits"
  }
}

Adding events

New event types are additive and never change the shape of an existing one, see versioning. A subscriber that ignores unknown type values keeps working as the list grows.