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

# Core Concepts

> Understand the Bota domain model and how entities relate

This guide explains the key entities in the Bota platform and how they work together.

## Entity Overview

```mermaid theme={null}
erDiagram
    Organization ||--o{ Project : has
    Project ||--o{ APIKey : has
    Project ||--o{ WebhookEndpoint : has
    Project ||--o{ EndUser : has
    Project ||--o{ Device : has
    EndUser ||--o{ Device : "bound to"
    Device ||--o{ Recording : captures
    EndUser ||--o{ Recording : owns
    Recording ||--o{ Transcription : has
```

## Platform Entities

These entities represent your relationship with Bota.

### Organization

An **Organization** is your company's account in Bota. It's the top-level tenant in our multi-tenant architecture.

* Created when you sign up for Bota
* Contains one or more Projects
* Has Organization Users (your team members) with dashboard access

### Project

A **Project** is an isolated environment within your organization. All data-plane operations are scoped to a single project.

| Use Case               | Description                                                             |
| ---------------------- | ----------------------------------------------------------------------- |
| Environment separation | Create separate projects for `development`, `staging`, and `production` |
| Multiple products      | If your company has multiple apps, each can have its own project        |
| Customer isolation     | Enterprise customers may want dedicated projects for compliance         |

<Info>
  All API calls require a project-scoped API key. You cannot query across projects.
</Info>

### API Key

**API Keys** authenticate requests to the Bota API. Each key is scoped to a single project.

| Type         | Prefix                 | Use Case                                        |
| ------------ | ---------------------- | ----------------------------------------------- |
| Secret Key   | `sk_live_`, `sk_test_` | Full access, server-side only                   |
| Device Token | `dtok_`                | Cellular device direct uploads, long-lived      |
| Upload Token | `up_`                  | Single upload authorization, expires in minutes |

See [Authentication](/authentication) for details on each key type.

### Webhook Endpoint

**Webhook Endpoints** receive real-time notifications when events occur in your project.

Supported events:

* `recording.created` — New recording created
* `recording.uploaded` — Audio upload completed
* `transcription.completed` — Transcription finished
* `transcription.failed` — Transcription failed
* `summary.completed` — Summary generation finished

See [Webhooks](/api-reference/webhooks/overview) for setup instructions.

***

## Customer Entities

These entities represent your users and their data.

### End User

An **EndUser** represents a person who wears a Bota device. They are subjects of recordings but don't have accounts in Bota.

```json theme={null}
{
  "id": "eu_abc123",
  "external_id": "your_user_id_123",
  "name": "John Doe",
  "email": "john@example.com",
  "metadata": {
    "department": "sales",
    "role": "account_executive"
  },
  "created_at": "2025-01-15T10:00:00Z"
}
```

**Key points:**

* **No Bota login** — EndUsers don't authenticate with Bota. Your app handles their identity.
* **external\_id mapping** — Link Bota EndUsers to users in your system via `external_id`.
* **Data ownership** — All recordings belong to an EndUser for compliance and access control.
* **Deletion support** — Delete an EndUser to remove all their data (GDPR, HIPAA compliance).

<Tip>
  Use the `external_id` field to store your system's user ID. This lets you look up Bota EndUsers by your own identifiers.
</Tip>

### Device

A **Device** represents a physical Bota wearable. Each device has a unique serial number.

```json theme={null}
{
  "id": "dev_xyz789",
  "serial_number": "SN-2025-001234",
  "model": "bota_pin",
  "firmware_version": "1.2.0",
  "status": "bound",
  "end_user_id": "eu_abc123",
  "created_at": "2025-01-15T10:01:00Z",
  "bound_at": "2025-01-15T10:05:00Z"
}
```

**Device states:**

| Status    | Description                             |
| --------- | --------------------------------------- |
| `unbound` | Registered but not assigned to a user   |
| `bound`   | Assigned to an EndUser, ready to record |

**Device lifecycle:**

```mermaid theme={null}
stateDiagram-v2
    [*] --> Unbound: Register
    Unbound --> Bound: Bind to EndUser
    Bound --> Unbound: Unbind
    Bound --> Bound: Reassign (unbind + bind)
```

**Key points:**

* **One user at a time** — A device can only be bound to one EndUser. Unbind before reassigning.
* **Recordings follow binding** — When a device creates a recording, it's automatically associated with the bound EndUser.
* **Token on bind** — When a device is bound, a device token (`dtok_*`) is issued for direct uploads via WiFi or cellular.
* **Token rotation** — Device tokens are rotated when a device is unbound for security.

#### Cellular Device Support

Devices with cellular connectivity (e.g., Bota Pin 4G) can upload recordings directly to Bota without a companion mobile app. When a cellular-capable device is bound to an EndUser, it receives a **device token** (`dtok_*`) that authenticates direct API calls.

**Device token permissions:**

