> ## Documentation Index
> Fetch the complete documentation index at: https://messages.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Receive Messages

> Get notified when new messages arrive

Incoming messages, reactions, and delivery events arrive as signed HTTPS
POSTs to a URL you control. You write the handler once and it runs
unchanged in dev and in production.

## 1. Handle the event

```typescript theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
import { verifyWebhook } from "@messages-dev/sdk";

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

  if (event.event === "message.received") {
    console.log(`${event.data.sender}: ${event.data.text}`);
  }

  res.sendStatus(200);
});
```

`verifyWebhook` handles HMAC-SHA256 verification, timing-safe comparison,
and replay protection, then returns a typed discriminated-union event. If
you're not using the SDK, see the manual verification snippets in
[Webhooks › Verifying signatures](/concepts/webhooks#verifying-signatures).

## 2. Stream events to your handler (local dev)

The fastest way to drive your handler while you're building is the
[`messages-dev` CLI](/cli). It POSTs each real account event to a local
URL with the same headers a registered webhook would, so you don't need a
public URL or a webhook registration.

[Install the CLI and authenticate](/cli#install), then:

```sh theme={"theme":{"light":"github-light","dark":"github-dark-high-contrast"}}
messages-dev listen --forward-to http://localhost:3000/webhooks
```

The CLI prints a per-session HMAC secret on first run. Set it as
`WEBHOOK_SECRET` in your handler, or pin one with
`MESSAGES_LISTEN_SECRET=…` so it doesn't rotate between runs.

<Tip>
  Without `--forward-to`, `messages-dev listen` prints events to your
  terminal as they happen. Useful for tailing a line while you debug.
</Tip>

## 3. Register a webhook (production)

When you're ready to deploy, go to the **Webhooks** page in your
[dashboard](https://app.messages.dev), click **Add Webhook**, enter your
public HTTPS endpoint, and copy the signing secret into your environment as
`WEBHOOK_SECRET`. The handler from step 1 is unchanged.

You can also [create webhooks via the API](/concepts/webhooks#creating-a-webhook)
if you need to provision them programmatically.

## Next steps

* [Webhooks](/concepts/webhooks) — full event list, payload shapes, and
  replay-protection rules.
* [CLI reference](/cli) — `listen` filtering flags, output modes, and
  other recipes.

<Note>
  Prefer to use [ngrok](https://ngrok.com), Cloudflare Tunnel, or another
  tunnel for local dev? Expose your local server on a public URL and
  register a regular webhook pointing at it. Same payload, same handler
  code — see [Webhooks](/concepts/webhooks) for setup.
</Note>
