> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bota.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Get Device OTA Status

> The device’s most recent firmware assignment and what became of it

Returns the device's **most recent** assignment, whatever became of it. Read
`status` to see whether the update landed.

`data` is `null` only when the device has never been assigned firmware.

## Authentication

Requires an [API key](/authentication) with `devices:read` scope.

## Path Parameters

<ParamField path="id" type="string" required>
  The device's unique identifier (e.g., `dev_abc123`).
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl https://api.bota.dev/v1/devices/dev_abc123/ota \
    -H "Authorization: Bearer sk_live_..."
  ```

  ```javascript Node.js theme={null}
  const { data: assignment } = await fetch(
    'https://api.bota.dev/v1/devices/dev_abc123/ota',
    { headers: { 'Authorization': 'Bearer sk_live_...' } },
  ).then((r) => r.json());

  if (!assignment) {
    // Never assigned firmware.
  } else if (assignment.status === 'applied') {
    // The update is installed.
  } else if (assignment.status === 'pending' || assignment.status === 'delivered') {
    // Still in flight.
  }
  ```

  ```python Python theme={null}
  import requests

  assignment = requests.get(
      'https://api.bota.dev/v1/devices/dev_abc123/ota',
      headers={'Authorization': 'Bearer sk_live_...'},
  ).json()['data']

  if assignment is None:
      ...  # Never assigned firmware.
  elif assignment['status'] == 'applied':
      ...  # The update is installed.
  ```
</RequestExample>

<ResponseExample>
  ```json 200 (In flight) theme={null}
  {
    "data": {
      "id": "ota_7Rp2XvB4nT6yL8cW1kQ9mZa3",
      "device_id": "dev_abc123",
      "firmware_release_id": "fw_3kQ9mZa7Rp2XvB4nT6yL8cW1",
      "status": "delivered",
      "assigned_at": "2026-08-14T12:00:00Z",
      "delivered_at": "2026-08-14T12:01:30Z",
      "applied_at": null,
      "error_message": null
    }
  }
  ```

  ```json 200 (Installed) theme={null}
  {
    "data": {
      "id": "ota_7Rp2XvB4nT6yL8cW1kQ9mZa3",
      "device_id": "dev_abc123",
      "firmware_release_id": "fw_3kQ9mZa7Rp2XvB4nT6yL8cW1",
      "status": "applied",
      "assigned_at": "2026-08-14T12:00:00Z",
      "delivered_at": "2026-08-14T12:01:30Z",
      "applied_at": "2026-08-14T12:06:12Z",
      "error_message": null
    }
  }
  ```

  ```json 200 (Never assigned) theme={null}
  {
    "data": null
  }
  ```

  ```json 404 theme={null}
  {
    "error": {
      "code": "not_found",
      "message": "Device not found"
    }
  }
  ```
</ResponseExample>

## Response Fields

| Field | Type | Description |
| - | - | - |
| `id` | string | Assignment identifier (`ota_*`) |
| `device_id` | string | The device this was assigned to |
| `firmware_release_id` | string | The release that was assigned |
| `status` | string | See the table below |
| `assigned_at` | string | ISO 8601 |
| `delivered_at` | string \| null | When the device was handed the update |
| `applied_at` | string \| null | When the device reported running the assigned version |
| `error_message` | string \| null | Why it failed, when `status` is `failed` |

## Assignment status

| Status | Meaning |
| - | - |
| `pending` | Assigned. The device has not been handed the update yet. |
| `delivered` | The device received the update in a heartbeat and is installing it. |
| `applied` | The device reported running the assigned version. Done. |
| `failed` | The device reported a failure, or the assignment was settled when the device moved between projects. Read `error_message`. |
| `cancelled` | Called off through [Cancel Device OTA Assignment](/api-reference/firmware/cancel-ota). |

`pending` and `delivered` are the in-flight states, and either one blocks a new
assignment. The other three are terminal.

## Notes

* This is one assignment, not a history. Use
  [List Device OTA History](/api-reference/firmware/ota-history) to see earlier
  ones.
* A device reports its firmware version in every heartbeat; when it matches the
  assigned release, the assignment moves to `applied` on its own.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.