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

# Webhooks

> Real-time event subscriptions — receive Tread events for Orders, Jobs, Loads, Tickets, and imported records.

Webhooks push real-time events from Tread to a URL you control. Use webhooks when your downstream system (data warehouse, ERP, custom dashboard) needs to react the moment something happens in Tread — an Order is created, a Ticket is approved, a Project is updated — instead of polling the API.

## Prerequisites

* An HTTPS endpoint you control. HTTP is rejected.
* A Tread admin user with the **Integrations** permission.
* Ability to verify HMAC signatures on the receiving side.
* A retry-tolerant handler. Tread retries failed deliveries.

## How it works

1. **Register a subscription** — Set the destination URL, the HMAC signing secret, and any custom request headers in **Settings → Integrations → Webhooks**.
2. **Pick triggers** — Each subscription listens to one or more triggers. A trigger is a topic plus an event (for example, `Order::create`).
3. **Tread fires events** — When a matching action happens in the app, Tread builds a JSON envelope and POSTs it to your URL.
4. **Verify the signature** — Tread signs the body with HMAC-SHA256 using your secret. The signature lands in the `X-Tread-Hmac-sha256` header.
5. **Acknowledge with 2xx** — A 2xx response marks the event delivered. Anything else triggers a retry.

## Event topics and types

Tread emits events on these topics:

| Topic             | What it is                                                                       |
| ----------------- | -------------------------------------------------------------------------------- |
| `Order`           | A daily [Order](/concepts/orders-projects)                                       |
| `Job`             | One [Driver's](/concepts/driver-lifecycle) assignment for one Order              |
| `Load`            | One pickup-to-drop-off cycle                                                     |
| `Ticket`          | The [record of one Load](/concepts/tickets-timesheets) — proof the work happened |
| `ImportedProject` | A Project pushed in via the import API                                           |
| `ImportedOrder`   | An Order pushed in via the import API                                            |
| `ImportedTicket`  | A Ticket pushed in via the import API                                            |

Each topic supports these event types: `create`, `update`, `state_change`, `skip`, `error`. Subscribe to the combinations you care about.

## Payload format

Every delivery has the same envelope:

```json theme={null}
{
  "subscription_id": "uuid",
  "trigger_id": "uuid",
  "event_id": "uuid",
  "delivery_id": "uuid",
  "attempt": 1,
  "event_time": "2026-04-30T14:21:09Z",
  "event": "Order::create",
  "payload": { },
  "meta": {
    "company_id": "uuid"
  }
}
```

The `payload` field holds the resource as it appears in the Tread API. The `event` field is the topic and event type joined by `::`. The `attempt` field starts at 1 and increments on retry.

## Setup

<Steps>
  <Step title="Open Webhooks settings">
    Go to **Settings → Integrations → Webhooks**.
  </Step>

  <Step title="Add a subscription">
    Enter your HTTPS endpoint URL. Generate or paste an HMAC signing secret. Tread will include the signature on every delivery.
  </Step>

  <Step title="Pick triggers">
    Select the topic-and-event combinations you want. Start narrow — `Order::create` and `Ticket::state_change` cover most use cases.
  </Step>

  <Step title="Add custom headers (optional)">
    If your endpoint needs an auth header or routing token, add it under request headers.
  </Step>

  <Step title="Send a test event">
    Use the **Send test** button to confirm your endpoint receives, verifies, and acknowledges. Inspect the delivery log for the response code.
  </Step>
</Steps>

## Signature verification

For each delivery, Tread computes:

```
HMAC-SHA256(secret, request_body) → hex digest
```

The digest is sent in the `X-Tread-Hmac-sha256` header. Recompute on your side using the raw request body and compare. Reject any request where the signature does not match.

## Retry behavior

* Failed deliveries (non-2xx, timeout, redirect) are retried at increasing intervals.
* Each event has a retry limit. Once hit, delivery stops and the failure is logged.
* The `attempt` field on the envelope tells you which retry you're seeing.
* Delivery timeout is 10 seconds. Acknowledge fast and process async.

## Limitations

* HTTPS only. HTTP URLs are rejected at registration.
* One destination URL per subscription. To fan out, register multiple subscriptions.
* 10-second delivery timeout. Long-running handlers must respond first and process in the background.
* Tread does not guarantee event ordering. Use `event_time` to reconcile.
* Replays are not supported. Once a delivery exhausts retries, it's gone — design for at-least-once delivery and idempotent handlers.

## Troubleshooting

**Signature mismatch**

1. Confirm you're hashing the raw request body, not a parsed copy.
2. Confirm you're using the same HMAC cipher (default: SHA-256).
3. Rotate the secret if it may have leaked.

**Endpoint times out**

1. Reduce handler work — acknowledge immediately, queue the actual processing.
2. Check the delivery log for response time.

**Events not firing**

1. Confirm the subscription has the right trigger (topic + event).
2. Confirm the action in Tread matches the topic. `Order::create` fires on Order creation, not Order updates — add `Order::update` separately.

## Related

* [API Reference](/api-reference/introduction) — the resource shapes returned in the payload
* [Agave](/integrations/agave) — accounting integration for AR/AP
