> ## 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.

# Cancel Device OTA Assignment

> Call off the assignment in flight so the device can be given another

Calls off the device's in-flight assignment, freeing it to be given another one.
Use this when firmware was assigned by mistake, or when a device has been sitting
on an update it never installed.

Returns the assignment, now `cancelled`.

<Warning>
  Cancelling cannot recall an update the device already holds. If the returned
  assignment has a `delivered_at`, the device was handed the update before you
  cancelled and may still install it — check
  [Get Device OTA Status](/api-reference/firmware/get-ota) after its next
  heartbeat.
</Warning>

## Authentication

Requires an [API key](/authentication) with `devices:write` 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 -X DELETE https://api.bota.dev/v1/devices/dev_abc123/ota \
    -H "Authorization: Bearer sk_live_..."
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.bota.dev/v1/devices/dev_abc123/ota', {
    method: 'DELETE',
    headers: { 'Authorization': 'Bearer sk_live_...' },
  });

  if (response.status === 404) {
    // Nothing was in flight.
  } else {
    const cancelled = await response.json();
    if (cancelled.delivered_at) {
      // The device already had it; it may still install.
    }
  }
  ```

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

  response = requests.delete(
      'https://api.bota.dev/v1/devices/dev_abc123/ota',
      headers={'Authorization': 'Bearer sk_live_...'},
  )

  if response.status_code == 404:
      ...  # Nothing was in flight.
  else:
      cancelled = response.json()
      if cancelled['delivered_at']:
          ...  # The device already had it; it may still install.
  ```
</RequestExample>

<ResponseExample>
  ```json 200 (Cancelled before the device saw it) theme={null}
  {
    "id": "ota_7Rp2XvB4nT6yL8cW1kQ9mZa3",
    "device_id": "dev_abc123",
    "firmware_release_id": "fw_3kQ9mZa7Rp2XvB4nT6yL8cW1",
    "status": "cancelled",
    "assigned_at": "2026-08-14T12:00:00Z",
    "delivered_at": null,
    "applied_at": null,
    "error_message": null
  }
  ```

  ```json 200 (Cancelled after delivery — the device may still install it) theme={null}
  {
    "id": "ota_7Rp2XvB4nT6yL8cW1kQ9mZa3",
    "device_id": "dev_abc123",
    "firmware_release_id": "fw_3kQ9mZa7Rp2XvB4nT6yL8cW1",
    "status": "cancelled",
    "assigned_at": "2026-08-14T12:00:00Z",
    "delivered_at": "2026-08-14T12:01:30Z",
    "applied_at": null,
    "error_message": null
  }
  ```

  ```json 404 (Unknown device, or nothing in flight) theme={null}
  {
    "error": {
      "code": "not_found",
      "message": "OTA assignment not found"
    }
  }
  ```
</ResponseExample>

## Notes

* Both in-flight states can be cancelled — `pending` and `delivered`. Both block
  a new assignment, so cancelling only `pending` would leave a device that never
  installed its update stuck behind a `409` with no way out.
* An assignment that already reached `applied`, `failed` or `cancelled` is not
  in flight, so there is nothing to call off and the request is a `404`.
* The cancelled assignment stays in
  [the device's history](/api-reference/firmware/ota-history).


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