# Testing your integration

Test safely before you go live.

> **In a nutshell:** Use a test key (sk_test_). It works on sandbox businesses, whose WhatsApp is simulated end to end - connect, send, receive, statuses, callbacks - without Meta. Then test the failure paths on purpose.

## The sandbox

A **test key** (`sk_test_...`) works on sandbox businesses only - a separate set from
your live ones, created the usual way with [`POST /businesses`](/docs/api/upsert-business).
Their WhatsApp is simulated: nothing reaches Meta or anyone's phone.

1. **Connect.** Create a connect link and open it: the page connects a simulated account in one click, with a number and approved templates (`fee_reminder`, `welcome`), and sends `whatsapp.connection`.
2. **Receive.** Simulate an incoming message - it creates the contact and conversation and sends `message.received`, as live.
3. **Send.** Send text (inside the window) or templates as usual. Messages are `sent` at once; to a number ending in `0001` they fail with `131026`, like a number not on WhatsApp.
4. **Deliver.** Simulate a delivery status - `delivered`, `read` or `failed` - and get `message.status`.

Callbacks from sandbox businesses carry `"sandbox": true`. Templates you create in the
sandbox are approved at once.

## Staging with a real number

1. **Ask for a staging product.** A PaalChat operator creates it and gives you a token with the abilities you need.
2. **Connect a test number.** Meta gives every app a test WhatsApp number that can message up to five verified recipients. Connect it through the normal connect link.
3. **Expose your callback endpoint.** Run your app locally behind an HTTPS tunnel and ask the operator to set that URL as the staging callback URL.
4. **Import the Postman collection.** Download it, set `token` and `external_id`, and call `Get product`.

> [!NOTE]
> With a live key and Meta's test number, messages are real WhatsApp messages, so only
> use numbers you control.

## Test these paths on purpose

- [ ] `GET /me` shows every ability your code uses.
- [ ] Creating the same business twice returns `201` then `200`.
- [ ] Free-form text to a number that has not messaged you returns `422 outside_service_window`, and your app offers a template.
- [ ] A send to a number that is not on WhatsApp ends as `message.status` `failed` with code `131026`.
- [ ] Sending the same `reference` twice returns `202` then `200`, and only one message arrives.
- [ ] Your callback endpoint answers `401` to a bad signature and to a signature older than 5 minutes.
- [ ] Delivering the same callback twice changes nothing the second time.
- [ ] A `whatsapp.connection` `disconnected` callback disables WhatsApp features in your app.
