Skip to main content
The sandbox is a safe practice environment. Use it while building and testing your integration.
Sandbox and live data are completely separate. A recipient or delivery created in the sandbox does not exist in live mode. Sandbox responses make this visible:

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.
You can safely use example names, numbers, and addresses that meet validation rules. Avoid copying real customer data into a test environment unless you need it and are permitted to do so.

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 at booked. In real life, riders and operations move the status forward. In the sandbox, call the transition helper yourself.
The allowed order is:
Deliveries created with 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:
  • booked directly to delivered;
  • delivered back to in_transit;
  • any transition after a terminal state.
An invalid change returns 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.
Keep using manual transitions for automated tests that need exact control over timing.

Start a simulation when you create the delivery

Add a sandbox object to POST /deliveries, or to any item of POST /deliveries/bulk:
  • scenario is required. Pick one from the table below.
  • step_delay_seconds is 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

The response is 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 with failed_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 a simulation 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

The delivery stays at whatever status it had reached. Calling it again is safe and returns the delivery unchanged.

Simulations and manual changes

While a simulation is running, the sandbox owns the delivery’s next steps:
  • POST /test-helpers/deliveries/{id}/transition and /settle return 409 SIMULATION_RUNNING. Stop the simulation first, then continue by hand.
  • A second simulate call on the same delivery also returns 409 SIMULATION_RUNNING.
  • POST /deliveries/{id}/cancel still 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_LIMIT until 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:
  1. Create a separate live key beginning with hsg_live_key_.
  2. Change the base URL to https://developer.haulstow.co/v1.
  3. Keep your request JSON and response parsing the same.
  4. Remove any calls to /test-helpers/...; that route exists only on the sandbox host.
  5. Start with a controlled real delivery and monitor its webhook or polling flow.
Never make your code automatically fall back from sandbox to live or from live to sandbox.