What the sandbox does not do
It does not:- dispatch a real rider;
- send SMS, email, or push notifications to a recipient;
- charge or collect money;
- create invoices or accounting entries;
- reserve stock;
- change a live order;
- provide a live tracking link.
Deterministic quotes
Sandbox prices are fixed test values based on straight-line distance. They are designed to make tests predictable, not to forecast the exact price of a future live delivery.
A trip over 15 km returns:
Simulate status changes
When you create a sandbox delivery, it starts atbooked. In real life, riders and operations move the status forward. In the sandbox, call the transition helper yourself.
POST /deliveries/bulk also start at booked and use the same helper, one delivery at a time.
booked and assigned may also move to cancelled or outsourced. in_transit may move to failed. A failed delivery may move back to assigned, which is how a live delivery is retried after a failed attempt. An outsourced delivery may move to delivered.
Each call moves exactly one step. For example, these are invalid:
bookeddirectly todelivered;deliveredback toin_transit;- any transition after a terminal state.
409 SANDBOX_TRANSITION_INVALID.
Each accepted transition creates the same versioned event and signed webhook shape used in live mode. That makes the sandbox suitable for testing deduplication, ordering, signature verification, and terminal-state handling.
Automatic simulation
Manual transitions are perfect for tests that must be exact and repeatable. They do not show you what a real delivery feels like: statuses changing on their own, webhooks arriving over several minutes, money collected at the door and paid out later. An automatic simulation does that for you. You pick a named scenario and the sandbox moves the delivery one step at a time, sending the same signed webhooks, in the same order, that a live delivery would send. Use it when you want to:- watch your webhook handler deal with a realistic stream of events;
- try a case that is hard to set up by hand, such as a failed attempt that is retried;
- demo your integration without clicking through every status yourself.
Start a simulation when you create the delivery
Add asandbox object to POST /deliveries, or to any item of POST /deliveries/bulk:
scenariois required. Pick one from the table below.step_delay_secondsis optional. It is the wait before each step, from 1 to 60 seconds. The default is 5.
sandbox works only with a test key. If a live key sends it, the request fails with 400 SANDBOX_ONLY_FIELD and nothing is created, so a test payload can never run against live by accident.
Start a simulation on an existing delivery
202 Accepted with the delivery. The scenario picks up from the delivery’s current status. For example, delivered on an in_transit delivery has just one step left. If the current status is not a point the scenario passes through, the call returns 409 SIMULATION_NOT_APPLICABLE.
Scenarios
Whenever a delivery reaches
delivered with money due at the door, delivery.payment_collected follows straight after delivery.delivered, exactly as it does with a manual transition. In cod_partial_collection the collection comes one step later and its collection.status is partially_collected, with amount_collected showing what the rider took.
Every scenario uses only event sequences a live delivery can produce, so what you test here is what you will see in production.
Example timeline
Here is what your webhook endpoint receives for a COD delivery created withfailed_then_retried and step_delay_seconds: 5:
The
sequence number keeps rising across the retry, so a handler that ignores older sequences works without changes. Times are approximate: a step can run up to about a second after it is due.
Watch progress
While a simulation exists, sandbox delivery responses include asimulation object. It is null on a sandbox delivery that never had one, and live deliveries do not have the field at all.
status is one of:
running: steps are still being taken;completed: every step ran;stopped: you stopped it, the delivery was cancelled, or it ran for more than 24 hours;failed: a step could not be applied, so the simulation ended where it was.
Stop a simulation
Simulations and manual changes
While a simulation isrunning, the sandbox owns the delivery’s next steps:
POST /test-helpers/deliveries/{id}/transitionand/settlereturn409 SIMULATION_RUNNING. Stop the simulation first, then continue by hand.- A second
simulatecall on the same delivery also returns409 SIMULATION_RUNNING. POST /deliveries/{id}/cancelstill works, because a real customer can cancel at any time before pickup. Cancelling stops the simulation.
Limits
- One application can have up to 100 running simulations. Starting another returns
429 SIMULATION_LIMITuntil some finish or you stop them. - A simulation that is still running 24 hours after it started is stopped automatically.
Moving to live mode
When your sandbox flow works:- Create a separate live key beginning with
hsg_live_key_. - Change the base URL to
https://developer.haulstow.co/v1. - Keep your request JSON and response parsing the same.
- Remove any calls to
/test-helpers/...; that route exists only on the sandbox host. - Start with a controlled real delivery and monitor its webhook or polling flow.
