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

# Bind Device

> Bind a device to an end user and receive a device token for 4G uploads

Bind a device to an end user. A device can only be bound to one user at a time. If you need to reassign a device, unbind it first.

When a device is bound, a **device token** (`dtok_*`) is returned. This token enables 4G-equipped devices to upload recordings directly to the Bota API without requiring a companion mobile app.

<Warning>
  The device token is only shown once in the bind response. Store it securely on the device. If lost, you must unbind and rebind the device to get a new token.
</Warning>

## Authentication

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

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://api.bota.dev/v1/devices/dev_abc123/bind \
    -H "Authorization: Bearer sk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "end_user_id": "eu_xyz789"
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.bota.dev/v1/devices/dev_abc123/bind', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk_live_...',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      end_user_id: 'eu_xyz789',
    }),
  });

  const device = await response.json();
  // Store device.device_token securely on the device
  ```

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

  response = requests.post(
      'https://api.bota.dev/v1/devices/dev_abc123/bind',
      headers={
          'Authorization': 'Bearer sk_live_...',
          'Content-Type': 'application/json',
      },
      json={
          'end_user_id': 'eu_xyz789',
      },
  )

  device = response.json()
  # Store device['device_token'] securely on the device
  ```
</RequestExample>

## Path Parameters

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

## Request Body

<ParamField body="end_user_id" type="string" required>
  The ID of the end user to bind this device to.
</ParamField>

## Response

Returns the device object with a `device_token` field.

<ResponseExample>
  ```json 200 theme={null}
  {
    "id": "dev_abc123",
    "serial_number": "SN-2025-001234",
    "model": "bota_pin",
    "firmware_version": "1.2.0",
    "status": "bound",
    "end_user_id": "eu_xyz789",
    "metadata": {},
    "created_at": "2025-01-15T10:30:00Z",
    "updated_at": "2025-01-15T11:00:00Z",
    "device_token": "dtok_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
  }
  ```

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

  ```json 409 theme={null}
  {
    "error": {
      "code": "device_already_bound",
      "message": "Device is already bound to another user. Unbind it first."
    }
  }
  ```
</ResponseExample>

## Response Fields

| Field                 | Type            | Description                                                                      |
| --------------------- | --------------- | -------------------------------------------------------------------------------- |
| `id`                  | string          | Device identifier (`dev_*`)                                                      |
| `serial_number`       | string          | Physical serial number                                                           |
| `model`               | string          | Device model (`bota_pin` or `bota_note`)                                         |
| `firmware_version`    | string \| null  | Current firmware version                                                         |
| `status`              | string          | `bound` (always bound after successful bind)                                     |
| `end_user_id`         | string          | Bound end user (`eu_*`)                                                          |
| `device_token`        | string          | Device authentication token (`dtok_*`). **Shown only once** — store it securely. |
| `battery_percent`     | integer \| null | Battery level (0-100)                                                            |
| `storage_used_mb`     | integer \| null | Storage used in MB                                                               |
| `storage_total_mb`    | integer \| null | Total storage capacity in MB                                                     |
| `signal_strength_dbm` | integer \| null | Signal strength in dBm                                                           |
| `last_heartbeat_at`   | string \| null  | Last heartbeat timestamp (ISO 8601)                                              |
| `recording_state`     | object \| null  | Current recording state                                                          |
| `metadata`            | object          | Custom key-value metadata                                                        |
| `created_at`          | string          | Creation timestamp (ISO 8601)                                                    |
| `updated_at`          | string          | Last update timestamp (ISO 8601)                                                 |

## Device Token

The `device_token` returned in the response is a limited-permission credential that allows the device to:

* Create recordings (`POST /v1/recordings`)
* Get upload URLs (`POST /v1/recordings/:id/upload-url`)
* Mark uploads complete (`POST /v1/recordings/:id/upload-complete`)
* Report device status (`POST /v1/devices/:id/heartbeat`)
* Refresh its token (`POST /v1/devices/:id/token/refresh`)

The device token is automatically scoped to the bound end user - recordings created with this token are automatically associated with the correct end user.

<Note>
  Device tokens have very limited permissions compared to API keys. They cannot list recordings, access other users' data, or perform administrative operations.
</Note>

<Warning>
  A device can only be bound to one end user at a time. Attempting to bind an already-bound device returns a `409 Conflict` error. Use the [Unbind Device](/api-reference/devices/unbind) endpoint first.
</Warning>
