> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reply.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook event payloads

> Example payloads for every webhook event.

When a webhook subscription fires, Reply sends a JSON payload to your configured URL.

This page documents the payload for each supported event type. The examples match the structure of real webhook deliveries.

## Event envelope

Every webhook delivery includes the same top-level event envelope:

```json theme={null}
{
  "event": {
    "date": "2026-04-21T09:30:00.000Z",
    "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1",
    "type": "email_replied",
    "user_id": 1234,
    "team_id": 100,
    "subscription_id": 42
  },
  // event-specific fields follow, flat at the top level
}
```

| Field                   | Type         | Notes                                                                   |
| ----------------------- | ------------ | ----------------------------------------------------------------------- |
| `event.date`            | ISO-8601 UTC | Time the event occurred in Reply.                                       |
| `event.id`              | UUID         | Unique event identifier. Use it for idempotency when processing events. |
| `event.type`            | string       | Event type. Matches the subscription's `eventType`.                     |
| `event.user_id`         | int          | ID of the Reply user associated with the subscription.                  |
| `event.team_id`         | int          | ID of the team associated with the event.                               |
| `event.subscription_id` | int          | ID of the subscription that triggered the event.                        |

## Shared conventions

* Property names use `snake_case`, for example `event_type`, `sequence_fields`, and `reply_message_url`.
* Enum values are PascalCase strings, for example `"Personal"`, `"EmailDetected"`, and `"Hard"`.
* Timestamps use ISO-8601 UTC format with millisecond precision.
* Events associated with a contact include a `contact_fields` object. Use `contact_fields.id` as the stable contact identifier.
* If the subscription was created with `includeProspectCustomFields: true`, a `contact_custom_fields` object is also included.
* Events associated with a sequence include a `sequence_fields` object.
* If `SequenceId` is `0`, the event is not associated with a sequence and `sequence_fields` may be empty or omitted.
* Email-related events respect the subscription's `includeEmailUrl` and `includeEmailText` settings. Disabled fields are omitted from the payload.

## Reusable blocks

The following objects appear in multiple event payloads.

### `contact_fields`

```json theme={null}
{
  "id": 12345,
  "email": "prospect@example.com",
  "first_name": "Test",
  "last_name": "Prospect",
  "full_name": "Test Prospect",
  "title": "Test Title",
  "company": "Test Company",
  "linkedin_profile_url": "https://linkedin.com/in/test",
  "city": "Test City",
  "state": "Test State",
  "country": "Test Country",
  "time_zone_id": "America/Los_Angeles",
  "phone": "+1234567890",
  "domain": "example.com",
  "company_size": "51-200 employees",
  "industry": "Software",
  "linkedin_sales_navigator": "https://www.linkedin.com/sales/people/test",
  "linkedin_recruiter": "https://www.linkedin.com/recruiter/people/test"
}
```

### `contact_custom_fields`

Only included when the subscription was created with `payloadConfig.includeProspectCustomFields: true`.

Keys match the custom field names configured on the contact.

```json theme={null}
{
  "Custom Field 1": "Custom Value 1"
}
```

### `sequence_fields`

```json theme={null}
{
  "id": 200,
  "name": "Test Sequence",
  "step_number": 1
}
```

***

## Event reference

### `email_replied`

**When it fires:** Once per recorded email reply — when Reply detects an incoming reply to a sequence email, or a direct reply that is not tied to a sequence.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "email_replied", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "email_account_id": 1,
  "sent_email_id": 999,
  "reply_date": "2026-04-21T09:30:00.000Z",
  "reply_message_id": "test-reply-msg-id",
  "email_from": "account@example.com",
  "reply_message_url": "https://example.com/test-email-blob",
  "email_text": "<html>…</html>",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field notes

* `email_account_id`
  * The Reply email account that received the reply.
* `sent_email_id`
  * The sequence email that was replied to. `null` for direct replies that are not tied to a sequence email.
* `email_from`
  * Present when the replying email account is known.
* `reply_message_url`
  * Included when `includeEmailUrl: true`.
* `email_text`
  * Included when `includeEmailText: true`.
* `sequence_fields`
  * Omitted for direct replies that have no sequence context.
* `contact_custom_fields`
  * Included when `includeProspectCustomFields: true`.
* `sequence_fields` includes `id`, `name`, and `step_number`.

### `reply_categorized`

