Skip to main content Skip to main content

How to Test PagerDuty Webhooks (v3)

· 5 min read

PagerDuty is the central nervous system for incident response. When a critical alert fires, you often need to trigger custom automations—like creating a Jira ticket, posting a summary to an internal dashboard, or spinning up a dedicated Zoom room.

To build these automations, you need to rely on PagerDuty webhooks. PagerDuty is currently on the "v3" version of their webhook architecture. Testing these webhooks requires understanding their highly structured payload format and robust security model.

The PagerDuty v3 Payload Structure

A single PagerDuty webhook can contain multiple event objects if several things happen simultaneously. The payload is a JSON object with an event property containing the critical data.

PagerDuty events are extremely detailed. If an incident is acknowledged, the payload includes the ID of the incident, the exact time the state changed, the details of the service that triggered it, and information about the user who clicked "Acknowledge".

{
  "event": {
    "id": "01BZ...",
    "event_type": "incident.acknowledged",
    "resource_type": "incident",
    "occurred_at": "2024-03-01T14:30:00Z",
    "agent": {
      "id": "PXPGF42",
      "type": "user_reference"
    },
    "data": {
      "id": "P912A3B",
      "title": "Database CPU High",
      "status": "acknowledged"
    }
  }
}

Because PagerDuty integrates deeply with hundreds of other tools, these payloads can quickly grow massive with nested metadata.

Capturing an Incident Event

Stop reading raw JSON

Payloader shows you what your PagerDuty webhook actually did — in plain English. See the event, amount, status, and more at a glance.

Start free trial →

Before you write the logic to extract the specific data.id of the incident, you should capture a real event.

You can use a dedicated webhook workspace like Payloader to capture the data without writing any code:

  1. Create a new endpoint URL in Payloader.
  2. Log in to PagerDuty, navigate to Integrations > Generic Webhooks (v3), and add a new webhook.
  3. Paste your Payloader URL and select the event types you want to monitor, such as incident.triggered and incident.resolved.
  4. Trigger a test incident in PagerDuty using a developer service.

Payloader captures the massive JSON payload and parses it immediately. It identifies the event_type and extracts the incident title and status, providing a clean summary. You can instantly see that the event was an acknowledgment for the "Database CPU High" incident, rather than hunting through the nested JSON structure.

Local Development Workflow

Writing an automation script requires testing your local code against these real PagerDuty events.

Configure Payloader to forward the incoming PagerDuty webhooks to your local development environment. When an incident state changes in PagerDuty, the payload is immediately proxied to your localhost.

If your script fails to create the Jira ticket correctly, you do not need to resolve the incident and trigger a brand new one in PagerDuty. You can simply hit the "Replay" button in Payloader to resend the exact same webhook data to your local machine until your code works.

Verifying PagerDuty Signatures

Because PagerDuty events deal with critical infrastructure security, you must verify that the webhooks you receive are actually from PagerDuty and not an attacker trying to trigger fake incident responses.

PagerDuty v3 webhooks are signed using an HMAC-SHA256 hash. When you create the webhook in PagerDuty, you are provided with a Secret.

Every incoming request will contain an x-webhook-signature-v2 HTTP header. This header contains multiple signatures separated by commas, formatted like v1=hash1,v1=hash2 (PagerDuty supports multiple secrets for zero-downtime rotation).

Your application must:

  1. Extract the signatures from the header.
  2. Hash the exact, unparsed raw JSON request body using your stored Secret.
  3. Compare your calculated hash against the signatures provided in the header. If it matches any of them, the request is valid.

Ensuring your application processes the raw bytes of the request exactly as they were received is crucial for this verification step to succeed.