Event catalogue

One entry per event that GET /v1/webhooks/events lists, at a stable anchor: /reference/webhooks/catalogue#<event>. Each entry says when the event fires, its source, whether a new webhook gets it by default, how late it can arrive, how to subscribe (CLI first) and a full example delivery with every key the event can carry.

A webhook has one source. Omit account_ids (REST) to cover every account you can operate, now and later; omit events for the source's default set. Every webhook also takes motion_ids to receive only the events of those Motions.

The examples show a Motion-linked delivery where one exists: outside a Motion, motion_id, enrollment_id, motion_name and contact are null on message.* and connection.accepted.

Messaging events

message.received

An inbound message arrived in any chat (classic / InMail).

  • Source: messaging
  • Subscription: default: subscribed when you omit events
  • Latency: Real time: seconds after LinkedIn reports it.

Subscribe with the CLI:

curviate webhook create --source messaging --events message.received --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "messaging",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "message.received"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "message.received",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "message.received",
    "chat_id": "chat_YOUR_CHAT_ID",
    "message_id": "msg_YOUR_MESSAGE_ID",
    "text": "Hello, I saw your profile and wanted to connect.",
    "sender": {
      "name": "Alex Jordan",
      "profile_url": "https://www.linkedin.com/in/alexjordan",
      "provider_id": "urn:li:member:123456789"
    },
    "attachments": [],
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "occurred_at": "2026-05-28T14:22:05.000Z"
  },
  "delivered_at": "2026-05-28T14:22:06.789Z"
}

message.read

A message in a chat was read by the recipient.

  • Source: messaging
  • Subscription: opt-in: name it in events
  • Latency: Real time: seconds after LinkedIn reports it.

Subscribe with the CLI:

curviate webhook create --source messaging --events message.read --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "messaging",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "message.read"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "message.read",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "message.read",
    "chat_id": "chat_YOUR_CHAT_ID",
    "message_id": "msg_YOUR_MESSAGE_ID",
    "text": "Hello, I saw your profile and wanted to connect.",
    "sender": {
      "name": "Alex Jordan",
      "profile_url": "https://www.linkedin.com/in/alexjordan",
      "provider_id": "urn:li:member:123456789"
    },
    "read_by": "urn:li:member:987654321",
    "attachments": [],
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "occurred_at": "2026-05-28T14:25:00.000Z"
  },
  "delivered_at": "2026-05-28T14:25:01.012Z"
}

message.reaction

A reaction was added to a message.

  • Source: messaging
  • Subscription: opt-in: name it in events
  • Latency: Real time: seconds after LinkedIn reports it.

Subscribe with the CLI:

curviate webhook create --source messaging --events message.reaction --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "messaging",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "message.reaction"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "message.reaction",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "message.reaction",
    "chat_id": "chat_YOUR_CHAT_ID",
    "message_id": "msg_YOUR_MESSAGE_ID",
    "text": "Thanks for reaching out, happy to connect.",
    "reaction": "👍",
    "sender": {
      "name": "Alex Jordan",
      "profile_url": "https://www.linkedin.com/in/alexjordan",
      "provider_id": "urn:li:member:123456789"
    },
    "attachments": [],
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "occurred_at": "2026-05-28T14:26:30.000Z"
  },
  "delivered_at": "2026-05-28T14:26:31.234Z"
}

message.edited

A message was edited after send.

  • Source: messaging
  • Subscription: opt-in: name it in events
  • Latency: Real time: seconds after LinkedIn reports it.

Subscribe with the CLI:

curviate webhook create --source messaging --events message.edited --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "messaging",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "message.edited"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "message.edited",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "message.edited",
    "chat_id": "chat_YOUR_CHAT_ID",
    "message_id": "msg_YOUR_MESSAGE_ID",
    "text": "Thanks for reaching out, let's schedule a call.",
    "sender": {
      "name": "Jordan Lee",
      "profile_url": "https://www.linkedin.com/in/jordanlee",
      "provider_id": "urn:li:member:987654321"
    },
    "attachments": [],
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "occurred_at": "2026-05-28T14:27:45.000Z"
  },
  "delivered_at": "2026-05-28T14:27:46.789Z"
}

