Skip to main content
Pongo sends alert notifications via webhooks. Configure channels once and reference them in your alert definitions.

Defining Channels

1

Open channels.ts

Edit pongo/channels.ts to define your webhook endpoints:
import { channels } from "../src/lib/config-types";

export default channels({
  slack: {
    type: "webhook",
    url: process.env.SLACK_WEBHOOK_URL!,
  },
});
2

Set environment variables

Add your webhook URLs to .env:
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXX
PAGERDUTY_ROUTING_KEY=your-integration-key
3

Reference channels in alerts

Use channel IDs in your monitor alert configurations:
alerts: [
  {
    id: "api-down",
    name: "API Down",
    condition: { consecutiveFailures: 3 },
    channels: ["slack"],
    severity: "critical",
  },
]

Channel Configuration

All channels have the same structure:
export default channels({
  "channel-id": {
    type: "webhook",
    url: "https://example.com/webhook",
    headers?: { /* optional headers */ },
  },
});
FieldTypeRequiredDescription
type"webhook"YesChannel type (currently only webhooks supported)
urlstringYesWebhook endpoint URL
headersobjectNoAdditional HTTP headers

Webhook Payload Structure

Pongo sends a standardized JSON payload to all webhook channels:
{
  event: "alert.fired" | "alert.resolved",
  alert: {
    id: string,
    name: string,
    monitorId: string,
    monitorName: string,
    severity: "critical" | "warning" | "info"
  },
  timestamp: string,  // ISO 8601 format
  snapshot: {
    consecutiveFailures: number,
    consecutiveSuccesses: number,
    lastStatus: string,
    lastResponseTimeMs: number | null,
    lastMessage: string | null
  },
  checkResult: {
    id: string,
    status: string,
    responseTimeMs: number,
    message: string | null,
    checkedAt: string
  },
  region?: string,
  firingRegions?: string[],
  healthyRegions?: string[]
}

Example Payload

{
  "event": "alert.fired",
  "alert": {
    "id": "api-down",
    "name": "API Down",
    "monitorId": "api",
    "monitorName": "Production API",
    "severity": "critical"
  },
  "timestamp": "2025-12-15T10:30:00Z",
  "snapshot": {
    "consecutiveFailures": 3,
    "consecutiveSuccesses": 0,
    "lastStatus": "down",
    "lastResponseTimeMs": 5000,
    "lastMessage": "Connection timeout"
  },
  "checkResult": {
    "id": "check-123",
    "status": "down",
    "responseTimeMs": 5000,
    "message": "Connection timeout",
    "checkedAt": "2025-12-15T10:30:00Z"
  },
  "region": "us-east"
}

Retry Behavior

Pongo automatically retries failed webhook deliveries:
  • Retry strategy: Exponential backoff
  • Max retries: 3 (configurable via SCHEDULER_MAX_RETRIES)
  • Base delay: 5 seconds (configurable via SCHEDULER_RETRY_DELAY_MS)
  • Retry delays: 5s, 10s, 20s
Webhooks are considered successful if they return a 2xx status code.

Slack Integration

1

Create Slack webhook

  1. Go to https://api.slack.com/apps
  2. Click “Create New App” → “From scratch”
  3. Enable “Incoming Webhooks”
  4. Click “Add New Webhook to Workspace”
  5. Copy the webhook URL
2

Configure channel

Add the webhook URL to your channels:
export default channels({
  slack: {
    type: "webhook",
    url: process.env.SLACK_WEBHOOK_URL!,
  },
});
3

Format messages (optional)

For richer Slack formatting, consider using a middleware webhook that transforms Pongo’s payload into Slack’s Block Kit format.

Basic Slack Webhook

import { channels } from "../src/lib/config-types";

export default channels({
  "ops-slack": {
    type: "webhook",
    url: process.env.OPS_SLACK_WEBHOOK!,
  },
  "dev-slack": {
    type: "webhook",
    url: process.env.DEV_SLACK_WEBHOOK!,
  },
});

PagerDuty Integration

1

Create PagerDuty integration

  1. In PagerDuty, go to Services → Your Service
  2. Click “Integrations” → “Add Integration”
  3. Select “Events API v2”
  4. Copy the integration key
2

Configure channel with auth

export default channels({
  pagerduty: {
    type: "webhook",
    url: "https://events.pagerduty.com/v2/enqueue",
    headers: {
      Authorization: `Token token=${process.env.PAGERDUTY_ROUTING_KEY}`,
      "Content-Type": "application/json",
    },
  },
});
3

Transform payload (optional)

PagerDuty expects a specific format. Consider creating a middleware webhook to transform Pongo’s payload.

Custom Integrations

Integrate with any service that accepts webhooks:
export default channels({
  "custom-service": {
    type: "webhook",
    url: "https://api.example.com/webhooks/alerts",
    headers: {
      "X-API-Key": process.env.CUSTOM_API_KEY!,
      "Content-Type": "application/json",
    },
  },
});

Multiple Channels

Send alerts to multiple destinations:
// pongo/channels.ts
export default channels({
  "ops-slack": {
    type: "webhook",
    url: process.env.OPS_SLACK_WEBHOOK!,
  },
  pagerduty: {
    type: "webhook",
    url: "https://events.pagerduty.com/v2/enqueue",
    headers: {
      Authorization: `Token token=${process.env.PAGERDUTY_KEY}`,
    },
  },
  discord: {
    type: "webhook",
    url: process.env.DISCORD_WEBHOOK!,
  },
});
// pongo/monitors/critical-service.ts
alerts: [
  {
    id: "critical-down",
    name: "Critical Service Down",
    condition: { consecutiveFailures: 2 },
    channels: ["ops-slack", "pagerduty"],  // Multiple channels
    severity: "critical",
  },
  {
    id: "degraded",
    name: "Service Degraded",
    condition: { latencyAboveMs: 2000, forChecks: 5 },
    channels: ["ops-slack"],  // Single channel
    severity: "warning",
  },
]

Testing Webhooks

Test your webhook configuration:
  1. Use webhook.site for debugging:
    export default channels({
      test: {
        type: "webhook",
        url: "https://webhook.site/your-unique-url",
      },
    });
    
  2. Trigger a test alert by temporarily lowering your threshold:
    condition: { consecutiveFailures: 1 }
    
  3. Check scheduler logs for delivery status:
    bun scheduler
    # Watch for webhook delivery logs
    

Environment Variables

Store all webhook URLs and credentials in environment variables:
# .env
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
PAGERDUTY_ROUTING_KEY=your-key
DISCORD_WEBHOOK=https://discord.com/api/webhooks/...
CUSTOM_API_KEY=your-api-key
Never commit credentials to version control.

Build docs developers (and LLMs) love