Skip to content
TruTecDevelopers
Get an API key

Saved measurements & imagery

Read the takeoffs your team saved in TruTec, download their map exports and imagery, and find out which imagery they were measured on.

View as Markdown

A saved measurement is a takeoff saved in the TruTec app, including every edit your estimators made. These endpoints read them.

Detection calls (/detect/full, /detect/address, /detect/tiles) do not create saved measurements. Store detection results in your own database, or fetch an async result again from GET /v1/detect/status/{job_id}. See Measure a site.

All endpoints on this page need the Read measurements permission, except the tile and map picture URLs, which carry their own token.

Endpoints#

List saved measurements#

GET /v1/measurements

Permission: Read measurements

Returns your workspace's saved measurements, newest first.

Name Type Required Description
job_id integer No Only measurements on this job.
limit integer No Page size. Default 50, maximum 100.
offset integer No Rows to skip. Default 0.
curl "https://trutec.ai/api/v1/measurements?job_id=4812&limit=20" \
  -H "X-API-Key: sk_your_api_key_here"
{
  "data": [
    {
      "id": 90311,
      "name": "Northgate Plaza - Takeoff",
      "type": "parking_lot",
      "job_id": 4812,
      "area": 186420.4,
      "created_at": "2026-10-08T14:22:51.318204"
    }
  ],
  "pagination": {"total": 1, "limit": 20, "offset": 0}
}

area is the total drawn area in square feet. created_at is UTC.

Get a saved measurement#

GET /v1/measurements/{measurement_id}

Permission: Read measurements

Returns the takeoff as it is saved now, with quantities per category, per area and per phase.

Name Type Required Description
measurement_id integer (path) Yes From the list.
unit string No Area unit for counter_summary values: sf (default), sy, sm or acres.
curl "https://trutec.ai/api/v1/measurements/90311?unit=sf" \
  -H "X-API-Key: sk_your_api_key_here"
{
  "data": {
    "id": 90311,
    "name": "Northgate Plaza - Takeoff",
    "type": "parking_lot",
    "area": 186420.4,
    "created_at": "2026-10-08T14:22:51.318204",
    "counter_summary": {
      "stalls": {
        "label": "Stalls",
        "data_type": "marker",
        "default_display": "count",
        "count": 401,
        "formatted": "401",
        "values": {
          "count": {"value": 401, "formatted": "401"},
          "linear_feet": {"value": 7140.0, "unit": "LF", "formatted": "7,140 LF"}
        },
        "linear_feet": 7140
      }
    },
    "parking_areas": [
      {
        "id": "area-1",
        "type": "parking_detection",
        "phase": "Phase 1",
        "spec": null,
        "area_sqft": 154210.4,
        "rings": [[[30.40104, -97.72225], [30.40101, -97.72066], [30.39993, -97.72068], [30.39996, -97.72229]]],
        "is_hole": false,
        "is_carport": false,
        "is_concrete": false,
        "is_sidewalk": false,
        "objects_counted": true
      }
    ],
    "phases": [
      {"name": "Phase 1", "area_sqft": 154210.4, "areas": [], "specs": {}, "striping": {}}
    ],
    "deducted_counts": {"stalls": 401},
    "measurement_types_by_object": {},
    "striping_by_phase": {},
    "custom_items_summary": {},
    "geometry": {},
    "metrics": {}
  }
}
Field Description
counter_summary One entry per category, same shape as in a detection result. See Measurement result reference. Labels use your workspace's names.
parking_areas[] Every drawn area: type, phase, spec (the surface spec chosen in the app, if any), area_sqft, rings ([lat, lng], first ring is the outline), and flags for holes, carports, concrete and sidewalk.
phases[] Drawn areas grouped by phase, with area_sqft (holes excluded), area per spec in specs, and striping quantities in striping.
deducted_counts Final count per category.
striping_by_phase Striping quantities split by phase.
custom_items_summary Custom items your team added in the app.
geometry, metrics The raw data the app saves. Their shape can change; use the fields above where you can.

Returns 404 {"error": "Measurement not found"} when the id doesn't exist or belongs to another workspace, and 403 {"error": "API key lacks measurement read permission"} without Read measurements.

Download the map export#

GET /v1/measurements/{measurement_id}/export-image

Permission: Read measurements

Downloads the rendered aerial map with the takeoff drawn on it and your logo, as in the app's map export.

Name Type Required Description
measurement_id integer (path) Yes
format string No png (default) or pdf.
curl -o northgate-map.png \
  "https://trutec.ai/api/v1/measurements/90311/export-image?format=png" \
  -H "X-API-Key: sk_your_api_key_here"

The response is the file, sent as a download. Headers X-TruTec-Measurement-Id, X-TruTec-Job-Id and X-TruTec-Project-Id (when set) identify it.

Status error
400 format must be either pdf or png
404 Measurement not found
422 Measurement has no drawn areas to export (also returned for plan-sheet takeoffs)
422 Unable to render map export for this measurement

Download the raw imagery#

GET /v1/measurements/{measurement_id}/imagery

Permission: Read measurements