**When it fires:** An email reply is categorized automatically by Reply or manually by a user.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "reply_categorized", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "sent_email_id": 999,
  "reply_date": "2026-04-21T09:30:00.000Z",
  "reply_message_id": "test-reply-msg-id",
  "reply_inbox_category_name": "Interested",
  "reply_message_url": "https://example.com/test-email-blob",
  "email_text": "<html>…</html>",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field notes

* `reply_inbox_category_name`
  * Human-readable category name.
  * Built-in values include:
    * `"No categories"`
    * `"Interested"`
    * `"Not interested"`
    * `"Do not contact"`
    * `"Not now"`
    * `"Forwarded"`
    * `"Meeting intent"`
  * Teams can create custom categories. Treat this field as a free-form string.
* `reply_message_id`
  * May be `null` for older replies where the original message ID was not captured.
* `reply_date`
  * May be `null` for older replies where the original timestamp is unavailable.
* `reply_message_url`
  * Included when `includeEmailUrl: true` and a stored reply is available.
* `email_text`
  * Included when `includeEmailText: true` and the reply body can be extracted.
* `contact_custom_fields`
  * Included when `includeProspectCustomFields: true`.
* `sequence_fields` includes `id`, `name`, and `step_number`. Omitted if the reply is not associated with a sequence.

### `email_sent`

**When:** Reply sends an email from a sequence step.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "email_sent", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "email_account_id": 1,
  "sent_email_id": 999,
  "sent_email_message_id": "test-message-id",
  "sent_email_date": "2026-04-21T09:30:00.000Z",
  "sent_message_url": "https://example.com/test-email-blob",
  "email_text": "<html>…</html>",
  "email_from": "account@example.com",
  "sent_email_variant": "A",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field notes

* `sent_email_variant` identifies the A/B variant that was sent. Omitted when the step has only one variant.
* `sent_message_url` is included when `includeEmailUrl` is enabled and the message blob is available.
* `email_text` is included when `includeEmailText` is enabled and the message body can be parsed.
* `contact_custom_fields` is included when `includeProspectCustomFields` is enabled.
* `sequence_fields` includes `id`, `name`, and `step_number`.

### `email_opened`

**When:** A recipient opens a tracked email.

Opens from IP addresses in the user's exclusion list are ignored.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "email_opened", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "email_account_id": 1,
  "sent_email_id": 999,
  "sent_email_message_id": "test-message-id",
  "email_open_date": "2026-04-21T09:30:00.000Z",
  "opens_count": 1,
  "email_from": "account@example.com",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field notes

* `opens_count` is the total number of opens for the email. It increases each time the email is opened.
* `contact_custom_fields` is included when `includeProspectCustomFields` is enabled.
* `sequence_fields` includes `id`, `name`, and `step_number`.

### `email_link_clicked`

**When:** A recipient clicks a tracked link in an email.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "email_link_clicked", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "email_link_url": "https://example.com/test-link",
  "email_from": "account@example.com",
  "contact_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### `email_bounced`

**When:** A sent email bounces or is rejected by the recipient's mail server.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "email_bounced", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "email_account_id": 1,
  "sent_email_id": 999,
  "bounce_date": "2026-04-21T09:30:00.000Z",
  "bounce_type": "Hard",
  "bounce_message_id": "test-bounce-id",
  "sent_message_url": "https://example.com/test-email-blob",
  "email_text": "<html>…</html>",
  "email_from": "account@example.com",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field notes

* `bounce_type` can be:
  * `Unknown`
  * `Soft`
  * `Hard`
  * `GmailApiLimitWarning`
  * `Office365LimitWarning`
  * `MailboxFull`
  * `AuthenticationFailure`
  * `SpamRejection`
  * `PolicyViolation`
* `sent_message_url` is included when `includeEmailUrl` is enabled and the message blob is available.
* `email_text` is included when `includeEmailText` is enabled and the message body can be parsed.
* `contact_custom_fields` is included when `includeProspectCustomFields` is enabled.
* `sequence_fields` includes `id`, `name`, and `step_number`.

### `email_auto_reply`

**When:** Reply identifies an incoming message as an auto-reply or out-of-office message.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "email_auto_reply", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "email_account_id": 1,
  "sent_email_id": 999,
  "reply_date": "2026-04-21T09:30:00.000Z",
  "reply_message_id": "test-reply-id",
  "reply_subject": "Out of Office: Test Subject",
  "reply_type": "AutoReply",
  "reply_message_url": "https://example.com/test-email-blob",
  "email_text": "<html>…</html>",
  "email_from": "account@example.com",
  "user_name": "Test User",
  "user_email": "user@example.com",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field notes