message.deleted

A message was deleted.

  • Source: messaging
  • Subscription: opt-in: name it in events
  • Latency: Real time: seconds after LinkedIn reports it.

Subscribe with the CLI:

curviate webhook create --source messaging --events message.deleted --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "messaging",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "message.deleted"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "message.deleted",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "message.deleted",
    "chat_id": "chat_YOUR_CHAT_ID",
    "message_id": "msg_YOUR_MESSAGE_ID",
    "sender": {
      "name": "Jordan Lee",
      "profile_url": "https://www.linkedin.com/in/jordanlee",
      "provider_id": "urn:li:member:987654321"
    },
    "attachments": [],
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "occurred_at": "2026-05-28T14:28:00.000Z"
  },
  "delivered_at": "2026-05-28T14:28:01.345Z"
}

chat.updated

A chat's container state changed (e.g. archived, muted, read-state); useful for inbox automation.

  • Source: messaging
  • Subscription: opt-in: name it in events
  • Latency: Real time: seconds after LinkedIn reports it.

Subscribe with the CLI:

curviate webhook create --source messaging --events chat.updated --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "messaging",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "chat.updated"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "chat.updated",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "chat.updated",
    "chat_id": "chat_YOUR_CHAT_ID",
    "occurred_at": "2026-05-28T14:30:00.000Z"
  },
  "delivered_at": "2026-05-28T14:30:01.000Z"
}

chat.deleted

A chat thread was deleted.

  • Source: messaging
  • Subscription: opt-in: name it in events
  • Latency: Real time: seconds after LinkedIn reports it.

Subscribe with the CLI:

curviate webhook create --source messaging --events chat.deleted --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "messaging",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "chat.deleted"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "chat.deleted",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "chat.deleted",
    "chat_id": "chat_YOUR_CHAT_ID",
    "occurred_at": "2026-05-28T14:31:00.000Z"
  },
  "delivered_at": "2026-05-28T14:31:01.000Z"
}

User events

connection.accepted

A pending invitation sent through Curviate (by a Motion or a direct send) was accepted by the recipient. Detected by Curviate's own polling, not real-time: latency up to about 160 in-window minutes while Motion invitations are pending, about 580 otherwise, longer while an account warms up.

  • Source: user
  • Subscription: default: subscribed when you omit events
  • Latency: Not real time: about 2 hours after the acceptance (acceptances are polled).

Subscribe with the CLI:

curviate webhook create --source user --events connection.accepted --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "user",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "connection.accepted"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "connection.accepted",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "connection.accepted",
    "user": {
      "full_name": "Alex Jordan",
      "provider_id": "urn:li:member:123456789",
      "public_identifier": "alexjordan",
      "profile_url": "https://www.linkedin.com/in/alexjordan",
      "picture_url": "https://media.licdn.com/dms/image/example/photo.jpg"
    },
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "occurred_at": "2026-05-28T16:45:00.000Z"
  },
  "delivered_at": "2026-05-29T00:45:01.012Z"
}

connection.new

A new relation appeared on the account (any new LinkedIn connection, not just ones you invited). Polled, not real-time; up to ~4h delay; a freshly connected account may see a backfill burst of these on first connect.

  • Source: user
  • Subscription: opt-in: name it in events
  • Latency: Not real time: up to about 4 hours, and a backfill burst after a new connect.

Subscribe with the CLI:

curviate webhook create --source user --events connection.new --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "user",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "connection.new"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "connection.new",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "connection.new",
    "user": {
      "full_name": "Sam Rivera",
      "provider_id": "urn:li:member:246813579",
      "public_identifier": "samrivera",
      "profile_url": "https://www.linkedin.com/in/samrivera",
      "picture_url": "https://media.licdn.com/dms/image/example/photo.jpg"
    },
    "occurred_at": "2026-05-28T18:00:00.000Z"
  },
  "delivered_at": "2026-05-28T22:00:01.500Z"
}

Account status events

account.created

