When a subscription fires, ReplyDocumentation Index
Fetch the complete documentation index at: https://docs.reply.io/llms.txt
Use this file to discover all available pages before exploring further.
POSTs a JSON body to your configured url. This page lists the shape for every event type. It’s a reference you can read without signing up — the samples mirror what a live delivery looks like.
Envelope
Every delivery carries a commonevent envelope at the top level:
| Field | Type | Notes |
|---|---|---|
event.date | ISO-8601 UTC | When the event occurred in Reply. |
event.id | UUID | Unique id for this delivery. Use for idempotency if you persist events. |
event.type | string | Event name — matches the eventType on the subscription (see below). |
event.user_id | int | Reply user id that owns the subscription. |
event.team_id | int | Team id the event belongs to. |
event.subscription_id | int | Subscription id that fired. |
Shared conventions
- Keys are snake_case.
event_type,sequence_fields,reply_message_url. - Enum values are PascalCase strings.
"Personal","EmailDetected","Hard". - Timestamps are ISO-8601 UTC with millisecond precision.
- Contact reference — events tied to a prospect include a nested
contact_fieldsobject. Usecontact_fields.idas the stable reference. Subscriptions created withincludeProspectCustomFields: truealso getcontact_custom_fieldsalongside it. - Sequence reference — events tied to a sequence include a
sequence_fieldsobject. IfSequenceIdis 0 (manual action outside a sequence), the object is empty or omitted. - Email body toggles — events covering an email respect the subscription’s
includeEmailUrl/includeEmailTextflags. Whenfalse, the corresponding field is absent.
Reusable blocks
These appear in several events. Shown once here, referenced by name below.contact_fields
contact_custom_fields
Only present when the subscription was created with payloadConfig.includeProspectCustomFields: true. Keys are the custom field titles configured on the contact.
sequence_fields
Event reference
email_replied
When: a prospect replies to a sequence email (auto-detected by Reply), or a Reply user manually marks the prospect as replied. The two paths emit the same event with a different reason and a different set of populated fields — see the field notes below.
reason—"EmailDetected"when Reply detected the inbound message,"StatusSetManually"when a user flipped the status manually.email_account_id— may benullon the manual-reply path when no email account is associated.reply_message_id— non-null only on the auto-detect path;nullwhenreasonis"StatusSetManually".email_from— present only on the auto-detect path and only whenemail_account_idis known. Absent on manual replies.reply_message_url— present when the subscription hasincludeEmailUrl: true(auto-detect path only).email_text— present when the subscription hasincludeEmailText: true(auto-detect path only).contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.
reply_categorized
When: an email reply is categorized — either automatically by Reply’s AI categorizer, or manually by a user setting a category in the Consolidated Inbox or legacy Inbox.
reply_inbox_category_name— human-readable category name. Built-in values:"No categories","Interested","Not interested","Do not contact","Not now","Forwarded","Meeting intent". Teams may also configure custom category labels — treat the field as a free-form string when matching.reply_message_id— may benullon legacy code paths where the inboundMessage-Idheader was not captured.reply_date— may benullon legacy code paths that don’t carry the original reply timestamp.reply_message_url— present when the subscription hasincludeEmailUrl: trueand a stored reply blob is available.email_text— present when the subscription hasincludeEmailText: trueand the reply body could be parsed from the blob.contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.sequence_fields— only theidkey is emitted for this event (nostep_numberorname); the object is absent if the reply isn’t tied to a sequence.
email_sent
When: Reply successfully dispatches an email from a sequence step (fired after the sent-email record is persisted by the CampaignSending Cloud Function).
sent_email_variant— letter identifying which A/B variant was sent (omitted when the step has a single variant). Derived from the sorted position of the step’s email template; wraps to"A1","B1"… after"Z".sent_message_url— present when the subscription hasincludeEmailUrl: trueand the sent message blob is available.email_text— present when the subscription hasincludeEmailText: trueand the blob body parses successfully.contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.sequence_fields— emitsidandstep_numberonly;nameis not populated for this event.
email_opened
When: a tracked email is opened by the recipient. Opens from IP addresses configured as the user’s own (in the user’s IP exclusion list) are silently filtered before the event is raised.
opens_count— cumulative lifetime open count for this sent email (always>= 1; increments on each re-open). Not a per-delivery delta.contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.sequence_fields— emitsidandstep_numberonly;nameis not populated for this event.
email_link_clicked
When: a recipient clicks a tracked link inside an email.
email_bounced
When: a sent email bounces or is rejected by the recipient mail system. Fired both from the replies-fetching pipeline (when an inbound message is classified as a bounce) and from the campaign service when sent emails are flagged as bounced.
bounce_type— one of:"Unknown","Soft","Hard","GmailApiLimitWarning","Office365LimitWarning","MailboxFull","AuthenticationFailure","SpamRejection","PolicyViolation". When no specific type can be determined, the value is"Unknown".sent_message_url— present when the subscription hasincludeEmailUrl: trueand the sent message blob is available.email_text— present when the subscription hasincludeEmailText: trueand the blob body parses successfully.contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.sequence_fields— emitsidonly; nostep_numberornamefor this event.
email_auto_reply
When: Reply’s replies-fetching pipeline classifies an inbound message as an auto-reply or out-of-office responder. Both classifications fire this same event — see reply_type below.
reply_type—"AutoReply"for vacation/auto-responder messages,"OutOfOffice"for out-of-office classifications. Both values flow through this event; use this field to distinguish.email_account_id— may benullif the underlying event has no associated email account.email_from— present only whenemail_account_idis known; absent otherwise.reply_message_url— present when the subscription hasincludeEmailUrl: true.email_text— present when the subscription hasincludeEmailText: trueand the reply body parses successfully.user_name/user_email— the Reply user that owns the sequence at event-raise time (full name and login email). Omitted if the user record cannot be loaded.contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.
email_account_connection_lost
When: a connected mailbox stops authenticating (OAuth revoked, password changed, etc.). No prospect context — this is an account-level event.
email_account_error
When: a connected mailbox surfaces a non-empty IMAP or SMTP error — token invalidation, send failure, health-check failure, disconnect detection, reputation issue, sending pause, limit hit. Fires every time the underlying error string is updated to a non-empty value; clearing the warning does not fire.
email_account_error— free-form error string. Always carries a"Receiving: "(IMAP) or"Sending: "(SMTP) prefix produced by the warning-update handler; the remainder is the raw underlying exception or status message.email_account_address— omitted when the email account lookup returns no record (rare but possible after deletion).
contact_finished
When: a contact’s participation in a sequence ends — either by completing all steps, hitting a terminal status, or being manually finished. See finish_reason below for the specific cause.
finish_reason— one of:"Replied"— contact replied to a sequence email."Bounced"— sending bounced and the contact was removed."Manual"— a user manually finished the contact."FinishedAfterXdays"— time-based finish from the sequence’s max-days setting."None"— no specific reason recorded."Called"— finished after a phone call interaction."OptOut"— contact opted out (unsubscribe link, manual, or “Do Not Contact” categorization)."MeetingBooked"— a meeting was booked with the contact."ForbiddenStep"— the next step’s content was rejected by guardrails.
contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.sequence_fields— emitsidonly; nostep_numberornamefor this event.
contact_opted_out
When: a contact is opted out via any of three paths: clicking the unsubscribe link in an email, a user manually opting them out in the web app, or a reply being categorized as “Do Not Contact” in the inbox. All three paths fire this same event with the same payload shape — there is no source or reason field distinguishing them.
contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.sequence_fields— emitsidonly.
contact_called
When: a phone call with this contact reaches a deliverable state — connected, missed, voicemail, logged manually, or timed out. Reply accumulates call-event parts (start, status, resolution, recording) and only fires the webhook once all required parts arrive (or a cloud-function timeout forces delivery with partial data).
from_number— the outbound number used for the call (a number assigned to the user or a pooled number).duration— call length in seconds.0for manually-logged calls or calls that never connected.disposition—"Answered","LoggedManually","NoAnswer","Busy", or"Fail". Mapped from the underlying Twilio call status.resolution— either one of the built-in values ("Positive","ToCall","Negative") or a user-defined custom resolution name configured by the team (which fully replaces the enum value on the wire). Treat as a free-form string when matching.notes— free-form resolution notes the user entered.nullwhen no notes were saved.recording_url— signed URL to replay the call recording.nullwhen the call was not recorded (e.g. no-answer, busy, logged manually, recording disabled).contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.sequence_fields— emitsidonly.
linkedin_connection_request_sent
When: Reply successfully sends a LinkedIn connection request on behalf of the user as part of a sequence step.
sender_linkedin_account_id— the Reply-internal LinkedIn account ID (not a LinkedIn public identifier).initial_message— the connection request body actually sent. May benullif the request was sent without a note.contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.sequence_fields— emitsidonly.
linkedin_connection_request_accepted
When: Reply’s LinkedIn polling detects that a previously-sent connection request has been accepted. Only fires for connections originally sent through Reply — connections accepted outside Reply are not reported.
contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.sequence_fields— emitsidonly.
linkedin_message_sent
When: Reply sends a LinkedIn message (regular message or InMail). Voice messages are emitted with is_voice_attached: true; InMails always carry is_voice_attached: false.
linkedin_message_id— Reply’s internal grouped-message identifier (string), not the native LinkedIn platform message ID.is_inmail—truefor InMail steps,falsefor regular messages.is_voice_attached—truewhen a voice attachment was sent (only possible on regular messages).contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.
linkedin_message_replied
When: Reply’s LinkedIn thread polling detects an inbound message on a thread tied to an active sequence contact. Only fires when the thread maps to a known sequence prospect in Reply.
linkedin_message_id— UUID of the persisted reply row in Reply’s DB (not a LinkedIn platform identifier).linkedin_message— raw reply text as fetched from the LinkedIn thread.contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.sequence_fields— always emitsname;idis included only when the contact is currently tied to a sequence (SequenceId > 0).
linkedin_reply_categorized
When: Reply’s categorizer assigns a category to one or more LinkedIn threads. Fires per affected thread.
reply_inbox_category_name— one of the fixed built-in category names:"No categories","Interested","Not interested","Do not contact","Not now","Forwarded","Meeting intent". Unlike the emailreply_categorizedevent, LinkedIn categorization does not support team-custom label names.last_reply_date— present only when the underlying event reports it (latest message timestamp on the thread); otherwise omitted.contact_custom_fields— present when the subscription hasincludeProspectCustomFields: true.- Note: this event has no
sequence_fieldsblock — the underlying event args don’t carry sequence context.
autopilot_stopped
When: an evergreen sequence’s autopilot is deactivated. Only three reasons emit this event — see autopilot_error_message below. (Other internal pause reasons like NotEnoughCredits and AdvancedDataSearchNotAllowed silently suppress the event.)
autopilot_error_message— one of three exact strings:"the sequence has been deactivated"— sequence was manually deactivated."the active contacts limit has been reached"— contacts limit hit."there are no more contacts/companies matching the filter criteria"— search pool exhausted.
user_name/user_email— the Reply user who triggered the deactivation (full name and login email). Omitted when the user record cannot be loaded.sequence_owner_name/sequence_owner_email— the user who originally created the sequence. Omitted when the owner cannot be resolved.- Dual delivery on team accounts: when the user who triggered deactivation is not the sequence owner, the event fires twice — once with
user_idof the acting user and once withuser_idof the sequence owner. Both carry identicalsequence_fieldsandautopilot_error_message.
linkedin_account_alerts
When: Reply detects a LinkedIn account-level condition that needs the user’s attention — Sales Navigator disconnected, weekly connection-request limit reached, or InMail credits exhausted.
linkedin_id/linkedin_name— the LinkedIn account the alert is about.linkedin_account_alert— human-readable alert text. See the variant list below for the exact strings Reply currently emits.team_name— name of the team that owns the LinkedIn account. Omitted when the team has no name set.linkedin_owner_name/linkedin_owner_email— the user who originally connected the LinkedIn account. Both are omitted when the owner cannot be resolved.- Underlying variants and their re-fire window per
(linkedinAccountId, variant):SalesNavigatorDisconnected— Sales Navigator session lost. Text:Sales Navigator is disconnected. Please reconnect your LinkedIn account to continue sending InMail steps.Re-fires at most every 12 hours.InMailCreditsExhausted— InMail credit balance hit zero. Text:InMail credits are used up — this account can't send InMails until credits renew.Re-fires at most every 24 hours.ConnectionRequestWeeklyLimitReached— LinkedIn weekly connection-request quota reached. Text:Weekly connection request limit reached. Sending new connection requests will resume after LinkedIn resets the quota.Re-fires at most every 24 hours.
Verifying in your own account
Once you have a subscription, fire a synthetic delivery to your URL withPOST /v3/webhooks/{id}/test — the body matches the shapes above exactly, with deterministic placeholder data.