# Redeliver an event

POST

/v1/webhook-endpoints/{endpointId}/deliveries/{deliveryId}/redeliver

```sh
curl --request POST \
  --url https://example.com/v1/webhook-endpoints/example/deliveries/example/redeliver \
  --header 'Authorization: Bearer <token>'
```

Queues the delivery again now, whatever its status; its attempts start over.

## Authorizations

- **[bearerAuth](https://docs.kindgi.com/v0.4.0/reference/api.md#bearerauth)**

## Parameters

### Path Parameters

**endpointId**

required

string

The webhook endpoint id.

**deliveryId**

required

string

The delivery id.

### Header Parameters

**Idempotency-Key**

string

\>= 1 characters

Caller-supplied idempotency key, scoped to the caller: the same key from someone else in the tenant is their own request (from 0.1.5). Retries with the same key return the original response byte-identical (per `docs/API-ROUTE-CONVENTIONS.md` §3.1). A retry sent while the first request still runs is answered `409 idempotency-key-in-flight` with `Retry-After`, on a runtime whose store holds keys (from 0.1.5); retry after it, and you get the first request’s answer. An answer that carries a secret (a new API key or public run token, a session token, a generated signing secret) isn’t kept: a retry gets `409 idempotency-key-replay-withheld`, with the first request’s status and when it succeeded (from 0.1.5). A request whose key store can’t be read before it runs is answered `503 idempotency-store-unavailable` with `Retry-After`: nothing ran, so retry with the same key (from 0.3.0).

## Responses

### 202

Queued.

application/json

object

**deliveryId**

required

string

**endpointId**

required

string

**event**

required

One of: discriminator: type

- **object**

  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 pinned for the run’s scope (`pinned`); or the latest, nothing being pinned (`latest`). Absent on runs from before Kindgi 0.1.4.

  string

  Allowed values: explicit flow-pin conversation pinned latest

  **pinnedScope**

  One of: discriminator: kind

  - **object**

    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

- **object**

  An Improve run ended (`completed`, `failed` or `cancelled`): one a person started, or one an `improve` schedule did. Its outcome names the suggested change it wrote, if it wrote one.

  object

  **id**

  required

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

  string

  **type**

  required

  string

  Allowed value: improve-run.finished

  **createdAt**

  required

  string format: date-time

  **data**

  required

  object

  **improveRun**

  required

  The Improve run, as `GET /v1/improve-runs/{improveRunId}` shows it.

  object

  **id**

  required

  string format: uuid

  **agentId**

  required

  string

  **projectId**

  The project it works in. Absent from older servers, and on a run started for a tenant or an org before Improve runs worked in a project.

  string format: uuid

  **startsFrom**

  required

  The version an Improve run starts from: the one the project runs, pinned there (`pin`) or the agent’s latest (`latest`).

  object

  **version**

  required

  string

  **follows**

  required

  string

  Allowed values: pin latest

  **testSetVersion**

  The version of the project’s test set it searches and proves on; absent until it’s frozen.

  string

  **setAside**

  The test set’s cases set aside for the proof: `cases` of `of`. None with fewer than five. Absent from older servers.

  object

  **cases**

  required

  integer

  **of**

  required

  integer

  **tiers**

  required

  The tiers it tries, the prompt tier first.

  Array\<string>

  Allowed values: settings prompt

  **objective**

  required

  string

  Allowed values: passRate weightedPrecisionAtK

  **groupWeights**

  required

  Which corrections its comparisons count.

  string

  Allowed values: as-recorded experts-only

  **model**

  For the prompt tier: the provider and model that drafts the templates.

  object

  **providerId**

  required

  string

  **model**

  required

  string

  **candidates**

  For the prompt tier: how many templates it drafts.

  integer

  \>= 1 <= 5

  **budget**

  required

  object

  **maxCostUsd**

  required

  The most the Improve run’s comparisons may cost, in US dollars.

  number

  \> 0 <= 100

  **maxCandidates**

  required

  The most candidates it compares.

  integer

  \>= 1 <= 200

  **requestedBy**

  required

  `user:<id>` or `service:<id>`.

  string

  **status**

  required

  string

  Allowed values: running completed failed cancelled

  **tried**

  required

  Candidates tried so far.

  integer

  **costUsd**

  required

  What its comparisons have cost so far (US dollars).

  string

  **outcome**

  One of: discriminator: kind

  - **object**

    A change passed more cases than the version the run started from, and failed none that passed: the run wrote it as a suggested change for a reviewer to decide.

    object

    **kind**

    required

    string

    Allowed value: suggested

    **suggestedChangeId**

    required

    string format: uuid

  - **object**

    No change the run tried did better: `reason` says why, and `holdOut` has the best change’s numbers when one got that far.

    object

    **kind**

    required

    string

    Allowed value: nothing-better

    **reason**

    required

    string

    **holdOut**

    The best change’s proof numbers, when one got that far: on every case, or on the set-aside part for a run stored before that.

    object

    **baseline**

    required

    number | null

    **candidate**

    required

    number | null

    **delta**

    required

    number | null

    **spread**

    number

  - **object**

    The run reached its budget with nothing kept.

    object

    **kind**

    required

    string

    Allowed value: cost-cap

    **spentUsd**

    required

    What it spent, in US dollars.

    string

  - **object**

    The run failed: `message` says why.

    object

    **kind**

    required

    string

    Allowed value: failed

    **message**

    required

    string

  **takes**

  The ids of the corrections it took when it started. Absent from older servers.

  Array\<string>

  **cancelReason**

  Why a `cancelled` Improve run stopped when nobody cancelled it: a comparison’s test run was cancelled for it (that run’s `cancelReason`, e.g. `project-suspended`). It wrote no suggested change. Absent when it was cancelled.

  string

  **comparisons**

  Its comparisons so far, each a test run to open: `reference` (the version as it is, on each part: what the proof is held to, case by case), each `candidate` (the block and the values it changed, on the search part: what picks the change to suggest), and the `proof` (the suggested change, on `all` the cases at the reference’s repetitions: what keeps it or not; an Improve run from before 0.4 ran its proof on the hold-out part). Absent from older servers.

  Array\<object>

  object

  **testRunId**

  string format: uuid

  **role**

  required

  string

  Allowed values: reference candidate proof

  **part**

  required

  string

  Allowed values: search hold-out all

  **blockId**

  string

  **changed**

  object

  **_key_**

  additional properties

  any

  **score**

  number | null

  **failed**

  string

  **refused**

  For a drafted template that was never compared: why the check refused it (what it reads or names that the agent doesn’t have, or its size).

  Array\<object>

  object

  **path**

  required

  string

  **message**

  required

  string

  **why**

  For a drafted template: what the drafter meant it to change.

  string

  **trigger**

  The improve schedule and fire that started it (`GET /v1/schedules/{triggerId}/fires`); absent for an Improve run a person started.

  object

  **triggerId**

  required

  string

  **fireId**

  required

  string

  **createdAt**

  required

  string format: date-time

  **updatedAt**

  required

  string format: date-time

  **finishedAt**

  string format: date-time

- **object**

  An approval was asked for: a reviewer’s decision is waiting. Sent once per approval (an escalation is a new approval). `projectId` in the endpoint’s filter narrows it to the approval’s project.

  object

  **id**

  required

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

  string

  **type**

  required

  string

  Allowed value: approval.requested

  **createdAt**

  required

  string format: date-time

  **data**

  required

  object

  **approval**

  required

  The approval an `approval.requested` event names. What it is about stays behind sign-in: no `context`, no tool call or run input.

  object

  **approvalId**

  required

  string

  **projectId**

  string

  **requiredRole**

  required

  The least reviewer role that may decide it.

  string

  Allowed values: standard senior admin

  **title**

  string

  **assignedTo**

  The one reviewer it is assigned to, when it is.

  string

  **createdAt**

  required

  string format: date-time

  **expiresAt**

  string format: date-time

  **url**

  Its page in the console, when the runtime knows its public address.

  string

- **object**

  object

  **id**

  required

  string

  **type**

  required

  string

  Allowed value: webhook.test

  **createdAt**

  required

  string format: date-time

  **data**

  required

  object

  **endpointId**

  required

  string

**status**

required

`pending`: waiting for its next attempt. `delivered`: the endpoint answered 2xx. `failed`: every attempt failed, or the endpoint was unregistered first; redeliver queues it again.

string

Allowed values: pending delivered failed

**attempts**

required

integer

**nextAttemptAt**

required

string | null format: date-time

**lastAttemptAt**

required

string | null format: date-time

**lastResponseStatus**

required

HTTP status of the last attempt; `null` when it got no response.

integer | null

**lastError**

required

Why the last attempt failed (`timeout`, `connection-refused`, `url-refused`, …).

string | null

**createdAt**

required

string format: date-time

**deliveredAt**

required

string | null format: date-time

##### Example

```json
{
  "event": {
    "type": "run.finished",
    "data": {
      "run": {
        "status": "completed",
        "agent": {
          "via": "explicit",
          "pinnedScope": {
            "kind": "tenant"
          }
        }
      }
    }
  },
  "status": "pending"
}
```

### 400

Malformed request body.

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

### 401

Missing / malformed / expired / revoked bearer token.

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

### 403

Not a tenant admin (`permission-denied`). Without an authorization store, a tenant admin is the deployment’s API token, an admin key, or a console signed in with either.

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

### 404

No endpoint, or no delivery with that id for it.

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

### 409

Idempotency-Key was reused with a different body, or resource-state conflict.

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

### 500

Server error (unmapped domain code or framework crash).

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

### 503

The `Idempotency-Key` store couldn’t be read before the request ran (`idempotency-store-unavailable`), so nothing was changed; `Retry-After` (whole seconds) says when to try again with the same key.

application/json

object

**error**

required

object

**code**

required

Stable machine-readable discriminant. Values match domain error codes (see `docs/API-ROUTE-CONVENTIONS.md` §4.3).

string

**message**

required

string

**details**

Optional, kind-specific.

object

**_key_**

additional properties

any

**requestId**

required

Server-assigned request id; also echoed via `X-Request-Id` header.

string

##### Examplegenerated

```json
{
  "error": {
    "code": "example",
    "message": "example",
    "details": {},
    "requestId": "example"
  }
}
```

## See also

- [`GET /v1/webhook-endpoints/{endpointId}`: Fetch a webhook endpoint](https://docs.kindgi.com/v0.4.0/reference/api/operations/webhookendpointsget.md)
- [`PATCH /v1/webhook-endpoints/{endpointId}`: Update a webhook endpoint](https://docs.kindgi.com/v0.4.0/reference/api/operations/webhookendpointsupdate.md)
- [`POST /v1/webhook-endpoints/{endpointId}/unregister`: Unregister a webhook endpoint (soft delete)](https://docs.kindgi.com/v0.4.0/reference/api/operations/webhookendpointsunregister.md)
- [`GET /v1/webhook-endpoints/{endpointId}/deliveries`: List a webhook endpoint's deliveries](https://docs.kindgi.com/v0.4.0/reference/api/operations/webhookendpointslistdeliveries.md)
- [Error code `idempotency-store-unavailable`](https://docs.kindgi.com/v0.4.0/reference/errors.md#idempotency-store-unavailable)
- [Error code `permission-denied`](https://docs.kindgi.com/v0.4.0/reference/errors.md#permission-denied)
- [Every error code](https://docs.kindgi.com/v0.4.0/reference/errors.md)