| Action           | Endpoint                                  |
| ---------------- | ----------------------------------------- |
| Create recording | `POST /v1/recordings`                     |
| Get upload URL   | `POST /v1/recordings/:id/upload-url`      |
| Complete upload  | `POST /v1/recordings/:id/upload-complete` |
| Send heartbeat   | `POST /v1/devices/:id/heartbeat`          |
| Refresh token    | `POST /v1/devices/:id/token/refresh`      |

**Direct upload flow (WiFi/Cellular):**

```mermaid theme={null}
sequenceDiagram
    participant Device as Cellular Device
    participant API as Bota API
    participant S3 as Bota S3

    Note over Device: Device has dtok_* from initial bind

    Device->>API: 1. POST /recordings<br/>Authorization: Bearer dtok_...
    API-->>Device: 2. Recording created

    Device->>API: 3. POST /recordings/:id/upload-url
    API-->>Device: 4. Pre-signed URL

    Device->>S3: 5. PUT audio file

    Device->>API: 6. POST /recordings/:id/upload-complete
    API-->>Device: 7. Recording status: uploaded
```

**Fleet monitoring:**

Cellular-capable devices can report health status via the [heartbeat endpoint](/api-reference/devices/heartbeat):

* Battery level
* Storage usage
* Signal strength
* Firmware version

<Note>
  Device tokens have limited permissions compared to API keys. They cannot list recordings, access other users' data, or perform administrative operations. See [Authentication](/authentication) for details.
</Note>

#### Device Settings

**Device Settings** configure device behavior for connectivity, uploads, and processing. Settings use the [hierarchical configuration system](/guides/hierarchical-config) — defaults can be set at the organization or project level and overridden per end user or device.

Settings are organized into three sections:

| Section      | Description                                                       |
| ------------ | ----------------------------------------------------------------- |
| `connection` | Network connectivity, upload network preference, power management |
| `upload`     | Streaming uploads, data limits, roaming, off-peak scheduling      |
| `processing` | Auto-transcription and auto-summary settings                      |

**Example: Upload settings**

```json theme={null}
{
  "connection": {
    "enabled_connections": { "wifi": true, "cellular": true },
    "upload_network_preference": ["wifi", "ble", "cellular"],
    "power_management": {
      "wifi_idle_timeout_seconds": 180,
      "cellular_idle_timeout_seconds": 180
    }
  },
  "upload": {
    "streaming_enabled": true,
    "daily_data_limit_mb": 500,
    "allow_roaming": false,
    "pause_on_low_battery": true
  },
  "audio": {
    "codec": "opus",
    "sample_rate_khz": 16,
    "bitrate_kbps": 32
  },
  "power": {
    "auto_sleep_minutes": 30,
    "low_battery_threshold_percent": 20
  }
}
```

**Configuration levels:**

```
Organization → Project → End User → Device
(broadest)                          (most specific)
```

**Connection settings:**

| Field                       | Description                                                                                                                                                                  |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled_connections`       | Which radios are available (`wifi`, `cellular`). Bluetooth is always on.                                                                                                     |
| `upload_network_preference` | Ordered list of preferred connections for uploads                                                                                                                            |
| `power_management`          | Radio idle timeouts — powers down WiFi/cellular after inactivity to save battery. Default: 180s. `-1` = never power down, `0` = power down immediately after work completes. |

Overrides at lower levels are deep-merged with parent values. You only need to specify the fields you want to change.

When `streaming_enabled` is `true`, devices with WiFi or cellular connectivity can upload audio in chunks while recording. This enables:

* **Real-time processing** — Start transcription before recording finishes
* **Bandwidth management** — Upload in smaller chunks instead of one large file
* **Data caps** — Respect `daily_data_limit_mb` limits to control cellular costs

See the [Cellular Mode Guide](/guides/cellular-mode) for implementation details, the [Hierarchical Configuration Guide](/guides/hierarchical-config) for full config inheritance details, and the [Auto-Processing Guide](/guides/auto-processing) for automatic transcription and summarization setup.

### Recording

A **Recording** represents a captured conversation. It contains metadata and links to the audio file and transcription.

```json theme={null}
{
  "id": "rec_abc123",
  "device_id": "dev_xyz789",
  "end_user_id": "eu_abc123",
  "name": "Weekly client call - Acme Corp",
  "status": "completed",
  "duration_ms": 1800000,
  "file_size_bytes": 28800000,
  "mime_type": "audio/wav",
  "started_at": "2025-01-15T09:00:00Z",
  "ended_at": "2025-01-15T09:30:00Z",
  "transcription_id": "txn_def456",
  "metadata": {
    "meeting_type": "client_call",
    "location": "office"
  },
  "created_at": "2025-01-15T10:05:00Z",
  "uploaded_at": "2025-01-15T10:06:00Z"
}
```

**Recording lifecycle:**

```mermaid theme={null}
stateDiagram-v2
    [*] --> pending: Create
    pending --> uploaded: Upload complete
    uploaded --> processing: Start transcription
    processing --> completed: Transcription done
    processing --> failed: Transcription error
