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

# Simulating Inbound Messages

> Programmatically simulate inbound SMS and WhatsApp messages from a user to your application using the Playground inbound API

The Playground inbound API lets you programmatically simulate an inbound message *as if a user had sent it to your application*. This is useful for end-to-end tests, CI pipelines, and local development against your real webhook endpoint -- without sending a real SMS or WhatsApp message.

<Note>
  Both endpoints are **only available to test apps**. Calling them with a live API key (`sk_live_app_*`) returns a `test_app_required` error. The browser-based [Playground](/concepts/playground) uses the same underlying pipeline.
</Note>

## How it works

1. You `POST` to the inbound endpoint with `from`, `to`, and `text`.
2. Chirp accepts the request synchronously (`202 Accepted`) and queues an internal webhook event.
3. The same processing pipeline that handles real Telnyx (SMS) or Meta (WhatsApp) webhooks runs against the simulated event.
4. Your configured `messages.sms.received` (SMS) or `messages.whatsapp.received` (WhatsApp) webhook fires, exactly as if the message were real.

This means whatever logic you've built around inbound messages -- auto-replies, classification, tool calls -- runs unchanged.

## Authentication

Use a test app key (`sk_test_app_*`). If you've set up a production / test app pair, the test key belongs to the test app linked to your live app.

## Phone number behavior

You don't need to allocate the `to` phone number to your test app first. On the first inbound simulation to a number that isn't yet known, Chirp auto-creates a system phone number record and links it to your test app. Subsequent simulations to the same `to` number reuse that record.

This means a fresh test app can start receiving simulated traffic immediately -- no setup required.

## Simulate an inbound SMS

Send a `POST` request to `/v1/playground/sms/inbound`:

```bash icon="terminal" title="Simulate inbound SMS" theme={null}
curl -X POST https://api.buildwithchirp.com/v1/playground/sms/inbound \
  -H "Authorization: Bearer YOUR_TEST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "+15559876543",
    "to": "+15551234567",
    "text": "Hello from a simulated user!"
  }'
```

**Response:**

```json icon="code" title="202 Accepted" theme={null}
{
  "id": "iwhe_01H...",
  "status": "QUEUED"
}
```

### Request fields

| Field     | Type           | Required | Description                                                        |
| --------- | -------------- | -------- | ------------------------------------------------------------------ |
| `from`    | string (E.164) | yes      | Phone number simulating the external user (the sender).            |
| `to`      | string (E.164) | yes      | Your Chirp phone number that should receive the simulated message. |
| `text`    | string         | yes      | Message text content delivered to your webhook.                    |
| `subject` | string         | no       | Optional subject line (MMS-style).                                 |

## Simulate an inbound WhatsApp message

Send a `POST` request to `/v1/playground/whatsapp/inbound`:

```bash icon="terminal" title="Simulate inbound WhatsApp message" theme={null}
curl -X POST https://api.buildwithchirp.com/v1/playground/whatsapp/inbound \
  -H "Authorization: Bearer YOUR_TEST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "+15559876543",
    "to": "+15551234567",
    "text": "Hello from a simulated WhatsApp user!"
  }'
```

**Response:**

```json icon="code" title="202 Accepted" theme={null}
{
  "id": "iwhe_01H...",
  "status": "QUEUED"
}
```

### Request fields

| Field  | Type           | Required | Description                                                                    |
| ------ | -------------- | -------- | ------------------------------------------------------------------------------ |
| `from` | string (E.164) | yes      | Phone number simulating the external WhatsApp user (the sender).               |
| `to`   | string (E.164) | yes      | Your WhatsApp Business phone number that should receive the simulated message. |
| `text` | string         | yes      | Message text content delivered to your webhook.                                |

<Note>
  Only WhatsApp **text** messages can be simulated via this endpoint today. To simulate media, voice, image, or sticker messages, use the [browser-based Playground](/concepts/playground).
</Note>

## Errors

| HTTP | Code                   | Meaning                                               |
| ---- | ---------------------- | ----------------------------------------------------- |
| 400  | `invalid_phone_number` | `from` or `to` is not in E.164 format.                |
| 401  | --                     | Missing or invalid API key.                           |
| 403  | `test_app_required`    | A live API key was used. Switch to your test API key. |

See [Error Codes](/api_reference/error-codes) for the full error response format.

## Using it in tests

A typical end-to-end test looks like this:

1. Boot your application against your test app keys.
2. `POST` to `/v1/playground/sms/inbound` (or the WhatsApp variant) with the message you want to simulate.
3. Assert that your webhook handler received the expected `messages.sms.received` (or `messages.whatsapp.received`) event and that any side effects (DB writes, outbound replies, etc.) ran as expected.

Because the simulated message flows through the same processor as real provider webhooks, your test exercises the real handler -- no mocking required.
