Webhooks
Receive real-time notifications when campaign events occur.
Overview
Webhooks allow you to receive HTTP POST requests when events occur in your campaigns. Configure a webhook URL when creating a campaign or in your dashboard settings.
Configuration
Per-Campaign Webhook
POST /campaigns
{
"mcp": "sales-outreach",
"target_url": "acme.com",
"reporting": {
"webhook_url": "https://your-server.com/webhooks/mcpfactory"
}
}Global Webhook (Dashboard)
Go to Settings → Webhooks to configure a webhook that receives events from all campaigns.
Webhook Payload
All webhooks are sent as HTTP POST with JSON body:
POST https://your-server.com/webhooks/mcpfactory
Content-Type: application/json
X-MCPFactory-Signature: sha256=xxxxx
{
"id": "evt_abc123",
"event": "reply.received",
"created_at": "2026-01-31T14:23:00Z",
"campaign_id": "camp_abc123",
"data": {
// Event-specific data
}
}Events
campaign.started
Campaign has begun processing.
{
"event": "campaign.started",
"campaign_id": "camp_abc123",
"data": {
"mcp": "sales-outreach",
"target_url": "acme.com"
}
}campaign.milestone
Reached a volume milestone (100, 500, 1000 emails).
{
"event": "campaign.milestone",
"campaign_id": "camp_abc123",
"data": {
"milestone": "100_emails",
"stats": {
"emails_sent": 100,
"delivered": 94,
"opened": 21,
"replied": 3
}
}
}campaign.paused
Campaign was paused (manually or due to budget).
{
"event": "campaign.paused",
"campaign_id": "camp_abc123",
"data": {
"reason": "budget_exceeded",
"budget_spent_usd": 10.23,
"budget_limit_usd": 10.00
}
}campaign.completed
Campaign finished (trial ended or schedule complete).
{
"event": "campaign.completed",
"campaign_id": "camp_abc123",
"data": {
"reason": "trial_ended",
"final_stats": {
"emails_sent": 487,
"delivered": 456,
"opened": 112,
"replied": 23,
"meetings_booked": 5
},
"total_cost_usd": 8.74
}
}reply.received
Someone replied to a campaign email.
{
"event": "reply.received",
"campaign_id": "camp_abc123",
"data": {
"reply_id": "reply_xyz789",
"email": "john@prospect.com",
"name": "John Smith",
"company": "Prospect Inc",
"title": "CTO",
"sentiment": "positive",
"preview": "Thanks for reaching out! I'd love to schedule a call to discuss...",
"received_at": "2026-01-31T14:23:00Z"
}
}meeting.booked
A meeting was scheduled via calendar link.
{
"event": "meeting.booked",
"campaign_id": "camp_abc123",
"data": {
"email": "john@prospect.com",
"name": "John Smith",
"company": "Prospect Inc",
"meeting_time": "2026-02-03T15:00:00Z",
"calendar_link": "https://calendar.google.com/..."
}
}budget.warning
80% of daily/weekly/monthly budget used.
{
"event": "budget.warning",
"campaign_id": "camp_abc123",
"data": {
"budget_type": "daily",
"spent_usd": 8.12,
"limit_usd": 10.00,
"percentage": 81
}
}Verifying Signatures
All webhooks include an X-MCPFactory-Signature header. Verify it to ensure the request is from MCP Factory:
import crypto from 'crypto';
function verifyWebhook(payload: string, signature: string, secret: string) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}Get your webhook secret from Dashboard → Settings → Webhooks.
Retries
If your endpoint returns a non-2xx status, we retry with exponential backoff:
- Retry 1: 1 minute
- Retry 2: 5 minutes
- Retry 3: 30 minutes
- Retry 4: 2 hours
- Retry 5: 24 hours
After 5 failed retries, the webhook is marked as failed.
Testing
Use Dashboard → Webhooks → Test to send a test event to your endpoint.