Skip to main content

Overview

Webhooks enable Mission Control to push events to your external services in real-time. Configure webhook endpoints to receive notifications about tasks, agents, activities, and security events.
Webhooks use HMAC-SHA256 signatures for security and include automatic retry with exponential backoff.

Quick Start

1

Create Webhook

Response:
Save the secret immediately! It’s only shown once. You’ll need it to verify webhook signatures.
2

Verify Signature in Your Handler

Validate incoming webhooks using the HMAC signature:
3

Test Webhook

Response:

Event Types

Subscribe to specific events or use * for all events.

Activity Events

Agent Events

Notification Events

Security Events

Wildcard

Start with * during development, then narrow to specific events for production to reduce traffic.

Webhook Payload Format

All webhooks deliver JSON with this structure:
string
Event type identifier
number
Unix timestamp (seconds) when event occurred
object
Event-specific payload. Structure varies by event type.

HTTP Headers

Mission Control sends these headers with every webhook:

Signature Verification

Mission Control signs all webhook payloads using HMAC-SHA256.

Signature Format

The signature is computed as:

Verification Algorithm

1

Extract Components

  • Get X-MC-Signature header
  • Get raw request body (UTF-8 string, before parsing JSON)
  • Get webhook secret from creation response
2

Compute Expected Signature

3

Compare Using Constant-Time Function

Always use constant-time comparison to prevent timing attacks:
  • Node.js: crypto.timingSafeEqual()
  • Python: hmac.compare_digest()
  • Go: hmac.Equal()
Never use === or == for signature comparison!

Helper Function

Mission Control exports a verification helper:

Retry Logic

Webhooks automatically retry on failure with exponential backoff.

Retry Schedule

Total attempts: 6 (1 initial + 5 retries)
Retries include ±20% jitter to prevent thundering herd issues.

Success Criteria

A delivery is considered successful if:
  • HTTP status code: 200-299
  • Response received within 10 seconds

Failure Criteria

A delivery fails if:
  • HTTP status code: ≥300 or connection error
  • Request times out after 10 seconds
  • Network error (DNS, connection refused, etc.)

Circuit Breaker

After 5 consecutive failures (configurable via MC_WEBHOOK_MAX_RETRIES):
  • Webhook is automatically disabled
  • No further deliveries are attempted
  • Log entry: Webhook circuit breaker tripped — disabled after exhausting retries
To re-enable:
This:
  • Resets consecutive_failures to 0
  • Sets enabled to true
  • Allows new deliveries

Management API

List Webhooks

Response:

Update Webhook

number
required
Webhook ID to update
string
New webhook name
string
New endpoint URL
array
New event subscriptions
boolean
Enable or disable webhook
boolean
Generate new secret (returns in response)
boolean
Reset circuit breaker and re-enable webhook

Delete Webhook

Deletes webhook and all delivery history.

View Delivery History

Response:
Mission Control keeps the last 200 deliveries per webhook.

Manual Retry

Manually retry a failed delivery (useful for debugging).

Environment Configuration

Best Practices

Idempotency

Webhooks may deliver the same event multiple times (retries). Design handlers to be idempotent:

Fast Response

Respond quickly (< 1s) to avoid timeouts:

Secret Rotation

Rotate webhook secrets periodically:
  1. Create new webhook with new secret
  2. Update your handler to accept both secrets
  3. Wait for old deliveries to drain (24h)
  4. Delete old webhook

Monitor Failures

Set up alerts for:
  • consecutive_failures > 3
  • circuit_open = true
  • Sudden spike in failed deliveries
Query delivery stats:

Troubleshooting

Cause: Your handler’s signature verification is incorrect.Debug steps:
  1. Ensure you’re using raw body (before JSON parsing)
  2. Log both signatures for comparison:
  3. Verify secret matches (check for leading/trailing whitespace)
  4. Use timingSafeEqual() for comparison
Test with curl:
Cause: Your endpoint is unreliable or timing out.Solutions:
  • Check webhook delivery logs: GET /api/webhooks/deliveries?webhook_id=1
  • Ensure your handler responds within 10 seconds
  • Return 200 status code on success
  • Check for network/firewall issues
  • Temporarily disable circuit breaker: MC_WEBHOOK_MAX_RETRIES=999
Reset circuit:
Cause: Event not in subscription list or event mapping issue.Debug:
  1. List webhook config: GET /api/webhooks
  2. Check events array includes the event type
  3. Update subscription:
  4. Test delivery: POST /api/webhooks/test
Internal events vs webhook events: Some internal events are mapped to webhook event types (see EVENT_MAP in /src/lib/webhooks.ts:36).
Cause: Scheduler not running or deliveries not recorded.Check scheduler:
Manually trigger retry processing:

Security Considerations

Always verify signatures in production. An attacker could forge webhook payloads without signature verification.

HTTPS Only

Use HTTPS endpoints in production:
Mission Control allows HTTP for local development only.

IP Whitelisting

Restrict webhook requests to Mission Control server IPs:

Rate Limiting

Protect your webhook endpoint:

Logging

Log all webhook deliveries for audit:

CLI Integration

Real-time events via Server-Sent Events

GitHub Sync

Webhook automation examples

Event Bus

Internal event system