The PagerDuty Events API v2 format, explained
Learn the PagerDuty Events API v2 format. See required fields, dedup_key logic, and a curl example for triggers and resolves.
Published 14 November 2026.
The PagerDuty Events API v2 is an asynchronous HTTP API. It takes machine events from monitoring tools and routes them to a PagerDuty service (Events API v2 overview). Prometheus Alertmanager sends this format when you set routing_key in a pagerduty_config (Alertmanager configuration). Some other alert receivers accept the same JSON. Every field and limit below comes from PagerDuty's developer documentation.
Endpoints and keys
The API exposes two endpoints, one for each event type:
| Event type | Endpoint | Notifies anyone? |
|---|---|---|
| Alert | https://events.pagerduty.com/v2/enqueue | Yes |
| Change | https://events.pagerduty.com/v2/change/enqueue | No |
Send a POST request with a JSON body to either endpoint. The routing_key field in that body directs the event. Use the 32-character integration key from an Events API v2 integration on a service, or from a global ruleset (Sending an alert event). Ruleset keys start with R and reject change events (overview). Store the key securely. Anyone with access to it can trigger alerts on that service.
The top-level fields
| Field | Required | Notes |
|---|---|---|
routing_key | Yes | The 32-character integration key |
event_action | Yes | trigger, acknowledge or resolve |
dedup_key | For acknowledge and resolve | Up to 255 characters. Identifies the alert |
payload | For trigger | The event details, below |
client | No | Name of the sending tool. Trigger only |
client_url | No | Link back to the sending tool. Trigger only |
links | No | Array of { "href", "text" }. href is required |
images | No | Array of { "src", "href", "alt" }. src is required and must be HTTPS |
You can find the full specification in the Sending an alert event guide and the API reference.
The payload fields
The payload object follows the PagerDuty Common Event Format, PD-CEF (overview).
| Field | Required | Notes | Example |
|---|---|---|---|
summary | Yes | Becomes the alert title. Up to 1024 characters | DISK at 99% on machine prod-datapipe03.example.com |
source | Yes | The affected system, preferably a hostname or FQDN | prod-datapipe03.example.com |
severity | Yes | One of critical, error, warning, info | critical |
timestamp | No | ISO 8601. PagerDuty fills it in if missing | 2015-07-17T08:42:58.315+0000 |
component | No | The broken part of the source | mysql |
group | No | A cluster or grouping of sources | prod-datapipe |
class | No | The class or type of event | disk |
custom_details | No | Free-form object | {"free space": "1%"} |
The on-call person sees summary first, whether on a lock screen or in an SMS. State what is wrong, where it is, and how bad it is. See writing alert messages people can act on. Use the four severity values deliberately. The format allows no others, so map your own severity levels to them.
How dedup_key works
The dedup_key ties a trigger to its follow-up acknowledge and resolve events (Sending an alert event):
- A trigger with a
dedup_keythat matches an open alert adds a log entry to that alert. It does not open a second one. - A trigger with no
dedup_keyalways opens a new alert. PagerDuty generates a UUID and returns it in the response. - Acknowledge and resolve events apply only to an open alert with the same
dedup_key, sent with the samerouting_key. Otherwise they are dropped. They never create an alert. - After an alert is resolved, a new trigger with the same key opens a new alert. It does not reopen the old one.
The sensible default is to set the key yourself from stable values like service, environment, and check name. A repeat trigger then folds into the open alert, and the resolve finds it without you storing state. See alert deduplication and grouping for more.
A worked example: trigger, then resolve
This example triggers an alert for a high error rate. The script reads the integration key from an environment variable. This practice keeps the key out of shell history and scripts. The host names and values in the example are illustrative.
curl -sS -X POST https://events.pagerduty.com/v2/enqueue \
-H 'Content-Type: application/json' \
-d '{
"routing_key": "'"$PD_ROUTING_KEY"'",
"event_action": "trigger",
"dedup_key": "checkout-api/prod/high-error-rate",
"payload": {
"summary": "checkout-api prod: 5xx rate 7.2% (threshold 2%) for 10m",
"source": "checkout-api.prod.example.com",
"severity": "critical",
"timestamp": "2026-11-14T09:30:00.000+0000",
"component": "checkout-api",
"group": "prod-eu-west-1",
"class": "high error rate",
"custom_details": {
"error_rate": "7.2%",
"threshold": "2%",
"runbook": "https://runbooks.example.com/checkout-api/high-error-rate"
}
},
"client": "Example Monitoring",
"client_url": "https://monitoring.example.com",
"links": [
{
"href": "https://grafana.example.com/d/checkout",
"text": "Checkout dashboard"
}
]
}'
A 202 response returns a JSON body like this (API reference):
{
"status": "success",
"message": "Event processed",
"dedup_key": "checkout-api/prod/high-error-rate"
}
When the error rate recovers, send a resolve event with the same dedup_key. You do not need a payload for this request:
curl -sS -X POST https://events.pagerduty.com/v2/enqueue \
-H 'Content-Type: application/json' \
-d '{
"routing_key": "'"$PD_ROUTING_KEY"'",
"event_action": "resolve",
"dedup_key": "checkout-api/prod/high-error-rate"
}'
An acknowledge event has the same structure, but uses "event_action": "acknowledge". PagerDuty sends no further notifications while an incident is acknowledged, even if new triggers arrive.
Responses, limits and retries
| Response | Meaning | Retry? |
|---|---|---|
202 | Accepted | No |
400 | Bad request. Check the JSON is valid | No |
429 | Too many API calls | Yes, after a while |
500 or other 5xx | PagerDuty server error | Yes, after a while |
| Network error | Could not reach PagerDuty | Yes, after a while |
Source: overview, response codes. Error bodies carry status, message and an errors array.
Limits:
- The payload size limit is 512 KB (overview).
- Each integration key allows about 120 calls per minute, measured over a rolling 60-second window. Account-level limits also apply. Exceeding the limit returns
429and drops the event (rate limits). - PagerDuty adjusts throttling based on traffic volume. It recommends retrying up to 3 times with 30-second intervals. For events that must not be lost, use a backoff of a few minutes.
The API is asynchronous, so a 202 status means the event was accepted, not that it reached a person. Notification delivery depends on the service configuration, the escalation policy, and individual contact rules.
Change events
Change events record deployments or config changes. They appear on the service and incident timeline. They never trigger notifications (Sending a change event).
The body requires routing_key and a payload with a summary (max 1024 characters). Optional fields include source, timestamp, custom_details, and links. The format excludes event_action and dedup_key. PagerDuty retains change events for 90 days.
{
"routing_key": "samplekeyhere",
"payload": {
"summary": "Build Success: Increase snapshot create timeout to 30 seconds",
"timestamp": "2020-07-17T08:42:58.315+0000",
"source": "acme-build-pipeline-tool-default-i-9999",
"custom_details": {
"build_state": "passed",
"build_number": "2",
"run_time": "1236s"
}
},
"links": [
{
"href": "https://acme.pagerduty.dev/build/2",
"text": "View more details in Acme!"
}
]
}
That example is copied from PagerDuty's docs.
How Alertmanager fills these fields
This minimal Alertmanager receiver sends Events API v2 events:
receivers:
- name: pagerduty-critical
pagerduty_configs:
- routing_key_file: /etc/alertmanager/secrets/pd-routing-key
severity: '{{ if .CommonLabels.severity }}{{ .CommonLabels.severity }}{{ else }}error{{ end }}'
links:
- href: '{{ .CommonAnnotations.runbook_url }}'
text: Runbook
The mapping between Alertmanager fields and the PagerDuty format comes from the configuration reference and the notifier source:
- Use
routing_keyorrouting_key_fileto select Events API v2. Theservice_keyfield targets the older Prometheus integration. send_resolvedistrueby default. Alertmanager sends aresolveevent when a group resolves.severitydefaults toerror. The template in the example passes the alert'sseveritylabel directly, so that label must contain one of the four PagerDuty values.- The
descriptionfield maps tosummary. Alertmanager truncates it to 1024 characters. dedup_keyis a hash of the alert group key. Each Alertmanager group becomes one PagerDuty alert, sogroup_bycontrols how alerts merge. See Alertmanager routing.detailsdefaults to the firing and resolved alerts as JSON, along with their counts.
The receiver above passes amtool check-config (Alertmanager v0.35.0) when included in a config that also defines a route.
Tools
The directory categorizes event senders and receivers into alert routing and notification delivery and on-call and escalation. Test any new receiver that claims PagerDuty compatibility by sending a trigger and a resolve with the same dedup_key before you switch.