Downloads the clean aerial image behind a takeoff: the same imagery source the takeoff was measured on, covering the takeoff, with no drawings, legend or logo. Use it to keep the imagery next to the quantities in your own system. The longest side is at most 3,600 pixels.

Name Type Required Description
measurement_id integer (path) Yes
format string No png (default) or jpeg (jpg also accepted).
curl -o northgate-imagery.jpg \
  "https://trutec.ai/api/v1/measurements/90311/imagery?format=jpeg" \
  -H "X-API-Key: sk_your_api_key_here"

The X-TruTec-Imagery-Source header says which imagery was used, for example google or nearmap:88f1e2a0-1234-5678-abcd-1234567890ab (Nearmap plus the survey id). X-TruTec-Measurement-Id and X-TruTec-Job-Id are also set.

Status error
400 format must be png or jpeg
404 Measurement not found
422 Measurement has no mapped area to fetch imagery for
422 Unable to fetch imagery for this measurement

POST /v1/measurements/{measurement_id}/map-link

Permission: Read measurements

Returns a link that opens the takeoff's map picture in a browser for 24 hours, with no API key. Use it to show a map to someone, or in a chat app, without handing out your key.

Name Type Required Description
measurement_id integer (path) Yes
style string (body) No annotated (default): the takeoff drawn on the aerial with its legend and your logo, like the map export. aerial: the clean imagery.
curl -X POST https://trutec.ai/api/v1/measurements/90311/map-link \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"style": "annotated"}'
{
  "data": {
    "measurement_id": 90311,
    "url": "https://trutec.ai/api/v1/map-images/eyJtIjo5MDMxMX0.abc123.def456.jpg",
    "style": "annotated",
    "expires_at": "2026-10-14T15:04:11Z"
  }
}

The annotated picture leaves out internal assessment pins and takeoff notes, because a link can be forwarded. The export-image download above keeps them.

Status error
400 style must be one of: annotated, aerial
404 Measurement not found
422 Measurement has no drawn areas to export (also returned for plan-sheet takeoffs)

Fetch a map picture#

GET /v1/map-images/{token}.jpg

Permission: None. The token in the URL is the credential.

Use the url from the call above rather than building this URL yourself. Returns a JPEG, at most 2,400 pixels on its long side. Anyone with the URL can see the map until it expires, so treat it like a secret.

An expired or altered link returns an empty 404. The link also stops working early when the key that made it is revoked or the takeoff leaves the workspace; get a new link then. A 503 with a Retry-After header means the map is still being drawn: try again after that many seconds.

Get a Nearmap tile layer#

GET /v1/measurements/{measurement_id}/imagery-tiles

Permission: Read measurements

For drawing a takeoff on your own map over the same Nearmap imagery it was measured on. Returns an XYZ tile URL template that needs no headers, limited to the area around the site.

curl https://trutec.ai/api/v1/measurements/90311/imagery-tiles \
  -H "X-API-Key: sk_your_api_key_here"
{
  "data": {
    "measurement_id": 90311,
    "imagery_source": "nearmap",
    "tiles": {
      "provider": "nearmap",
      "survey_id": "88f1e2a0-1234-5678-abcd-1234567890ab",
      "url_template": "https://trutec.ai/api/v1/imagery-tiles/eyJtIjo5MDMxMX0.abc123/{z}/{x}/{y}.jpg",
      "tile_size": 256,
      "min_zoom": 15,
      "max_zoom": 21,
      "bounds": {"south": 30.39685, "west": -97.72536, "north": 30.40412, "east": -97.71758},
      "attribution": "Imagery © Nearmap",
      "expires_at": "2027-01-10T15:04:11Z"
    }
  }
}

tiles is null when the takeoff is on Google imagery, when your plan no longer includes Nearmap, or when the takeoff spans more than about 3.5 miles. Keep your own base map in that case. The URL expires after 90 days; fetch a new one before then.

Fetch a tile#

GET /v1/imagery-tiles/{token}/{z}/{x}/{y}.jpg

Permission: None. The token in the URL is the credential.

Use the url_template from the call above rather than building this URL yourself. Returns a JPEG tile. Tiles outside the site area or below zoom 15 return an empty 404. The layer also stops working if the key that created it is revoked, the workspace loses Nearmap, or the takeoff is re-measured on another survey; fetch a new layer then. Treat the URL like a secret.

Imagery source and capture date#

Where Source Capture date
Detection result (imagery_source) google by default; nearmap when you pass nearmap_survey_id Google: none. Nearmap: only the nearmap_date you sent, copied back.
GET /v1/measurements/{id}/imagery X-TruTec-Imagery-Source header: google or nearmap:<survey id> Not returned
GET /v1/measurements/{id}/imagery-tiles imagery_source and tiles.survey_id Not returned
GET /v1/measurements/{id} Not returned Not returned
Condition ratings (image) google or nearmap Nearmap: image.capture_date of the survey used. Google: null. See Condition ratings.

Google does not publish capture dates for its satellite imagery. When the date of the imagery matters, measure on a Nearmap survey whose date you know, or upload your own dated imagery with /detect/tiles.