Documentation Index
Fetch the complete documentation index at: https://docs.poly.ai/llms.txt
Use this file to discover all available pages before exploring further.
Use webhooks when your systems need to react to PolyAI events in real time–for example, triggering incident response when an alert fires or updating a dashboard. Webhooks include HMAC-SHA256 signatures and automatic retries, with support for secret rotation.
The Webhooks API lets you register HTTP endpoints that receive real-time notifications when events occur in your PolyAI account. Webhooks are currently used by the Alerts API and will expand to other services in the future.
Key features
- Signed delivery - Every webhook includes an HMAC-SHA256 signature you can verify
- Automatic retries - Failed deliveries retry with exponential backoff
- Secret rotation - Rotate signing secrets without recreating the endpoint
Limits
| Resource | Maximum per account |
|---|
| Webhook endpoints | 10 |
Requests to create a webhook endpoint beyond the limit return a 409 Conflict error.
Event types
| Event | Description |
|---|
alerts.triggered | An alert rule transitioned into a firing state |
alerts.resolved | A firing alert transitioned back to ok |
Each webhook request includes these headers:
| Header | Description |
|---|
X-PolyAI-Timestamp | Unix timestamp (seconds) when the webhook was sent |
X-PolyAI-Signature | HMAC-SHA256 signature for verification |
X-PolyAI-Event-ID | Unique event identifier for deduplication |
Retry policy
Failed webhook deliveries are retried with exponential backoff:
| Attempt | Delay | Cumulative time |
|---|
| 1 | Immediate | 0 |
| 2 | 1 minute | 1 minute |
| 3 | 5 minutes | 6 minutes |
| 4 | 15 minutes | 21 minutes |
| 5 | 1 hour | ~1.5 hours |
| 6 | 4 hours | ~5.5 hours |
Retried failures:
- Timeout
- Network error
- HTTP 408, 429, 5xx
Not retried:
Signature verification
Verify webhook signatures to ensure requests are from PolyAI.
Algorithm: HMAC-SHA256
Signed message format: {timestamp}.{raw_request_body}
import hmac
import hashlib
import time
def verify_webhook(payload: bytes, timestamp: str, signature: str, secret: str) -> bool:
# Reject requests older than 5 minutes
if abs(time.time() - int(timestamp)) > 300:
return False
# Compute expected signature
message = f"{timestamp}.{payload.decode('utf-8')}"
expected = hmac.new(
secret.encode('utf-8'),
message.encode('utf-8'),
hashlib.sha256
).hexdigest()
# Constant-time comparison
return hmac.compare_digest(expected, signature)
const crypto = require('crypto');
function verifyWebhook(payload, timestamp, signature, secret) {
// Reject requests older than 5 minutes
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - parseInt(timestamp)) > 300) {
return false;
}
// Compute expected signature
const message = `${timestamp}.${payload}`;
const expected = crypto
.createHmac('sha256', secret)
.update(message)
.digest('hex');
// Constant-time comparison
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"math"
"strconv"
"time"
)
func verifyWebhook(payload []byte, timestamp, signature, secret string) bool {
// Reject requests older than 5 minutes
ts, err := strconv.ParseInt(timestamp, 10, 64)
if err != nil {
return false
}
if math.Abs(float64(time.Now().Unix()-ts)) > 300 {
return false
}
// Compute expected signature
message := timestamp + "." + string(payload)
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(message))
expected := hex.EncodeToString(mac.Sum(nil))
// Constant-time comparison
return hmac.Equal([]byte(expected), []byte(signature))
}
Use X-PolyAI-Event-ID for deduplication since retries can deliver the same event more than once.
Authentication
All Webhooks API endpoints use API key authentication with the x-api-key header. Resources are automatically scoped to your account.
API keys are not yet available through self-service. To request access, email developers@poly.ai.