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

# Alerts and Webhooks API: Real-Time Event Notifications

> Manage Smart Alert watchers via the API and receive real-time webhook event callbacks for booking, release, and bond_change activity.

The Alerts endpoints let you programmatically create, list, and delete Smart Alert watchers for individuals you want to monitor. Webhooks take monitoring a step further: instead of polling, DocketStream pushes a structured event payload to your server the moment a monitored individual has activity — a new booking, a release, or a bond change. Together, alerts and webhooks eliminate polling latency and let you build truly real-time correctional intelligence workflows.

<Note>
  Both Alerts and Webhooks are **Enterprise-only** features. Ensure your account
  is on the Enterprise plan before configuring watchers or webhook endpoints.
  Contact [support@docketstream.org](mailto:support@docketstream.org) to
  upgrade.
</Note>

***

## Alerts

### POST /alerts — Create a Watcher

Register a new Smart Alert watcher. DocketStream will monitor all indexed counties (or a specific county) for activity matching the provided name and notify your webhook endpoint when a matching event occurs.

```bash theme={null}
POST https://api.docketstream.org/v1/alerts
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

{
  "name": "John Doe",
  "county": "clayton",
  "events": ["booking", "release", "bond_change"]
}
```

#### Body Parameters

<ParamField body="name" type="string" required>
  The full name of the individual to watch. DocketStream performs fuzzy matching
  against this name across incoming booking records. Use the most complete name
  available (first and last) to minimize false positives.
</ParamField>

<ParamField body="county" type="string">
  Restrict monitoring to a specific county slug (e.g., `"clayton"`, `"fulton"`).
  Omit this field to monitor all available counties.
</ParamField>

<ParamField body="events" type="array of strings">
  List of event types to receive notifications for. Accepted values: `"booking"`,
  `"release"`, `"bond_change"`. Omit this field to subscribe to all three event
  types by default.
</ParamField>

#### Response — 201 Created

```json theme={null}
{
  "id": "alert-abc123",
  "name": "John Doe",
  "county": "clayton",
  "events": ["booking", "release", "bond_change"],
  "created_at": "2024-06-10T14:32:00Z"
}
```

<ResponseField name="id" type="string">
  The unique identifier for this watcher. Use this ID to delete the watcher via
  `DELETE /alerts/{id}`.
</ResponseField>

<ResponseField name="name" type="string">
  The name configured for this watcher.
</ResponseField>

<ResponseField name="county" type="string | null">
  The county scope for this watcher, or `null` if monitoring all counties.
</ResponseField>

<ResponseField name="events" type="array of strings">
  The event types this watcher is subscribed to.
</ResponseField>

<ResponseField name="created_at" type="string">
  ISO 8601 timestamp of when the watcher was created.
</ResponseField>

***

### GET /alerts — List All Watchers

Returns a paginated list of all active alert watchers on your account.

```bash theme={null}
GET https://api.docketstream.org/v1/alerts
Authorization: Bearer YOUR_API_KEY
```

#### Response — 200 OK

```json theme={null}
{
  "total": 12,
  "limit": 50,
  "offset": 0,
  "alerts": [
    {
      "id": "alert-abc123",
      "name": "John Doe",
      "county": "clayton",
      "events": ["booking", "release", "bond_change"],
      "created_at": "2024-06-10T14:32:00Z"
    }
  ]
}
```

***

### DELETE /alerts/{id} — Remove a Watcher

Delete an active alert watcher. Once deleted, DocketStream stops monitoring for the associated individual and no further webhook events are fired for that watcher.

```bash theme={null}
DELETE https://api.docketstream.org/v1/alerts/alert-abc123
Authorization: Bearer YOUR_API_KEY
```

#### Path Parameter

<ParamField path="id" type="string" required>
  The unique watcher ID returned when the alert was created (e.g.,
  `"alert-abc123"`).
</ParamField>

#### Response — 204 No Content

A successful deletion returns HTTP `204` with an empty response body.

***

## Webhooks

### Register a Webhook Endpoint

Tell DocketStream where to send event payloads by registering a webhook URL. Your endpoint must be publicly accessible over HTTPS and able to accept `POST` requests.

```bash theme={null}
POST https://api.docketstream.org/v1/webhooks
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

{
  "url": "https://yourdomain.com/hook",
  "events": ["booking", "release", "bond_change"]
}
```

<ParamField body="url" type="string" required>
  The publicly accessible HTTPS URL where DocketStream will POST event payloads.
  HTTP URLs are not accepted.
