ChannelConfig Interface
Defines a webhook endpoint for alert notifications.
interface ChannelConfig {
type: "webhook";
url: string;
headers?: Record<string, string>;
}
Fields
Channel typeCurrently only "webhook" is supported. Future versions may support email, Slack, PagerDuty, etc.
Webhook endpoint URLPongo sends POST requests with alert payloads to this URL. Must be HTTPS in production.
Custom HTTP headers for webhook requestsUse for authentication tokens, content type, or custom routing headers.Example:headers: {
"Authorization": "Bearer token",
"X-Custom-Header": "value"
}
ChannelsConfig Type
Map of channel IDs to configurations.
type ChannelsConfig = Record<string, ChannelConfig>
Channel IDs are referenced in AlertConfig.channels arrays.
channels() Helper
Type-safe wrapper for channel configuration.
function channels(config: ChannelsConfig): ChannelsConfig
Usage
import { channels } from "../src/lib/config-types";
export default channels({
"ops-team": {
type: "webhook",
url: process.env.OPS_WEBHOOK_URL!,
},
});
Webhook Payload
Pongo sends this JSON payload to webhook URLs:
interface WebhookPayload {
event: "alert.fired" | "alert.resolved";
alert: {
id: string;
name: string;
monitorId: string;
monitorName: string;
severity: "critical" | "warning" | "info";
};
timestamp: string; // ISO 8601
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; // ISO 8601
};
region?: string;
firingRegions?: string[];
healthyRegions?: string[];
}
Example Payload: Alert Fired
{
"event": "alert.fired",
"alert": {
"id": "api-down",
"name": "API Down",
"monitorId": "api",
"monitorName": "Production API",
"severity": "critical"
},
"timestamp": "2026-03-04T10:30:00.000Z",
"snapshot": {
"consecutiveFailures": 3,
"consecutiveSuccesses": 0,
"lastStatus": "down",
"lastResponseTimeMs": 5234,
"lastMessage": "HTTP 503"
},
"checkResult": {
"id": "check_xyz789",
"status": "down",
"responseTimeMs": 5234,
"message": "HTTP 503",
"checkedAt": "2026-03-04T10:30:00.000Z"
},
"region": "us-east-1",
"firingRegions": ["us-east-1", "eu-west-1"],
"healthyRegions": ["ap-southeast-1"]
}
Example Payload: Alert Resolved
{
"event": "alert.resolved",
"alert": {
"id": "api-down",
"name": "API Down",
"monitorId": "api",
"monitorName": "Production API",
"severity": "critical"
},
"timestamp": "2026-03-04T10:35:00.000Z",
"snapshot": {
"consecutiveFailures": 0,
"consecutiveSuccesses": 2,
"lastStatus": "up",
"lastResponseTimeMs": 234,
"lastMessage": null
},
"checkResult": {
"id": "check_abc123",
"status": "up",
"responseTimeMs": 234,
"message": null,
"checkedAt": "2026-03-04T10:35:00.000Z"
}
}
Real Examples
Basic Webhook
import { channels } from "../src/lib/config-types";
export default channels({
"ops-team": {
type: "webhook",
url: "https://hooks.example.com/alerts",
},
});
Webhook with Authentication
import { channels } from "../src/lib/config-types";
export default channels({
"ops-team": {
type: "webhook",
url: process.env.OPS_WEBHOOK_URL!,
headers: {
"Authorization": `Bearer ${process.env.WEBHOOK_TOKEN}`,
},
},
});
Multiple Channels
import { channels } from "../src/lib/config-types";
export default channels({
"ops-team": {
type: "webhook",
url: process.env.OPS_WEBHOOK_URL!,
headers: {
"Authorization": `Bearer ${process.env.OPS_TOKEN}`,
},
},
"engineering": {
type: "webhook",
url: process.env.ENG_WEBHOOK_URL!,
headers: {
"Authorization": `Bearer ${process.env.ENG_TOKEN}`,
},
},
"pagerduty": {
type: "webhook",
url: "https://events.pagerduty.com/v2/enqueue",
headers: {
"Authorization": `Token token=${process.env.PAGERDUTY_TOKEN}`,
"Content-Type": "application/json",
},
},
});
Slack Webhook
import { channels } from "../src/lib/config-types";
export default channels({
"slack-ops": {
type: "webhook",
url: process.env.SLACK_WEBHOOK_URL!,
},
});
Discord Webhook
import { channels } from "../src/lib/config-types";
export default channels({
"discord-ops": {
type: "webhook",
url: process.env.DISCORD_WEBHOOK_URL!,
},
});
import { channels } from "../src/lib/config-types";
export default channels({
"internal-api": {
type: "webhook",
url: "https://internal.example.com/webhook",
headers: {
"X-Service": "pongo",
"X-Environment": process.env.NODE_ENV!,
"X-API-Key": process.env.INTERNAL_API_KEY!,
},
},
});
Webhook Integration Guide
Receiving Webhooks
Your webhook endpoint should:
- Accept POST requests with JSON payload
- Respond with 2xx status code (200-299)
- Process payload asynchronously if needed
- Handle both
alert.fired and alert.resolved events
Example Express Handler
app.post("/webhook/pongo", express.json(), (req, res) => {
const payload: WebhookPayload = req.body;
if (payload.event === "alert.fired") {
console.log(`Alert fired: ${payload.alert.name}`);
console.log(`Severity: ${payload.alert.severity}`);
console.log(`Monitor: ${payload.alert.monitorName}`);
console.log(`Status: ${payload.checkResult.status}`);
console.log(`Message: ${payload.checkResult.message}`);
} else if (payload.event === "alert.resolved") {
console.log(`Alert resolved: ${payload.alert.name}`);
}
res.status(200).json({ received: true });
});
Retry Behavior
Pongo retries failed webhook deliveries:
- Retries on 5xx errors or network failures
- Does not retry on 4xx client errors
- Exponential backoff between retries
- Maximum 3 retry attempts
Security
- Use HTTPS URLs in production
- Validate webhook signatures (coming soon)
- Use authentication headers
- Whitelist Pongo IP addresses if needed
File Location
Channel configuration must be in:
This file is required even if empty. Use the starter template:
import { channels } from "../src/lib/config-types";
export default channels({
// Add your channels here
});