A new account link completed successfully for the first time (initial-connect path).

  • Source: account_status
  • Subscription: default: subscribed when you omit events
  • Latency: Real time.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.created --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.created"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.created",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.created",
    "status": "active",
    "occurred_at": "2026-05-28T08:00:00.000Z"
  },
  "delivered_at": "2026-05-28T08:00:01.123Z"
}

account.connected

The account is in a healthy, connected state. Also sent when a connect reactivates an account you had previously disconnected and it comes back healthy.

  • Source: account_status
  • Subscription: default: subscribed when you omit events
  • Latency: Real time.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.connected --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.connected"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.connected",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.connected",
    "status": "active",
    "occurred_at": "2026-05-28T08:05:00.000Z"
  },
  "delivered_at": "2026-05-28T08:05:01.456Z"
}

account.synced

A synchronization cycle completed successfully. No longer pushed in real time; v2 has no equivalent event; no read-path alternative exists.

  • Source: account_status
  • Subscription: default: subscribed when you omit events
  • Latency: Not delivered any more: subscribing succeeds and nothing arrives. Read the account instead.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.synced --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.synced"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.synced",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.synced",
    "status": "active",
    "occurred_at": "2026-05-28T08:10:00.000Z"
  },
  "delivered_at": "2026-05-28T08:10:01.789Z"
}

account.reconnected

An existing account was re-authorized in place (credentials refreshed). Reactivating an account you had previously disconnected does not send this event; that connect reports the state the account comes back in.

  • Source: account_status
  • Subscription: default: subscribed when you omit events
  • Latency: Real time.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.reconnected --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.reconnected"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.reconnected",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.reconnected",
    "status": "active",
    "occurred_at": "2026-05-28T10:00:00.000Z"
  },
  "delivered_at": "2026-05-28T10:00:01.234Z"
}

account.reconnect_needed

Credentials expired / cookie invalidated; the account needs reconnection.

  • Source: account_status
  • Subscription: default: subscribed when you omit events
  • Latency: Real time.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.reconnect_needed --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.reconnect_needed"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.reconnect_needed",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.reconnect_needed",
    "status": "reconnect_needed",
    "occurred_at": "2026-05-28T11:30:00.000Z"
  },
  "delivered_at": "2026-05-28T11:30:01.567Z"
}

account.restricted

The account is connected, but some actions on it fail: LinkedIn restricted the account, or one LinkedIn product on it (such as Sales Navigator or Recruiter) needs re-authentication or is failing. Surface it to a human. If a single product is failing, a reconnect may restore it. A LinkedIn restriction is usually detected by a daily account reconciliation (within about 24 hours) or immediately by a connect; a failing product is reported immediately. An on-demand account read always reports the current state.

  • Source: account_status
  • Subscription: default: subscribed when you omit events
  • Latency: Not real time: a LinkedIn restriction is usually detected within about 24 hours; a failing product immediately.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.restricted --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.restricted"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.restricted",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.restricted",
    "status": "restricted",
    "occurred_at": "2026-05-28T13:30:00.000Z"
  },
  "delivered_at": "2026-05-28T13:30:01.204Z"
}

account.creation_failed

The initial account-link attempt failed before completion (terminal; no account was established). No longer pushed in real time; detect via an on-demand account read.

  • Source: account_status
  • Subscription: default: subscribed when you omit events
  • Latency: Not delivered any more: subscribing succeeds and nothing arrives. Read the account instead.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.creation_failed --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.creation_failed"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.creation_failed",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.creation_failed",
    "status": "disconnected",
    "occurred_at": "2026-05-28T07:55:00.000Z"
  },
  "delivered_at": "2026-05-28T07:55:01.345Z"
}

account.disconnected

The account is in the disconnected state and cannot act until it is reconnected. This includes an explicit disconnect or deletion, and a connect or reconnect attempt that observes an already-disconnected account without removing it. Where the account was actually removed, its id will 404 on a later read.

  • Source: account_status
  • Subscription: default: subscribed when you omit events
  • Latency: Real time.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.disconnected --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.disconnected"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.disconnected",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.disconnected",
    "status": "disconnected",
    "occurred_at": "2026-05-28T15:00:00.000Z"
  },
  "delivered_at": "2026-05-28T15:00:01.456Z"
}

