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

# Webhooks

> How Brudcast notifies your server: signed HTTP POSTs sent in the background and retried when your server doesn't answer.

A webhook is an HTTP `POST` that Brudcast sends to a URL you own when something happens in your
organization. You register the URL once as a **webhook endpoint**, choose the events it cares about,
and Brudcast calls it. You don't have to poll the API to find out.

<Warning>
  Brudcast currently sends two event types: `push.token_invalidated` and `test.event`. The email,
  contact and campaign event types are in the event list and you can subscribe to them, but
  Brudcast doesn't send deliveries for them. [Event types](/developers/webhooks/event-types) lists
  the API calls to use for those instead.
</Warning>

## How a delivery works

1. Something happens in your organization. For example, Firebase Cloud Messaging rejects a device
   token.
2. Brudcast records one **delivery** for each active endpoint that subscribes to that event type.
3. Brudcast checks for due deliveries every five seconds. It sends each one as a JSON `POST`,
   signed with the endpoint's secret.
4. If your server sends back any HTTP response, the delivery is marked **Delivered**. If there's
   no response before the endpoint's timeout, or the connection fails, Brudcast tries again later.
   The wait doubles after each failed attempt, until the endpoint's **Max Retries** is used up.

```mermaid theme={"system"}
sequenceDiagram
    participant B as Brudcast
    participant Y as Your endpoint
    Note over B: Event recorded as a pending delivery
    B->>Y: POST, attempt 1
    Y--xB: No response (timeout or connection error)
    Note over B: failed, next attempt in 5 s
    B->>Y: POST, attempt 2
    Y--xB: No response
    Note over B: failed, next attempt in 10 s
    B->>Y: POST, attempt 3
    Y-->>B: HTTP 200
    Note over B: delivered
```

## Why it works this way

**Every request is signed.** The `X-Webhook-Signature` header is an HMAC of the exact request body,
keyed with your endpoint's secret. Anyone can send a `POST` to a public URL, so check the signature
before you trust the body. See [Verify signatures](/developers/webhooks/verifying-signatures).

**Any response ends the delivery.** Brudcast records your status code but doesn't retry on it. A
`500` or `401` from your server counts as delivered, just like a `200`. So store the event first,
return `200`, and process it afterwards. If your code fails after that, you still have the event.

**Only silence is retried.** Brudcast tries again when it gets no HTTP response at all. That
includes timeouts, refused connections, DNS failures and TLS errors.

**Every attempt sends the same body.** `delivery_id` and `timestamp` don't change between retries
or manual resends. If your server handled a request but Brudcast timed out waiting for the reply, a
retry brings the same event back. Record each `delivery_id` you process and skip repeats.

## Rules and limits

|                            |                                                                                                                                               |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Events per endpoint        | At least one                                                                                                                                  |
| Endpoints per organization | Set by your plan. At the limit, creating one fails with `Webhook endpoint limit reached (used/limit). Upgrade your plan to add more.`         |
| Request timeout            | Default 30 seconds. The dashboard offers 5, 10, 15, 30 or 60 seconds; the API accepts up to 300                                               |
| Max Retries                | Default 5. This is the **total** number of attempts, including the first. The dashboard offers 0–5; the API accepts 0–20                      |
| Wait between attempts      | 5 seconds × 2^(attempt − 1), capped at 24 hours. See [Retries and deliveries](/developers/webhooks/create-an-endpoint#retries-and-deliveries) |
| Order                      | Each delivery is sent on its own. Don't rely on arrival order                                                                                 |
| Your response body         | The first 1,000 characters are stored with the delivery and shown in the delivery log                                                         |

## Manage webhooks with the API

Everything in **Developers > Webhooks** is also available on the platform API, under
`https://core-service.prod.brudcast.com/api/v1/user`. Your API key needs the scope shown.

| Method and path                                  | Scope            | What it does                                                          |
| ------------------------------------------------ | ---------------- | --------------------------------------------------------------------- |
| `GET /webhook-endpoints`                         | `webhooks:read`  | List endpoints with their delivery totals and success rate            |
| `POST /webhook-endpoints`                        | `webhooks:write` | Create an endpoint. The response is the only place the secret appears |
| `GET /webhook-endpoints/statistics`              | `webhooks:read`  | Endpoint counts and the overall success rate                          |
| `GET /webhook-endpoints/{id}`                    | `webhooks:read`  | One endpoint with its retry policy and statistics                     |
| `PATCH /webhook-endpoints/{id}`                  | `webhooks:write` | Change the URL, events, headers, timeout, retries or `isActive`       |
| `DELETE /webhook-endpoints/{id}`                 | `webhooks:write` | Delete the endpoint and its delivery history                          |
| `POST /webhook-endpoints/{id}/test`              | `webhooks:write` | Queue a `test.event` delivery                                         |
| `POST /webhook-endpoints/{id}/regenerate-secret` | `webhooks:write` | Replace the signing secret                                            |
| `GET /webhook-deliveries`                        | `webhooks:read`  | List deliveries, newest first, cursor paginated                       |
| `GET /webhook-deliveries/{id}`                   | `webhooks:read`  | One delivery with every attempt                                       |
| `POST /webhook-deliveries/{id}/retry`            | `webhooks:write` | Send a delivery that hasn't been delivered again                      |

<Columns cols={2}>
  <Card title="Create an endpoint" icon="plus" href="/developers/webhooks/create-an-endpoint">
    Register a URL, pick events, save the secret and set retries.
  </Card>

  <Card title="Verify signatures" icon="shield-check" href="/developers/webhooks/verifying-signatures">
    Check the HMAC in Node.js, Python, PHP or Go.
  </Card>

  <Card title="Payload reference" icon="braces" href="/developers/webhooks/payload-reference">
    Headers, the envelope and each event's data.
  </Card>

  <Card title="Event types" icon="list" href="/developers/webhooks/event-types">
    What each event means and which are delivered.
  </Card>
</Columns>
