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 404 Not Found and sends nothing.

Before you start

  • Your team has Test numbers access. See What is Sandbox?.
  • The project has a Test number. Put its Number ID in the request path. The Test number’s project is the project the request acts on, so a project key works only for Test numbers in its own project.
  • 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 to the Test number’s test-events path:
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/test-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.
  • session.restriction_updated: the restriction starts, ending in 24 hours. Set restrictionActive to false for the event that ends it.
  • template.status: APPROVED. Set templateStatus to REJECTED and an optional reason to test a rejection.

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 session.restriction_updated 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. Send a message.received request to the recipient’s path, POST /messaging/my-test-number/test-events, and set fromNumber to the sender’s Number ID:
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. fromNumber must be a different Test number from the one in the path, and it 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