Skip to main content

Overview

Webhooks push events to your server as they happen, no polling required. Register a URL, choose which events you care about, and Messages.dev will POST to it in real time.

Events

EventDescription
message.receivedA new incoming message on the line
message.sentAn outgoing message was delivered
reaction.addedA reaction was added to a message
reaction.removedA reaction was removed
typing.startedSomeone started typing in a chat
typing.stoppedSomeone stopped typing
receipt.readA read receipt was received

Creating a webhook

The easiest way to create a webhook is from the Webhooks page in your dashboard. Click Add Webhook, enter your URL, select the events you care about, and copy the signing secret.
The dashboard is the recommended way to manage webhooks. It shows the signing secret once on creation and makes it easy to enable, disable, or delete webhooks without writing code.
You can also create webhooks via the API:
import { createClient } from "@messages-dev/sdk";

const client = createClient();

const webhook = await client.createWebhook({
  from: "+15551234567",
  url: "https://your-server.com/webhooks",
  events: ["message.received", "message.sent"],
});
Each webhook is scoped to a single line. Create one per line if you have multiple lines.

Payload format

POST /webhooks HTTP/1.1
Content-Type: application/json
X-Webhook-Signature: a1b2c3d4e5f6...

{
  "event": "message.received",
  "data": {
    "object": "message",
    "id": "msg_abc123",
    "chat_id": "cht_def456",
    "sender": "+15559876543",
    "text": "Hey there!",
    "is_from_me": false,
    "sent_at": 1710000000000
  },
  "timestamp": 1710000000123
}

Verifying signatures

Every webhook delivery is signed with HMAC-SHA256. The SDK handles this automatically:
import { verifyWebhook } from "@messages-dev/sdk";

app.post("/webhooks", async (req, res) => {
  const event = await verifyWebhook(
    req.body,
    req.headers["x-webhook-signature"],
    "your_webhook_secret",
  );

  console.log(event.event, event.data);
  res.sendStatus(200);
});
If the signature is invalid, verifyWebhook throws a SignatureVerificationError. If you’re not using the SDK, verify manually:
import { createHmac } from "crypto";

function verifyWebhook(body, signature, secret) {
  const expected = createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  return expected === signature;
}
Always verify the signature before processing a webhook payload. This prevents attackers from sending forged events to your endpoint.

Deleting a webhook

You can delete webhooks from the Webhooks page in your dashboard, or in code:
await client.deleteWebhook({ id: "wh_abc123" });
When using the REST API directly, the webhook ID is passed in the request body, not in the URL path.