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

# Webhook endpoints

> Manage the endpoints Plinth delivers signed events to.

Plinth pushes signed, retried events to the endpoints you register here. For the consumer side —
verifying signatures and handling events — see [Receiving webhooks](/guides/receiving-webhooks).

## Create an endpoint

```bash cURL theme={null}
curl -X POST https://api.useplinth.com/v1/webhook-endpoints \
  -H "Authorization: Bearer sk_test_DOCS_SHARED_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://yourapp.com/api/plinth/webhook", "description": "Production" }'
```

<ParamField body="url" type="string" required>
  The `http(s)` endpoint that receives events.
</ParamField>

<ParamField body="description" type="string">
  Optional human label.
</ParamField>

<ParamField body="event_types" type="string[]">
  Event types to subscribe to. **Omit or pass `[]` to receive all events.**
</ParamField>

```json Response (201) theme={null}
{
  "object": "webhook_endpoint",
  "id": "whep_01KWG...",
  "url": "https://yourapp.com/api/plinth/webhook",
  "description": "Production",
  "enabled": true,
  "event_types": [],
  "secret": "whsec_a51e29ea...",
  "created_at": "2026-07-02T00:00:00Z",
  "updated_at": "2026-07-02T00:00:00Z"
}
```

<Warning>
  The `secret` (`whsec_…`) is returned **only** on create and rotate. Store it — it signs every
  delivery to this endpoint. Normal reads omit it.
</Warning>

## List endpoints

```bash cURL theme={null}
curl https://api.useplinth.com/v1/webhook-endpoints \
  -H "Authorization: Bearer sk_test_DOCS_SHARED_KEY"
```

Returns `{ "object": "list", "data": [ <webhook_endpoint>, … ] }` (secrets omitted).

## Update an endpoint

`PATCH` any of `url`, `description`, `enabled`, `event_types`.

```bash cURL theme={null}
curl -X PATCH https://api.useplinth.com/v1/webhook-endpoints/whep_01KWG... \
  -H "Authorization: Bearer sk_test_DOCS_SHARED_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": false }'
```

## Rotate the signing secret

Issues a fresh `whsec_…` (returned once) and invalidates the old one.

```bash cURL theme={null}
curl -X POST https://api.useplinth.com/v1/webhook-endpoints/whep_01KWG.../rotate-secret \
  -H "Authorization: Bearer sk_test_DOCS_SHARED_KEY"
```

## Delete an endpoint

```bash cURL theme={null}
curl -X DELETE https://api.useplinth.com/v1/webhook-endpoints/whep_01KWG... \
  -H "Authorization: Bearer sk_test_DOCS_SHARED_KEY"
```

## Inspect deliveries

Every event × endpoint produces a delivery row with status and retry history — the same data the
dashboard **Webhooks** view shows.

```bash cURL theme={null}
curl https://api.useplinth.com/v1/webhook-endpoints/whep_01KWG.../deliveries \
  -H "Authorization: Bearer sk_test_DOCS_SHARED_KEY"
```

```json Response theme={null}
{
  "object": "list",
  "counts": { "succeeded": 12, "retrying": 1 },
  "data": [
    {
      "object": "webhook_delivery",
      "id": "whd_01KWG...",
      "event_type": "subscription.activated",
      "status": "succeeded",
      "attempts": 1,
      "response_code": 200,
      "error": null,
      "next_retry_at": null,
      "last_attempt_at": "2026-07-02T00:00:01Z",
      "created_at": "2026-07-02T00:00:00Z"
    }
  ]
}
```

A failed delivery (non-2xx or timeout) retries with exponential backoff up to 8 attempts, then is
marked `failed`. `status` is one of `pending | retrying | succeeded | failed`.

## Resend a delivery

Re-queue a delivery for an immediate re-attempt (e.g. after fixing your endpoint).

```bash cURL theme={null}
curl -X POST https://api.useplinth.com/v1/webhook-endpoints/whep_01KWG.../deliveries/whd_01KWG.../resend \
  -H "Authorization: Bearer sk_test_DOCS_SHARED_KEY"
```

See the [event catalog](/webhook-events) for every event `type` and its payload.
