This guide explains the key entities in the Bota platform and how they work together.
Entity Overview
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 |
All API calls require a project-scoped API key. You cannot query across projects.
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 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 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.
{
"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).
Use the external_id field to store your system’s user ID. This lets you look up Bota EndUsers by your own identifiers.
Device
A Device represents a physical Bota wearable. Each device has a unique serial number.
{
"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:
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):
Fleet monitoring:
Cellular-capable devices can report health status via the heartbeat endpoint:
- Battery level
- Storage usage
- Signal strength
- Firmware version
Device tokens have limited permissions compared to API keys. They cannot list recordings, access other users’ data, or perform administrative operations. See Authentication for details.
Device Settings
Device Settings configure device behavior for connectivity, uploads, and processing. Settings use the hierarchical configuration system — 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
{
"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). BLE 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) |
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 for implementation details, the Hierarchical Configuration Guide for full config inheritance details, and the Auto-Processing Guide for automatic transcription and summarization setup.
Recording
A Recording represents a captured conversation. It contains metadata and links to the audio file and transcription.
{
"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:
| 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.
{
"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:
// 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:
# 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):
// 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:
// 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 for details.