Overview

Your balance, recent activity, and a place to order a report without writing any code.

Available credit
Ready to spend right now
Residential reports left
 
Products
Reports
Aerial roof measurements
Live
Instant Squares
Instant roof size estimate
Coming soon

One balance and one set of API keys cover every product.

Recent orders
Loading…
Order a report

Same pipeline the API uses. Sandbox orders draw no balance.

Balance & billing

Reports draw against a prepaid balance. Your card is only charged when you top up — never per order.

Available credit

One number, and it's always the real one. Spend that Stripe hasn't finished deducting is already taken off, so this never briefly overstates itself while an order settles. It reads straight from Stripe on every load — add credit by hand in the Stripe dashboard and it shows up here on the next refresh.

Top up

Charges your default card and adds the amount to your balance immediately.

Payment methods
Loading…
Auto-recharge

Tops your balance up automatically so orders never fail for want of credit. Checked right after each order: if your balance has fallen below the threshold, your card is charged and the credit is added straight away.

If the balance has gone negative, the charge covers the shortfall as well as the amount above — one top-up always clears the threshold. A declined card switches auto-recharge off rather than retrying on every order.

Report branding

These are your defaults — used whenever a report is downloaded without branding of its own. You can also pass branding on the download itself (companyName, brandColor, brandTextColor, logoUrl as query params), which overrides everything here for that one file. See API docs → White labeling.

Setting a company name is what makes a report white-labeled: the header, footer, attribution and legal contact block all become yours. A small RoofQuery watermark stays in the footer. Leave the name blank and reports carry full RoofQuery branding. Either way it's applied at download time, so a change here re-skins reports you already ordered.

Leave the text color alone unless you need it — by default it's picked automatically for contrast against your brand color.

API keys

One key works across every RoofQuery product — they're account-wide, not per product. rq_live_sk_* keys draw real balance; rq_test_sk_* keys run sandbox timelines and never spend anything.

Loading…
Webhooks

Account-wide, not per product: one endpoint receives events from everything you use. Today that's the report stream, which carries every status change — switch on the payload's status field in your handler.

Loading…
Orders

Every order placed through the API or this dashboard.

Loading…
Sandbox

Sandbox orders are free — no credit is drawn and no card is charged. Order with a rq_test_sk_* key at any address below to trigger a specific timeline. Matching is case-insensitive, and coordinates within ~110m match too. Anything unlisted runs the unrecognized timeline. Override with the X-RoofQuery-Sandbox-Scenario header.

Loading…
What sandbox does and doesn't do
  • Sandbox and live are strictly separate. A rq_test_sk_* key can never place a real order, and a rq_live_sk_* key can never run a sandbox timeline. The environment comes from the key prefix, not from anything in your request, and an order is refused outright if the two ever disagree.
  • An unlisted address stays in sandbox. Order any address you like — out of coverage, made up, malformed. It runs the unrecognized timeline. There is no address that turns a sandbox order into a real one.
  • Sandbox never draws credit. Your balance is untouched and no card is charged, however many orders you place. The response still shows the real price so you can see what a live order would cost.
  • Completed sandbox orders carry genuine XML — same parser and same PDF path as live.
  • Webhooks fire for real against your configured endpoints.
  • payment_failed and order_failed return a 402/502 from the order call itself, because that's what happens in production. They never arrive as a webhook.
Instant Squares

Not available yet.

Coming soon

An instant roof-size estimate returned in the API response, with no measuring turnaround — for triage and quoting where a full measured report is more than you need.

Your existing API keys and webhook endpoints will cover it — those are account-wide, not per product, so there'll be nothing new to set up. It'll draw against the same balance too.

API reference

Base URL: https://api.roofquery.com. Authenticate with Authorization: Bearer <your key>.

Account-wide

One API key and one set of webhook endpoints cover every product, and every product draws on the same balance. These don't change as products are added.

MethodPathPurpose
GET/api/v1/identityWho the key belongs to, and whether it can order
GET/api/v1/balanceAvailable credit and per-product prices
GET/api/v1/webhooksList your endpoints
Reports
MethodPathPurpose
GET/api/v1/reports/pricingReport products and prices
POST/api/v1/reports/ordersPlace an order
GET/api/v1/reports/orders/:idOrder status and measurements
GET/api/v1/reports/orders/:id/statusThe same order, plus a resolved statusDetail block
GET/api/v1/reports/orders/:id/pdfBranded PDF (rendered per request)
GET/api/v1/reports/orders/:id/xmlDelivered XML, verbatim
POST/api/v1/reports/orders/:id/revisionsRequest a revision
GET/api/v1/reports/revision-optionsValid revision topics
GET/api/v1/reports/sandbox/scenariosSandbox addresses and timelines
Downloading a report