</ParamField>

<ParamField body="events" type="array of strings" required>
  Event types to deliver to this endpoint. Accepted values: `"booking"`,
  `"release"`, `"bond_change"`. You can register multiple webhook endpoints with
  different event subsets.
</ParamField>

***

### Webhook Event Payload

When a monitored individual has matching activity, DocketStream sends a `POST` request to your registered URL with the following JSON body:

```json theme={null}
{
  "event": "booking",
  "alert_id": "alert-abc123",
  "timestamp": "2024-06-10T14:32:00Z",
  "record": {
    "id": "cltn-2024-00123",
    "name": "John Doe",
    "county": "Clayton",
    "booking_date": "2024-06-10T14:32:00Z",
    "charges": ["Theft by Taking"],
    "bond_amount": 5000
  }
}
```

<ResponseField name="event" type="string">
  The type of event that triggered this delivery: `"booking"`, `"release"`, or
  `"bond_change"`.
</ResponseField>

<ResponseField name="alert_id" type="string">
  The ID of the alert watcher that matched this activity.
</ResponseField>

<ResponseField name="timestamp" type="string">
  ISO 8601 timestamp of when the event was detected by DocketStream.
</ResponseField>

<ResponseField name="record" type="object">
  A summary of the roster record associated with the event. For full record
  detail, pass `record.id` to `GET /roster/{id}`.

  <ResponseField name="record.id" type="string">
    DocketStream roster record ID.
  </ResponseField>

  <ResponseField name="record.name" type="string">
    Individual's name as recorded in the booking.
  </ResponseField>

  <ResponseField name="record.county" type="string">
    County where the event occurred.
  </ResponseField>

  <ResponseField name="record.booking_date" type="string">
    ISO 8601 timestamp of the booking.
  </ResponseField>

  <ResponseField name="record.charges" type="array of strings">
    Charges associated with the booking at the time of the event.
  </ResponseField>

  <ResponseField name="record.bond_amount" type="number | null">
    Bond amount in USD at the time of the event. For `bond_change` events, this
    reflects the **new** bond amount.
  </ResponseField>
</ResponseField>

***

### Responding to Webhooks

<Warning>
  Your endpoint must return an **HTTP `200` response within 5 seconds** of
  receiving the request. If your server times out or returns a non-`2xx` status,
  DocketStream treats the delivery as failed and begins the retry sequence.
</Warning>

To keep response times under 5 seconds, acknowledge the webhook immediately and process the payload asynchronously using a background job or queue.

***

### Retry Policy

DocketStream retries failed webhook deliveries up to **3 times** using exponential backoff:

| Attempt   | Delay After Failure |
| --------- | ------------------- |
| 1st retry | \~30 seconds        |
| 2nd retry | \~5 minutes         |
| 3rd retry | \~30 minutes        |

If all three retries fail, the event is dropped and no further delivery attempts are made. Monitor your endpoint's availability to avoid missing critical booking or release events.

***

### Verifying Webhook Signatures

DocketStream signs every webhook delivery so you can verify that the request originated from DocketStream and that the payload has not been tampered with.

Each request includes an `X-DocketStream-Signature` header containing an **HMAC-SHA256** digest of the raw request body, computed using your webhook secret. You can find your webhook secret in **Account Settings → API Keys** after registering a webhook endpoint.

Verify the signature in your handler before processing the payload:

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

  def verify_signature(payload_body: bytes, signature_header: str, secret: str) -> bool:
      expected = hmac.new(
          secret.encode("utf-8"),
          payload_body,
          hashlib.sha256,
      ).hexdigest()
      return hmac.compare_digest(expected, signature_header)
  ```

  ```javascript JavaScript theme={null}
  const crypto = require("crypto");

  function verifySignature(payloadBody, signatureHeader, secret) {
    const expected = crypto
      .createHmac("sha256", secret)
      .update(payloadBody)
      .digest("hex");
    return crypto.timingSafeEqual(
      Buffer.from(expected),
      Buffer.from(signatureHeader)
    );
  }
  ```
</CodeGroup>

<Tip>
  Always use a **timing-safe comparison** (e.g., `hmac.compare_digest` in
  Python or `crypto.timingSafeEqual` in Node.js) when comparing HMAC digests.
  Standard string equality is vulnerable to timing attacks.
</Tip>

Reject any request where the signature does not match with an HTTP `401` response.
