Webhook Specification
Overview
The Passport for AI Agents can send webhook notifications when agent passport status changes occur.
Configuration
Webhooks are configured via environment variables:
WEBHOOK_URL: Target webhook endpoint URLWEBHOOK_SECRET: Secret key for webhook signature verification
Webhook Events
Status Change Events
passport.created- New passport createdpassport.updated- Passport data updatedpassport.suspended- Passport suspendedpassport.revoked- Passport revokedpassport.activated- Suspended passport reactivated
Payload Format
Headers
Content-Type: application/json
X-Webhook-Signature: sha256=abc123...
X-Webhook-Event: passport.updated
X-Webhook-Timestamp: 1640995200
Payload Structure
{
"event": "passport.updated",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"agent_id": "ap_a2d10232c6534523812423eec8a1425c",
"previous_status": "active",
"current_status": "suspended",
"reason": "Policy violation",
"updated_by": "[email protected]"
},
"passport": {
"agent_id": "ap_a2d10232c6534523812423eec8a1425c",
"owner": "AI Research Lab",
"role": "Tier-1",
"status": "suspended",
"updated_at": "2024-01-15T10:30:00Z"
}
}
Signature Verification
Webhooks include a signature header for verification:
X-Webhook-Signature: sha256=abc123...
The signature is generated using HMAC-SHA256:
signature = hmac-sha256(webhook_secret, payload_body)
Retry Logic
- Initial Retry: 1 second delay
- Subsequent Retries: Exponential backoff (2s, 4s, 8s, 16s, 32s)
- Max Retries: 5 attempts
- Timeout: 30 seconds per attempt
- Success Criteria: HTTP 2xx response
Security
- HTTPS Required: All webhook URLs must use HTTPS
- Signature Verification: Always verify webhook signatures
- Timestamp Validation: Reject webhooks older than 5 minutes
- IP Allowlisting: Optional IP allowlisting for additional security
Error Handling
Webhook Endpoint Errors
- 4xx Errors: Will not be retried
- 5xx Errors: Will be retried according to retry logic
- Timeout: Will be retried
- Network Errors: Will be retried
Failed Webhooks
After max retries, failed webhooks are logged but not retried. Check logs for failed webhook deliveries.
Testing
Webhook Testing Endpoint
POST /api/admin/webhook-test
Test webhook delivery without changing actual passport status.
Example Test Request
curl -X POST "https://api.aport.io/api/admin/webhook-test" \
-H "Authorization: Bearer your-admin-token" \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://your-endpoint.com/webhook",
"event": "passport.updated"
}'
Implementation Examples
Node.js Express Handler
const crypto = require('crypto');
app.post('/webhook', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const payload = JSON.stringify(req.body);
// Verify signature
const expectedSignature = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (signature !== `sha256=${expectedSignature}`) {
return res.status(401).send('Invalid signature');
}
// Process webhook
const { event, data, passport } = req.body;
console.log(`Received ${event} for agent ${passport.agent_id}`);
res.status(200).send('OK');
});
Python Flask Handler
import hmac
import hashlib
import json
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
signature = request.headers.get('X-Webhook-Signature')
payload = request.get_data()
# Verify signature
expected_signature = hmac.new(
WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256
).hexdigest()
if signature != f'sha256={expected_signature}':
return 'Invalid signature', 401
# Process webhook
data = request.get_json()
event = data['event']
passport = data['passport']
print(f'Received {event} for agent {passport["agent_id"]}')
return 'OK', 200
Monitoring
Webhook delivery metrics are available via the /api/metrics endpoint:
{
"webhooks": {
"totalSent": 1250,
"successfulDeliveries": 1200,
"failedDeliveries": 50,
"successRate": 96.0,
"averageDeliveryTime": 1.2
}
}