The word people expect is "sandbox", meaning a separate environment with its own credentials where nothing is real. Bird does not have one, and the thing it has instead is better in one way and worse in another, so it is worth knowing which before you write a test suite.

## Is there a test environment?

No. There is no test mode to enable, no test API key, and no separate host. Your integration points at production and always did.

What exists instead is a set of **magic destinations**. You send through the normal endpoints with your normal key, and the recipient you chose determines the outcome. Everything else about the request is real: the same `202`, the same processing, the same per-recipient events, the same signed webhook deliveries.

The advantage is that you are testing the path you will actually use, rather than a mock of it. The disadvantage is that nothing marks the send as a test, which the last section covers.

## What are the magic email addresses?

Local parts on `messagebird.dev`. The address selects the outcome, and seven are documented:

| Address                    | What it simulates                                                                                          |
| -------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `delivered@`               | The receiving server accepts it, the happy path                                                            |
| `bounce@` or `hardbounce@` | A hard bounce, SMTP `550`                                                                                  |
| `softbounce@`              | A soft bounce, SMTP `451`                                                                                  |
| `deferred@` or `delay@`    | A deferral, and the simulated one is terminal: no retry follows                                            |
| `complaint@` or `spam@`    | The recipient reports it as spam                                                                           |
| `suppressed@`              | The recipient is treated as already suppressed, so it short-circuits with no processing or delivery events |
| `reject@`                  | Rejected before any delivery attempt                                                                       |

Four rules about matching are worth reading once rather than debugging later. Detection is by **local part only and only on `messagebird.dev`**, so `bounce@yourdomain.com` is an ordinary address. Only the documented local parts are magic; anything else at that domain is a normal recipient. Matching is case-insensitive. And **`+label` subaddressing is stripped before matching**, so `bounce+signup-flow@messagebird.dev` still bounces.

Two behaviours make these reusable in a way real failures are not. A simulated bounce or complaint does **not** write to your suppression list and does not affect sending reputation, so the same address works every time. And a send can mix sandbox and real recipients, each getting its own lifecycle, which is how you rehearse a broadcast without mailing anyone.

## What are the magic phone numbers?

Six US destinations, in the Twilio-style range so they will look familiar:

| Destination    | What your integration sees                                |
| -------------- | --------------------------------------------------------- |
| `+15005550001` | Rejected at submission with `invalid_destination`         |
| `+15005550002` | `sms.sent`, then `sms.undelivered` with `unreachable`     |
| `+15005550003` | `sms.sent`, then `sms.failed` with `provider_unavailable` |
| `+15005550004` | `sms.sent`, then `sms.failed` with `blocked_by_carrier`   |
| `+15005550006` | `sms.sent`, then `sms.delivered`                          |
| `+15005550009` | `sms.sent`, then `sms.failed` with `recipient_opted_out`  |

Two conditions catch people out on a fresh workspace, and both follow from these being real US sends. **The United States has to be [enabled](/docs/guides/sms/migrate)** under Destinations, and your `from` has to be a sender valid for the US, which an alphanumeric sender ID is not.

That `+15005550004` row is worth noting if you have read our page on [carrier filtering](/explained/sms/why-are-my-sms-messages-being-filtered-by-carriers): `blocked_by_carrier` is a code the live pipeline does not produce, and this magic number is the one place you will see it.

## What does a simulated send still cost?

More than people expect, and this is the part to design around.

**An SMS to a magic number is billed** at the destination's [normal rate](/pricing/sms). Nothing reaches a handset, and the wallet charge is real, so a smoke test that loops has a bill attached.

**A simulated email recipient counts against your send allowance.** Rehearsing a broadcast against sandbox addresses exercises the same quota the real send would.

**And sandbox traffic lands in your statistics.** Simulated sends count toward your workspace's aggregate stats and its bounce and complaint rates, so heavy sandbox bouncing skews your dashboards even though it leaves your sending reputation alone. That pair is easy to get wrong in the reassuring direction: reputation is protected, the charts are not.

So size a test suite the way you would size production traffic, and prefer asserting on a handful of destinations over sweeping every outcome on every run.

## How do I tell a test send from a real one?

Not from the payload, which is the honest answer and the one that shapes how you build.

A sandbox send returns the same `202`, produces the same event shapes, and arrives on the same signed webhooks. **There is no test flag.** So your handler, your log and your metrics cannot distinguish a simulated bounce from a real one by looking at the event.

Two things help. On email, `+label` subaddressing survives into the events and webhooks even though it is stripped for matching, so `bounce+ci-run-421@messagebird.dev` tags a run in a way you can filter on afterwards. And the events land on the message timeline in the log and on the events API, so you can drive the sandbox and read the outcome back without running a webhook endpoint at all.

[Test email delivery](/docs/guides/email/testing-sandbox) has every address with its exact SMTP codes and bounce classes, and [migrating to Bird](/docs/guides/sms/migrate) has the SMS numbers with a worked smoke test.