Skip to main content
Trigger a named test event for a Test number to check how your integration handles it. Polymorfa delivers the event to your webhooks and the events API in the same format as production events, signed with your endpoint’s signing secret. You don’t need a phone, a second person, or a real WhatsApp account. Test events work only for Test numbers (testMode: true). A request for any other number returns 400 Bad Request and sends nothing.

Before you start

  • Your team has Test numbers access. See What is Sandbox?.
  • The project has a Test number. Use its session name in each request.
  • You have a project key, or a team key, with the sandbox:write scope. Listing fixtures needs sandbox:read. Client tokens can’t trigger test events.

Trigger an event

Send the fixture name as event and the Test number as session:
The API returns 202 Accepted:
Webhook subscribers to message.received receive the event with the same envelope and signature headers as any other event. Look it up by eventId with GET /platform/projects/{projectId}/events/{eventId}; see Event history. Test events carry source: "test" and environment: "development", so you can tell them apart from events produced by WhatsApp activity. With the TypeScript SDK:

Fixtures

Each fixture name is the event type it produces. List the fixtures and their overrides with GET /messaging/testing/{projectId}/events/fixtures. A fixture rejects an override it doesn’t list with 400 Bad Request. Without overrides, each fixture uses these values:
  • message.received: a text message from +15550100001. Set mediaType to image, video, audio, document, or sticker to send media metadata instead, with an optional caption for images, videos, and documents. Generated media events contain no downloadable file.
  • message.ack: ackStatus is delivered. Also read, played, or error.
  • message.failed: failureReason is send_failed.
  • session.status: DISCONNECTED with STREAM_ERROR.
  • template.status: APPROVED. Set templateStatus to REJECTED and an optional reason to test a rejection.
  • bansafe.enforcement: enforcementKind is cap_warning. Also cap_reached, timelock, or temporary_ban.
  • bansafe.risk_changed: riskLevel is high.

What test events don’t change

A test event reaches your webhooks and the events API only. It doesn’t change the Test number: a session.status event doesn’t disconnect it, a bansafe.enforcement event doesn’t restrict it, and call events don’t ring Calls clients. Test events don’t count toward campaign reply metrics. Contact and message IDs in generated events are random. They don’t refer to a conversation, so you can’t reply to them.

Send a simulated message between Test numbers

To test a full round trip, including replies, send a real simulated message from another connected Test number in the same project. Set fromSession on a message.received request:
The response has "delivery": "simulated" and "eventId": null. The message.received event arrives shortly after as ordinary Test number activity, with source: "runtime", and you can reply to it. Both Test numbers must be connected. fromSession accepts only the text override.

Limits

Each project can trigger 30 test events per minute. Further requests return 429 Too Many Requests with a Retry-After header that gives the seconds to wait. Every trigger is recorded in your team’s audit log as testing.event.trigger.

Retry safely

Send an Idempotency-Key header, up to 255 printable ASCII characters, to make a trigger safe to retry. A repeated request with the same key and body gets the same eventId, so your event history and webhooks receive the event once. A different body with the same key creates a separate event.

Errors