Measurement Annotation Persistence

Stable measurement identities, conflict handling, and personal trade profiles.

Ordinary length, area and count measurements use the annotation endpoints. Trade classification, material, presentation, quantity and source-frame metadata belong to the measurement payload. They are independent of the annotation's measurement_note category. Volume calculations retain their dedicated definition and calculation workflow.

Capability and Identity

GET /v1/spatial/locations/{locationId}/annotations returns items, hasNextPage and annotationPersistenceVersion: 2. Clients must check this capability before making annotations authoritative for legacy measurements. Pages exclude deleted annotations. They are not an incremental deletion feed; updatedSince alone cannot establish the complete current inventory.

Create a measurement with POST /v1/spatial/locations/{locationId}/annotations and a stable clientKey of 1–256 characters. The location/key combination is unique, including deleted records. Retrying identical content returns the same annotation. Reusing a key for different content or a deleted record returns HTTP 409 (annotation_identity_conflict). Concurrent creates can also produce 409; reload and compare the saved record before retrying. Never invent a new key merely to bypass a conflict. Unkeyed legacy creates are also rejected when the envelope identifies a measurement already reserved by the canonical pixmeas-v1: SHA-256 key, including tombstones.

Responses include clientKey and a decimal string revision. Existing unkeyed records may acquire a key through a conditional PATCH. Once assigned, a key cannot be changed or cleared. Volume annotations do not accept these keys.

Conditional Changes and Deletion

Send the last observed string baseRevision and matching clientKey with PATCH. A missing or mismatching key on a keyed row returns 409 (annotation_identity_required), preventing older config-shadow clients from overwriting migrated data even after fetching a fresh revision. Keyed measurements require the exact record revision, including when changes touch different fields: the payload and coordinate frame form one measurement. Ordinary unkeyed notes retain the existing field-level conflict behavior. A stale measurement write returns HTTP 409 and must not overwrite the remote record automatically.

Delete keyed measurements with:

DELETE /v1/spatial/annotations/{annotationId}?baseRevision=7

The revision must match. Missing or stale preconditions return 409; malformed revisions return 400. The server retains a tombstone and the identity reservation so a delayed create cannot resurrect deleted work. Deleted rows are excluded from ordinary reads, lists, counts and shared-model annotation delivery. A missing/deleted annotation does not invalidate surviving captured model content.

Location and document authorization applies before identity lookup and mutation. The API never takes the measurement author from a caller-supplied user ID.

Payload and Migration

Ordinary note bodies remain limited to 4,000 characters. Measurement-note bodies may contain a validated __pixmeas: 1 JSON envelope up to 262,144 characters, including the measurement ID/type, coordinate-space marker, checksum and data. The client is responsible for verifying the complete payload, source/frame and checksum before rendering or declaring a legacy migration verified. A local payload's placeholder WGS84 coordinates are not replacement measurement points.

Keep a recoverable legacy snapshot and pending edits until every migrated row has been reloaded and verified. Partial inventory, failed writes, malformed payloads and revision conflicts must block authoritative completion. Never interpret an incomplete or failed load as an empty dataset to save over.

The additive schema migration preserves existing annotation revisions and content. Downgrade refuses to discard keys, tombstones, larger bodies or saved user preferences; reconciliation/export is required before removing that schema.

Personal Picker Default

Read and save defaultMeasurementProfileId through GET/PATCH /v1/users/me. Profiles are roofing, roadworks, utilities and earthworks; unset accounts use roofing. This is a personal preference across devices. Several users may work on the same model with different defaults. Switching a picker profile never changes saved classifications or filters persistence and reports.

On this page