A completed order exposes two files. Each is fetched with the same key you ordered with, and each appears in the order payload's files[] array so you can hand the URLs straight to your own code.

FilePathWhat it is
report.pdf /orders/:id/pdf The white-labeled report. Served inline so you can iframe it; add ?download=1 to force a save dialog.
report.xml /orders/:id/xml The measurement document exactly as delivered, byte for byte.
curl -H "Authorization: Bearer rq_live_sk_..." \
  "https://api.roofquery.com/api/v1/reports/orders/rq_ord_abc123/pdf?download=1" \
  -o report.pdf

All three return 409 not_ready until the order reaches completed. Wait for the webhook rather than polling.

White labeling

Reports are white-labeled — they carry your brand. Set a company name and the header, footer, cover-page attribution and legal contact block all become yours; a small RoofQuery watermark remains in the footer. Leave it blank and the report falls back to full RoofQuery branding.

Two ways to supply it. Account-wide — set it once under Report branding and every report uses it. Per request — pass query params on the PDF URL to override the saved values for a single download, which is how you brand a report for one of your customers without touching your account settings.

ParameterExampleEffect
companyNameAcme%20RoofingHeader, footer, attribution and legal block. Setting this is what turns white labeling on. A small RoofQuery watermark stays in the footer.
brandColor%231668B8Header band, table headers, accents. Hex — remember to URL-encode the #.
brandTextColor%23ffffffText on the header band. Picked automatically for contrast if omitted.
logoUrlhttps://.../logo.pngLogo on the header band. Must be publicly fetchable.
curl -H "Authorization: Bearer rq_live_sk_..." \
  "https://api.roofquery.com/api/v1/reports/orders/rq_ord_abc123/pdf\
?companyName=Acme%20Roofing\
&brandColor=%231668B8\
&logoUrl=https://acme.example.com/logo.png" \
  -o acme-report.pdf

Nothing is cached — the PDF is rendered at the moment you request it. Change your branding and every report you've already ordered comes back re-skinned on its next download. The XML file carries no branding at all.

Order lifecycle
StatusMeaning
processingAccepted. First status you'll see.
in-progressMeasurement work has started.
on-holdPaused for clarification. Resolves on its own.
completedXML available, measurements populated, files listed.
updatedA completed report received new geometry.
cancelledEnded without delivery. The cost was refunded as account credit.
revisions_requestedA revision is open against a delivered report.
revision_completedThe corrected report has been re-delivered.

Insufficient balance and upstream rejections are not statuses — they come back as a 402/502 from the order call before an order exists, so there's nothing to webhook about.

Checking status

GET /api/v1/reports/orders/:id/status returns the entire order — property, report settings, billing, revisions, measurements and file links — plus a statusDetail block that answers the two questions you'd otherwise write a switch statement for.

{
  "orderId": "rq_ord_abc123",
  "status": "in-progress",
  "statusDetail": {
    "code": "in-progress",
    "label": "In progress",
    "description": "A technician is measuring the property.",
    "terminal": false,          // is anything further expected?
    "filesReady": false,        // can I download yet?
    "known": true,              // false if we add a status your code hasn't seen
    "changedAt": "2026-07-31T14:02:11.000Z",
    "estimatedDeliveryHours": 2,
    "estimatedReadyAt": "2026-07-31T15:47:00.000Z",
    "openRevisionId": null
  },
  "totals": null,               // populated once measured
  "files": []                   // populated once measured
}

status stays the same plain string it is in the webhook payload, so a handler written against webhooks works here unchanged. Turnaround is an estimate from the product's typical time — around 2 hours residential and 8 commercial — not a commitment, and it's only meaningful while the order is still moving.

Errors
CodeHTTPMeaning
unauthorized401Missing, invalid, or revoked key
validation400A field is missing or malformed
INSUFFICIENT_CREDITS402Available balance won't cover the report
BILLING_SETUP_REQUIRED402No card or balance on the account yet
ORDER_FAILED502Order could not be accepted; cost refunded as account credit
not_found404No such order on this account
not_ready409Report hasn't completed, so the file doesn't exist yet
REVISION_ALREADY_OPEN409One open revision per report