```

| Status       | Description                             |
| ------------ | --------------------------------------- |
| `pending`    | Created, awaiting audio upload          |
| `uploaded`   | Audio uploaded, ready for transcription |
| `processing` | Transcription in progress               |
| `completed`  | Transcription complete                  |
| `failed`     | Processing failed                       |

**Key points:**

* **Upload flow** — Create recording → Get upload URL → Upload to S3 → Mark complete
* **Automatic user association** — If `end_user_id` isn't specified, uses the device's bound user
* **Name** — Optional human-readable name for easy identification (e.g., "Weekly standup")
* **Metadata** — Store custom data like meeting type, location, or CRM opportunity ID

### Transcription

A **Transcription** is the result of processing a recording. It contains the full text and timestamped segments with speaker labels.

```json theme={null}
{
  "id": "txn_def456",
  "recording_id": "rec_abc123",
  "status": "completed",
  "language": "en",
  "duration_ms": 1800000,
  "text": "Hello, thanks for joining us today. Happy to be here!",
  "segments": [
    {
      "text": "Hello, thanks for joining us today.",
      "speaker": "SPEAKER_0",
      "start": 0.0,
      "end": 2.5,
      "confidence": 0.97
    },
    {
      "text": "Happy to be here!",
      "speaker": "SPEAKER_1",
      "start": 2.8,
      "end": 4.2,
      "confidence": 0.95
    }
  ],
  "created_at": "2025-01-15T10:10:00Z",
  "completed_at": "2025-01-15T10:15:00Z"
}
```

**Transcription output:**

| Field                      | Description                                                |
| -------------------------- | ---------------------------------------------------------- |
| `text`                     | Full transcript as a single string                         |
| `segments`                 | Array of segments with speaker, timestamps, and confidence |
| `segments[].speaker`       | Speaker label (e.g., `SPEAKER_0`, `SPEAKER_1`)             |
| `segments[].start` / `end` | Timestamp in seconds                                       |
| `segments[].confidence`    | Confidence score (0-1)                                     |

**Key points:**

* **Async processing** — Transcription is a job. Poll for status or use webhooks.
* **Speaker diarization** — Enabled by default. Identifies different speakers in the conversation.
* **Processing time** — Typically 10-30% of audio duration (30 min audio ≈ 3-10 min processing)

***

## Entity Relationships

### Project Scoping

All entities belong to a single project. You cannot:

* Query EndUsers across projects
* Use a device registered in one project for recordings in another
* Share transcriptions between projects

### ID Prefixes

Every entity has a prefixed ID for easy identification:

| Entity           | Prefix | Example      |
| ---------------- | ------ | ------------ |
| End User         | `eu_`  | `eu_abc123`  |
| Device           | `dev_` | `dev_xyz789` |
| Recording        | `rec_` | `rec_abc123` |
| Transcription    | `txn_` | `txn_def456` |
| Webhook Endpoint | `we_`  | `we_ghi789`  |
| Event            | `evt_` | `evt_jkl012` |

### Cascade Behavior

| Action           | Result                                                     |
| ---------------- | ---------------------------------------------------------- |
| Delete EndUser   | All recordings and transcriptions deleted, devices unbound |
| Delete Recording | Audio file and transcription deleted                       |
| Unbind Device    | Future recordings won't have an EndUser until rebound      |

***

## Common Patterns

### Mapping Users

Store a mapping between your user IDs and Bota EndUser IDs:

```javascript theme={null}
// Your database schema
{
  your_user_id: "user_123",
  bota_end_user_id: "eu_abc123"
}

// When creating recordings, look up the mapping
const botaEndUserId = await getBotaEndUserId(yourUserId);
```

Or use `external_id` to query directly:

```bash theme={null}
# Look up by external_id
curl "https://api.bota.dev/v1/end-users?external_id=user_123" \
  -H "Authorization: Bearer sk_live_..."
```

### Handling Multiple Devices

An EndUser can have multiple devices (e.g., different form factors or replacements):

```javascript theme={null}
// List devices for a user
const devices = await fetch(
  'https://api.bota.dev/v1/devices?end_user_id=eu_abc123',
  { headers: { 'Authorization': 'Bearer sk_live_...' } }
).then(r => r.json());
```

### Compliance Deletion

When a user requests data deletion:

```javascript theme={null}
// Delete the EndUser — cascades to all their data
await fetch('https://api.bota.dev/v1/end-users/eu_abc123', {
  method: 'DELETE',
  headers: { 'Authorization': 'Bearer sk_live_...' },
});

// Clean up your mapping
await removeUserMapping(yourUserId);
```

See [End User Deletion](/api-reference/end-users/delete) for details.
