# Webhooks

> Tracon documentation. Tracon is a .NET package family that adds a control
> plane on Microsoft Agent Framework, published as NuGet packages that run
> inside your own ASP.NET Core application.
>
> Page: https://tracon.dev/http-api/webhooks/
> Summary: The webhooks endpoints of the Tracon HTTP API — 6 operations.

6 operations. `{prefix}` is the route prefix passed to
`MapTracon`; the template uses `/tracon`.

## GET {prefix}/api/webhooks

**Operation ID:** `TraconListWebhooks`

**Lists a tenant's webhook subscriptions.**

The response carries no signing secret; only the NAME of the signing key is returned. 'headerConfigurationKeys' carries configuration key NAMES and is returned as stored. Extra headers are returned with their NAMES only: every header value is replaced with '***'.

**Authorization:** bearer authentication; `Admin` role policy when that policy is registered; `PlatformRead` API-key scope.

| Response | Body | Headers |
|---|---|---|
| **200** OK | `application/json` → array of [`WebhookSubscription`](/http-api/schemas/webhooksubscription/) | — |

## GET {prefix}/api/webhooks/{name}

**Operation ID:** `TraconGetWebhook`

**Gets a single subscription.**

As in the list, no signing secret is returned — only the configuration key its value is read from at delivery time. A secret is never stored in the database and never leaves through this API. 'headerConfigurationKeys' is returned as stored (key names only). Extra header values are replaced with '***'. An unknown name returns 404.

**Authorization:** bearer authentication; `Admin` role policy when that policy is registered; `PlatformRead` API-key scope.

| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
| `name` | path | yes | `string` | — |

| Response | Body | Headers |
|---|---|---|
| **200** OK | `application/json` → [`WebhookSubscription`](/http-api/schemas/webhooksubscription/) | — |

## PUT {prefix}/api/webhooks/{name}

**Operation ID:** `TraconSaveWebhook`

**Creates or updates a webhook subscription.**

The address passes an SSRF check: only https is accepted (http only when AllowInsecureHttp is enabled and only to loopback targets). Private network addresses are re-checked again at delivery time. 'secretConfigurationKey' must be under the configured allowed prefix and inside the tenant's own key space — '{prefix}{tenantId}:...'; a flat name directly under the prefix belongs to the default tenant (400 otherwise). A credential header (Authorization, X-Api-Key, Cookie, any name ending in '-key') is declared in 'headerConfigurationKeys' as the NAME of the configuration key its value is read from, under the same key space rule; the same header in plain 'headers' is rejected with 400. Plain header values are stored and sent as given, but the saved subscription comes back with every one replaced by '***', and a header whose value is '***' is rejected with 400. A header name may appear only once across both maps (case-insensitive), may not be one of Tracon's own X-Tracon-* headers in 'headerConfigurationKeys', and both maps together may carry at most MaxExtraHeaders entries (400 otherwise). 'headers' or 'headerConfigurationKeys' left out or null keeps the stored map; '{}' removes it. Every other field is replaced. Changing 'url' without sending the maps keeps them, so the stored headers and the resolved credential values go to the NEW address.

**Authorization:** bearer authentication; `Admin` role policy when that policy is registered; `PlatformAdmin` API-key scope.

| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
| `name` | path | yes | `string` | — |

**Request body** (required):

- `application/json` → [`WebhookSaveRequest`](/http-api/schemas/webhooksaverequest/)

| Response | Body | Headers |
|---|---|---|
| **200** OK | `application/json` → [`WebhookSubscription`](/http-api/schemas/webhooksubscription/) | — |

## DELETE {prefix}/api/webhooks/{name}

**Operation ID:** `TraconDeleteWebhook`

**Deletes a subscription and its delivery history.**

The delivery history cascades with the subscription, so export it first if it is needed for an audit; there is no way to recover it afterwards. Events raised after the delete match no subscription and are simply not delivered. An unknown name returns 404.

**Authorization:** bearer authentication; `Admin` role policy when that policy is registered; `PlatformAdmin` API-key scope.

| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
| `name` | path | yes | `string` | — |

| Response | Body | Headers |
|---|---|---|
| **204** No Content | — | — |

## GET {prefix}/api/webhooks/{name}/deliveries

**Operation ID:** `TraconListWebhookDeliveries`

**Lists a subscription's delivery history.**

This is a history table, not a queue: scheduling and retry live in the job queue. There is one entry per event, carrying the latest status, the attempt count, and the endpoint's last response code — a retry updates that entry rather than adding another. Filter with '?status=' to find failures. Paging is offset based — 'skip' defaults to 0, 'take' to 50, and 'take' is clamped to 1..200 instead of being rejected. An unknown subscription name returns 404.

**Authorization:** bearer authentication; `Admin` role policy when that policy is registered; `PlatformRead` API-key scope.

| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
| `name` | path | yes | `string` | — |
| `status` | query | no | [`WebhookDeliveryStatus`](/http-api/schemas/webhookdeliverystatus/) | — |
| `skip` | query | no | `integer (int32)` | pattern `^-?(?:0\\|[1-9]\d*)$` |
| `take` | query | no | `integer (int32)` | pattern `^-?(?:0\\|[1-9]\d*)$` |

| Response | Body | Headers |
|---|---|---|
| **200** OK | `application/json` → array of [`WebhookDelivery`](/http-api/schemas/webhookdelivery/) | — |

## POST {prefix}/api/webhooks/{name}/test

**Operation ID:** `TraconTestWebhook`

**Sends a test event to the subscription's endpoint.**

The event is written to the queue and delivered by a background worker; the response reports that it was queued, not the delivery outcome.

**Authorization:** bearer authentication; `Admin` role policy when that policy is registered; `PlatformAdmin` API-key scope.

| Parameter | In | Required | Type | Description and rules |
|---|---|---|---|---|
| `name` | path | yes | `string` | — |

| Response | Body | Headers |
|---|---|---|
| **200** OK | `application/json` → [`WebhookTestResponse`](/http-api/schemas/webhooktestresponse/) | — |
