Receiving messages▾
Receiving messages
Stand up a webhook receiver end to end: verify, acknowledge, enqueue, reply.
A complete inbound path in four moves. The two that people get wrong are verifying against the raw body and replying before the work is done.
- 1
Answer the verification challenge
Registering an endpoint triggers a one-off
GET ?challenge=…. Echo the token as plain text.Nodeapp.get("/hooks/sendport", (req, res) => res.type("text/plain").send(String(req.query.challenge ?? "")), ); - 2
Verify the signature
Use the raw body — see verifying signatures. Never parse before verifying.
- 3
Acknowledge, then work
Return
200inside 5 seconds and push the event onto a queue. Doing the work inline is how you end up with duplicate deliveries.Nodeapp.post("/hooks/sendport", express.raw({ type: "application/json" }), (req, res) => { if (!verify(req.body, req.headers["sendport-signature"] as string, SECRET)) { return res.status(400).send("bad signature"); } const event = JSON.parse(req.body.toString()); res.sendStatus(200); if (event.type === "message.received") queue.push(event); }); - 4
Reply inside the window
An inbound message opens 24 hours of free-form replies. Read
data.session_expires_aton the event and send text while it is in the future; after that you need a template.Nodeawait fetch("https://api.sendport.tech/v1/messages", { method: "POST", headers: { Authorization: `Bearer ${process.env.SENDPORT_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ to: event.data.from, type: "text", text: { body: "Thanks — checking now." }, }), });
Testing locally
Webhooks cannot reach localhost. Use sendport webhooks listen to tunnel deliveries to your machine — see the CLI.
sendport webhooks listen --forward http://localhost:3000/hooks/sendportDeduplicate on the envelope id
evt_…. Store seen ids for 24 hours and drop repeats — every handler must be idempotent.