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

# Webhooks overview

> Subscribe to real-time alert events with HMAC-signed HTTP delivery.

Telemax webhooks push alert event payloads to a URL you control the moment an alert fires. No polling required.

## How it works

1. Create a webhook via [`POST /v2/api/webhooks`](/v2/api-reference/post-webhooks). You receive a plaintext **HMAC secret** in the response — save it securely, it is returned only once.
2. Link one or more alert configurations to the webhook (via `alertIds` on creation, or later via [`POST /v2/api/webhooks/{id}/link-alert`](/v2/api-reference/post-webhooks-id-link-alert)). Alternatively, set `isGlobal: true` to receive all alerts for your company.
3. When a linked alert fires, Telemax sends an HTTP `POST` to your URL with a signed JSON payload.

## Payload shape

```json theme={null}
{
  "alertType": "Speeding",
  "vehicleId": 88421,
  "vehicleName": "Delivery Van 07",
  "position": { "lat": -33.8688, "lng": 151.2093 },
  "direction": 270,
  "timestamp": "2026-04-28T06:14:22Z",
  "address": {
    "street": "42 George St",
    "suburb": "Sydney",
    "state": "NSW",
    "postcode": "2000",
    "country": "Australia"
  },
  "data": { ... }
}
```

| Field                           | Type           | Description                       |
| ------------------------------- | -------------- | --------------------------------- |
| alertType                       | string         | Human-readable alert type label   |
| vehicleId                       | integer        | Vehicle ID                        |
| vehicleName                     | string         | Vehicle display name              |
| `position.lat` / `position.lng` | number         | GPS coordinates at trigger        |
| direction                       | integer        | Heading in degrees (0–359)        |
| timestamp                       | datetime       | UTC trigger time                  |
| address                         | object \| null | Reverse-geocoded location         |
| data                            | object \| null | Type-specific payload (see below) |

## Type-specific `data` payloads

The `data` field carries additional context depending on `alertType`:

**Geofence**

```json theme={null}
{ "geofenceName": "Depot Zone", "isExit": true }
```

**Ignition**

```json theme={null}
{ "isStarted": true }
```

**Low battery**

```json theme={null}
{ "voltage": 11.8, "threshold": 12.0 }
```

**Speeding**

```json theme={null}
{ "speed": 127.4, "maxSpeed": 110.0 }
```

For all other alert types, `data` is `null`.

## Supported alert types

Webhooks can be linked to alert configurations with the following type IDs (as returned by [`GET /v2/api/companies/{id}/alerts`](/v2/api-reference/get-companies-id-alerts)): `1`, `2`, `5`, `8`, `9`, `10`. A maximum of **50 alert configurations** can be linked to a single webhook.

## Request headers

Every delivery includes two headers:

| Header              | Description                                                    |
| ------------------- | -------------------------------------------------------------- |
| X-Telemax-Signature | `sha256=<hex>` — HMAC-SHA256 signature of the raw request body |
| X-Telemax-Delivery  | UUID uniquely identifying this delivery attempt                |

## Verifying the signature

Compute `HMAC-SHA256(secret, rawBody)` and compare the hex digest to the value after `sha256=` in `X-Telemax-Signature`. Always compare using a constant-time function to prevent timing attacks.

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

  def verify(secret: str, body: bytes, header: str) -> bool:
      expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
      received = header.removeprefix("sha256=")
      return hmac.compare_digest(expected, received)
  ```

  ```javascript JavaScript theme={null}
  import { createHmac, timingSafeEqual } from "crypto";

  function verify(secret, body, header) {
    const expected = createHmac("sha256", secret).update(body).digest("hex");
    const received = header.replace("sha256=", "");
    return timingSafeEqual(Buffer.from(expected), Buffer.from(received));
  }
  ```
</CodeGroup>

## Global vs alert-scoped webhooks

|                     | Global (`isGlobal: true`)                            | Alert-scoped                           |
| ------------------- | ---------------------------------------------------- | -------------------------------------- |
| Fires for           | All alert types across the company and sub-companies | Only the linked alert configurations   |
| `alertIds` required | No                                                   | Yes (at least one)                     |
| Mixed payload types | Yes — `data` shape varies per alert                  | Predictable if only one type is linked |

<Note>
  When multiple alert types are linked to one webhook, `data` will have different structures per delivery. The `alertType` field tells you which shape to expect. Consider using one webhook per alert type for simpler integration.
</Note>

## Delivery retries

Telemax retries failed deliveries (non-2xx response or connection error) with exponential backoff. Respond with a `2xx` status as quickly as possible — perform any heavy processing asynchronously. Idempotency is guaranteed via `X-Telemax-Delivery`: the same UUID will not be delivered more than once per attempt window.

## Managing webhooks

<CardGroup cols={2}>
  <Card title="Create" href="/v2/api-reference/post-webhooks">POST /v2/api/webhooks</Card>
  <Card title="List" href="/v2/api-reference/get-webhooks">GET /v2/api/webhooks</Card>
  <Card title="Get" href="/v2/api-reference/get-webhooks-id">GET /v2/api/webhooks/{id}</Card>
  <Card title="Update" href="/v2/api-reference/put-webhooks-id">PUT /v2/api/webhooks/{id}</Card>
  <Card title="Delete" href="/v2/api-reference/delete-webhooks-id">DELETE /v2/api/webhooks/{id}</Card>
  <Card title="Link alert" href="/v2/api-reference/post-webhooks-id-link-alert">POST /v2/api/webhooks/{id}/link-alert</Card>
</CardGroup>
