EN
Unipile MCP · Webhooks

Wire messaging webhooks with a coding agent: LinkedIn, WhatsApp, email

LinkedIn has no public webhook for a member's messages. Unipile pushes message.new, email.new and account events to your endpoint for every channel, on the accounts your users connected. With the Unipile MCP server, your coding agent reads the webhook contract, creates the endpoint, subscribes to the right events and writes an idempotent handler in your stack. Part of the Unipile MCP server.
POST /v2/webhooks/endpoints/
message.new, email.new
account.add, account.status.*
One secret per endpoint
One endpoint, the events you handle, a queued and idempotent handler. 7-day free trial, no credit card.
Your agent · crm-app
Unipile MCP connected
Sarah
Subscribe to Unipile new-message webhooks and update the contact timeline: create the endpoint for message.new and email.new, add an idempotent handler, and queue the processing.
Run requestPOST /v2/webhooks/endpoints/201 · we_…
Created the endpoint on the Development app, added POST /webhooks/unipile that returns 200 immediately and enqueues the event, and a worker that dedupes on the object ID before writing to the contact timeline.
3 files changed · first event received in under a second
Now handle account.status.disconnected with a Reconnect button.
Read endpointGET /v2/webhooks/conversations/delivery log
Writing the account handler
Describe the next feature…
The job

What you are trying to do

Show a new message or email in your product the moment it arrives, and react when an account disconnects, without polling. LinkedIn has no public message webhook for a member account; Unipile pushes the same event for every channel.
LinkedInNew LinkedIn messageon the account your user connected
WhatsAppNew WhatsApp messagesame event, other channel
GmailNew emailGmail, Outlook or IMAP
message.newmessage.newemail.new
Your app · contact timelinePOST /webhooks/unipile
LinkedInSarah K. replied on LinkedIn0.4 s
WhatsAppTom R. sent a WhatsApp message0.3 s
GmailAna L. emailed the proposal0.5 s
Queued, deduplicated, written once
Without it Polling loops and blind spots
A job that polls every account every thirty seconds, most of the time for nothing.
No LinkedIn message event at all, because the platform does not expose one for a member account.
A disconnected account discovered by the user, not by your product.
With the Unipile MCP server The result in your application
A webhook endpoint subscribed to the events you handle, created on your Development application.
A handler that answers at once, processes from a queue and writes each event once.
A contact timeline and an account status that update in under a second, tested before you ship.
Prompt, steps, code

Give your agent the prompt

Two prompts, each with the Unipile endpoints the agent reads and runs and what lands in your project. Paths are complete, on the API base URL https://api.unipile.com, with your scoped key in the X-API-KEY header.
Your agent · crm-appDevelopment app
Subscribe to Unipile new-message webhooks and update the contact timeline: create the webhook endpoint for message.new and email.new, add an idempotent handler in this application, and queue the processing.
Read endpointPOST /v2/webhooks/endpoints/schema loaded
Run requestPOST /v2/webhooks/endpoints/201 · we_… + secret
Created the endpoint with trigger_events: ["message.new", "email.new"] and the public URL of the app, stored the returned secret server-side, added POST /webhooks/unipile that validates the delivery, answers 200 at once and enqueues the payload, and a worker that dedupes on the object ID before writing to the contact timeline. Sent a test message on the Development app: timeline updated.3 files changed · queued, idempotent, verified

Acknowledge first, process later, write once

The agent reads the endpoint contract through the server: trigger_events and url are required, account_ids narrows the scope, and the response carries the endpoint ID and its secret. It then writes the handler the way a webhook needs it: immediate 2xx, asynchronous processing, deduplication on the object identifier, and a check of the delivery log when something looks missing.
Endpoints the agent uses
POST/v2/webhooks/endpoints/GET/v2/webhooks/endpoints/GET/v2/webhooks/conversations/GET/v2/{account_id}/chats/{chat_id}/messages/{message_id}
Common mistake: Doing the work inside the handler. Answer 2xx right away and process the event from a queue, or deliveries time out and retry.
Feed a unified inbox with these events
Your agent · crm-appDevelopment app
Handle account lifecycle webhooks: on account.status.disconnected mark the account as needing attention and surface a Reconnect button, and on account.add store the new account_id against the workspace carried in state.
Read endpointPOST /v2/webhooks/endpoints/event enum
Run requestPATCH /v2/webhooks/endpoints/{id}200 · events updated
Added account.add, account.reconnect and account.status.disconnected to the endpoint. On account.add the worker stores the account_id on the workspace found in state; on account.status.disconnected it flags the account and the Settings page shows the Reconnect button that calls the Hosted Auth reconnect route. Verified by disconnecting the mock account on the Development app.2 files changed · reconnect surfaced in the UI

