Features
Features are fleet-owned map shapes and routes used by mission templates and Field Rules.
Authentication
Reads use features:read. Draft authoring, deployment, decomposition, and Field Rule writes use features:write. Tracked-object reads use robots:read; tracked-object writes use robots:write.
Read features
Nested paths start with /v1/orgs/{org_id}/fleets/{fleet_id}.
GET …/features
GET …/features/{feature_id}
The list includes draft and deployed features and returns { "items": [{ "featureId", "name", "featureType", "spatialDataType", "featureRole", "rev", "updatedAt" }] }. Detail adds spatialData and live decomposition feedback.
For automation, query-entities and get-entity with kind: "feature" cover the same fleet features.
Save a feature draft
POST /v1/features
Omit id to create a draft or include it to update one. The body carries fleetId, name, role, scope, and either shape or route data.
{
"fleetId": "fleet-uuid",
"name": "North pad",
"areaType": "zone",
"isRoute": false,
"scope": "fleet",
"shapeType": "polygon",
"shapeData": { "polygon": { "exterior": [] } }
}
The flat DELETE /v1/features/{id} deletes undeployed drafts only. It returns 409 for a deployed feature.
Deploy or delete a live feature
POST …/features/{feature_id}/deploy
DELETE …/features/{feature_id}
Deploy promotes a stored draft and sends it to fleet robots. Delete removes a deployed feature and sends the deletion. An optional deploy body can restrict delivery with robotIds.
Responses identify persistence and robot-delivery outcomes. A known delivery failure after persistence returns 207 partial_failure with structured details; do not treat it as a rollback.
Decomposition controls
| Endpoint | Purpose |
|---|---|
PUT …/features/{feature_id}/decomposition |
Configure geometry policy, coverage, limits, and whether the feature is dynamic. |
POST …/features/{feature_id}/reset-decomposer |
Clear components and current holders. |
PUT …/features/{feature_id}/lock |
Lock or unlock the resource. |
POST …/features/{feature_id}/assign-spot |
Add or relocate a spot on a dynamic feature. |
The Agent API control-feature tool covers the immediate lock, unlock, and reset intents.
Demand belongs to the mission step, not the feature decomposition. Set step demand in the mission template's step_config rather than sending createsDemand in the decomposition body.
A dynamic feature begins without components and receives spots through assign-spot.
Tracked objects
GET …/objects
GET …/objects/{object_id}
POST …/objects
DELETE …/objects/{object_id}
List and detail omit expired rows. A missing or expired object returns 404. Agent API query-entities and get-entity with kind: "object" read the same live set.
Object upsert accepts the same tracked-object shape used by Rover Nexus messaging and optional robotIds. expiresAtMs must be 0 for no expiration or a future timestamp. An already expired object returns 400 before persistence or delivery.
Object writes also return structured persistence and delivery results, with 207 for known partial delivery.
Field Rules
GET …/field-rules
POST …/field-rules
GET …/field-rules/{directive_id}
PUT …/field-rules/{directive_id}
PUT …/field-rules/{directive_id}/active
DELETE …/field-rules/{directive_id}
Field Rule reads include active and inactive rules. Create, update, and delete validate referenced robots, features, actions, and fleet ownership.
On POST, the server owns the identifier. Omit directiveId, or send it blank or nil. A real client-supplied id returns 400. On PUT, the path id is authoritative and a nonblank body id must match it.
PUT …/field-rules/{directive_id}/active toggles a rule with { "active": true } or { "active": false } without a full upsert. Agent API control-feature (enable_field_rule / disable_field_rule) and upsert-field-rule cover the same intents.
A successful create returns 201; update and delete return 200. Persistence followed by incomplete robot delivery returns 207 with per-target errors. An empty robotIds list means all active robots in the fleet.