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

# Webhooks

> Signed account lifecycle events with retries, redelivery, and deduplication.

Subscribe to account lifecycle events via the Webhooks endpoints and react in
your backend the moment something happens — no polling.

## Event types

| Event                                                                             | Fires when                                |
| --------------------------------------------------------------------------------- | ----------------------------------------- |
| `account.created`                                                                 | A trading account is provisioned          |
| `account.status_changed`                                                          | Any status transition                     |
| `account.updated`                                                                 | Balance, metadata, or config changed      |
| `account.passed`                                                                  | Evaluation passed (profit target reached) |
| `account.failed`                                                                  | A rule breach failed the account          |
| `account.imported` / `account.unlinked`                                           | Import-key lifecycle                      |
| `account.lockout_created` / `account.lockout_updated` / `account.lockout_removed` | Trading lockouts                          |
| `account.payout_processed`                                                        | A payout was recorded                     |
| `account.max_payouts_reached`                                                     | Account hit its payout cap                |
| `purchase.created` / `purchase.status_changed`                                    | Purchase lifecycle                        |
| `trader.created`                                                                  | A trader joined your organization         |
| `snapshot.ready`                                                                  | End-of-day snapshot available             |
| `fill.created`                                                                    | Per-fill stream (high volume)             |

Subscribe with an explicit list or `"*"` for everything.

<Warning>
  High-volume events (`fill.created`) are **never** delivered through a `*`
  subscription — an endpoint must list them explicitly. This protects existing
  wildcard endpoints from suddenly receiving a firehose of per-fill events.
</Warning>

Events carry contextual blocks where relevant: `trigger` (what caused it,
for example `rule_violation`, `profit_target`, `first_trade`), `ruleType`
(which rule fired, for example `max_loss`, `daily_loss`), `payout` (payout ID, amounts,
balances), `import` (import key details), and `previousAttributes` for
change events.

## Verifying signatures

Every delivery is HMAC-SHA256 signed with your endpoint's secret
(`whsec_...`, shown when you create the webhook).

Request headers:

| Header                  | Contents                                   |
| ----------------------- | ------------------------------------------ |
| `X-Hyperprop-Signature` | `sha256=<hex digest>`                      |
| `X-Hyperprop-Timestamp` | Unix timestamp used in the signature       |
| `X-Hyperprop-Delivery`  | Unique delivery ID — use for deduplication |

The signed message is `` `${timestamp}.${rawBody}` ``:

```typescript theme={null}
import crypto from "crypto";

function verify(rawBody: string, headers: Record<string, string>, secret: string): boolean {
  const timestamp = headers["x-hyperprop-timestamp"];
  // Reject stale timestamps to prevent replay (5 minutes is a good window).
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;

  const expected =
    "sha256=" +
    crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(headers["x-hyperprop-signature"]),
  );
}
```

<Note>
  Compute the HMAC over the **raw request body**, before any JSON parsing —
  re-serialized JSON may not match byte-for-byte.
</Note>

## Delivery, retries, and auto-disable

* Your endpoint should respond **2xx within 10 seconds**; anything else
  counts as a failed attempt.
* Failed deliveries retry up to **5 attempts** with backoff: immediately,
  then after 1 min, 5 min, 30 min, and 2 h.
* Consecutive failures eventually **auto-disable** the endpoint (you can
  re-enable it from the dashboard or API once your endpoint is healthy).
* Any event can be **redelivered** on demand from the dashboard or API —
  which is also why you should deduplicate.

## Deduplication

Store `X-Hyperprop-Delivery` IDs you've processed and skip repeats. Retries
and manual redeliveries reuse the same event payload, so an idempotent
consumer is all you need for exactly-once effects.


## Related topics

- [Update a webhook](/platform-api/organization/update-a-webhook.md)
- [Delete a webhook](/platform-api/organization/delete-a-webhook.md)
- [List all webhooks](/platform-api/organization/list-all-webhooks.md)
- [Get webhook details](/platform-api/organization/get-webhook-details.md)
- [Redeliver a webhook delivery](/platform-api/organization/redeliver-a-webhook-delivery.md)
