Base URL: https://api.roofquery.com. Authenticate with Authorization: Bearer <your key> — except the file routes (report and storm report files), which take no key.
Copies this whole page as Markdown, so you can paste it into an assistant and have it write the integration. Nothing secret goes on the clipboard — your keys aren't included.
Places an order and returns 201 with the order in its initial state.
Measurements arrive later — wait for the completed webhook rather than
polling.
| Field | Required | Description |
|---|---|---|
country | Yes | US or CA. Validated first — every other field depends on it |
street | Yes | string |
city | Yes | string |
state | Yes | 2-letter state or province abbreviation |
postalCode | Yes | US 12345 or 12345-6789; CA A1A 1A1. Format only — we don't check it agrees with the state |
latitude | Yes | number, −90 to 90 |
longitude | Yes | number, −180 to 180 |
scope | Yes | primary_only, primary_and_garage, or all_structures. Not defaulted |
reportType | No | residential (default), commercial, rapid_squares (Rapid Squares), or storm (Storm Reports, which take their own fields) |
esx | No | true to include the Xactimate .esx (+$5, or your account's ESX price in pricing), false to leave it out. Left out, your account's default applies (see esx.default in pricing; you can change it under Balance & billing). Residential and commercial only: true on rapid_squares is 400 ESX_NOT_SUPPORTED. You can also add it later |
brand | No | The contractor this order is for: a brand profile id. Its PDF carries that brand for good, and a download link can't change it. Left out, the report carries your account's own branding, also for good. An id that isn't one of your profiles is 400 BRAND_NOT_FOUND and nothing is ordered |
claim | No | Claim number for the job, up to 64 characters. It goes on the Xactimate .esx, and the file downloads as <claim>.esx — see the ESX endpoint. Set here or not at all |
notes | No | Free text for the technician |
Send an Idempotency-Key header (8–200 characters of letters, digits and
_ . : -) and a retry with the same key never places a second order. It returns the
first order with 200 instead of 201, even if the retry's body differs. While
the first attempt is still being placed, a retry gets 409 ORDER_IN_PROGRESS; if it
failed, 502 ORDER_FAILED with nothing charged, and a new key places a new order.
curl -X POST "https://api.roofquery.com/api/v1/reports/orders" \
-H "Idempotency-Key: henderson-6515-turnbridge" \
-H "Authorization: Bearer rq_live_sk_..." \
-H "Content-Type: application/json" \
-d '{
"country": "US",
"street": "6515 Turnbridge Pl",
"city": "Prospect",
"state": "KY",
"postalCode": "40059",
"latitude": 38.3526391,
"longitude": -85.6208045,
"scope": "primary_and_garage",
"reportType": "residential",
"esx": true,
"brand": "rq_brand_7f3a21c9d4e07b16",
"claim": "CLAIM12345",
"notes": "Detached garage at rear."
}'
201 Created. totals, structures and files are empty until the report is delivered. billing.amount is the whole charge, and billing.items breaks it down: the report, and the ESX when the order pays for one.
{
"orderId": "rq_ord_8f3a21c9d4e07b16",
"status": "processing",
"previousStatus": null,
"event": null,
"reason": null,
"sandbox": false,
"sandboxScenario": null,
"createdAt": "2026-08-12T14:03:11.000Z",
"updatedAt": "2026-08-12T14:03:11.000Z",
"completedAt": null,
"property": {
"address": "6515 Turnbridge Pl, Prospect, KY 40059, USA",
"latitude": 38.3526391,
"longitude": -85.6208045
},
"report": {
"type": "residential",
"brand": { "id": "rq_brand_7f3a21c9d4e07b16", "companyName": "Acme Roofing" },
"claim": "CLAIM12345",
"scope": "primary_and_garage",
"scopeLabel": "Primary structure and detached garage",
"notes": "Detached garage at rear.",
"format": "xml",
"esxIncluded": true
},
"billing": {
"amount": 15,
"currency": "usd",
"method": "account_balance",
"holdReference": "rq_ord_8f3a21c9d4e07b16",
"items": [
{ "item": "report", "amount": 10 },
{ "item": "esx", "amount": 5 }
],
"refunded": false,
"released": false
},
"revisions": [],
"totals": null,
"structures": null,
"files": []
}
Sandbox. A rq_test_sk_* key runs a scheduled timeline
against your real webhooks and nothing is measured. The scenario is chosen by
the address you order and nothing else — see
sandbox scenarios. There is no header
or body field that forces one, so a sandbox order and a live order are the same
request; only the key differs. esx works the same as live, including
your account's default, and nothing is charged.
validation and VALIDATION (400) for a missing or malformed field,
ESX_NOT_SUPPORTED (400) for "esx": true on Rapid Squares,
BRAND_NOT_FOUND (400) for a brand that isn't one of your profiles,
INSUFFICIENT_CREDITS and BILLING_SETUP_REQUIRED (402),
PRODUCT_NOT_ENABLED (403) for a beta product not turned on for the account, and
ORDER_FAILED (502). Every code is under Errors.