---
title: "Custom webhook"
description: "Send alerts from any tool that can POST JSON to Uptimeify Incident Management, and define your own field mapping in the dashboard."
---

The **Custom webhook** preset is the starting point for any monitoring or alerting tool that doesn't have a dedicated preset: a firewall appliance, an internal script, a niche SaaS product, anything that can send an HTTP `POST` request with a JSON body. Unlike the other presets, it ships with only a minimal default mapping; you fill in the rest yourself once you can see your tool's real payload shape.

## 1. Create the alert source in Uptimeify

Go to **Incident Management → Alert Sources → New**, pick the **Custom webhook** preset, name it, and create it. On the success screen, copy the ingest URL (`https://<your-domain>/api/im/ingest/<token>`). It is shown once and never displayed again in cleartext. If you lose it, rotate the token from the source's **Settings** tab.

## 2. Point your tool at the ingest URL

Configure your tool's webhook/notification target to send an HTTP `POST` request with a JSON body to the ingest URL, whenever it fires or resolves an alert. There is no fixed request schema on the receiving end. Send whatever your tool produces.

```bash
curl -X POST "https://<your-domain>/api/im/ingest/<token>" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Disk usage above 90% on db-primary",
    "status": "open"
  }'
```

## 3. Adjust the field mapping to your payload

The default mapping only extracts a title and a status: reasonable defaults for a generic payload, but almost certainly not everything you want:

1. Send a real (or representative test) payload from your tool once, so you can see its exact field names. The source's **Live activity** view on the alert source detail page shows the most recent raw payloads received.
2. Open the source's **Payload Mapping** tab and edit the selectors: add `severity`, `host`, and `dedupKey` selectors pointing at your payload's actual field names (dot/bracket paths like `data.host.name` or `alerts[0].id` are supported, and `a || b` fallback chains for fields that aren't always present). Add a `severityMap` if your tool sends its own severity vocabulary, so it maps onto Uptimeify's `sev1` to `sev4` scale.
3. Save, then use the **Payload Mapping** tab's test panel to send a sample payload through your edited mapping and confirm the extracted title/severity/status/host look right before relying on it for real alerts.

## Default field mapping

| Selector | Normalized field | Notes |
|---|---|---|
| `title \|\| message` | Title | Tries `title` first, falls back to `message` |
| `status` | Status: values in `resolveValues` resolve the alert, anything else keeps it open | Default `resolveValues`: `resolved`, `closed` |
| *(none by default)* | Severity | Every alert uses the source's configured default severity until you add a `severity` selector and `severityMap` |
| *(none by default)* | Host | Empty until you add a `host` selector |
| *(none by default)* | Dedup key | Falls back to a deterministic hash of the title + host until you add a `dedupKey` selector |

## Sample payload

This is the shape of payload the default mapping expects out of the box:

```json
{
  "title": "Disk usage above 90% on db-primary",
  "message": "Disk usage above 90% on db-primary",
  "status": "open"
}
```

You can send this exact payload against your source's mapping from the **Payload Mapping** tab in the dashboard, a good way to confirm the default mapping works before you start customizing selectors for your real tool.
