Webhooks API¶
The SubDepthTech Test Deployment Portal supports webhooks for real-time notifications about deployment events.
Overview¶
Webhooks allow you to receive HTTP callbacks when deployment events occur, enabling:
- Custom automation workflows
- Third-party integrations
- Real-time monitoring
- Incident response automation
Configuration¶
Register a Webhook¶
Endpoint: POST /api/webhooks
Request:
{
"url": "https://your-endpoint.example.com/webhook",
"events": ["deployment.started", "deployment.completed", "deployment.failed"],
"secret": "your-webhook-secret"
}
Response:
{
"webhook_id": "wh_abc123",
"url": "https://your-endpoint.example.com/webhook",
"events": ["deployment.started", "deployment.completed", "deployment.failed"],
"created_at": "2025-11-02T10:15:30Z"
}
Event Types¶
deployment.started¶
Triggered when a deployment begins.
Payload:
{
"event": "deployment.started",
"deployment_id": "dep_xyz789",
"project": "ai-agent-swarm-showcase",
"branch": "deploy-pages",
"commit": {
"sha": "a1b2c3d4",
"message": "feat: add new feature",
"author": "developer@example.com"
},
"timestamp": "2025-11-02T10:15:30Z"
}
deployment.completed¶
Triggered when a deployment succeeds.
Payload:
{
"event": "deployment.completed",
"deployment_id": "dep_xyz789",
"project": "ai-agent-swarm-showcase",
"url": "https://dep-xyz789--ai-agent-swarm-showcase.pages.dev",
"duration_seconds": 127,
"timestamp": "2025-11-02T10:17:37Z"
}
deployment.failed¶
Triggered when a deployment fails.
Payload:
{
"event": "deployment.failed",
"deployment_id": "dep_xyz789",
"project": "ai-agent-swarm-showcase",
"error": {
"code": "BUILD_FAILED",
"message": "MkDocs build exited with code 1"
},
"duration_seconds": 89,
"timestamp": "2025-11-02T10:16:59Z"
}
rollback.started¶
Triggered when a rollback begins.
Payload:
{
"event": "rollback.started",
"deployment_id": "dep_xyz789",
"previous_deployment_id": "dep_abc456",
"trigger": "automatic|manual",
"reason": "deployment_failed",
"timestamp": "2025-11-02T10:17:05Z"
}
rollback.completed¶
Triggered when a rollback succeeds.
Payload:
{
"event": "rollback.completed",
"deployment_id": "dep_xyz789",
"restored_deployment_id": "dep_abc456",
"duration_seconds": 42,
"timestamp": "2025-11-02T10:17:47Z"
}
Security¶
Signature Verification¶
All webhook requests include an X-Webhook-Signature header with HMAC-SHA256 signature:
Signature Format:
Verification Example (Python):
import hmac
import hashlib
def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool:
expected_signature = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
received_signature = signature.replace('sha256=', '')
return hmac.compare_digest(expected_signature, received_signature)
Verification Example (Node.js):
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
const receivedSignature = signature.replace('sha256=', '');
return crypto.timingSafeEqual(
Buffer.from(expectedSignature),
Buffer.from(receivedSignature)
);
}
Retry Policy¶
If your webhook endpoint fails to respond:
| Attempt | Delay | Timeout |
|---|---|---|
| 1 (initial) | 0s | 10s |
| 2 | 30s | 10s |
| 3 | 5m | 10s |
| 4 | 30m | 10s |
| 5 (final) | 2h | 10s |
After 5 failed attempts, the webhook is temporarily disabled.
Rate Limits¶
- Maximum requests per webhook: 100/minute
- Maximum webhooks per project: 10
- Maximum payload size: 1MB
Testing¶
Test Your Webhook¶
Endpoint: POST /api/webhooks/{webhook_id}/test
Sends a test event to your webhook:
Debug Logs¶
View recent webhook deliveries:
Endpoint: GET /api/webhooks/{webhook_id}/deliveries
Response:
{
"deliveries": [
{
"id": "del_123",
"event": "deployment.completed",
"status_code": 200,
"duration_ms": 145,
"timestamp": "2025-11-02T10:17:37Z"
},
{
"id": "del_124",
"event": "deployment.failed",
"status_code": 500,
"duration_ms": 10002,
"error": "Connection timeout",
"timestamp": "2025-11-02T10:18:42Z"
}
]
}
Examples¶
Slack Integration¶
// Webhook handler for Slack notifications
app.post('/webhook/deployment', async (req, res) => {
const { event, deployment_id, project } = req.body;
if (event === 'deployment.completed') {
await sendSlackMessage({
channel: '#deployments',
text: `✅ Deployment ${deployment_id} for ${project} completed successfully!`
});
} else if (event === 'deployment.failed') {
await sendSlackMessage({
channel: '#deployments',
text: `❌ Deployment ${deployment_id} for ${project} failed. Rollback initiated.`
});
}
res.status(200).send('OK');
});
Discord Integration¶
import discord
from aiohttp import web
async def handle_webhook(request):
data = await request.json()
if data['event'] == 'deployment.completed':
await discord_channel.send(
f"✅ Deployment {data['deployment_id']} succeeded!\n"
f"URL: {data['url']}"
)
elif data['event'] == 'rollback.completed':
await discord_channel.send(
f"🔄 Rollback completed. Restored deployment: {data['restored_deployment_id']}"
)
return web.Response(status=200)
Best Practices¶
- Always verify signatures: Prevent unauthorized webhook calls
- Return 2xx quickly: Process webhooks asynchronously
- Handle retries gracefully: Implement idempotency
- Log webhook data: Aid debugging and auditing
- Monitor delivery failures: Alert on high failure rates