Skip to content

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:

X-Webhook-Signature: sha256=<hex_digest>

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:

{
  "event": "webhook.test",
  "webhook_id": "wh_abc123",
  "timestamp": "2025-11-02T10:15:30Z"
}

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

  1. Always verify signatures: Prevent unauthorized webhook calls
  2. Return 2xx quickly: Process webhooks asynchronously
  3. Handle retries gracefully: Implement idempotency
  4. Log webhook data: Aid debugging and auditing
  5. Monitor delivery failures: Alert on high failure rates