Get Pipeline events as they happen
Send signed, versioned events to your CRM, warehouse, automations, or agent runtime. Each endpoint subscribes to an explicit set of events and can optionally filter campaign activity.
Send signed, versioned events to your CRM, warehouse, automations, or agent runtime. Each endpoint subscribes to an explicit set of events and can optionally filter campaign activity.
whsec_ secret once.{"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5","type": "linkedin.reply.received","api_version": "2026-08-17","timestamp": "2026-08-17T15:04:05.000Z","workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009","data": {"object": {"id": "reply_123","prospect_id": "prospect_123","conversation_id": "conversation_123","body": "Interested. Can you send over times?","body_truncated": false,"first_reply": true},"context": {"campaign_id": "campaign_123"},"actor": {"type": "system"}}}
Pipeline signs webhook-id.webhook-timestamp.raw-request-body. Reject stale timestamps, compare signatures in constant time, and do not parse or reserialize the body before verification.
import { createHmac, timingSafeEqual } from 'node:crypto'const secret = process.env.PIPELINE_WEBHOOK_SECRET!const rawBody = await request.text()const id = request.headers.get('webhook-id')!const timestamp = request.headers.get('webhook-timestamp')!const signatures = request.headers.get('webhook-signature')!.split(' ')const timestampSeconds = Number(timestamp)if (!Number.isFinite(timestampSeconds) || Math.abs(Date.now() / 1000 - timestampSeconds) > 300) {throw new Error('Stale webhook timestamp')}const key = Buffer.from(secret.replace('whsec_', ''), 'base64')const expected = createHmac('sha256', key).update(`${id}.${timestamp}.${rawBody}`).digest('base64')const expectedBytes = Buffer.from(expected)const valid = signatures.some((signature) => {const receivedBytes = Buffer.from(signature.replace('v1,', ''))return receivedBytes.length === expectedBytes.length && timingSafeEqual(receivedBytes, expectedBytes)})if (!valid) {throw new Error('Invalid webhook signature')}
v1 signatures during rotation.Only 2xx responses succeed. After the first attempt, retries are scheduled around 5 seconds, 5 minutes, 30 minutes, 2 hours, 5 hours, 10 hours, 14 hours, 20 hours, and 24 hours, with ±10% jitter. Valid Retry-After values are respected up to 24 hours.
Delivery is at least once and ordering is not guaranteed. Deduplicate with the event id or webhook-id.
Requests time out after 15 seconds. Redirects are not followed and count as failures.
HTTP 410 pauses an endpoint immediately. Repeated failures can auto-pause it. Resume after fixing the destination to wake due deliveries.
Pipeline publishes compact snapshots of durable business outcomes. Events marked planned document the stable contract but cannot be selected until their authoritative producer ships. Payloads never include credentials, raw provider payloads, prompts, or arbitrary table columns.
campaign.createdA campaign was created.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "campaign.created",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "campaign_123",
"name": "Founder outreach",
"status": "draft"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}campaign.startedA campaign began execution.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "campaign.started",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "campaign_123",
"name": "Founder outreach",
"status": "active"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}campaign.pausedA campaign was paused.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "campaign.paused",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "campaign_123",
"name": "Founder outreach",
"status": "paused"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}campaign.resumedA paused campaign resumed.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "campaign.resumed",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "campaign_123",
"name": "Founder outreach",
"status": "active"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}campaign.completedA campaign completed all terminal work.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "campaign.completed",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "campaign_123",
"name": "Founder outreach",
"status": "completed"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}campaign.failedA campaign entered a terminal failed state.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "campaign.failed",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "campaign_123",
"name": "Founder outreach",
"status": "failed",
"failure_code": "sender_unavailable"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}linkedin.connection_request.sentLinkedIn confirmed a connection request send.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "linkedin.connection_request.sent",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "action_123",
"action": "connection_request",
"prospect_id": "prospect_123",
"campaign_id": "campaign_123"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}linkedin.connection.acceptedA LinkedIn connection acceptance was persisted.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "linkedin.connection.accepted",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "connection_123",
"prospect_id": "prospect_123",
"campaign_id": "campaign_123"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}linkedin.message.sentLinkedIn confirmed a direct message send.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "linkedin.message.sent",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "action_124",
"action": "message",
"prospect_id": "prospect_123",
"campaign_id": "campaign_123"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}linkedin.inmail.sentLinkedIn confirmed an InMail send.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "linkedin.inmail.sent",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "action_125",
"action": "inmail",
"prospect_id": "prospect_123",
"campaign_id": "campaign_123"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}linkedin.reply.receivedA LinkedIn reply was persisted.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "linkedin.reply.received",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "reply_123",
"prospect_id": "prospect_123",
"conversation_id": "conversation_123",
"body": "Interested. Can you send over times?",
"body_truncated": false,
"first_reply": true
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}linkedin.action.failedA LinkedIn action reached a terminal failure.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "linkedin.action.failed",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "action_126",
"action": "message",
"prospect_id": "prospect_123",
"campaign_id": "campaign_123",
"error_code": "provider_rejected"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}linkedin.account.disconnectedA connected LinkedIn account became unavailable.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "linkedin.account.disconnected",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "account_123",
"name": "Founder account",
"status": "disconnected",
"reason": "credentials_expired"
},
"actor": {
"type": "system"
}
}
}linkedin.account.reconnectedA disconnected LinkedIn account returned to ready.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "linkedin.account.reconnected",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "account_123",
"name": "Founder account",
"status": "connected"
},
"actor": {
"type": "system"
}
}
}reply.classifiedPipeline persisted a reply intent classification.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "reply.classified",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "classification_123",
"conversation_id": "conversation_123",
"prospect_id": "prospect_123",
"classification": "interested"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}prospect.enrolledA prospect was added to a campaign.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "prospect.enrolled",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "prospect_123",
"campaign_id": "campaign_123",
"linkedin_url": "https://www.linkedin.com/in/example"
},
"context": {
"campaign_id": "campaign_123"
},
"actor": {
"type": "system"
}
}
}prospect.stage.changedA prospect changed canonical conversion stage.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "prospect.stage.changed",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "prospect_123",
"stage": "meeting_booked"
},
"previous_attributes": {
"stage": "interested"
},
"actor": {
"type": "system"
}
}
}meeting.bookedA meeting booking was persisted and linked.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "meeting.booked",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "meeting_123",
"prospect_id": "prospect_123",
"campaign_id": "campaign_123",
"starts_at": "2026-08-20T14:00:00.000Z"
},
"actor": {
"type": "system"
}
}
}workflow.run.startedA workflow run entered running.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "workflow.run.started",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "run_123",
"workflow_id": "workflow_123",
"name": "ICP outbound",
"status": "running"
},
"context": {
"workflow_run_id": "run_123"
},
"actor": {
"type": "system"
}
}
}workflow.run.completedA workflow run completed successfully.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "workflow.run.completed",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "run_123",
"workflow_id": "workflow_123",
"name": "ICP outbound",
"status": "completed"
},
"context": {
"workflow_run_id": "run_123"
},
"actor": {
"type": "system"
}
}
}workflow.run.failedA workflow run failed terminally.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "workflow.run.failed",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "run_123",
"workflow_id": "workflow_123",
"name": "ICP outbound",
"status": "failed"
},
"context": {
"workflow_run_id": "run_123"
},
"actor": {
"type": "system"
}
}
}workflow.run.awaiting_approvalA workflow run stopped at an approval gate.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "workflow.run.awaiting_approval",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "run_123",
"workflow_id": "workflow_123",
"name": "ICP outbound",
"status": "awaiting_approval"
},
"context": {
"workflow_run_id": "run_123"
},
"actor": {
"type": "system"
}
}
}approval.requiredA human approval item was created.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "approval.required",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "approval_123",
"subject_type": "workflow_run",
"subject_id": "run_123",
"status": "required"
},
"context": {
"workflow_run_id": "run_123"
},
"actor": {
"type": "system"
}
}
}approval.resolvedA human approval item was approved, rejected, or canceled.
{
"id": "7b60d0cb-b735-4a8c-9c30-4180ab1c98d5",
"type": "approval.resolved",
"api_version": "2026-08-17",
"timestamp": "2026-08-17T15:04:05.000Z",
"workspace_id": "39dba13f-6246-4b14-a310-a6710aa53009",
"data": {
"object": {
"id": "approval_123",
"subject_type": "workflow_run",
"subject_id": "run_123",
"status": "approved"
},
"context": {
"workflow_run_id": "run_123"
},
"actor": {
"type": "system"
}
}
}Webhook operations use the same bearer authentication and workspace permissions as the rest of the Pipeline API. Each operation below links to its typed parameters and response schemas.
Manual redelivery requires an Idempotency-Key header so a retried API request cannot enqueue the same redelivery twice.
v1 signature during secret rotation.id or webhook-id header.