Base URL: https://api.roofquery.com. Authenticate with Authorization: Bearer <your key> — except the four file routes, 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 | Rules |
|---|---|---|
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) or commercial |
reportName | No | Your own label, printed on the report |
claim | No | Claim number for the job, up to 64 characters. The annotators put it 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 |
clientInfo | No | Object. Only firstName, lastName, email, phone, street, city, state, county are kept — anything else is dropped. 200 chars each |
curl -X POST "https://api.roofquery.com/api/v1/reports/orders" \
-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",
"reportName": "Henderson — 6515 Turnbridge",
"claim": "CLAIM12345",
"notes": "Detached garage at rear.",
"clientInfo": {
"firstName": "Dana",
"lastName": "Henderson",
"email": "[email protected]",
"phone": "502-555-0148"
}
}'
201 Created. totals, structures and files are empty until the report is delivered.
{
"orderId": "rq_ord_8f3a21c9",
"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",
"name": "Henderson — 6515 Turnbridge",
"claim": "CLAIM12345",
"scope": "primary_and_garage",
"scopeLabel": "Primary structure and detached garage",
"notes": "Detached garage at rear.",
"format": "xml"
},
"clientInfo": {
"firstName": "Dana",
"lastName": "Henderson",
"email": "[email protected]",
"phone": "502-555-0148"
},
"billing": {
"amount": 13,
"currency": "usd",
"method": "account_balance",
"holdReference": "rq_ord_8f3a21c9",
"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 never contacts the provider. 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.