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

# Webhook events

> Planned event catalog, signature verification, retry policy, and replay window. Preview only until Phase 2 ships.

<Note>
  Webhook delivery is on the Phase 2 roadmap. The event shapes on this
  page are the current draft and may change before GA. Contact
  [info@growyourbrand.io](mailto:info@growyourbrand.io) to join the
  Phase 2 beta.
</Note>

## Event catalog

| Event                  | Fires when                                                                                           |
| ---------------------- | ---------------------------------------------------------------------------------------------------- |
| `calc.completed`       | A landed-cost calculation persists. Payload mirrors the `/v1/calc` response.                         |
| `calc.compliance_flag` | A calculation triggers a critical compliance flag (denied party, restricted product, active AD/CVD). |
| `rates.updated`        | A rate change lands for a country plus HS pair you have subscribed to.                               |
| `shipment.checkpoint`  | Tracking polls a new milestone for an auto-detected shipment.                                        |
| `quota.threshold`      | Monthly quota consumption crosses 50, 80, and 100 percent.                                           |

## Envelope

Every event uses the same envelope. `data` carries the event-specific
payload.

```json theme={null}
{
  "id": "evt_01H7Z5V4J8F9K2M3N4P5Q6R7S8",
  "type": "calc.compliance_flag",
  "created_at": "2026-08-24T14:03:00Z",
  "livemode": true,
  "data": {
    "calc_id": "5f6b7c8d-1234-4abc-9def-0123456789ab",
    "flag": {
      "kind": "ad_cvd",
      "severity": "critical",
      "title": "Active AD/CVD case matched",
      "legal_citation": "A-570-000, C-570-001"
    }
  }
}
```

## Signature verification

Every request is signed with HMAC-SHA256 over the raw body plus a
timestamp. The signature and timestamp ship in headers:

```http theme={null}
X-LandedFees-Timestamp: 1755273600
X-LandedFees-Signature: v1=abcdef1234567890...
```

To verify:

1. Compute `expected = hex(HMAC_SHA256(secret, timestamp + "." + raw_body))`.
2. Constant-time compare `expected` against the value after `v1=`.
3. Reject requests where `abs(now - timestamp) > 300` seconds (five
   minutes) to block replay attacks.

<CodeGroup>
  ```python Python theme={null}
  import hmac, hashlib, time

  def verify(secret: str, ts: str, body: bytes, sig: str) -> bool:
      if abs(time.time() - int(ts)) > 300:
          return False
      expected = hmac.new(
          secret.encode(),
          f"{ts}.".encode() + body,
          hashlib.sha256,
      ).hexdigest()
      return hmac.compare_digest(expected, sig.removeprefix("v1="))
  ```

  ```ts TypeScript theme={null}
  import { createHmac, timingSafeEqual } from "node:crypto";

  export function verify(
    secret: string,
    timestamp: string,
    rawBody: Buffer,
    signature: string,
  ): boolean {
    if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
    const expected = createHmac("sha256", secret)
      .update(`${timestamp}.`)
      .update(rawBody)
      .digest("hex");
    const actual = signature.replace(/^v1=/, "");
    const a = Buffer.from(expected, "hex");
    const b = Buffer.from(actual, "hex");
    return a.length === b.length && timingSafeEqual(a, b);
  }
  ```
</CodeGroup>

## Retry policy

* The endpoint must return `2xx` within 15 seconds.
* Non-2xx or timeout triggers exponential backoff: 30 s, 2 min, 10 min,
  1 h, 6 h, 24 h.
* Delivery is retried for up to 72 hours, then the event is marked
  `delivery_failed` and surfaced in the dashboard.
* The same `event.id` may be delivered more than once. Consumers must
  be idempotent on `event.id`.

## Replay window

The 500 most recent events per endpoint are retained for 30 days.
Replay any event from the dashboard or via
`POST /v1/webhooks/events/{event_id}/redeliver` once the Phase 2
endpoint ships.

## Rotating the secret

Endpoint signing secrets can be rotated from the dashboard. Rotation
issues a second active secret; both verify for a 24-hour overlap
window before the old one is retired. Verify against either secret
during the window.