account.error

Account synchronization encountered an error (not a credentials issue; needs investigation).

  • Source: account_status
  • Subscription: default: subscribed when you omit events
  • Latency: Real time.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.error --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.error"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.error",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.error",
    "status": "reconnect_needed",
    "occurred_at": "2026-05-28T12:00:00.000Z"
  },
  "delivered_at": "2026-05-28T12:00:01.890Z"
}

account.paused

Account synchronization was stopped or paused externally. No longer pushed in real time; detect via an on-demand account read.

  • Source: account_status
  • Subscription: default: subscribed when you omit events
  • Latency: Not delivered any more: subscribing succeeds and nothing arrives. Read the account instead.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.paused --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.paused"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.paused",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.paused",
    "status": "reconnect_needed",
    "occurred_at": "2026-05-28T13:00:00.000Z"
  },
  "delivered_at": "2026-05-28T13:00:01.012Z"
}

account.connecting

An account link is in progress. Transient and high-frequency; opt in explicitly. The account is not yet active. No longer pushed in real time; v2 has no equivalent event.

  • Source: account_status
  • Subscription: default: subscribed when you omit events
  • Latency: Not delivered any more: subscribing succeeds and nothing arrives. Read the account instead.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.connecting --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.connecting"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.connecting",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.connecting",
    "status": "connecting",
    "occurred_at": "2026-05-28T07:59:30.000Z"
  },
  "delivered_at": "2026-05-28T07:59:31.678Z"
}

account.permission_revoked

A LinkedIn-side scope/permission the account relies on was withdrawn. No longer pushed in real time; detect via an on-demand account read.

  • Source: account_status
  • Subscription: default: subscribed when you omit events
  • Latency: Not delivered any more: subscribing succeeds and nothing arrives. Read the account instead.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.permission_revoked --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.permission_revoked"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.permission_revoked",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.permission_revoked",
    "status": "restricted",
    "occurred_at": "2026-05-28T14:00:00.000Z"
  },
  "delivered_at": "2026-05-28T14:00:01.234Z"
}

account.initial_sync.running

The initial history backfill for a newly connected account has started (informational; bracket-open).

  • Source: account_status
  • Subscription: opt-in: name it in events
  • Latency: Real time.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.initial_sync.running --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.initial_sync.running"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.initial_sync.running",
  "data": {
    "status": "active",
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.initial_sync.running",
    "occurred_at": "2026-05-28T08:00:00.000Z"
  },
  "delivered_at": "2026-05-28T08:00:01.000Z"
}

account.initial_sync.completed

The initial history backfill completed; full LinkedIn history is now queryable.

  • Source: account_status
  • Subscription: opt-in: name it in events
  • Latency: Real time.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.initial_sync.completed --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.initial_sync.completed"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.initial_sync.completed",
  "data": {
    "status": "active",
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.initial_sync.completed",
    "occurred_at": "2026-05-28T08:12:00.000Z"
  },
  "delivered_at": "2026-05-28T08:12:01.000Z"
}

account.initial_sync.failed

The initial history backfill failed. The delivered payload carries a neutral reason; one of internal, proxy, or provider.

  • Source: account_status
  • Subscription: opt-in: name it in events
  • Latency: Real time.

Subscribe with the CLI:

curviate webhook create --source account_status --events account.initial_sync.failed --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "account_status",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "account.initial_sync.failed"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "account.initial_sync.failed",
  "data": {
    "status": "active",
    "reason": "provider",
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "account.initial_sync.failed",
    "occurred_at": "2026-05-28T08:12:00.000Z"
  },
  "delivered_at": "2026-05-28T08:12:01.000Z"
}

Post events

post.published

A scheduled post was published. The payload carries draft_id, post_id (null when the platform returned none), account_id, scheduled_at, published_at, and safety_warning when a warn-posture safety limit was breached. Never carries the post text or media.

  • Source: post
  • Subscription: default: subscribed when you omit events
  • Latency: Real time: when the scheduled post fires.

