Your users already have a job record with an address on it. The feature they want is a button on that record that produces a measured roof, under your brand, with the numbers flowing straight into the estimate. This guide is how to build that on RoofQuery, and the decisions that are yours to make rather than ours.
What does the integration look like?
Five calls, in this order.
- Order. When a user clicks the button, POST the job's address and coordinates with a
scope. Store the returned order id on the job. - Show progress. The order starts
processingand moves toin-progresswhen a technician picks it up. Surface that on the job so the rep knows it is coming. - Receive. The
completedwebhook carries every measurement. Write squares, pitch areas and edge lengths into your estimate model directly from the webhook body. No second call. - Present. Link the PDF from the job with the contractor's brand profile on it, so their customer sees their company and logo.
- Correct. Give the user a "request a revision" action. It is free, and the original stays available while it is redone.
Who pays, and how much?
RoofQuery charges your account $13 per residential report and $35 per commercial, from a prepaid balance with auto-recharge. What you charge your users is your call. Common models: a per-report fee with margin, a bundle of reports in a plan tier, or free reports as a retention feature funded by the subscription. The API does not care which. Pricing is also available from the API, so your product can show it without hardcoding.
How does branding work with many contractors?
One brand profile per contractor. When a contractor signs
up to your platform, create a profile with their name, contact details, colors and logo, and
store the profile id on their record. Every PDF link for their jobs carries
?brand=<their id>, and their customer sees their company, logo included.
Your own account defaults never change. Read
how white-label branding works before
you design the settings screen.
Which scope should the button use?
Ask the user, or default sensibly per job type. A re-roof quote usually wants
all_structures; a storm inspection on the main house may only want
primary_only. There is no server-side default on purpose.
How do report fields map to estimate lines?
| Estimate line | Drive it from |
|---|---|
| Shingles or membrane | totalSquares, plus your waste factor by complexity |
| Steep-slope labour | pitchAreas above your steep threshold |
| Drip edge and starter | edgeTotals.EAVE + edgeTotals.RAKE |
| Ridge cap and vent | hipsAndRidgesLengthFt |
| Ice and water, valley metal | edgeTotals.VALLEY |
| Step and wall flashing | edgeTotals.STEP_FLASHING, edgeTotals.WALL_FLASHING |
| Detached garage as a separate option | structures[1] onward |
The fields are defined under report data and in the glossary.
Which edge cases need handling?
- Cancelled orders. Unmeasurable property. Show the reason, clear the pending state, and note that the cost came back as credit.
- Redeliveries. A corrected report arrives as an
updatedevent on an order that is stillcompleted. Re-download, and re-run any estimate maths. The lifecycle reference explains the alternation. - Insufficient balance. A 402 on the order call, before an order exists. Auto-recharge makes it rare; a clear error makes it harmless.
Build the whole thing in sandbox first. The test addresses run the happy path, a commercial roof, a cancelled order and a failed payment in seconds, with real webhooks. Testing in sandbox has the details.
Frequently asked questions
Can a roofing CRM resell RoofQuery reports?
Yes. There is no reseller agreement to sign and no minimum. Reports are $13 residential and $35 commercial to your account, and you set your own price to your users.
Can each contractor on my platform have their own branding?
Yes, including their logo. Create a brand profile per contractor and put its id on their PDF links.
How long does the integration take?
The core is five calls and a webhook handler. Most teams have a working sandbox integration in a day, because the sandbox runs the whole lifecycle in seconds.