Bird SMS used to be outbound only. Now, when someone texts one of your numbers, Bird stores the message beside your sends and pushes it to your endpoint as `sms.received`, so you can answer a reply without polling for it.

## What's new

- **The `sms.received` webhook.** Subscribe from the API, the SDKs, `bird webhooks create`, or the MCP server. The payload carries the body, the segment breakdown, both numbers, and the sending operator where the carrier reports one, so you can act on a reply without a second request.
- **Inbound messages in the API and the log.** `GET /v1/sms/messages?direction=inbound` returns what you received, and each message opens in the SMS log with its body and timeline.
- **Received-message metrics.** The SMS Metrics page shows received volume with its period-over-period change, and a Received messages page breaks it down by number, country and sending operator, so you can see which of your numbers is taking the traffic.

## Replies are yours to act on

Bird records a reply and passes it to you; it does not interpret it. A `STOP` arrives as an ordinary `sms.received`, and suppressing future sends to that number is your integration's job for now. We will say so clearly here when that changes.

## One change to existing webhooks

`carrier` and `mcc_mnc` are now **omitted** from `sms.sent`, `sms.delivered` and `sms.received` payloads when the carrier does not report them, rather than arriving as `null`. That matches the way the message resource has always reported these fields. If you branch on `null` for either, check for absence instead. `sms.accepted` now also carries `segments`, the count your send is billed on.