Skip to Content

Webhook Events

Receive notifications when users connect, operations complete, or events occur.

Webhook Configuration

Set up webhooks in four steps:

  1. Go to the API Keys page in your Warm AI dashboard
  2. Open Settings for the relevant API key
  3. Enter your Webhook URL (must be HTTPS)
  4. Set a Webhook Secret for signature verification

Webhook Format

All webhook payloads are sent as JSON via POST to your configured URL.

Payload Structure:

{ "type": "event_type", "timestamp": "2026-03-19T10:30:00Z", "idempotency_key": "idem_abc123", "data": { } }
FieldTypeDescription
typestringThe event type identifier
timestampstringISO 8601 timestamp of the event
idempotency_keystring | nullCorrelation key if the event was triggered by an API call with one
dataobjectEvent-specific payload

Headers:

HeaderValue
Content-Typeapplication/json
X-WarmAI-Signaturesha256=<hmac>

Verifying Webhook Signatures

Every webhook request includes an X-WarmAI-Signature header containing an HMAC-SHA256 signature of the raw request body, signed with your webhook secret.

Node.js Example:

import crypto from 'crypto'; function verifyWebhookSignature(rawBody, signature, secret) { const expected = 'sha256=' + crypto .createHmac('sha256', secret) .update(rawBody) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expected) ); } // Usage in an Express handler app.post('/webhooks/warmai', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.headers['x-warmai-signature']; const isValid = verifyWebhookSignature(req.body, signature, process.env.WEBHOOK_SECRET); if (!isValid) { return res.status(401).send('Invalid signature'); } const event = JSON.parse(req.body); console.log('Received event:', event.type); res.status(200).send('OK'); });

Always verify the signature before processing a webhook event. Use crypto.timingSafeEqual to prevent timing attacks.


Event Types

user_signup

Fired when a user creates their Warm AI account through the connect link.

{ "type": "user_signup", "timestamp": "2026-03-19T10:30:00Z", "data": { "user_id": "usr_abc123", "email": "jane@example.com" } }

linkedin_connected

Fired when a user successfully connects their LinkedIn account via OAuth.

{ "type": "linkedin_connected", "timestamp": "2026-03-19T10:32:00Z", "data": { "user_id": "usr_abc123", "linkedin_url": "https://linkedin.com/in/janedoe", "linkedin_name": "Jane Doe" } }

linkedin_connection_failed

Fired when a user’s LinkedIn OAuth connection fails.

{ "type": "linkedin_connection_failed", "timestamp": "2026-03-19T10:32:00Z", "data": { "user_id": "usr_abc123", "error": "oauth_denied" } }

settings_complete

Fired when a user completes the Setup Wizard (all 4 steps finished).

{ "type": "settings_complete", "timestamp": "2026-03-19T10:45:00Z", "data": { "user_id": "usr_abc123", "first_name": "Jane", "last_name": "Doe", "calendar_link": "https://calendly.com/janedoe/30min", "cta_preference": "meeting", "communication_style": "professional", "message_length": "moderate", "connection_request_with_note": true, "product": { "id": "prod_xyz789", "name": "Acme CRM", "status": "approved" } } }

product_approved

Fired when a user’s product is reviewed and approved.

{ "type": "product_approved", "timestamp": "2026-03-19T11:00:00Z", "data": { "user_id": "usr_abc123", "product_id": "prod_xyz789", "product_name": "Acme CRM" } }

progress_update

Fired as an outreach operation progresses through its pipeline stages.

{ "type": "progress_update", "timestamp": "2026-03-19T11:05:00Z", "idempotency_key": "idem_abc123", "data": { "user_id": "usr_abc123", "prospect_url": "https://linkedin.com/in/prospect", "status": "generating_message", "progress": 60 } }

Use the idempotency_key in progress_update events to correlate them back to the original API request that triggered the operation.


Progress Status Reference

StatusProgressDescription
analysing_prospect10%Analysing the prospect’s LinkedIn profile
researching_prospect20%Researching the prospect’s background
analysing_company30%Analysing the prospect’s company
researching_company40%Researching company details
compiling_research50%Compiling research results
generating_message60%Generating the outreach message
reviewing_message70%AI review of the generated message
message_ready80%Message is ready for delivery
queued85%Message is queued for sending
sending90%Message is being sent via LinkedIn
delivered95%Message delivered to LinkedIn
sent100%Operation complete
failed0%Operation failed
cancelled0%Operation was cancelled
Last updated on