Webhooks¶
Webhooks allow you to receive real-time HTTP notifications when events occur in AMP.
Overview¶
When an event occurs (e.g., content published, mission completed), AMP sends an HTTP POST request to your configured endpoint with event details.
sequenceDiagram
participant AMP
participant Your Server
AMP->>Your Server: POST /webhook
Note right of Your Server: Event payload
Your Server-->>AMP: 200 OK Configuring Webhooks¶
Create Webhook Endpoint¶
POST /webhooks
curl -X POST https://api.amp.dev/v1/webhooks \
-H "Authorization: Bearer $AMP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhooks/amp",
"events": ["content.published", "mission.completed"],
"secret": "whsec_your_secret_key"
}'
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Yes | HTTPS endpoint URL |
events | array | Yes | Events to subscribe to |
secret | string | No | Signing secret (auto-generated if not provided) |
enabled | boolean | No | Whether webhook is active (default: true) |
Response¶
{
"id": "whk_2xK9mPqR4vN8sT3w",
"url": "https://your-server.com/webhooks/amp",
"events": ["content.published", "mission.completed"],
"secret": "whsec_xxxxxxxxxxxxxxxxxxxx",
"status": "active",
"created_at": "2024-01-15T10:30:00Z"
}
Event Types¶
Content Events¶
| Event | Description |
|---|---|
content.created | New content generated |
content.approved | Content approved for publishing |
content.rejected | Content rejected during review |
content.scheduled | Content scheduled for publishing |
content.published | Content successfully published |
content.failed | Content publishing failed |
Mission Events¶
| Event | Description |
|---|---|
mission.created | New mission created |
mission.started | Mission pipeline started |
mission.paused | Mission paused |
mission.resumed | Mission resumed |
mission.completed | Mission duration ended |
Pipeline Events¶
| Event | Description |
|---|---|
pipeline.stage_completed | Pipeline stage finished |
pipeline.job_completed | Entire job finished |
pipeline.job_failed | Job failed after retries |
Analytics Events¶
| Event | Description |
|---|---|
analytics.kpi_achieved | KPI target reached |
analytics.anomaly_detected | Unusual performance detected |
Webhook Payload¶
All webhooks follow this structure:
{
"id": "evt_3yL0mPqR5wN9tU4v",
"type": "content.published",
"created_at": "2024-01-15T10:30:00Z",
"data": {
"content_id": "cnt_xxx",
"mission_id": "msn_yyy",
"platform": "twitter",
"platform_post_id": "1747293847293847",
"platform_url": "https://twitter.com/yourbrand/status/1747293847293847",
"published_at": "2024-01-15T10:30:15Z"
}
}
Payload Fields¶
| Field | Type | Description |
|---|---|---|
id | string | Unique event ID |
type | string | Event type |
created_at | datetime | When event occurred |
data | object | Event-specific data |
Event Payloads¶
content.published¶
{
"id": "evt_xxx",
"type": "content.published",
"created_at": "2024-01-15T10:30:00Z",
"data": {
"content_id": "cnt_xxx",
"mission_id": "msn_yyy",
"platform": "twitter",
"type": "thread",
"platform_post_id": "1747293847293847",
"platform_url": "https://twitter.com/...",
"published_at": "2024-01-15T10:30:15Z"
}
}
mission.completed¶
{
"id": "evt_xxx",
"type": "mission.completed",
"created_at": "2024-01-15T10:30:00Z",
"data": {
"mission_id": "msn_yyy",
"name": "Q1 Developer Outreach",
"duration_days": 90,
"summary": {
"content_published": 180,
"total_impressions": 523400,
"total_engagements": 18234,
"kpis_achieved": 3,
"kpis_total": 4
}
}
}
pipeline.job_failed¶
{
"id": "evt_xxx",
"type": "pipeline.job_failed",
"created_at": "2024-01-15T10:30:00Z",
"data": {
"job_id": "job_xxx",
"mission_id": "msn_yyy",
"failed_stage": "content",
"error": {
"code": "provider_error",
"message": "LLM provider rate limited"
},
"attempts": 3
}
}
Signature Verification¶
All webhook requests include a signature header for verification:
Verification Steps¶
- Extract the timestamp and signature from headers
- Concatenate timestamp and request body:
timestamp.body - Compute HMAC-SHA256 with your webhook secret
- Compare with the signature header
Example¶
const crypto = require('crypto');
function verifyWebhook(payload, signature, timestamp, secret) {
const signedPayload = `${timestamp}.${payload}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(`sha256=${expectedSignature}`)
);
}
// Express middleware
app.post('/webhooks/amp', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-amp-signature'];
const timestamp = req.headers['x-amp-timestamp'];
if (!verifyWebhook(req.body, signature, timestamp, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
// Handle event...
res.status(200).send('OK');
});
import hmac
import hashlib
def verify_webhook(payload, signature, timestamp, secret):
signed_payload = f"{timestamp}.{payload}"
expected = hmac.new(
secret.encode(),
signed_payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
# Flask route
@app.route('/webhooks/amp', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-AMP-Signature')
timestamp = request.headers.get('X-AMP-Timestamp')
if not verify_webhook(request.data, signature, timestamp, WEBHOOK_SECRET):
return 'Invalid signature', 401
event = request.json
# Handle event...
return 'OK', 200
func verifyWebhook(payload, signature, timestamp, secret string) bool {
signedPayload := fmt.Sprintf("%s.%s", timestamp, payload)
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(signedPayload))
expected := hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(signature), []byte("sha256="+expected))
}
Retry Policy¶
If your endpoint returns a non-2xx status or times out, AMP retries with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
After 5 failed attempts, the webhook is marked as failing and notifications are sent.
Managing Webhooks¶
List Webhooks¶
Update Webhook¶
curl -X PUT https://api.amp.dev/v1/webhooks/whk_xxx \
-H "Authorization: Bearer $AMP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": ["content.published", "content.failed"],
"enabled": true
}'
Delete Webhook¶
Test Webhook¶
Send a test event to verify your endpoint:
Best Practices¶
- Always verify signatures — Prevents spoofed requests
- Respond quickly — Return 200 within 5 seconds, process asynchronously
- Handle duplicates — Use event
idfor idempotency - Monitor failures — Set up alerts for webhook failures
- Use HTTPS — Required for production webhooks