Skip to main content
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.
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 uses the same underlying pipeline.

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:
Simulate inbound SMS
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:
202 Accepted
{
  "id": "iwhe_01H...",
  "status": "QUEUED"
}

Request fields

FieldTypeRequiredDescription
fromstring (E.164)yesPhone number simulating the external user (the sender).
tostring (E.164)yesYour Chirp phone number that should receive the simulated message.
textstringyesMessage text content delivered to your webhook.
subjectstringnoOptional subject line (MMS-style).

Simulate an inbound WhatsApp message

Send a POST request to /v1/playground/whatsapp/inbound:
Simulate inbound WhatsApp message
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:
202 Accepted
{
  "id": "iwhe_01H...",
  "status": "QUEUED"
}

Request fields

FieldTypeRequiredDescription
fromstring (E.164)yesPhone number simulating the external WhatsApp user (the sender).
tostring (E.164)yesYour WhatsApp Business phone number that should receive the simulated message.
textstringyesMessage text content delivered to your webhook.
Only WhatsApp text messages can be simulated via this endpoint today. To simulate media, voice, image, or sticker messages, use the browser-based Playground.

Errors

HTTPCodeMeaning
400invalid_phone_numberfrom or to is not in E.164 format.
401Missing or invalid API key.
403test_app_requiredA live API key was used. Switch to your test API key.
See 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.