* `reply_type` is:
  * `AutoReply` for automatic responder messages
  * `OutOfOffice` for out-of-office messages
* `email_account_id` may be `null`.
* `email_from` is included only when the email account is known.
* `reply_message_url` is included when `includeEmailUrl` is enabled.
* `email_text` is included when `includeEmailText` is enabled and the message body can be parsed.
* `user_name` and `user_email` identify the Reply user who owns the sequence when the event is generated.
* `contact_custom_fields` is included when `includeProspectCustomFields` is enabled.
* `sequence_fields` includes `id`, `name`, and `step_number`.

### `email_account_connection_lost`

**When:** A connected mailbox can no longer authenticate, such as after an OAuth revocation or password change.

This is an account-level event and does not include contact or sequence information.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "email_account_connection_lost", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "email_account_id": 1,
  "email_account_address": "account@example.com"
}
```

### `email_account_error`

**When:** A connected mailbox reports an IMAP or SMTP error, such as an authentication failure, send failure, health check failure, reputation issue, or sending limit.

The event is generated each time the underlying error changes to a non-empty value. Clearing the error does not generate an event.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "email_account_error", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "email_account_id": 1,
  "email_account_error": "Sending: SMTP authentication failed",
  "email_account_address": "account@example.com"
}
```

### Field notes

* `email_account_error` is a free-form error message.
* Error messages always begin with either:
  * `Receiving:` for IMAP-related errors
  * `Sending:` for SMTP-related errors
* `email_account_address` may be omitted if the email account can no longer be loaded.

### `contact_finished`

**When:** A contact's participation in a sequence ends.

This can happen when the contact completes the sequence, reaches a terminal status, or is manually finished.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "contact_finished", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "finish_reason": "Replied",
  "finished_date": "2026-04-21T09:30:00.000Z",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence" }
}
```

### Field notes

`finish_reason` can be one of:

| Value                | Description                                          |
| :------------------- | :--------------------------------------------------- |
| `Replied`            | The contact replied to a sequence email.             |
| `Bounced`            | An email bounced and the contact was removed.        |
| `Manual`             | A user manually finished the contact.                |
| `FinishedAfterXdays` | The contact reached the sequence's maximum duration. |
| `None`               | No specific reason was recorded.                     |
| `Called`             | The contact was finished after a phone call.         |
| `OptOut`             | The contact opted out.                               |
| `MeetingBooked`      | A meeting was booked with the contact.               |
| `ForbiddenStep`      | The next step was blocked by content guardrails.     |

Additional fields:

* `contact_custom_fields` is included when `includeProspectCustomFields` is enabled.
* `sequence_fields` includes `id` and `name`. The whole sequence has ended, so this event is not tied to a single step and `step_number` is not included.

### `contact_opted_out`

**When:** A contact opts out of future outreach.

This event is generated when a contact:

* Clicks an unsubscribe link
* Is manually opted out by a user
* Is marked as **Do Not Contact**

All three scenarios generate the same event and payload. The event does not indicate which action caused the opt-out.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "contact_opted_out", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "opt_out_date": "2026-04-21T09:30:00.000Z",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field otes

* `contact_custom_fields` is included when `includeProspectCustomFields` is enabled.
* `sequence_fields` includes `id`, `name`, and `step_number`.

### `contact_called`

**When:** A call with a contact reaches a final state, such as answered, missed, busy, timed out, or logged manually.

The event is generated after call details have been collected and are ready to deliver.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "contact_called", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "from_number": "+1234567890",
  "duration": 60,
  "disposition": "Answered",
  "resolution": "Positive",
  "notes": "Spoke with prospect, scheduled a follow-up.",
  "recording_url": "https://example.com/test-call-recording",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field notes

* `from_number` is the phone number used to place the call.
* `duration` is the call length in seconds. It is `0` for manually logged calls and calls that never connected.
* `disposition` can be:
  * `Answered`
  * `LoggedManually`
  * `NoAnswer`
  * `Busy`
  * `Fail`
* `resolution` can be one of Reply's built-in values (`Positive`, `ToCall`, `Negative`) or a custom resolution defined by the team. Treat this field as a free-form string.
* `notes` contains any notes entered by the user. It is `null` when no notes were saved.
* `recording_url` contains a recording URL when a recording is available. It is `null` when the call was not recorded.
* `contact_custom_fields` is included when `includeProspectCustomFields` is enabled.
* `sequence_fields` includes `id`, `name`, and `step_number`. `step_number` is `0` for calls not tied to a sequence step.

### `linkedin_connection_request_sent`

**When:** Reply sends a LinkedIn connection request as part of a sequence step.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "linkedin_connection_request_sent", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "sender_linkedin_account_id": 50,
  "initial_message": "Test connection request",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence" }
}
```

