The naive version of this polls the inbox every minute, which burns the account's goodwill on a question whose answer is almost always no. The version that works is told.
1. Register an endpoint
curl -X POST "https://makehybrid.com/premium/webhooks/endpoints" \
-H "X-API-KEY: $MAKEHYBRID_KEY" \
-H "content-type: application/json" \
-d '{"url":"https://yours.example/hooks/linkedin","events":["message.received"]}'
Keep the secret that comes back. It is the only copy you will see, and it is what tells a real delivery from anything else that finds your URL.
2. Answer fast, then work
app.post("/hooks/linkedin", async (req, res) => {
if (!verify(req.rawBody, req.get("x-signature"), SECRET)) return res.sendStatus(401);
res.sendStatus(200); // first, always
await queue.add(req.body); // then the slow part
});
Replying after the work is what makes a slow handler look like a failed one, and a failed one is retried while it is still running.
3. Send the reply, once
curl -X POST "https://makehybrid.com/premium/v2/$ACCOUNT_ID/chats/$CHAT_ID/messages/send" \
-H "X-API-KEY: $MAKEHYBRID_KEY" \
-H "content-type: application/json" \
-d '{"text":"Thanks for the note — I will come back to you today."}'
Insert the message id into a table with a unique constraint before you send. If the insert fails, the same delivery already got a reply — and the person is not told twice.
What breaks, and how you notice
- 429 from the send: the account is being throttled. Back off; retrying sooner extends it.
- 404 on the chat: the account id is not yours, or the chat is gone. The two answer the same way on purpose.
- A 2xx and no message on LinkedIn: see the note on writes in the blog. Log the response, do not assume.