Editing takeoff shapes
List the shapes on a saved aerial takeoff and add, remove, reclassify, retype or rephase them, saved the same way the takeoff editor saves.
View as MarkdownA saved aerial takeoff is made of shapes: drawn areas, counted items (arrows, symbols, wheel stops, bollards), drawn lines (striping and curbs), painted shapes (crosswalks, hatching, stop bars) and custom item shapes. These endpoints let an integration or an AI assistant change those shapes the way a person does in the takeoff editor, and save the takeoff the way the editor saves it: the takeoff's counts, footage and areas follow, the change is kept in the takeoff's history, and estimates linked to the takeoff re-pull their quantities.
Typical flow:
GET /v1/measurements/{measurement_id}/shapesfor the shapes, their ids and the takeoff'srev.POST /v1/measurements/{measurement_id}/editswith thatrevasbase_revand a list of operations.GET /v1/measurements/{measurement_id}/itemsfor the new quantities (see Takeoffs).
Only aerial takeoffs can be edited here. Plan-sheet and landscape takeoffs return 422.
Note
Coordinates are [lat, lng], the order TruTec stores takeoffs in (the same as geometry in GET /v1/measurements/{id}). If your data is in GeoJSON order, send "coordinate_order": "lng_lat" with your edits. A new shape several kilometers from the takeoff's other shapes is refused, which catches swapped coordinates.
What the API edits#
| Shape | Add | Remove | Reclassify | Type | Phase | Surface |
|---|---|---|---|---|---|---|
| Areas (main, concrete, sidewalk, driveway, carport) | Yes | Yes | Yes | Yes | ||
Cut-outs (hole areas) |
Yes | Yes | ||||
Counts: arrows, abc (symbols), wheel_stop, bollard |
Yes | Yes | To another count category | Yes | Yes | |
Lines: lines_white, lines_yellow, lines_double_yellow, red_line, misc_lines, curb, curb_red, curb_yellow, curb_green, curb_blue |
Yes | Yes | To another line category | Yes | Yes | |
| Custom item shapes (points, lines, polygons) | Yes | Yes | To another item of the same kind | Phase-split area items |
These stay in the takeoff editor, because the editor works out their numbers from the whole layout. An operation that touches one returns 422 Edit in the takeoff editor with the reason:
- stalls, handicap, truck and parallel stalls (their striping footage comes from the stall layout), speed bumps, center lines and skip lane lines;
- painted crosswalks, hatching, stop bars and detected stripes;
- a category whose quantity someone typed over the measured one on this takeoff;
- an area or custom shape that carries a service, type, catalog item or work area (an area's phase can still change), and a cut-out inside one;
- custom items that count toward the takeoff's total area, and measuring-tape rulers.
The shapes listing marks each shape's allowed edits in actions, with a note when there are none.
List a takeoff's shapes#
GET /v1/measurements/{measurement_id}/shapes
Permission: Read measurements
| Name | Type | Description |
|---|---|---|
kind |
string | Only area, count, line, painted_shape or custom shapes. |
category |
string | Only one category (for example arrows) or custom item name. |
include_coordinates |
boolean | Default true. false leaves coordinates out for a lighter list. |
limit, offset |
integer | Paging. limit defaults to 100, max 500. |
curl "https://trutec.ai/api/v1/measurements/90311/shapes?kind=count" \
-H "X-API-Key: sk_your_api_key_here"
{
"data": [
{
"id": "trutec:counter_marker:arrows:0b6d2f7e-8f1c-4d61-b0a4-61c3f0d2e9b4",
"kind": "count",
"category": "arrows",
"label": "Arrows",
"geometry": "point",
"phase": "Phase 1",
"quantity": 1,
"unit": "EA",
"coordinates": [30.4006, -97.7203],
"actions": ["remove", "reclassify", "set_spec", "set_phase"]
}
],
"pagination": {"total": 1, "limit": 100, "offset": 0},
"measurement": {"id": 90311, "name": "Lakeside Plaza main lot", "job_id": 4812, "area": 18250.5,
"rev": "g1-3f9a0c27b1d84e65", "coordinate_order": "lat_lng"},
"options": {
"count_categories": ["arrows", "abc", "wheel_stop", "bollard"],
"line_categories": ["lines_white", "lines_yellow", "lines_double_yellow", "red_line", "misc_lines",
"curb", "curb_red", "curb_yellow", "curb_green", "curb_blue"],
"surfaces": ["main", "concrete", "sidewalk", "driveway", "carport", "hole"],
"custom_items": [{"name": "Asphalt patching", "type": "polygon", "on_takeoff": false}],
"types": {"lines_yellow": ["4\" Yellow"]},
"phases": ["Phase 1"]
}
}
| Field | Description |
|---|---|
id |
The shape's stable id. Use it in edits. A shape added through the API or the editor keeps its id. |
kind |
area, count, line, painted_shape or custom. |
surface |
Areas: main, concrete, sidewalk, driveway, carport, or hole for a cut-out. |
category, label |
Counts, lines and painted shapes. |
item |
Custom shapes: the custom item's name. |
geometry |
point, line or polygon. |
phase, spec |
The shape's phase and type (sub-type), when it has them. |
service_labels, service_id, item_key, item_name, work_area |
What an area or custom shape is assigned to, when it is. |
quantity, unit |
Square feet for areas and polygons, linear feet for lines (painted footage for dashed lines), 1 EA for points. |
coordinates |
[lat, lng] for a point, a list of points for a line, a list of rings for a polygon (the first ring is the outline, the rest are holes). |
actions |
The edits the API takes on this shape. |
measurement.rev |
The takeoff's revision. Send it as base_rev. It changes whenever anyone saves the takeoff. GET /v1/measurements/{id} returns it too. |
options |
What an edit may name: categories, types per category (they come from the services that price the item), custom items on the takeoff or in the workspace, and the takeoff's phases. |
Edit a takeoff's shapes#
POST /v1/measurements/{measurement_id}/edits
Permission: Write measurements. Operations that remove a shape also need Delete records.
| Name | Type | Required | Description |
|---|---|---|---|
base_rev |
string | Yes | measurement.rev from the shapes listing, or rev from your last edit. |
operations |
array | Yes | 1 to 200 operations, applied in order. |
coordinate_order |
string | No | lat_lng (default) or lng_lat. |
confirm_remove_all_areas |
boolean | No | Needed to remove every drawn area from a takeoff that keeps other shapes. |
All operations save together: if one is refused, nothing is saved and the error names it with operation_index.
op |
Fields | What it does |
|---|---|---|
add_area |
coordinates (a ring, or a list of rings), surface (default main), phase |
Draws an area. surface: "hole" cuts an area out; a cut-out takes the phase of the area it cuts. |
add_count |
category, coordinates ([lat, lng]), spec, phase |
Adds a counted item. |
add_line |
category, coordinates (2 or more points), spec, phase |
Draws a line. |
add_custom_shape |
item, coordinates, item_type, color, phase |
Adds a shape to a custom item: a point, line or polygon, matching the item. item can be on the takeoff already or one of the workspace's custom items; for a new item name send item_type (point, line or polygon). phase only for items split by phase. |
remove |
id |
Removes the shape. |
reclassify |
id, then category (+ optional spec) for a count or line, or item for a custom shape |
Moves the shape to another category or custom item. Its old type is dropped. |
set_spec |
id, spec (or null) |
Sets or clears a count's or line's type. |
set_phase |
id, phase |
Moves an area, count or line (or a phase-split custom area) to a phase. |
set_surface |
id, surface |
Changes an area to main, concrete, sidewalk, driveway or carport. |
A count or line added without phase takes the phase of the area it sits in, as in the editor. A spec must be one of the category's types in options.types: types come from the services that price the item, and the API never invents one. A line whose type has a dash pattern in the catalog counts its painted footage, as in the editor.
curl -X POST https://trutec.ai/api/v1/measurements/90311/edits \
-H "X-API-Key: sk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"base_rev": "g1-3f9a0c27b1d84e65",
"operations": [
{"op": "add_count", "category": "arrows", "coordinates": [30.4006, -97.7203]},
{"op": "add_line", "category": "lines_yellow", "coordinates": [[30.4010, -97.7208], [30.4010, -97.7198]]},
{"op": "reclassify", "id": "trutec:counter_line:lines_white:7c1e0f3a-2b44-4c8e-9d71-5a0f6e2b8c13", "category": "lines_yellow"},
{"op": "remove", "id": "trutec:counter_marker:abc:3e5d9b20-7a61-4f0c-8b2e-91d4c6a7f058"}
]
}'
Returns 200:
{
"data": {
"measurement_id": 90311,
"rev": "g1-8c41d2e05f7a93b6",
"area": 18250.5,
"results": [
{"index": 0, "op": "add_count", "id": "trutec:counter_marker:arrows:a1f3c2d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "quantity": 1, "unit": "EA"},
{"index": 1, "op": "add_line", "id": "trutec:counter_line:lines_yellow:b2e4d3c5-6f7a-4b8c-9d0e-1f2a3b4c5d6e", "quantity": 31.62, "unit": "LF"},
{"index": 2, "op": "reclassify", "id": "trutec:counter_line:lines_white:7c1e0f3a-2b44-4c8e-9d71-5a0f6e2b8c13", "category": "lines_yellow"},
{"index": 3, "op": "remove", "id": "trutec:counter_marker:abc:3e5d9b20-7a61-4f0c-8b2e-91d4c6a7f058"}
]
}
}
rev is the takeoff's new revision: send it as base_rev for your next edit. area is the takeoff's total area in square feet. New shapes' ids are in results.
The save is recorded as the person who created the API key, in the takeoff's revision history like any editor save, and estimates linked to the takeoff re-pull their quantities. Nothing is sent to anyone.
| Status | error |
|---|---|
| 400 | base_rev is required, operations is required, Invalid operation (with operation_index), Shape is far from the takeoff, Unknown category, Wrong shape for item, item_type is required, Unknown fields |
| 403 | API key lacks measurement write permission, API key lacks delete permission (a remove without Delete records), Key owner unavailable (the key's creator left the workspace) |
| 404 | Measurement not found, Shape not found (with operation_index: list the shapes again) |
| 409 | stale_measurement: someone saved the takeoff since base_rev. The body has current_rev; list the shapes again and resend. Takeoff locked for review. would_remove_all_areas: resend with confirm_remove_all_areas if that is what you mean. |
| 422 | Edit in the takeoff editor (see above), Unknown type, Takeoff would be empty (delete the takeoff instead), Not an aerial takeoff, Takeoff needs the editor first |
Note
The first edit of a takeoff that was saved from a detection through the API stores it in the editor's own format, as opening and saving it in the editor does. Its measured quantities (total area, counts, footage, custom items) carry over; a few raw detection values in its quantity list are replaced by the editor's equivalents.