# Oh Dear Webhooks

## When to Use This Skill

* How do I receive Oh Dear webhooks?
* How do I verify the `OhDear-Signature` header?
* Why is my Oh Dear webhook signature verification failing?
* How do I handle uptime, certificate, broken link, or scheduled task notifications from Oh Dear?
* Why does Oh Dear keep retrying or pause my webhook URL?

## Verification (core)

Oh Dear signs the **raw request body** with HMAC-SHA256, keyed with your team's signing secret, and sends the bare lowercase hex digest in the `OhDear-Signature` header (no prefix). Nothing else is signed: there is no timestamp or id, so there is no replay window to check. Verify the bytes exactly as received, validate the header format (64 hex characters) before decoding, and compare in constant time.

Node:

```javascript
const crypto = require('crypto');

function verify(rawBody, signatureHeader, secret) {
  // rawBody is a Buffer (express.raw), never a parsed/re-serialized object
  if (!/^[0-9a-fA-F]{64}$/.test(signatureHeader || '')) return false;
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest();
  const received = Buffer.from(signatureHeader.toLowerCase(), 'hex'); // format already validated
  return received.length === expected.length && crypto.timingSafeEqual(received, expected);
}

```

Python:

```python
import hashlib, hmac, re

def verify(raw_body: bytes, signature_header: str | None, secret: str) -> bool:
    if not signature_header or not re.fullmatch(r"[0-9a-fA-F]{64}", signature_header):
        return False
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
    return hmac.compare_digest(bytes.fromhex(signature_header), expected)

```

Missing, empty, malformed or mismatched signature: respond `401`. Respond `200` directly on success: Oh Dear treats anything other than HTTP 200 (including 301/302 redirects) as a failed delivery.

> **For complete handlers with route wiring, event dispatch, and tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/oh-dear-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/oh-dear-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/oh-dear-webhooks/examples/fastapi/).

## Common Event Types

Dispatch on the top-level `type` field of the JSON body (nested objects also have `type` keys; ignore those).

| Event (`type`) | Description |
| --- | --- |
| `monitorAddedNotification` | A monitor was added to the team |
| `httpUptimeCheckFailedNotification` | HTTP uptime check failed (`tcp...` and `ping...` variants exist) |
| `httpUptimeCheckRecoveredNotification` | Site is back up (`tcp...` and `ping...` variants exist) |
| `certificateExpiresSoonNotification` | TLS certificate is about to expire |
| `brokenLinksFoundNotification` | Broken links were found on the site |
| `cronFailedNotification` | A scheduled task reported a failure |

Oh Dear documents 37 event types in total (performance, mixed content, DNS, application health, sitemap, Lighthouse, AI checks and more). See [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/oh-dear-webhooks/references/overview.md) for the full list.

## Important Headers

| Header | Description |
| --- | --- |
| `OhDear-Signature` | Lowercase hex HMAC-SHA256 of the raw body |
| `Content-Type` | `application/json` |

The body also carries a `uuid`. A retry or manual Resend keeps the same `uuid`, so use it for idempotency.

## Environment Variables

```bash
OH_DEAR_WEBHOOK_SECRET=your_team_signing_secret   # "Web hook signing secret" in Oh Dear notification settings

```

## Local Development

```bash
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 oh-dear --path /webhooks/oh-dear

```

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/oh-dear-webhooks/references/overview.md) - Oh Dear webhook concepts, delivery rules, all event types
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/oh-dear-webhooks/references/setup.md) - Configure the webhook URL and find the signing secret
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/oh-dear-webhooks/references/verification.md) - Signature verification details and debugging