> ## Documentation Index
> Fetch the complete documentation index at: https://docs.roofkit.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Roof report requests

> Order a roof measurement report from a property address and read the measurements, the PDF, and the 3D model of the house.

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](https://docs.roofkit.ai/api-reference/reports/create-report-request.md) with the address and an `Idempotency-Key`. The response is `202` with `status: "preparing"`.
2. Poll [Get report request](https://docs.roofkit.ai/api-reference/reports/get-report-request.md), 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](#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

| Status | Meaning |
| - | - |
| `preparing` | The AI measures the roof. |
| `needs_attention` | The report waits for the workspace team in RoofKit. `attention_reason` tells why. |
| `rendering` | The report is registered. RoofKit makes the measurements, the PDF, and the 3D model. |
| `ready` | The deliverables are available. |
| `failed` | The deliverables failed three times, or the team archived the report before it was ready. `failure_code` tells why. |

`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

| Event | When |
| - | - |
| `report_request.ready` | Once, when the deliverables are made. Again when a create makes a failed 3D model again. |
| `report_request.needs_attention` | Each time the draft starts to wait for the team, and once when the request fails. |

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.

| Key | Content |
| - | - |
| `roof_material` | Roof finish of the report: `shingle`, `tile`, `metal`, or null before the team picks one. It is the new roof, not the roof that is there now. |
| `roof_area_sqft`, `roof_squares` | Measured roof area, before waste. Flat faces count. Slabs do not. |
| `sloped_area_sqft`, `sloped_squares` | Roof area of the faces that are not flat. |
| `flat_area_sqft`, `flat_squares` | Roof area of the flat faces. |
| `steep_slope_area_sqft`, `steep_slope_squares` | Roof area at 8/12 or steeper. |
| `predominant_pitch`, `predominant_pitch_rise` | Area-weighted pitch, such as `6/12`. |
| `facets` | Count of roof faces. |
| `suggested_waste_pct` | Waste that the roof shape suggests. |
| `waste_table` | Area and squares to order at each waste factor. Squares round up to a bundle, as in the PDF. |
| `area_by_pitch` | Area and share for each pitch. |
| `area_by_pitch_band_sqft` | `low` (6/12 and less), `mid` (7/12 to 9/12), and `steep` (10/12 and more). These are the labor bands. |
| `unpitched_area_sqft` | Area of faces with no pitch. These faces count as low. |
| `lengths_ft` | Line lengths in feet. See [Roof line names](#roof-line-names). |
| `penetrations` | Counts of `skylights`, `chimneys`, `vents`, and `pipe_boots`, or null. |
| `walls` | `perimeter_ft` and `gable_area_sqft`, or null. |
| `metal_panels` | `stock_ft`, `piece_count`, and `is_complete` for a metal panel layout, or null. |

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.

| Key | Name in the app and the PDF | Lines that it adds |
| - | - | - |
| `eaves` | Eaves | Eave |
| `eaves_flat` | None | Eave lines whose faces are all flat |
| `eaves_sloped` | None | All other eave lines, and eave lines with no face |
| `rakes` | Rakes | Rake |
| `ridges` | Ridges | Ridge |
| `hips` | Hips | Hip |
| `valleys` | Valleys | Valley |
| `step_flashing` | Step flashing | Step flashing and Sidewall |
| `wall_flashing` | Wall flashing | Apron flashing and Endwall |
| `parapets` | Parapet | Parapet |
| `slope_transitions` | Slope transition | Slope transition |
| `slope_transitions_pitch_to_pitch` | None | Slope transition lines between two sloped faces |
| `slope_transitions_flat_to_pitch` | None | Slope transition lines with a flat face on one side |
| `drip_edge` | Drip edge | Eaves plus rakes |
| `starter` | None | Eaves plus rakes |
| `ridge_cap` | Ridge cap | Ridges plus hips |
| `ridge_vent` | None | Ridges |

* `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.

| JobNimbus token | Key |
| - | - |
| Sloped Roof Squares (SQ) | `sloped_squares` |
| Flat Roof Squares (SQ) | `flat_squares` |
| Flat Roof Eaves (LF) | `lengths_ft.eaves_flat` |
| Total Eaves (Non Flat) (LF) | `lengths_ft.eaves_sloped` |
| Total Ridges (LF) | `lengths_ft.ridges` |
| Total Hips (LF) | `lengths_ft.hips` |
| Total Valleys (LF) | `lengths_ft.valleys` |
| Total Rakes (LF) | `lengths_ft.rakes` |
| Total Sidewall (LF) | `lengths_ft.step_flashing` |
| Total Headwall (LF) | `lengths_ft.wall_flashing` |
| Pitch-to-Pitch Slope Transition (LF) | `lengths_ft.slope_transitions_pitch_to_pitch` |
| Flat-to-Pitch Slope Transition (LF) | `lengths_ft.slope_transitions_flat_to_pitch` |
| Ridge Vent (LF) | `lengths_ft.ridge_vent` |
| Steep Squares (SQ) | `steep_slope_squares`, from 8/12. For another limit, add the `area_by_pitch` rows. |

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](https://docs.roofkit.ai/api-reference/reports/download-report-request-3d-model.md) 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.

```html theme={null}
<script type="module" src="https://cdn.jsdelivr.net/npm/@google/model-viewer@3.5.0/dist/model-viewer.min.js"></script>
<model-viewer
  src="https://your-site.example/models/house.glb"
  alt="3D model of the roof"
  camera-controls
  touch-action="pan-y"
  max-camera-orbit="auto 85deg auto"
  shadow-intensity="1"
  style="width: 100%; height: 480px"
></model-viewer>
```

* `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.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.