# Testing a roof report integration in sandbox before you spend

> RoofQuery sandbox keys run the complete order lifecycle in seconds against published test addresses, at no cost. Each address delivers a real roof recorded from a real property, through the same parser and PDF renderer a live order uses. Scenarios cover the happy path, a commercial flat roof, a failed payment and a cancelled order. Any completed sandbox order can be revised, and webhooks arrive in the same order and shape as live.

Category: Getting started. Last updated 2026-09-09.
Canonical: https://roofquery.com/guides/testing-in-sandbox-before-you-spend

The sandbox is not a mock. Every test address delivers a real roof, recorded from a real property and run through the same parser and PDF renderer a live order uses. What is scripted is the timing, so you can watch a complete order lifecycle in seconds instead of hours. The reference is the [sandbox scenarios endpoint](https://roofquery.com/docs/sandbox).

## How is a scenario chosen?

By the address you order. With a sandbox key, matching a published test address exactly, or by coordinates within about 110 metres, runs that scenario's timeline. Any address not on the list runs the `cancelled` timeline. There is no address that turns a sandbox order into a real one, and no header or body field that forces a scenario. A sandbox request and a live request are the same request; only the key differs.

The list is published in-band, so your code can discover it without leaving the API:

```
curl -H "Authorization: Bearer rq_test_sk_..." \
  "https://api.roofquery.com/api/v1/reports/sandbox/scenarios"
```

## What do the scenarios cover?

| Scenario | What happens | What it tests |
| --- | --- | --- |
| Happy path | `processing`, `in-progress`, `completed` over about 20 seconds. A residential roof with files. | The normal flow, file downloads, parsing |
| Happy path, commercial | Same timeline on a recorded flat roof. | Parapet walls, a commercial PDF and XML |
| Payment failed | The order call itself fails. No order row, no webhook. | Your handling of a rejected order call |
| Cancelled | Any unlisted address. Accepted, then ended without delivery, with a reason and a credit refund. | The unmeasurable-property path |

## When do webhooks arrive?

About five seconds after each transition, held back on purpose so the HTTP response to the call that caused a change always arrives before the webhook announcing it. Code that stores the order id from the response and then looks it up when the webhook lands will never see the webhook first. Live orders follow the same rule.

## Can I test revisions?

Yes, on any sandbox order that reaches `completed`. Open a revision and you get `revisions_requested` immediately and `revision_completed` about fifteen seconds later, the same two webhooks a live revision sends. The previously delivered files stay downloadable throughout. See the [revisions reference](https://roofquery.com/docs/revisions) for the rules.

## Can I see the files without ordering?

Yes. The Sandbox page in the dashboard lists every scenario with its PDF, XML and ESX. If you are writing a parser, pull the XML from there first; it is the same document a live order delivers.

> Keep the sandbox key in your staging environment after launch. Sandbox orders never draw balance, so every deploy can be smoke-tested end to end without spending anything.

Next: [order your first report](https://roofquery.com/guides/how-to-order-your-first-roof-report), then read the [order lifecycle](https://roofquery.com/docs/order-lifecycle).

## Frequently asked questions

### Is the RoofQuery sandbox free?

Yes. Sandbox orders never draw balance, and there is no limit on how many you place while building.

### Are sandbox reports real roofs?

Yes. Each test address delivers a roof recorded from a real property, through the same parser and PDF renderer a live order uses. Only the timing is scripted.

### Can a sandbox key place a live order by mistake?

No. Sandbox and live keys are strictly separated. No address and no field turns a sandbox order into a real one.
