Journeys Simulation API
The Journeys Simulation API allows external systems (such as AI agents) to interact with journeys conversationally without sending real WhatsApp messages. This is useful for testing, previewing, and integrating journey logic into external workflows.
This API is under active development and breaking changes are expected over the coming months. Backwards compatibility is not guaranteed until at least August 2026.
Authentication happens as per all other API calls with a Turn.io token specified
in the HTTP Authorization header prefixed with Bearer and followed by a token issued by the Turn.io user interface.
How it works
The simulation endpoint uses a single POST route that handles both creating new simulations and submitting input to existing ones:
- If no simulation exists for the given
simulation_id: a new simulation session is created and the journey starts executing. - If a simulation already exists for the given
simulation_id: the providedinputis submitted to the existing session.
The simulation_id is always required and provided by the caller. It can be any string identifier between 6 and 24 characters. The endpoint uses the combination of the journey UUID (from the URL) and the simulation_id (from the body) to identify simulation sessions.
Starting a simulation
To start a new simulation, make the following request:
$ curl -X POST "https://whatsapp.turn.io/v1/stacks/<journey-uuid>/simulation" \
-H "Authorization: Bearer token" \
-H "Content-Type: application/json" \
-d '{
"simulation_id": "my-session-001",
"revision": "production",
"contact": {
"name": "Test User",
"language": "eng"
}
}'
> {
"simulation_id": "my-session-001",
"state": "waiting_for_input",
"message": "Welcome! What is your name?",
"context": {
"contact": {
"name": "Test User",
"language": "eng"
}
}
}
Parameters
| Name | Required | Default | Description |
|---|---|---|---|
| simulation_id | yes | A caller-provided string identifier (6 to 24 characters) used to track the simulation session. | |
| revision | no | "production" | Which revision of the journey to simulate. Must be "production" or "staging". |
| contact | no | {} | An object of contact attributes to populate the simulated contact context. |
| input | no | Optional initial input to provide when starting the simulation. |
Response fields
| Name | Description |
|---|---|
| simulation_id | The simulation session identifier. |
| state | The current state of the simulation: "waiting_for_input" (journey expects a reply) or "end" (journey has finished). |
| message | The text output from the journey. Includes message content, button options, and media URLs. |
| context | The current variable context of the simulation, including contact fields and any variables set by the journey. |
Submitting input to a simulation
Once a simulation is in the waiting_for_input state, submit user input by making another request with the same simulation_id:
$ curl -X POST "https://whatsapp.turn.io/v1/stacks/<journey-uuid>/simulation" \
-H "Authorization: Bearer token" \
-H "Content-Type: application/json" \
-d '{
"simulation_id": "my-session-001",
"input": "Santiago"
}'
> {
"simulation_id": "my-session-001",
"state": "end",
"message": "Thanks Santiago! Your registration is complete."
}
Parameters
| Name | Required | Description |
|---|---|---|
| simulation_id | yes | The same simulation ID used when starting the session. |
| input | yes | The user's response as a string. Must be non-empty. |
Multi-turn example
A typical multi-turn simulation involves starting the journey and then submitting input for each step that requires a response.
Step 1: Start the journey
$ curl -X POST "https://whatsapp.turn.io/v1/stacks/d144cb30-f759-4260-82ba-07353f0e389f/simulation" \
-H "Authorization: Bearer token" \
-H "Content-Type: application/json" \
-d '{
"simulation_id": "demo-session-01",
"revision": "production",
"contact": {
"name": "Maria",
"language": "eng"
}
}'
> {
"simulation_id": "demo-session-01",
"state": "waiting_for_input",
"message": "Hi Maria! How can we help you today?\n\nExclusively reply with one of the following options:\nBook appointment, Check status, Speak to agent",
"context": {
"contact": {
"name": "Maria",
"language": "eng"
}
}
}
Step 2: Submit user input
$ curl -X POST "https://whatsapp.turn.io/v1/stacks/d144cb30-f759-4260-82ba-07353f0e389f/simulation" \
-H "Authorization: Bearer token" \
-H "Content-Type: application/json" \
-d '{
"simulation_id": "demo-session-01",
"input": "Book appointment"
}'
> {
"simulation_id": "demo-session-01",
"state": "waiting_for_input",
"message": "Great! What date works for you?"
}
Step 3: Continue the conversation
$ curl -X POST "https://whatsapp.turn.io/v1/stacks/d144cb30-f759-4260-82ba-07353f0e389f/simulation" \
-H "Authorization: Bearer token" \
-H "Content-Type: application/json" \
-d '{
"simulation_id": "demo-session-01",
"input": "Next Monday"
}'
> {
"simulation_id": "demo-session-01",
"state": "end",
"message": "Your appointment is booked for next Monday. See you then!"
}
Error responses
The API returns appropriate HTTP status codes and error messages:
| Status | Error | Description |
|---|---|---|
| 400 | simulation_id is required | The simulation_id field is missing from the request body. |
| 400 | simulation_id must be between 6 and 24 characters | The simulation_id is too short or too long. |
| 400 | Invalid Journey UUID | The journey UUID in the URL is not a valid UUID. |
| 400 | Journey has no published production revision | The journey does not have a published production revision. |
| 400 | Journey has no staging revision | The journey does not have a staging revision (when revision is "staging"). |
| 400 | Journey is disabled | The journey is currently disabled. |
| 400 | Journey has been deleted | The journey has been deleted. |
| 400 | Invalid revision, must be 'production' or 'staging' | An invalid revision value was provided. |
| 400 | Invalid input, must be a non-empty string | The input field is empty or not a string. |
| 404 | Journey not found | No journey exists with the given UUID. |
| 404 | Simulation not found or expired | The simulation session has expired or does not exist. |
Notes
- Simulation sessions are ephemeral and will expire after a period of inactivity. If a session expires, start a new one with a fresh
simulation_id. - No real WhatsApp messages are sent during a simulation. The journey logic is executed in-memory.
- Media content (images, videos, audio, documents) in journey messages is returned as descriptive text with URLs, for example:
"Image available at: https://...". - When the journey includes button or list options, they are appended to the message text, for example:
"Exclusively reply with one of the following options: Option1, Option2". - AI agent blocks with memory enabled will persist conversation context across simulation turns, allowing the AI to reference earlier messages in the session.