Webhooks & Events API
Outbound event subscriptions — Reply pushes every reply, open, click, bounce, and LinkedIn event to your endpoint instead of making you poll.
- Base URL
https://api.reply.io/v3- Official reference
- docs.reply.io/api-reference/webhooks/list-webhook-subscriptions
- OpenAPI
- webhooks-events.openapi.yaml
- Markdown twin
- webhooks-events.md
- Scopes
webhooks:readwebhooks:writewebhooks:operate
What it does
The Webhooks & Events API is the push side of the platform: it manages subscriptions that make Reply POST a JSON payload to your URL every time an event fires. The management surface is ten operations — list, create, get, update (PUT), and delete subscriptions; enable and disable them without losing configuration; list the supported event types; send a test payload to a subscription’s URL; and read its delivery failure log. A subscription binds one eventType to one receiver URL, with a scope of personal (owner’s activity) or team (any team member), plus optional payload enrichment flags (email URL, email text, contact custom fields).
The event catalog covers the whole outreach loop: email engagement (email_sent, email_opened, email_link_clicked, email_replied, reply_categorized, email_bounced, email_auto_reply), email account health (email_account_connection_lost, email_account_error), LinkedIn (linkedin_connection_request_sent, linkedin_connection_request_accepted, linkedin_message_sent, linkedin_message_replied, linkedin_reply_categorized, linkedin_account_alerts), calls (contact_called), contact lifecycle (contact_finished, contact_opted_out), and sequence automation (autopilot_stopped).
Direction matters: the endpoints above are ordinary REST calls you make to Reply, but the deliveries are OUTBOUND — Reply POSTs to your endpoint. You need a publicly reachable https URL to receive them.
The problem it solves
A polling agent is always late and always wasteful. Checking the inbox every minute burns rate limit on empty responses and still reacts minutes after a prospect replies — which is exactly when interest is highest. Webhooks invert the flow: subscribe once, then react. A reply arrives, email_replied fires, the agent classifies the intent, drafts a response, and books the meeting — an event-driven pipeline instead of a polling loop. The same nervous system carries operational signals an agent should act on immediately: a bounce or opt-out prunes the contact list, email_account_connection_lost pauses sending before deliverability suffers, linkedin_account_alerts flags a channel that needs human attention, and autopilot_stopped tells the agent its evergreen sequence went quiet. If you cannot host an endpoint — a static agent with no server — the honest fallback is polling the Conversations & Inbox API; webhooks are strictly better only once you have somewhere for Reply to POST.
How an agent starts using it
Call GET /v3/webhooks/events to get the exact event type names, then POST /v3/webhooks with an eventType and your receiver url (scope webhooks:write). Verify the wiring with POST /v3/webhooks/{id}/test before relying on it, then handle the POSTs Reply sends to your endpoint. Use POST /v3/webhooks/{id}/enable and /disable (scope webhooks:operate) to pause during maintenance, and GET /v3/webhooks/{id}/logs (scope webhooks:read) when events stop arriving — it lists failed delivery attempts with event id, HTTP status, and timestamp. One subscription carries one event type, so an agent that needs replies, bounces, and opt-outs creates three subscriptions pointing at the same receiver.
Typical agent tasks
- Subscribe to email_replied so every prospect reply triggers classify-and-respond within seconds
- Send a test payload to verify the receiver endpoint parses events before going live
- Subscribe to email_bounced and contact_opted_out to keep the contact list clean automatically
- Disable a subscription during receiver maintenance and re-enable it without losing configuration
- Read the delivery failure log to diagnose why events stopped arriving
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
eventType | string | yes | Event to fire on — one name from GET /v3/webhooks/events (e.g. email_replied). |
url | string | yes | Absolute, publicly reachable https receiver URL (max 1,024 chars) that Reply will POST event payloads to. |
scope | string | no | personal (default) fires only on the owner's activity; team fires for any team member. organization is reserved and currently rejected. |
enabled | boolean | no | Create in a firing state (default true). After creation, toggle only via the enable/disable endpoints — PUT cannot change it. |
payloadConfig | WebhookPayloadConfig | no | Enrichment flags — includeEmailUrl, includeEmailText, includeProspectCustomFields. |
Outputs
| Name | Type | Description |
|---|---|---|
id | integer | Subscription identifier used by every other webhook endpoint. |
enabled | boolean | Whether the subscription currently fires. |
events | string[] | Supported event type names from GET /v3/webhooks/events — the valid eventType values. |
logs | WebhookDeliveryLog[] | Per-subscription failure log — triggering event id, HTTP status (null if the request never completed), and UTC attempt timestamp. Successful deliveries are not logged. |
Authentication
API key as Bearer token. Send Authorization: Bearer <API_KEY> on every request. Get an API key in the
Reply.io app under Settings → API Key —
authentication reference.
Rate limits
100 requests/minute and 3,000 requests/hour per user (shared across all of the user's API clients). On 429, honor the Retry-After header.
Example
curl -X POST https://api.reply.io/v3/webhooks \
-H "Authorization: Bearer $REPLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "eventType": "email_replied", "url": "https://agent.example.com/hooks/reply", "scope": "personal" }'
{
"id": 1823,
"eventType": "email_replied",
"url": "https://agent.example.com/hooks/reply",
"scope": "personal",
"enabled": true,
"createdAt": "2026-07-04T09:15:00Z"
}
{
"type": "https://docs.reply.io/api-reference/authentication",
"title": "Forbidden",
"status": 403,
"detail": "This API key does not have the required scope: webhooks:write."
}
Related APIs
Modules are designed to chain — combining them is the point.
Conversations & Inbox API
The unified inbox as an API — read threads across email and LinkedIn, classify replies with categories, detect meeting intent, and respond.
Sequence API
Create, populate, and control multichannel outreach sequences — email, LinkedIn, and calls in one campaign object.
Contact Data API
The CRM-grade contact and account store — create, import, filter, and organize the people and companies your agent works.
Platform Utilities API
Attachments (including LinkedIn voice), and background-job tracking for bulk and import operations.
Frequently asked questions
Should an agent use webhooks or poll the Inbox API?
Webhooks are outbound: Reply POSTs each event to a public https URL you host, so you react in seconds without spending rate limit on polling. An agent with no server gets the same signals by polling the Conversations & Inbox API — webhooks just remove the latency and the wasted requests.
How do I test a subscription before real traffic hits it?
POST /v3/webhooks/{id}/test (scope webhooks:operate) sends a test payload to the subscription's URL, so you can verify parsing and response handling before enabling it in production.
How do I debug missing events?
GET /v3/webhooks/{id}/logs returns the subscription's delivery failure log — each entry has the triggering event id, the HTTP status (null when the request never completed), and the UTC attempt timestamp. It records failures only; successful deliveries are not listed. Also check that the subscription is enabled.
Start here: get an API key and make your first call, or explore workflows that combine this module with others.