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

# Webhooks

> Get notified the moment a bill, document, event, or recommendation changes, and verify every delivery.

Webhooks allow PolicyMate to notify your application the moment something changes, so you don't need to poll the API.

## Configuring Webhooks

Webhooks are configured on an API key. From the **API Keys** screen, open a key, add the HTTPS URL that should receive deliveries, and choose the events you would like to receive. You may optionally narrow deliveries to a workspace, a topic, or a minimum importance level.

Once the webhook is saved, PolicyMate displays its signing secret. As with the API key itself, it is only displayed once.

## Available Events

| Event | Delivered when |
| - | - |
| `bill.created` | A new bill appears in a jurisdiction you may access |
| `bill.updated` | A bill gains a milestone, a text, or a new status |
| `document.created` | A source you may access publishes a new document |
| `event.created` | A new meeting, hearing, or deadline is announced |
| `recommendation.created` | A record is recommended to one of your workspaces |

Each delivery is a `POST` request containing a JSON payload. Payloads contain identifiers rather than full records, so you should retrieve the record from the API to get its current state:

```json theme={null}
{
  "id": "evt_2Hk9...",
  "type": "bill.updated",
  "created_at": "2027-02-04T06:10:02Z",
  "changes": ["milestones", "status"],
  "data": { "id": "9b3e2c1a-...", "jurisdiction": "US-TX", "status": "in_procedure" }
}
```

If your endpoint does not respond with a `2xx` status code, PolicyMate retries the delivery with an exponential backoff for up to 24 hours.

## Verifying Signatures

Every delivery includes a `PolicyMate-Timestamp` header and a `PolicyMate-Signature` header. You should verify every delivery before trusting it:

**1. Build the signed string**

Join the `PolicyMate-Timestamp` header, a period (`.`), and the raw request body into a single string.

**2. Compute the expected signature**

Compute an HMAC-SHA256 hash of that string, using your webhook's secret as the key, and encode it as lowercase hexadecimal.

**3. Compare the signatures**

Compare the result with the `PolicyMate-Signature` header using a constant-time comparison.

**4. Check the timestamp**

Reject the delivery if the signatures differ, or if the timestamp is more than five minutes old.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.