### Field notes

* `sender_linkedin_account_id` is the Reply LinkedIn account ID. It is not a LinkedIn public identifier.
* `initial_message` contains the connection request note that was sent. It may be `null` if no note was included.
* `contact_custom_fields` is included when `includeProspectCustomFields` is enabled.
* `sequence_fields` includes `id` and `name`. `step_number` is not included for this event.

### `linkedin_connection_request_accepted`

**When:** A LinkedIn connection request previously sent through Reply is accepted.

Only connection requests sent through Reply generate this event.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "linkedin_connection_request_accepted", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "sender_linkedin_account_id": 50,
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field notes

* `contact_custom_fields` is included when `includeProspectCustomFields` is enabled.
* `sequence_fields` includes `id`, `name`, and `step_number`.

### `linkedin_message_sent`

**When:** Reply sends a LinkedIn message or InMail.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "linkedin_message_sent", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "sender_linkedin_account_id": 50,
  "initial_message": "Test message",
  "is_inmail": false,
  "is_voice_attached": false,
  "linkedin_message_id": "test-msg-id",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field notes

* `linkedin_message_id` is a Reply-generated message identifier. It is not a LinkedIn message ID.
* `is_inmail` is `true` for InMail messages and `false` for regular LinkedIn messages.
* `is_voice_attached` is `true` when a voice attachment was included.
* `contact_custom_fields` is included when `includeProspectCustomFields` is enabled.
* `sequence_fields` includes `id`, `name`, and `step_number`.

### `linkedin_message_replied`

**When:** A contact replies to a LinkedIn conversation associated with a sequence contact.

Only replies linked to known contacts in Reply generate this event.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "linkedin_message_replied", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "sender_linkedin_account_id": 50,
  "linkedin_message_id": "01234567-89ab-cdef-0123-456789abcdef",
  "linkedin_message": "Test reply",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field notes

* `linkedin_message_id` is a Reply-generated identifier. It is not a LinkedIn message ID.
* `linkedin_message` contains the reply text.
* `contact_custom_fields` is included when `includeProspectCustomFields` is enabled.
* `sequence_fields.name` and `sequence_fields.step_number` are always included.
* `sequence_fields.id` is included only when the contact is currently associated with a sequence.

### `linkedin_reply_categorized`

**When:** Reply assigns a category to a LinkedIn conversation.

A separate event is generated for each affected conversation.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "linkedin_reply_categorized", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "linkedin_thread_id": 1,
  "reply_inbox_category_name": "Interested",
  "last_reply_date": "2026-04-21T09:30:00.000Z",
  "linkedin_message": "Test reply",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field notes

* `reply_inbox_category_name` can be one of:
  * `No categories`
  * `Interested`
  * `Not interested`
  * `Do not contact`
  * `Not now`
  * `Forwarded`
  * `Meeting intent`
* LinkedIn categories do not support custom category names.
* `last_reply_date` is included when available.
* `contact_custom_fields` is included when `includeProspectCustomFields` is enabled.
* `linkedin_message` contains the raw reply text from the contact. It is included only when `includeLinkedInMessageText` is enabled.
* `sequence_fields` includes `id`, `name`, and `step_number` when the conversation is associated with a sequence; it is empty when it is not.

### `autopilot_stopped`

**When:** An evergreen sequence's autopilot is disabled.

