Webhooks

Real-time notifications for lead magnet events and status updates

Overview

Webhooks allow your application to receive real-time notifications when events occur in Magnetite. Instead of polling our API for updates, we'll send HTTP POST requests to your specified endpoint whenever important events happen, such as lead magnet generation completion or failures.

Event Types

Magnetite supports the following webhook events:

lead.created
Triggered when a new lead is created

Sent immediately when a new lead magnet generation request is received and queued for processing.

research.started
Research agent begins execution

Fired when the research agent starts gathering data for lead personalization.

research.completed
Research phase finished successfully

Sent when research data collection is complete and content generation is about to begin.

research.failed
Research agent encountered an error

Triggered when the research phase fails due to tool errors, API limits, or other issues.

magnet.generated
Lead magnet content generated

Sent when the AI has successfully generated the personalized lead magnet content.

lead.completed
Lead magnet fully processed and ready

Final event when the lead magnet is completely processed and available for viewing.

lead.failed
Lead magnet generation failed

Triggered when lead magnet generation fails permanently after all retry attempts.

magnet.viewed
Someone viewed the lead magnet

Sent when a recipient opens and views the generated lead magnet.

Security & Verification

All webhook requests are signed using HMAC-SHA256 to ensure they're from Magnetite. The signature is included in the X-Magnetite-Signature header. You'll need the webhook secret (provided when you created the webhook) to verify these signatures.

Verifying Webhook Signatures

Node.js (Express)

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload, 'utf8')
    .digest('hex');
  
  const receivedSignature = signature.replace('sha256=', '');
  
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature, 'hex'),
    Buffer.from(receivedSignature, 'hex')
  );
}

// In your webhook handler
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-magnetite-signature'];
  const payload = req.body;
  const secret = process.env.WEBHOOK_SECRET;
  
  if (!verifyWebhookSignature(payload, signature, secret)) {
    return res.status(401).send('Unauthorized');
  }
  
  // Process the webhook
  const event = JSON.parse(payload);
  console.log('Received event:', event.event);
  
  res.status(200).send('OK');
});

Python (Flask)

import hmac
import hashlib
from flask import Flask, request, abort

def verify_webhook_signature(payload, signature, secret):
    expected_signature = hmac.new(
        secret.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    
    received_signature = signature.replace('sha256=', '')
    
    return hmac.compare_digest(expected_signature, received_signature)

@app.route('/webhook', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Magnetite-Signature')
    payload = request.get_data()
    secret = os.environ['WEBHOOK_SECRET']
    
    if not verify_webhook_signature(payload, signature, secret):
        abort(401)
    
    # Process the webhook
    event = request.get_json()
    print(f"Received event: {event['event']}")
    
    return 'OK', 200

Webhook Headers

Every webhook request includes these headers:

Content-Typeapplication/json
User-AgentMagnetite-Webhooks/1.0
X-Magnetite-Signaturesha256=[signature]
X-Magnetite-EventEvent type (e.g., lead.completed)
X-Magnetite-TimestampUnix timestamp when event occurred

Payload Structure

All webhook payloads follow this consistent structure:

{
  "event": "lead.completed",
  "timestamp": 1703123456789,
  "organization_id": "org_123abc",
  "project_id": "proj_456def",
  "lead_id": "lead_789ghi",
  "data": {
    // Event-specific data
  }
}

Event-Specific Data Examples

lead.created

{
  "event": "lead.created",
  "timestamp": 1703123456789,
  "organization_id": "org_123abc",
  "project_id": "proj_456def",
  "lead_id": "lead_789ghi",
  "data": {
    "lead_id": "lead_789ghi",
    "input_data": {
      "fullName": "John Smith",
      "company": "Acme Corp",
      "email": "john@acme.com"
    },
    "status": "processing",
    "created_at": 1703123456789
  }
}

lead.completed

{
  "event": "lead.completed",
  "timestamp": 1703123756789,
  "organization_id": "org_123abc",
  "project_id": "proj_456def",
  "lead_id": "lead_789ghi",
  "data": {
    "lead_id": "lead_789ghi",
    "status": "completed",
    "research_results": {
      "company_info": "...",
      "industry_insights": "..."
    },
    "generated_content": {
      "contentLength": 4521
    },
    "completed_at": 1703123756789
  }
}

magnet.viewed

{
  "event": "magnet.viewed",
  "timestamp": 1703124056789,
  "organization_id": "org_123abc",
  "project_id": "proj_456def",
  "lead_id": "lead_789ghi",
  "data": {
    "lead_id": "lead_789ghi",
    "viewer_ip": "203.0.113.42",
    "user_agent": "Mozilla/5.0...",
    "viewed_at": 1703124056789
  }
}

Retry Behavior

Magnetite implements exponential backoff retry logic for failed webhook deliveries:

Initial attempt: Immediate
Retry 1: After 1 second
Retry 2: After 2 seconds
Retry 3: After 4 seconds
Maximum: 30 seconds between attempts

Best Practices

Respond Quickly

Return a 200 status code as soon as possible. Process webhook data asynchronously if needed.

Verify Signatures

Always verify the HMAC signature to ensure requests are from Magnetite.

Handle Duplicates

Use the event timestamp and lead_id to detect and ignore duplicate deliveries.

Log Events

Keep detailed logs of webhook deliveries for debugging and monitoring.

Testing Webhooks

Use these tools and techniques to test your webhook implementation:

1. Local Development with ngrok

# Install ngrok
npm install -g ngrok

# Expose your local server
ngrok http 3000

# Use the https URL as your webhook endpoint
# https://abc123.ngrok.io/webhook

2. Webhook Testing Services

3. Manual Testing

Trigger webhooks by generating test lead magnets in your dashboard.

Troubleshooting

Common Issues

Webhook timeouts

Ensure your endpoint responds within 30 seconds. Move heavy processing to background jobs.

SSL certificate errors

Your webhook endpoint must use a valid SSL certificate. Self-signed certificates are not supported.

Missing events

Check your event subscriptions in the webhook configuration. Enable specific events you want to receive.

Need Help?

If you're having trouble with webhooks, check our troubleshooting guide or contact support.