Subscribe with the CLI:

curviate webhook create --source post --events post.published --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "post",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "post.published"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "post.published",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "post.published",
    "draft_id": "drf_YOUR_DRAFT_ID",
    "post_id": "post_YOUR_POST_ID",
    "scheduled_at": "2026-10-07T08:00:00.000Z",
    "published_at": "2026-10-07T08:00:04.000Z"
  },
  "delivered_at": "2026-10-07T08:00:05.100Z"
}

post.publish_failed

A scheduled post could not be published. The payload carries draft_id, account_id, scheduled_at, failure_code, and failure_message. Never carries the post text or media. A failure_code of outcome_unknown means the publish call timed out or ended without a usable answer after the request was sent; the post may be live, so check the account's posts before retrying.

  • Source: post
  • Subscription: default: subscribed when you omit events
  • Latency: Real time: when the scheduled post fires.

Subscribe with the CLI:

curviate webhook create --source post --events post.publish_failed --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "post",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "post.publish_failed"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "post.publish_failed",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "event": "post.publish_failed",
    "draft_id": "drf_YOUR_DRAFT_ID",
    "scheduled_at": "2026-10-07T08:00:00.000Z",
    "failure_code": "rate_limited",
    "failure_message": "The account hit a platform rate limit."
  },
  "delivered_at": "2026-10-07T08:00:02.400Z"
}

Motion events

motion.status_changed

A Motion changed status. Carries motion_id, motion_name, from, to, reason, reason_message and changed_by_user_id (null when Curviate made the change), with account_id null. Delivered once per webhook whose accounts overlap the Motion's sending accounts.

Carries no contact, and account_id is always null: it goes once to each webhook whose accounts overlap the Motion's sending accounts.

  • Source: motion
  • Subscription: default: subscribed when you omit events
  • Latency: Real time: within seconds of the Motion's own step or transition.

Subscribe with the CLI:

