# Set Up Webhooks

Sail pushes events to your server as jobs are completed. Connection status changes, account updates, and other data changes are delivered as webhook events. This is the primary way to know when new data is available to fetch.

In this guide, you'll register a webhook endpoint, verify event signatures with your webhook secret, and handle incoming events from Sail.

<CardGroup cols={2}>
  <Card title="Step 1: Register endpoint" href="#step-1-register-your-endpoint" icon="fa6-solid:plug">
    Contact Sail to register your endpoint and receive your webhook secret.
  </Card>

  <Card title="Step 2: Verify signature" href="#step-2-verify-the-signature" icon="fa6-solid:shield">
    Validate the Sail-Signature header on every incoming event.
  </Card>

  <Card title="Step 3: Handle events" href="#step-3-handle-events" icon="fa6-solid:bolt">
    Process event payloads and fetch updated resources by Id.
  </Card>
</CardGroup>

## Requirements

Before you configure webhooks, make sure you have the following:

- An [API key](/docs/get-started/get-started-overview/api-key).
- A webhook endpoint on your server that can receive events from Sail.

## Step 1: Register your endpoint

Contact the Sail team to register your webhook endpoint. Provide your endpoint URL and Sail will return a webhook secret for signature verification.

Your webhook endpoint must:

- Accept POST requests with a JSON payload.
- Return a 2xx status code after successfully receiving the event.
- Respond promptly to prevent unnecessary webhook retries.

## Step 2: Verify the signature

Every webhook delivery includes a `Sail-Signature` header. Verify this header before processing the event to confirm it came from Sail.

The header contains a timestamp (`t`) and a signature (`v1`):

```
Sail-Signature: t=<UNIX_TIMESTAMP>,v1=<HEX_SIGNATURE>
```

To verify, compute an HMAC-SHA256 of `<timestamp>.<raw_request_body>` using your webhook secret and compare it to the signature. Reject events with timestamps older than 5 minutes to prevent replay attacks.

## Step 3: Handle events

Sail sends every webhook as a JSON envelope:

```json
{
  "id": "evt_7f3k9m",
  "event": "connection.synced",
  "created_at": "2026-08-02T14:31:07Z",
  "user_id": "usr_abc123",
  "data": {
    "connection_id": "conn_4d81",
    "job_id": "job_r8v2",
    "balances_updated": true,
    "activity_updated": false,
    "expenses_updated": true
  }
}
```

The event field identifies what happened, while data contains the ids and event-specific information you need to retrieve the current state.

For example, when you receive a `connection.synced` event, the `data` field tells you which kinds of data moved (`balances_updated`, `activity_updated`, `expenses_updated`):

```json
{
  "event": "connection.synced",
  "data": {
    "connection_id": "conn_4d81",
    "job_id": "job_r8v2",
    "balances_updated": true,
    "activity_updated": false,
    "expenses_updated": true
  }
}
```

Use the `connection_id` and the flags to fetch only the resources that changed, such as expenses through [List Expenses](/reference/expenses/get-users-user-id-expenses). This ensures your application works with the latest resource state rather than relying on the event payload alone.

### What to expect from webhooks

Keep the following behaviors in mind when receiving and processing webhook events:

- The `data` object contains resource ids. Fetch the full resource by id to get current state.
- You may receive the same event more than once. Deduplicate on the event `id`.
- Events may arrive out of order. Treat each event as a signal to fetch the latest state, not as a state transfer.
- If your endpoint doesn't return a `2xx`response, Sail retries with exponential backoff for 24 hours.

## Next steps

Your setup is complete. Choose the guide that matches your integration path:

- To turn transactions into item-level purchase data, see [Enrich transactions with item-level data](/docs/guides/enrich-transactions-with-item-level-data).
- To classify transactions you already have, see [Classify your own transactions](/docs/guides/classify-your-own-transactions).
- To connect a user's HSA/FSA account, see [Connect HSA/FSA accounts](/docs/guides/connect-hsa-fsa-accounts).