This event is generated only for the reasons listed in `autopilot_error_message`.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "autopilot_stopped", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "autopilot_error_message": "the active contacts limit has been reached",
  "user_name": "Test User",
  "user_email": "user@example.com",
  "sequence_owner_name": "Test Owner",
  "sequence_owner_email": "owner@example.com",
  "sequence_fields": { "id": 200, "name": "Test Sequence" }
}
```

### Field notes

`autopilot_error_message` is one of:

* `the sequence has been deactivated`
* `the active contacts limit has been reached`
* `there are no more contacts/companies matching the filter criteria`

Additional fields:

* `user_name` and `user_email` identify the user who triggered the deactivation.
* `sequence_owner_name` and `sequence_owner_email` identify the sequence owner.
* Owner fields may be omitted if the corresponding user cannot be resolved.

**Team accounts**

If the user who triggered the deactivation is not the sequence owner, Reply generates two events:

* One for the acting user
* One for the sequence owner

Both events contain the same sequence information and error message.

### `linkedin_account_alerts`

**When:** Reply detects a LinkedIn account issue that requires attention.

Examples include a disconnected Sales Navigator account, exhausted InMail credits, or a connection request limit.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "linkedin_account_alerts", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "linkedin_id": 50,
  "linkedin_name": "Test LinkedIn Account",
  "linkedin_account_alert": "Sales Navigator is disconnected. Please reconnect your LinkedIn account to continue sending InMail steps.",
  "team_name": "Test Workspace",
  "linkedin_owner_name": "Test User",
  "linkedin_owner_email": "owner@example.com"
}
```

### Field notes

* `linkedin_id` and `linkedin_name` identify the LinkedIn account associated with the alert.
* `linkedin_account_alert` contains a human-readable description of the issue.
* `team_name` may be omitted if the workspace has no name.
* `linkedin_owner_name` and `linkedin_owner_email` may be omitted if the account owner cannot be resolved.

### Alert types

| Alert                                 | Description                               | Re-fire interval          |
| :------------------------------------ | :---------------------------------------- | :------------------------ |
| `SalesNavigatorDisconnected`          | Sales Navigator is disconnected.          | Up to once every 12 hours |
| `InMailCreditsExhausted`              | No InMail credits remain.                 | Up to once every 24 hours |
| `ConnectionRequestWeeklyLimitReached` | Weekly LinkedIn connection limit reached. | Up to once every 24 hours |

### `contact_replied`

**When it fires:** Each time a sequence contact is recorded as **replied** — Reply detects a reply to a sequence email (`reason: "EmailDetected"`), a sequence LinkedIn message (`reason: "LinkedInDetected"`), or a sequence SMS (`reason: "SmsDetected"`), or a user or the API marks the contact as replied (`reason: "StatusSetManually"`).

This is a channel-agnostic **status** signal: subscribe to it once to learn whenever a contact enters the replied state, regardless of channel, instead of combining `email_replied`, `linkedin_message_replied`, and manual actions yourself. It carries who replied, which sequence/step, when, and why — not the message content. For channel-specific detail (message body, mailbox, sender account) subscribe to the matching per-channel webhook and correlate by `reply_message_id`.

```json theme={null}
{
  "event": { "date": "2026-04-21T09:30:00.000Z", "id": "4c1b9e74-5ac3-4b0f-9a60-2a37a9b4a2d1", "type": "contact_replied", "user_id": 1234, "team_id": 100, "subscription_id": 42 },
  "reply_date": "2026-04-21T09:30:00.000Z",
  "reply_message_id": "test-reply-msg-id",
  "reason": "EmailDetected",
  "contact_fields": { "…": "see above" },
  "contact_custom_fields": { "…": "see above" },
  "sequence_fields": { "id": 200, "name": "Test Sequence", "step_number": 1 }
}
```

### Field notes

* `reason`
  * `"EmailDetected"` when Reply detects a reply to a sequence email.
  * `"LinkedInDetected"` when Reply detects a reply to a sequence LinkedIn message.
  * `"SmsDetected"` when Reply detects a reply to a sequence SMS.
  * `"StatusSetManually"` when a user or the API marks the contact as replied.
* `reply_message_id`
  * Correlation key to the matching per-channel webhook (`email_replied` / `linkedin_message_replied`): email reply message id, LinkedIn message id, or SMS provider message id. `null` for manually marked replies, which carry no stored message.
* `contact_fields`
  * The contact who replied. See the shared [`contact_fields`](#contact_fields) block above for the full field list.
* `sequence_fields`
  * Always present; `contact_replied` fires only for contacts in a sequence.
* `contact_custom_fields`
  * Included when `includeProspectCustomFields: true`.

***

## Test webhook deliveries

Once a webhook subscription is configured, you can send a test event to your endpoint:

```text theme={null}
POST /v3/webhooks/{id}/test
```

The test payload matches the event schemas shown on this page and uses predictable placeholder values.