curviate webhook create --source motion --events motion.status_changed --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "motion",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "motion.status_changed"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "motion.status_changed",
  "data": {
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "account_id": null,
    "from": "active",
    "to": "paused",
    "reason": "paused_by_user",
    "reason_message": null,
    "changed_by_user_id": "usr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "event": "motion.status_changed",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

enrollment.started

A Contact's Enrollment started. Carries account_id, account_name, account_profile_url, motion_id, motion_name, enrollment_id and contact (the Contact record, null once deleted), sequence_version and relationship_at_enrollment.

  • Source: motion
  • Subscription: default: subscribed when you omit events
  • Latency: Real time: within seconds of the Motion's own step or transition.

Subscribe with the CLI:

curviate webhook create --source motion --events enrollment.started --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "motion",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "enrollment.started"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "enrollment.started",
  "data": {
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "account_name": "Sam Rivera",
    "account_profile_url": null,
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "sequence_version": 3,
    "relationship_at_enrollment": "not_connected",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "event": "enrollment.started",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

enrollment.accepted

The Enrollment's invitation was accepted, once per Enrollment. Carries account_id, account_name, account_profile_url, motion_id, motion_name, enrollment_id and contact (the Contact record, null once deleted) and the invitation step's step_id, action and variant_id. connection.accepted (source user) fires for the same acceptance.

Fires once per Enrollment when its invitation is accepted, whatever the Enrollment's status. connection.accepted (source user) fires for the same acceptance; listen to either.

  • Source: motion
  • Subscription: default: subscribed when you omit events
  • Latency: About 2 hours after the acceptance, like connection.accepted (acceptances are polled).

Subscribe with the CLI:

curviate webhook create --source motion --events enrollment.accepted --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "motion",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "enrollment.accepted"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "enrollment.accepted",
  "data": {
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "account_name": "Sam Rivera",
    "account_profile_url": null,
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "step_id": "invite",
    "action": "invite.send",
    "variant_id": null,
    "step_event": "invite_sent",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "event": "enrollment.accepted",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

enrollment.replied

The Contact replied for the first time on this Enrollment, once per Enrollment. Carries account_id, account_name, account_profile_url, motion_id, motion_name, enrollment_id and contact (the Contact record, null once deleted), the latest messaging step's step_id, action and variant_id, the reply's chat_id and message_id, and reply_text (the text the Contact sent).

Fires once per Enrollment, on the Contact's first reply, whatever stop_on_engagement says; when the Motion stops on engagement it arrives before enrollment.finished. reply_text is the text the Contact sent. The text Curviate sent is never in a payload: step_id and variant_id say which copy went out. Needs inbox access to the account at delivery.

  • Source: motion
  • Subscription: default: subscribed when you omit events
  • Latency: Real time: seconds after the reply reaches the account.

Subscribe with the CLI:

curviate webhook create --source motion --events enrollment.replied --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "motion",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "enrollment.replied"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "enrollment.replied",
  "data": {
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "account_name": "Sam Rivera",
    "account_profile_url": null,
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "step_id": "dm1",
    "action": "message.send",
    "variant_id": "a",
    "step_event": null,
    "chat_id": "chat_YOUR_CHAT_ID",
    "message_id": "msg_YOUR_REPLY_ID",
    "reply_text": "Thanks, happy to talk next week.",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "event": "enrollment.replied",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

enrollment.seen

A Motion message's read receipt arrived, once per message. Opt-in. Carries account_id, account_name, account_profile_url, motion_id, motion_name, enrollment_id and contact (the Contact record, null once deleted), the message step's step_id, action and variant_id, chat_id and seen_recorded_at (when the receipt arrived, not when it was read).

Fires once per Motion message whose read receipt arrives. seen_recorded_at is when the receipt arrived, not when the person read it.

  • Source: motion
  • Subscription: opt-in: name it in events
  • Latency: When the read receipt reaches the account; never for recipients who turned receipts off.

Subscribe with the CLI:

curviate webhook create --source motion --events enrollment.seen --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "motion",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "enrollment.seen"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "enrollment.seen",
  "data": {
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "account_name": "Sam Rivera",
    "account_profile_url": null,
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "step_id": "dm1",
    "action": "message.send",
    "variant_id": "a",
    "step_event": null,
    "chat_id": "chat_YOUR_CHAT_ID",
    "message_id": "msg_YOUR_MESSAGE_ID",
    "seen_recorded_at": "2026-10-21T10:42:00.000Z",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "event": "enrollment.seen",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

enrollment.reassigned

An Enrollment moved to another sending account. Opt-in. Carries account_id, account_name, account_profile_url, motion_id, motion_name, enrollment_id and contact (the Contact record, null once deleted) of the new account, from_account_id, to_account_id and changed_by_user_id.

Fires when someone moves an Enrollment to another sending account. The account keys name the new account.

  • Source: motion
  • Subscription: opt-in: name it in events
  • Latency: Real time: within seconds of the Motion's own step or transition.

Subscribe with the CLI:

curviate webhook create --source motion --events enrollment.reassigned --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "motion",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "enrollment.reassigned"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "enrollment.reassigned",
  "data": {
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "account_name": "Sam Rivera",
    "account_profile_url": null,
    "account_id": "acc_NEW_ACCOUNT_ID",
    "from_account_id": "acc_YOUR_ACCOUNT_ID",
    "to_account_id": "acc_NEW_ACCOUNT_ID",
    "changed_by_user_id": "usr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "event": "enrollment.reassigned",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

enrollment.skipped

A Contact was not enrolled. Carries account_id (null when no account was assigned yet; then delivered once per webhook whose accounts overlap the Motion's), account_name, account_profile_url, motion_id, motion_name, enrollment_id, reason, reason_message, detail and contact.

  • Source: motion
  • Subscription: default: subscribed when you omit events
  • Latency: Real time: within seconds of the Motion's own step or transition.

Subscribe with the CLI:

curviate webhook create --source motion --events enrollment.skipped --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "motion",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "enrollment.skipped"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "enrollment.skipped",
  "data": {
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "account_name": "Sam Rivera",
    "account_profile_url": null,
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "reason": "in_exclusion_list",
    "reason_message": "The Contact is on one of the Motion's exclusion lists, so it was not enrolled.",
    "detail": null,
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "event": "enrollment.skipped",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

enrollment.finished

An Enrollment ended. Carries account_id, account_name, account_profile_url, motion_id, motion_name, enrollment_id and contact (the Contact record, null once deleted), reason (for example completed, stopped, removed, replied, messaged_manually, contact_deleted), reason_message, replied and last_step_id.

  • Source: motion
  • Subscription: default: subscribed when you omit events
  • Latency: Real time: within seconds of the Motion's own step or transition.

Subscribe with the CLI:

curviate webhook create --source motion --events enrollment.finished --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "motion",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "enrollment.finished"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "enrollment.finished",
  "data": {
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "account_name": "Sam Rivera",
    "account_profile_url": null,
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "reason": "replied",
    "reason_message": "The person replied and the Motion stops on engagement, so the Enrollment ended.",
    "replied": true,
    "last_step_id": "wait_reply",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "event": "enrollment.finished",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

step.executed

A Step ran. Opt-in because of its volume. Carries account_id, account_name, account_profile_url, motion_id, motion_name, enrollment_id and contact (the Contact record, null once deleted), step_id, action, variant_id, used_fallback, step_event (the step's custom event name or null), and chat_id and message_id for a message, or post_url for a post action. Never the text that was sent.

  • Source: motion
  • Subscription: opt-in: name it in events
  • Latency: Real time: within seconds of the Motion's own step or transition.

Subscribe with the CLI:

curviate webhook create --source motion --events step.executed --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "motion",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "step.executed"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "step.executed",
  "data": {
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "account_name": "Sam Rivera",
    "account_profile_url": null,
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "step_id": "dm1",
    "action": "message.send",
    "variant_id": "a",
    "step_event": "first_message_sent",
    "used_fallback": false,
    "chat_id": "chat_YOUR_CHAT_ID",
    "message_id": "msg_YOUR_MESSAGE_ID",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "event": "step.executed",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

A post action (post.react, post.comment) carries post_url instead of chat_id and message_id:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "step.executed",
  "data": {
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "account_name": "Sam Rivera",
    "account_profile_url": null,
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "step_id": "react",
    "action": "post.react",
    "variant_id": null,
    "step_event": null,
    "used_fallback": false,
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "event": "step.executed",
    "occurred_at": "2026-10-21T10:41:12.000Z",
    "post_url": "https://www.linkedin.com/feed/update/urn:li:activity:7254000000000000000"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

step.failed

A Step was skipped or failed. Carries account_id, account_name, account_profile_url, motion_id, motion_name, enrollment_id and contact (the Contact record, null once deleted), step_id, action, variant_id, step_event, outcome (skipped or failed), reason and reason_message.

  • Source: motion
  • Subscription: default: subscribed when you omit events
  • Latency: Real time: within seconds of the Motion's own step or transition.

Subscribe with the CLI:

curviate webhook create --source motion --events step.failed --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "motion",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "step.failed"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "step.failed",
  "data": {
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "account_name": "Sam Rivera",
    "account_profile_url": null,
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "step_id": "invite",
    "action": "invite.send",
    "variant_id": null,
    "step_event": "invite_sent",
    "outcome": "skipped",
    "reason": "already_connected",
    "reason_message": "Already connected to this Account, so no invitation was sent.",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "event": "step.failed",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

motion.custom_event

A step that ran named a custom event (its event key, or a legacy emit step). Carries name, step_id, account_id, account_name, account_profile_url, motion_id, motion_name, enrollment_id and contact (the Contact record, null once deleted). Was motion.signal: a webhook subscribed to motion.signal receives it under that name until 2027-01-19.

Fires once when a step that carries an event ran (a do step that executed, a tag step taken), or when a legacy emit step is reached; never for a skipped or failed step. An event an agent sends to an Enrollment (POST /v1/enrollments/{id}/events) is an input only and fires no webhook. It was called motion.signal: a webhook subscribed to motion.signal keeps receiving it under that name, with the same data, until 2027-01-19.

  • Source: motion
  • Subscription: default: subscribed when you omit events
  • Latency: Real time: within seconds of the Motion's own step or transition.

Subscribe with the CLI:

curviate webhook create --source motion --events motion.custom_event --request-url https://hooks.example.com/curviate

Or with the REST API:

curl -X POST https://api.curviate.com/v1/webhooks \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "motion",
    "request_url": "https://hooks.example.com/curviate",
    "events": [
        "motion.custom_event"
    ]
  }'

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "motion.custom_event",
  "data": {
    "name": "no_reply_7d",
    "motion_id": "mot_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "motion_name": "Q4 founders outreach",
    "enrollment_id": "enr_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
    "account_name": "Sam Rivera",
    "account_profile_url": null,
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "step_id": "no_reply",
    "action": null,
    "variant_id": null,
    "step_event": "no_reply_7d",
    "contact": {
      "id": "con_01J8Z3K9P0Q1R2S3T4V5W6X7Y8",
      "linkedin_url": "https://www.linkedin.com/in/alexjordan",
      "full_name": "Alex Jordan",
      "first_name": "Alex",
      "last_name": "Jordan",
      "headline": "Head of Operations at Northwind",
      "job_title": "Head of Operations",
      "company": "Northwind",
      "email": "alex@northwind.example",
      "location": "Berlin, Germany",
      "about": "Operations leader in logistics.",
      "extra": {
        "crm_id": "0035e00000AbCdE"
      },
      "tags": [
        "in-conversation"
      ]
    },
    "event": "motion.custom_event",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

Recruiter events

recruiter.applicant.added

A candidate or applicant was added to a hiring project pipeline.

  • Source: recruiter
  • Subscription: not subscribable yet (a webhook with this source is refused with 400 INVALID_REQUEST)
  • Latency: Not delivered yet: listed in the catalogue for completeness.

Check it in the catalogue with the CLI:

curviate webhook events --json

Or with the REST API:

curl https://api.curviate.com/v1/webhooks/events \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY"

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "recruiter.applicant.added",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "project_id": "prj_YOUR_PROJECT_ID",
    "candidate_id": "cnd_YOUR_CANDIDATE_ID",
    "event": "recruiter.applicant.added",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

recruiter.project.candidate_status_changed

A candidate's status in a hiring project pipeline changed (e.g. rejected).

  • Source: recruiter
  • Subscription: not subscribable yet (a webhook with this source is refused with 400 INVALID_REQUEST)
  • Latency: Not delivered yet: listed in the catalogue for completeness.

Check it in the catalogue with the CLI:

curviate webhook events --json

Or with the REST API:

curl https://api.curviate.com/v1/webhooks/events \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY"

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "recruiter.project.candidate_status_changed",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "project_id": "prj_YOUR_PROJECT_ID",
    "candidate_id": "cnd_YOUR_CANDIDATE_ID",
    "status": "rejected",
    "event": "recruiter.project.candidate_status_changed",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}

Sales Navigator events

sales_nav.inmail.received

An InMail arrived on a Sales Navigator seat.

  • Source: sales_nav
  • Subscription: not subscribable yet (a webhook with this source is refused with 400 INVALID_REQUEST)
  • Latency: Not delivered yet: listed in the catalogue for completeness.

Check it in the catalogue with the CLI:

curviate webhook events --json

Or with the REST API:

curl https://api.curviate.com/v1/webhooks/events \
  -H "Authorization: Bearer cvt_live_YOUR_API_KEY"

Example delivery:

{
  "id": "wdl_YOUR_DELIVERY_ID",
  "webhook_id": "wh_YOUR_WEBHOOK_ID",
  "event": "sales_nav.inmail.received",
  "data": {
    "account_id": "acc_YOUR_ACCOUNT_ID",
    "chat_id": "chat_YOUR_CHAT_ID",
    "message_id": "msg_YOUR_MESSAGE_ID",
    "text": "Hello from Sales Navigator.",
    "event": "sales_nav.inmail.received",
    "occurred_at": "2026-10-21T10:41:12.000Z"
  },
  "delivered_at": "2026-10-21T10:41:13.020Z"
}