# Set up PagerDuty alerts

PagerDuty integration lets a Down alert trigger a PagerDuty incident, and the matching Up alert resolve it
automatically. Under the hood a PagerDuty contact is an `http` contact with its `gateway` set to `PagerDuty` and
its `address` holding the integration key (a key, not a URL).

## Settings reference

| Setting (UI label) | API field (v2) | Type / allowed values | Default | Plan limits | What it does for you |
|---|---|---|---|---|---|
| Contact Type | `type` | `"http"` | - | - | PagerDuty is stored as a plain `http` contact |
| Gateway | `gateway` | `"PagerDuty"` | - (must be set explicitly) | - | Routes through the Events API v2 trigger/resolve flow instead of a plain webhook |
| Integration key | `address` | The PagerDuty Events API v2 integration key (not a URL) | - (required) | - | Identifies the PagerDuty service the alert pages |

`groupedAlerts` has no effect on this channel - see below.

## Set it up in the app

1. In PagerDuty, create a **service** (or use an existing one) and add an integration using the **Events API
   v2**. Copy its **integration key**.
2. In HostTracker, open **Contacts** and click **Add contact**.
3. Choose **PagerDuty**.
4. Paste the integration key and give the contact a name.
5. Save.

## How it behaves

- A **Down** alert **triggers** a new PagerDuty incident.
- The matching **Up** alert **resolves** it automatically - HostTracker links them by the outage's own event
  ID, so PagerDuty doesn't need you to close incidents by hand.
- On-call channels are **never grouped**: unlike chat channels, every individual Down and Up is sent as its own
  event, regardless of the contact's `groupedAlerts` setting - because that's what an on-call/incident tool is
  for. See [grouped alerts](/alerts/grouped-alerts/).

## Do it with the API or MCP

```
POST /contact
{ "type": "http", "gateway": "PagerDuty", "address": "<integration key>", "name": "On-call PagerDuty" }
```

MCP: use `api_request` with the body above - `create_contact` doesn't cover `http`/gateway contacts.

## What happens next

An `http` contact is born confirmed - there's no code to verify. [Test the contact](/alerts/test-a-contact/)
right after setup; because PagerDuty's address is a key rather than a URL, the test routes through the same
trigger/resolve sender a real alert uses, not the raw webhook diagnostic.

## Limits and gotchas

- Paste the **integration key** exactly as PagerDuty gives it - don't add a URL scheme or extra characters in
  front of it.
- The `gateway` must be spelled exactly `PagerDuty`; a plain `http` contact whose address happens to look like a
  key is never auto-detected as PagerDuty.
- [Test the contact](/alerts/test-a-contact/) after setup to confirm a real incident appears in PagerDuty.
- Being a **recognized gateway** also means PagerDuty can receive certificate-expiry, domain-expiry, DNSBL
  blacklist and Web Risk notices - a plain unrecognized webhook contact cannot (see
  [Webhook](/alerts/channels/webhook/#limits-and-gotchas)).

## Related

- [Opsgenie](/alerts/channels/opsgenie/)
- [Grouped alerts](/alerts/grouped-alerts/)
- [All channels](/alerts/channels/)
