# A top-level run completed, failed or was cancelled

POST

## Parameters

### Header Parameters

**webhook-id**

required

string

The event id; the same on every retry. Deduplicate on it.

**webhook-timestamp**

required

string

/^\[0-9]+$/

Unix seconds when the request was signed. Reject requests far from your clock.

**webhook-signature**

required

string

`v1,<base64 HMAC-SHA256 of "{webhook-id}.{webhook-timestamp}.{body}">` under the endpoint’s secret; space-separated when two secrets sign during a rotation.

## Request Bodyrequired

application/json

object

**id**

required

Event id, also sent as the `webhook-id` header; the same on every retry.

string

**type**

required

string

Allowed value: run.finished

**createdAt**

required

string format: date-time

**data**

required

object

**run**

required

A finished top-level run: its identity and outcome, never its input or output. Field names match `GET /v1/runs/{runId}`.

object

**id**

required

RunId.

string format: uuid

**projectId**

required

string format: uuid

**flowId**

required

string

**flowVersion**

required

string

**status**

required

string

Allowed values: completed failed cancelled

**dryRun**

required

boolean

**failureMessage**

required

Why the run failed or was cancelled; `null` when it completed.

string | null

**failure**

A failed run’s error, as `GET /v1/runs/{runId}` reads it back: its `code`, and the error’s own `details` when it has them. Absent unless the run failed, and from a runtime that doesn’t send it yet; read `failureMessage` then.

object

**code**

required

string

**message**

required

string

**cause**

What the error came from, when it says: e.g. for `capability-routing-failed`, the router’s `capability-unsatisfiable` with its reasons, by provider.

**reason**

The error’s own reason, when it gives one: for a turn that ended at its approval (`hitl-cancelled`), `timeout` when nobody decided in time. Absent from an older runtime and from errors without one; read `code` then.

string

**details**

The error’s own facts, for a code that has them: for `rate-limit-exceeded`, `limit` (the budget that refused: `schema-compile-time` or `template-render-time`) and `budgetMs`, the names the API’s `429` uses. Never the wait: read back later, it’s stale. Absent for any other code, and from an older runtime.

object

**_key_**

additional properties

any

**createdAt**

required

string format: date-time

**completedAt**

required

string format: date-time

**usage**

The model calls of the run tree (this run and every run it started) that the cost ledger had recorded when this run finished: a child run still running then isn’t in it. `calls` counts failed calls too. Absent when the runtime records no usage.

object

**calls**

required

integer

**costUsd**

required

number

**tokens**

required

object

**prompt**

required

integer

**completion**

required

integer

**cacheRead**

required

integer

**cacheWrite**

required

integer

**reasoning**

required

integer

**agent**

On an agent’s run: the agent, the version that ran and the conversation, as `GET /v1/runs/{runId}` shows them (an agent run’s `flowId` is `agent.turn`). Absent on a flow’s run, and from a runtime before Kindgi 0.1.6.

object

**id**

required

The agent id.

string

**version**

required

The agent version that ran (semver).

string

**conversationId**

required

string format: uuid

**via**

Why this version ran: named by the caller (`explicit`); held by the flow version a flow’s agent step runs in (`flow-pin`: the node’s `config.version`, else the version the flow version pinned when it was published); the conversation’s own (`conversation`); the version live for the run’s scope (`live`); or the latest, nothing being live (`latest`). Absent on runs from before Kindgi 0.1.4.

string

Allowed values: explicit flow-pin conversation live latest

**liveScope**

One of: discriminator: kind

- **object**

  The agent’s default for the whole tenant.

  object

  **kind**

  required

  string

  Allowed values: tenant

- **object**

  An org’s projects.

  object

  **kind**

  required

  string

  Allowed values: org

  **orgId**

  required

  string format: uuid

- **object**

  One project.

  object

  **kind**

  required

  string

  Allowed values: project

  **projectId**

  required

  string format: uuid

- **object**

  A segment path within a project: it covers every run whose path starts with it.

  object

  **kind**

  required

  string

  Allowed values: segment

  **projectId**

  required

  string format: uuid

  **path**

  required

  Array\<object>

  \>= 1 items <= 8 items

  object

  **key**

  required

  Lowercase, like an identifier: `company`, `contact-role`.

  string

  /^\[a-z]\[a-z0-9\_-]{0,63}$/

  **value**

  required

  string

  \>= 1 characters <= 256 characters

## Responses

### 2XX

Received. Any other answer, or none within 10 seconds, is retried.
