---
title: "Update a specific DeviceOperation for a specific Operation"
method: PUT
path: "/v0/operations/{operationsId}/devices/{deviceId}/"
tags: ["device_DeviceOperations"]
---

# Update a specific DeviceOperation for a specific Operation

`PUT /v0/operations/{operationsId}/devices/{deviceId}/`

Updates the recorded state of a single device's progress within a Dispatch operation.

Used to request cancellation for an invidual device operation (instead of a larger fleetwide operation) by specifying the sate as CANCELLATION_REQUESTED. Cancellation is not guaranteed and depends the command's exact state. 

**About Update Device Operation**

Each DeviceOperation record represents one device's slice of a larger Operation. As the underlying dispatch command progresses on the device side, the owning service reports the new state back through this endpoint, which then rolls up into the parent operation's aggregate stats (resolved, dispatched, failed, and success counts). Because this directly affects the parent operation's reported outcome, updates here should come from the service that owns the operation's execution rather than from ad hoc calls.

**Key Fields / Request Body**

operation_type — the operation type this device operation belongs to, for example CONVERGE

state — the new device operation state, for example SUCCESS

service_id — Optional. identifies the internal service reporting the update, for example drift-service

reason — free text explaining the state change

**Common Use Cases**

An internal service reporting that a device successfully completed its Converge action

Marking a device's operation as failed after the underlying command times out on the device

**Best Practices**

Only update state from the service that actually owns execution of the underlying command for that device

Always populate reason when reporting a failure so the cause is visible in the operation's activity history

**Workflow**

Identify the operationsId and deviceId for the device operation being updated

Determine the device's actual outcome from the underlying command or drift check

PUT the new state, service_id, and reason to this endpoint

Confirm the update is reflected in the parent operation's aggregate stats via GET /v0/operations/{operationId}/

## Path parameters

- `operationsId` string, uuid, required
- `deviceId` string, uuid, required

## Request body

- object
  - `operation_type` string — Optional; resolved from the database if not provided.
  - `state` string, required
  - `service_id` string
  - `reason` string

## Response `200`

Device Operation updated successfully

- object
  - `content` DeviceDeviceOperationWithStats
    - `id` string, uuid
    - `operation_id` string, uuid
    - `device_id` string, uuid
    - `state` 'CREATED' | 'INITIATED' | 'SUCCEDED' | 'FAILED'
    - `reason` string
    - `created_at` string, date-time
    - `updated_at` string, date-time
    - `device_operation_activity` DeviceDeviceOperationActivity[]
      - `device_operation_state` string — The state of the device operation (e.g., queued, processing).
      - `created_at` string, date-time — The start time of the device operation state.

## Other responses

- `400` — Bad Request
- `401` — Unauthorized
- `404` — Not found
- `500` — Internal Server Error

---

[API](https://skmtc.net/esper/apis/esper-api-reference.md) · [All operations](https://skmtc.net/esper/apis/esper-api-reference/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/esper/esper-api-reference/revisions/e1f64cbb488e/schema)