The account events close the loop with Hosted Auth

account.add and account.reconnect carry the state you set when creating the auth link, which makes the webhook the source of truth for a new connection. The status events tell your product when an account needs attention before the user notices. The agent wires both to the same endpoint and keeps the handler idempotent.
Endpoints the agent uses
PATCH/v2/webhooks/endpoints/{id}GET/v2/accounts/{account_id}POST/v2/auth/link
Common mistake: Subscribing to everything. Thirty-nine events exist; an endpoint subscribed to all of them receives read receipts and tracking opens non-stop. Subscribe to what you handle.
Implement the reconnect flow with an agent
Payload

The endpoint body, the response and the events

Verbatim from the v2 contract the agent reads through the server. Two fields are required, the response carries the secret, and the events come in families.
1Create the endpointtrigger_events and url are required. account_ids restricts the endpoint to some accounts; empty or omitted, it listens to every account of the application.POST https://api.unipile.com/v2/webhooks/endpoints/{ "trigger_events": ["message.new", "email.new", "account.add"], "url": "https://app.example.com/webhooks/unipile", "account_ids": ["acc_…"], "description": "crm timeline" }
2The responseA WebhookEndpoint with its id, the application, the secret to keep server-side, and the accounts it targets.{ "object": "WebhookEndpoint", "id": "we_…", "application_id": "app_…", "enabled": true, "secret": "…", "trigger_events": [ … ], "account_targets": [ … ] }
3The events, by familyAccount (status, add, reconnect, remove, sync), message (new, update, delete, receipts, reactions), chat, email (new, bounce, delete, drafts, folders), calendar (create, update, delete, event.*), tracking and relations.message.new · message.update · message.receipt.read · chat.updateemail.new · email.new.bounce · email.draft.new · email.folder.updateaccount.add · account.reconnect · account.status.disconnected · account.initial_sync.completed
Development to production

Test on a Development application first

Your Unipile dashboard separates a Development application from Production. Give the agent a scoped key from Development, one test account, and a tunnel URL: real events, no real customer.
1Create the endpoint on the Development appTunnel URL, trigger_events limited to what you handle.
2Receive one event end to endaccount.add from a mock Hosted Auth link, then message.new from the test account.
3Replay it, then switch the keyThe worker writes once; account_ids restricted to the right customer before Production.
crm-app · DevelopmentUsed by your agent
Scopedev-tests · 2 accounts
Keyscoped Account API key
AccountsLinkedIn test account, Gmail test mailbox
Webhooks1 endpoint · message events
crm-app · ProductionUntouched
Scopeone per workspace
Keyscoped keys, in your backend only
Accountsyour users' own accounts, via Hosted Auth
Troubleshooting

Common errors and what they mean

The four mistakes that make webhooks unreliable, and the fix for each. None of them is about the events themselves.
The endpoint answers slowly
Deliveries time out and pile up as retries. FixAnswer 2xx immediately and process from a queue. A handler that writes to the database before responding ends up replaying its own backlog.
A handler that is not idempotent
The same message appears twice in the timeline. FixThe same event can be delivered more than once. Dedupe on the object identifier carried by the payload before writing.
Subscribed to everything
The endpoint receives read receipts and tracking opens non-stop. Fixtrigger_events accepts thirty-nine values. Subscribe to the events you handle, and create several endpoints when the processing differs.
account_ids forgotten on a multi-customer product
One customer's worker receives another customer's events. FixEmpty or omitted, account_ids listens to every account of the application. Restrict it explicitly per customer, or filter on the account of the payload before writing.

Webhooks FAQ

Whether LinkedIn has a message webhook, how to create an endpoint, which events exist, how to scope an endpoint to one customer, and how to verify a delivery.
Not for a member account. LinkedIn's public webhooks cover organisation social actions and lead forms; member messages sit behind a compliance program that no longer accepts new partners. With Unipile, the message.new event covers LinkedIn like every other channel, on the account your user connected themselves.
POST https://api.unipile.com/v2/webhooks/endpoints/ with the X-API-KEY header and a body carrying trigger_events and url. The response carries an id in we_… and a secret.
Thirty-nine values across the account, message, chat, email, calendar, tracking and relation families. The most used are message.new, email.new, account.add, account.reconnect and account.status.disconnected.
With account_ids, an array of identifiers in acc_…. Omitted or empty, the endpoint listens to every account of the application.
Creating the endpoint returns a secret. Keep it server-side and validate every delivery before processing. Your URL must be HTTPS and publicly reachable; the delivery log is available on the webhook conversations route.