Skip to main content
A report request creates a roof measurement report from a US property address. A scheduling tool calls it when an inspection is booked. The report takes about 15 minutes, so the API is asynchronous.

Flow

  1. Create report request with the address and an Idempotency-Key. The response is 202 with status: "preparing".
  2. Poll Get report request, or subscribe a workspace webhook endpoint to the request events.
  3. When status is ready, read measurements, download report_pdf, and download the 3D model of the house from render_3d.download_url. See 3D model.
The workspace plan must include Reports. The create needs the reports.write scope. The reads need reports.read. Any key of the workspace with reports.read can read a request, so a key rotation keeps the requests of the old key.

Create rules

  • address is required and must look like a US property address.
  • lat and lng are optional, but they must come together. Without them, RoofKit locates the address, or the Google Places place_id when you send it.
  • An address that RoofKit cannot locate returns 400 VALIDATION_ERROR. Send lat and lng with the address.
  • external_report_id is your id, such as the inspection id. A live request with the same id answers the create with 200 and reused: true. A failed request does not count.
  • roof_material is shingle, tile, or metal. Without it, the workspace team chooses the finish later in RoofKit.
  • The same Idempotency-Key and payload replay the first response with Idempotency-Replayed: true. A replay starts nothing.
A workspace can also create requests from JobNimbus, without a partner call. Such a request has source: "jobnimbus" and takes the JobNimbus job id as external_report_id. If you send the same job id, you get that same request, so one booking never buys two reports.

Status

attention_reason values:
  • needs_outline: the AI could not trace the roof. A team member draws the outline in RoofKit, then the run continues.
  • preparation_failed: a stage stopped. A team member retries it in RoofKit.
  • insufficient_credits: the run is parked until the workspace buys credits and retries.
Each deliverable can fail alone. The request is then ready with report_pdf_failure_code or render_3d.failure_code. To make a failed or missing 3D model again, create the request again with the same external_report_id. The answer is 200 with reused: true, and the request goes back to rendering. Its measurements and PDF stay the same. You can do this three times per request.

Notifications

The workspace owner selects the events in Settings for your endpoint. data.details carries request_id and external_report_id. report_request.ready also carries source, revision_id, and pdf_export_id. report_request.needs_attention carries reason.

Credits

  • The create checks the report price first. A workspace that cannot pay gets 402 INSUFFICIENT_CREDITS and no draft.
  • The run charges the AI outline and the report, as the address flow of the app does.
  • The PDF charges one export per revision. The 3D model has no charge.

Measurements

The measurements are the figures that the app prints and prices for the delivered revision. Keys are stable snake_case with the unit in the name. Areas are in square feet. Lengths are in feet. version changes only when a key is renamed or removed. A squares value is its area divided by 100, to two decimals. Each value rounds alone, so sloped_squares plus flat_squares can differ from roof_squares by 0.01.

Flat and steep slope

  • A face is flat when the team marks it as a flat roof, or when its rise is less than 2/12. The rise rounds to a whole number first, so a face at 1.6/12 reads as 2/12 and is sloped.
  • A face without a pitch is not flat.
  • Steep slope starts at 8/12, where a crew cannot walk the roof.
  • The steep band of area_by_pitch_band_sqft starts at 10/12. It is the labor band of the price book.

Roof line names

The lengths_ft keys are the stable names of the roof lines. Every key is always present. A key is 0 when the roof has no such line.
  • eaves_flat plus eaves_sloped is eaves. The two slope transition keys add up to slope_transitions.
  • drip_edge, starter, ridge_cap, and ridge_vent follow the price book rules.
  • A reference line only marks the roof. It takes no trim, so no key counts it.

JobNimbus measurement tokens

These JobNimbus measurement tokens map to a measurement key. Fees, dump, tear-off, and permit tokens depend on rules outside the roof, such as the current roof material or the distance from the contractor. Compute them on your side.

3D model

The 3D model is a GLB file (binary glTF) of the house: the walls, the roof with the report finish, the trim, the gutters, and the openings. It has no lawn, sky, or trees. It is in meters, so AR shows the house at its real size. Download report request 3D model with your API key. It redirects (307) to the file. The storage URL does not expire, so treat it as a secret, and call the route again when you need the file. RoofKit serves no public link to the model. Host the file on your side and show it with Google’s <model-viewer>. The visitor drags to turn the house, and pinches or scrolls to zoom.
  • max-camera-orbit keeps the camera above the ground, as in the RoofKit editor.
  • touch-action="pan-y" lets a vertical swipe scroll your page on a phone. A horizontal swipe turns the house.
  • The test house gave a file of about 4.4 MB.
  • A request made before October 29, 2026 has an image, not a model. It reads render_3d.status: "failed" with failure_code: "model_missing". Create it again with the same external_report_id to make the model.