# Choose what a webhook receives

October 22, 2026 · Webhooks

A subscription now chooses its environment, and an endpoint that has not verified no longer drops its events.

## What changed

- **`receives`.** `POST /v1/console/apps/:appId/webhooks` and `PATCH .../webhooks/:id` take an optional `receives`: `"sandbox"`, `"live"` or `"both"`, the default. Anything else is `400 invalid_receives`. The console has a **Receives** selector, and `POST /v1/cli/apps/:app/webhooks` accepts the same field. The subscription object carries `receives`.
- **Held and expired deliveries.** While an endpoint has not verified, its events are `held`, in the delivery log and the events feed. A held delivery becomes `expired` after 72 hours, past 1,000 held for one endpoint, or when the endpoint is removed or verified while switched off. Neither can be replayed.
- **Automatic re-verification.** After a failed verification Layout checks the endpoint again after about 1 minute, 10 minutes, 1 hour and 6 hours, then daily for 7 days. `verification.nextCheckAt` on the subscription says when, or is `null`. These checks do not count against the 50 manual verifications a day, and each manual verify restarts the schedule. On the first 2xx the held events are delivered in order.
- **`POST /v1/cli/apps/:app/webhooks/:id/verify`** with `{ "environment": "sandbox" | "live" }` picks the signing secret tried first and answers `200 { environment, subscription }`. It works on an approved application. Errors: `404 not_found`, `403 app_suspended`, `429 rate_limited`, `503 unavailable`.

## What to do

Set a development tunnel to `sandbox` so it never sees a production order once your application is approved. See [Events held while an endpoint is unverified](https://developer.layout.link/reference/webhooks#held-events).

## Breaking changes

None. A webhook endpoint used to have no environment; the default `both` keeps every existing subscription receiving what it did.
