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

# email.replied

> Fires alongside email.received for every incoming message in a thread that is a conversation.

Fires together with [`email.received`](/dev/webhooks/events/email-received), for
every message from outside the workspace that arrives in a connected mailbox in a
thread that is a conversation.

<Warning>
  **Despite the name, this is not limited to replies.** The first message of a
  new thread fires it too, and the payload is identical to `email.received`'s,
  `messageId` included. A subscription to both events handles every incoming
  message twice.
</Warning>

## Payload

```json theme={null}
{
  "id": "whd_9Lm3qT7vR",
  "event": "email.replied",
  "createdAt": "2026-09-11T14:02:37.121Z",
  "data": {
    "messageId": "18f2d3e7a9b1c4f6",
    "threadId": "18f2d1c04b7e9a23",
    "channelId": "chan_4Kp8wN",
    "conversationId": "conv_3Hq9rT",
    "from": "ada@ravennafoods.com",
    "fromName": "Ada Lovell",
    "to": ["sales@acme.com"],
    "cc": [],
    "subject": "Re: Pricing for the Ravenna rollout",
    "receivedAt": "2026-09-11T14:02:31.000Z",
    "folder": "INBOX"
  }
}
```

<ResponseField name="messageId" type="string" required>
  The mail provider's id for the message. The same value the matching
  `email.received` carries. Always present.
</ResponseField>

<ResponseField name="threadId" type="string">
  The mail provider's id for the thread.
</ResponseField>

<ResponseField name="channelId" type="string">
  The connected mailbox the message arrived in.
</ResponseField>

<ResponseField name="conversationId" type="string">
  The conversation the thread belongs to. Present on every delivery.
</ResponseField>

<ResponseField name="from" type="string">
  The sender's address.
</ResponseField>

<ResponseField name="fromName" type="string">
  The sender's display name. **Omitted** when the message carries none.
</ResponseField>

<ResponseField name="to" type="string[]">
  The addresses the message was sent to.
</ResponseField>

<ResponseField name="cc" type="string[]">
  The addresses copied. An empty array when nobody was copied.
</ResponseField>

<ResponseField name="subject" type="string">
  The subject line. An empty string when the message has none.
</ResponseField>

<ResponseField name="receivedAt" type="string">
  The message's date, as an ISO 8601 timestamp.
</ResponseField>

<ResponseField name="folder" type="string">
  The provider's id for the first folder or label the message is filed under.
  **Omitted** when the provider lists none.
</ResponseField>

<ResponseField name="recordIds" type="string[]">
  Records the message is linked to. Mail from a connected mailbox does not carry
  them today, so this is omitted.
</ResponseField>

## When it fires

Exactly when `email.received` does: the sender is outside the workspace, the
message is not filed as spam, and the thread is a conversation. The
[`email.received`](/dev/webhooks/events/email-received) page lists what sends
nothing.

## Telling a reply from a first message

The payload does not say which one a message is. To act only on replies, keep
the `conversationId` of every `email.received` or `email.replied` and every
[`email.sent`](/dev/webhooks/events/email-sent) you handle: a message whose
conversation you have already seen continues a thread you know about. A
conversation that began before your endpoint subscribed reads as new the first
time it appears.

## Example

```ts theme={null}
custral.on("email.replied", async (event) => {
  const {conversationId, from, subject} = event.data;

  // Every incoming message fires this, the first one in a thread included.
  const key = `conversation:${conversationId}`;
  const seenBefore = await store.has(key);
  await store.add(key);
  if (!seenBefore) return;

  await followUps.markAnswered({conversationId, from, subject});
});
```


## Related topics

- [Email](/dev/webhooks/events/email.md)
- [email.received](/dev/webhooks/events/email-received.md)
- [Webhooks](/dev/webhooks/overview.md)
- [Event catalog](/dev/webhooks/events/overview.md)
- [Workflow Triggers](/automation/workflows/triggers.md)
