Base URL: https://api.digitalsamba.com
Version: 1.0.0
Your Developer Key is found in the Digital Samba Dashboard under Team Settings → Developer. It serves two purposes:
- API authentication — pass it in the
Authorizationheader for all REST API calls - JWT signing — use it as the HMAC-SHA256 secret when generating client-side access tokens
Security: Never expose the developer key in client-side code or browser requests. Use it only on your server.
Authorization: Bearer {DEVELOPER_KEY}
Or HTTP Basic Auth:
- Username:
{TEAM_ID} - Password:
{DEVELOPER_KEY}
All list endpoints support:
limit- Max 100 (default: 100)offset- Starting position (default: 0)order-ascordesc(default: desc)after- UUID for cursor-based pagination
Response format:
{
"total_count": 150,
"data": [...]
}Retrieve default settings applied to new rooms.
Response: Object with 50+ configuration properties (colors, features, limits)
Update default room settings.
Request Body:
{
"domain": "custom.domain.com",
"default_role": "attendee",
"session_length": 60,
"max_participants": 100
}Create a new room. All fields are optional — a room can be created with an empty body {} and will use your team's default settings.
Required fields: None. All fields below are optional.
Key Optional Fields:
| Field | Type | Default | Description |
|---|---|---|---|
friendly_url |
string | auto-generated | URL-safe room path (max 32 chars, must be unique per team) |
description |
string | null |
Room description |
privacy |
string | "public" |
"public" (anyone with URL) or "private" (requires JWT token) |
is_locked |
boolean | false |
When true, room requires approval to join |
max_participants |
integer | team default | Maximum concurrent participants |
session_length |
integer | team default | Max session duration in minutes (1–1440) |
default_role |
string | team default | Role assigned to users who join without a role in their token. Must be included in roles array |
roles |
array | team default | Available roles in this room. Must be provided when default_role is set |
join_screen_enabled |
boolean | true |
Show name/device entry screen before joining |
chat_enabled |
boolean | true |
Enable in-room chat |
qa_enabled |
boolean | false |
Enable Q&A panel |
recordings_enabled |
boolean | false |
Allow recording |
screenshare_enabled |
boolean | true |
Allow screen sharing |
raise_hand_enabled |
boolean | true |
Allow hand raising |
video_on_join_enabled |
boolean | true |
Auto-enable camera on join |
audio_on_join_enabled |
boolean | false |
Auto-enable microphone on join |
auto_pip_enabled |
boolean | team default | When enabled, Picture-in-Picture opens automatically when participants switch away from the main tab or app |
room_reactions_enabled |
boolean | team default | When enabled, all participants can use emoji reactions in the room |
invite_participants_advanced_enabled |
boolean | team default | Controls whether the "Invite people" UI is shown by default for users who can invite participants. Invitations are shared via copyable links or in-app actions, without opening an email client |
chat_reactions_enabled |
boolean | team default | When enabled, participants can react to chat messages with emojis |
chat_reactions_extended_enabled |
boolean | team default | When enabled, participants can react to chat messages using an expanded set of emojis |
virtual_backgrounds_v2_enabled |
boolean | team default | When enabled, participants will use the new virtual background engine |
connection_quality_indicator_enabled |
boolean | false |
When enabled, participants can see their local connection quality indicator in the room |
pin_panels_enabled |
boolean | team default | When enabled, roles with the relevant permission can force-pin tiles for everyone in the room |
chat_persistence_enabled |
boolean | false |
When enabled, public chat messages from previous sessions are retained and reloaded when rooms are reopened |
watermark_enabled |
boolean | false |
When enabled, a repeated text watermark is displayed across the screen to discourage unauthorized recording or sharing |
watermark_text |
string | null |
Custom watermark text. Latin characters, numbers, and basic punctuation only. Min 3, max 50 characters |
default_language |
string | "en" |
Room UI language. One of: ar-SA, ca-ES, en, es-ES, de-DE, it-IT, nb-NO, nl-NL, pt-PT, ro-RO, zh-CN, zh-TW |
toolbar |
object | {"position":"bottom","visible":true} |
Toolbar placement and visibility |
topbar_enabled |
boolean | true |
Show top bar |
logo_url |
string | null |
Custom logo URL |
primary_color |
string | null |
Hex color for UI accent |
background_color |
string | null |
Hex color for background |
Validation Rules:
friendly_url: Max 32 characters, URL-safe, unique per teamdefault_role: When set,rolesarray must also be provided and must containdefault_roleprivacy: Must be"public"or"private"session_length: Must be between 1 and 1440
Minimal Request (curl):
curl -X POST https://api.digitalsamba.com/api/v1/rooms \
-H "Authorization: Bearer YOUR_DEVELOPER_KEY" \
-H "Content-Type: application/json" \
-d '{"friendly_url": "my-meeting", "privacy": "public"}'Full Request (curl):
curl -X POST https://api.digitalsamba.com/api/v1/rooms \
-H "Authorization: Bearer YOUR_DEVELOPER_KEY" \
-H "Content-Type: application/json" \
-d '{
"friendly_url": "team-standup",
"description": "Daily standup meeting",
"privacy": "private",
"max_participants": 50,
"session_length": 60,
"default_role": "attendee",
"roles": ["moderator", "speaker", "attendee"],
"chat_enabled": true,
"recordings_enabled": true,
"screenshare_enabled": true,
"raise_hand_enabled": true
}'Node.js Example:
const response = await fetch('https://api.digitalsamba.com/api/v1/rooms', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.DS_DEVELOPER_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
friendly_url: 'team-standup',
privacy: 'private',
max_participants: 50,
default_role: 'attendee',
roles: ['moderator', 'speaker', 'attendee'],
chat_enabled: true,
recordings_enabled: true
})
});
if (!response.ok) {
const err = await response.json();
throw new Error(`${response.status}: ${err.message}`);
}
const room = await response.json();
console.log(`Room created: ${room.id}`);
console.log(`Room URL: ${room.room_url}`);Python Example:
import requests
response = requests.post(
'https://api.digitalsamba.com/api/v1/rooms',
headers={
'Authorization': f'Bearer {DEVELOPER_KEY}',
'Content-Type': 'application/json'
},
json={
'friendly_url': 'team-standup',
'privacy': 'private',
'max_participants': 50,
'default_role': 'attendee',
'roles': ['moderator', 'speaker', 'attendee'],
'chat_enabled': True,
'recordings_enabled': True
}
)
response.raise_for_status()
room = response.json()
print(f'Room created: {room["id"]}')
print(f'Room URL: {room["room_url"]}')Response (200 OK):
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"friendly_url": "team-standup",
"description": "Daily standup meeting",
"privacy": "private",
"is_locked": false,
"room_url": "https://yourteam.digitalsamba.com/team-standup",
"max_participants": 50,
"session_length": 60,
"default_role": "attendee",
"roles": ["moderator", "speaker", "attendee"],
"join_screen_enabled": true,
"chat_enabled": true,
"qa_enabled": false,
"recordings_enabled": true,
"screenshare_enabled": true,
"raise_hand_enabled": true,
"video_on_join_enabled": true,
"audio_on_join_enabled": false,
"topbar_enabled": true,
"auto_pip_enabled": false,
"room_reactions_enabled": true,
"invite_participants_advanced_enabled": false,
"chat_reactions_enabled": true,
"chat_persistence_enabled": false,
"watermark_enabled": false,
"watermark_text": null,
"default_language": "en",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}List all team rooms. Returns a paginated response.
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit |
integer | 100 | Max records to return (max 100) |
offset |
integer | 0 | Starting position for pagination |
order |
string | "desc" |
Sort order: "asc" or "desc" |
after |
string | - | Room UUID or friendly_url for cursor-based pagination |
tag |
string/array | - | Filter by tag(s) |
curl Example:
curl https://api.digitalsamba.com/api/v1/rooms?limit=10&order=desc \
-H "Authorization: Bearer YOUR_DEVELOPER_KEY"Node.js Example (with pagination):
async function listAllRooms() {
const allRooms = [];
let offset = 0;
const limit = 100;
while (true) {
const response = await fetch(
`https://api.digitalsamba.com/api/v1/rooms?limit=${limit}&offset=${offset}`,
{ headers: { 'Authorization': `Bearer ${process.env.DS_DEVELOPER_KEY}` } }
);
if (!response.ok) {
const err = await response.json();
throw new Error(`${response.status}: ${err.message}`);
}
const { data, total_count } = await response.json();
allRooms.push(...data);
if (allRooms.length >= total_count) break;
offset += limit;
}
return allRooms;
}
// Usage
const rooms = await listAllRooms();
rooms.forEach(r => console.log(`${r.friendly_url} (${r.privacy}) — ${r.id}`));Python Example (with pagination):
def list_all_rooms():
all_rooms = []
offset = 0
limit = 100
while True:
response = requests.get(
f'https://api.digitalsamba.com/api/v1/rooms?limit={limit}&offset={offset}',
headers={'Authorization': f'Bearer {DEVELOPER_KEY}'}
)
response.raise_for_status()
data = response.json()
all_rooms.extend(data['data'])
if len(all_rooms) >= data['total_count']:
break
offset += limit
return all_rooms
# Usage
rooms = list_all_rooms()
for r in rooms:
print(f'{r["friendly_url"]} ({r["privacy"]}) — {r["id"]}')Response (200 OK):
{
"total_count": 42,
"data": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"friendly_url": "team-standup",
"description": "Daily standup meeting",
"privacy": "private",
"max_participants": 50,
"is_locked": false,
"room_url": "https://yourteam.digitalsamba.com/team-standup",
"created_at": "2024-01-15T10:30:00Z"
}
]
}Get room details. {room} can be UUID or friendly_url.
Update room settings.
Delete a room.
Delete all rooms that have any of the specified tags. Rooms with active sessions are skipped.
Request Body:
{
"tags": ["tag1", "tag2"],
"delete_resources": false,
"delete_history": false,
"delete_library": false
}| Field | Type | Required | Description |
|---|---|---|---|
tags |
array | yes | Tag names — rooms matching any tag will be deleted |
delete_resources |
boolean | no | Hard delete all stored resource data for matching rooms |
delete_history |
boolean | no | Anonymise all participants PII for matching rooms |
delete_library |
boolean | no | Delete content library for matching rooms |
Generate JWT access token for a room.
Request Body:
{
"ud": "user-123",
"u": "John Doe",
"initials": "JD",
"role": "moderator",
"avatar": "https://example.com/avatar.jpg",
"breakoutId": "breakout-uuid",
"nbf": 1700000000,
"exp": 1700003600
}Response:
{
"token": "eyJ0eXAiOiJKV1Q...",
"link": "https://team.digitalsamba.com/room?token=eyJ..."
}Retrieve chat messages.
Query Parameters:
session_id- Filter by sessionlimit,offset,order,after
Response:
{
"data": [{
"id": "uuid",
"message": "Hello everyone",
"participant_id": "uuid",
"participant_name": "John",
"external_participant_id": "user-123",
"breakout_id": null,
"created_at": "2024-01-15T10:30:00Z"
}]
}Export chat as file.
Query Parameters:
session_idformat-txtorjson
Send a chat message to an active session.
Request Body:
{
"message": "Hello!"
}Delete all chat messages for a room.
Retrieve Q&A content.
Response:
{
"data": [{
"id": "uuid",
"question": "How do I...?",
"participant_id": "uuid",
"participant_name": "Jane",
"answers": [{
"id": "uuid",
"answer": "You can...",
"participant_name": "Moderator"
}],
"created_at": "2024-01-15T10:30:00Z"
}]
}Create a question in the room.
Request Body:
{
"participant": {
"name": "John Doe",
"external_id": "ABCDEF123"
},
"question": "My question?",
"anonymous": true,
"breakout_id": null
}| Field | Type | Required | Description |
|---|---|---|---|
participant |
object | yes | Either { "name", "external_id" } or { "id" } (UUID of existing participant) |
question |
string | yes | The question text |
anonymous |
boolean | no | Whether to show as anonymous |
breakout_id |
string | no | UUID of breakout room (nullable) |
Export Q&A as txt or json.
Delete all Q&A content.
Update an existing question's text.
Request Body:
{
"participant": { "id": "uuid" },
"question": "Updated question text"
}| Field | Type | Required | Description |
|---|---|---|---|
participant |
object | yes | Either { "name", "external_id" } or { "id" } (UUID of existing participant) |
question |
string | yes | Updated question text |
Delete a single question. Requires a participant object in the request body identifying the actor.
Mark a question as dismissed. Body: { "participant": { ... } }.
Reopen a previously dismissed question. Body: { "participant": { ... } }.
Upvote a question on behalf of a participant. Body: { "participant": { ... } }.
Remove a participant's vote from a question. Body: { "participant": { ... } }.
Post an answer to a question.
Request Body:
{
"participant": { "id": "uuid" },
"answer": "My answer",
"private": false
}| Field | Type | Required | Description |
|---|---|---|---|
participant |
object | yes | Either { "name", "external_id" } or { "id" } (UUID of existing participant) |
answer |
string | yes | The answer text |
private |
boolean | no | When true, the answer is private to the asker |
Update an existing answer.
Request Body:
{
"participant": { "id": "uuid" },
"answer": "Updated answer text"
}Delete a single answer. Body: { "participant": { ... } }.
Start a live (in-session) answer for a question. Body: { "participant": { ... } }.
Stop the currently active live answer for a question. Body: { "participant": { ... } }.
Cancel an in-progress live answer for a question. Body: { "participant": { ... } }.
Retrieve closed captions/transcripts.
Response:
{
"data": [{
"participant_id": "uuid",
"participant_name": "John",
"transcript": "I think we should...",
"start_time": "2024-01-15T10:30:00Z",
"end_time": "2024-01-15T10:30:05Z"
}]
}Export transcripts as txt or json.
Query Parameters: format (txt or json)
Request Body (optional):
| Field | Type | Description |
|---|---|---|
locale |
string | Export locale: en, it, de, es |
lang |
string | Export language: en, it, de, es |
Delete transcripts.
Delete AI-generated summaries.
List polls for a room. Returns paginated response with total_count and data array.
Create a new poll.
Request Body:
{
"question": "What topic should we cover next?",
"type": "single",
"anonymous": true,
"options": [
{"id": "uuid-optional", "label": "API Design"},
{"id": "uuid-optional", "label": "Security"},
{"id": "uuid-optional", "label": "Performance"}
]
}Poll Types:
| Type | Description |
|---|---|
single |
Single choice (one answer) |
multiple |
Multiple choices (select many) |
free |
Short answer (free text) |
Note: The
multipleboolean field is deprecated. Usetype: "multiple"instead.
Response:
{
"id": "uuid",
"question": "What topic...",
"status": "draft",
"type": "single",
"anonymous": true,
"options": [
{"id": "uuid", "label": "API Design"},
{"id": "uuid", "label": "Security"},
{"id": "uuid", "label": "Performance"}
],
"created_at": "2024-01-15T10:30:00Z"
}Delete all polls.
Import polls from a CSV file.
Request (multipart/form-data):
| Field | Type | Required | Description |
|---|---|---|---|
file |
binary | yes | CSV or TXT file, max 2MB |
Use GET /api/v1/rooms/{room}/polls/template to download the CSV template.
Download a CSV template for poll import.
Create and manage in-meeting quizzes with multiple choice questions.
List quizzes for a room.
Query Parameters: limit, offset, order, after
Response:
{
"total_count": 1,
"data": [{
"id": "uuid",
"title": "My quiz",
"time_limit_minutes": 45,
"status": "created",
"created_at": "2025-12-19T05:33:54Z"
}]
}Create a new quiz.
Request Body:
{
"title": "My quiz",
"time_limit_minutes": 60,
"questions": [
{
"text": "Question #1",
"multiple": false,
"choices": [
{"text": "Correct answer", "correct": true},
{"text": "Wrong answer", "correct": false}
]
},
{
"text": "Question #2 (multiple choice)",
"multiple": true,
"choices": [
{"text": "Correct answer #1", "correct": true},
{"text": "Wrong answer", "correct": false},
{"text": "Correct answer #2", "correct": true}
]
}
]
}Field Constraints:
| Field | Constraint |
|---|---|
title |
Min 1, max 512 characters |
questions[].text |
Min 1, max 512 characters |
time_limit_minutes |
Min 1, max 1440 (24 hours) |
time_limit_seconds |
Min 1, max 86400 (alternative to minutes) |
timing_mode |
"quiz" (whole quiz) or "question" (per question), nullable |
Response: Full quiz object with generated UUIDs for quiz, questions, and choices.
Get quiz details including all questions and choices.
Update a quiz. Include question/choice id to update existing items, omit to create new ones.
Delete a specific quiz.
Delete all quizzes for a room.
Get quiz results with participant responses.
Query Parameters:
session_id- Filter by session UUID
Response:
[{
"id": "uuid",
"session_id": "uuid",
"title": "My quiz",
"status": "launched",
"started": "2025-12-19T07:29:52Z",
"ended": "2025-12-19T07:30:52Z",
"questions": [{
"id": "uuid",
"question": "Question #1",
"voted": 4,
"votes": [{
"id": "uuid",
"text": "Answer #1",
"voted": 3,
"voters": [{"id": "uuid", "name": "John"}]
}]
}]
}]Import quizzes from a CSV file.
Request (multipart/form-data):
| Field | Type | Required | Description |
|---|---|---|---|
file |
binary | yes | CSV or TXT file, max 2MB |
Use GET /api/v1/rooms/{room}/quizzes/template to download the CSV template.
Download a CSV template for quiz import.
Export quiz results.
Query Parameters:
format-csv,txt, orjson
Delete all recordings for a room.
List all recordings.
Get recording details.
Download recording file.
Delete a specific recording.
Archive a recording.
List all sessions.
Get session details.
List participants in a session.
Get session statistics.
Get AI-generated summary of a session's transcribed content. Summaries are generated by self-hosted AI models — transcript data is not transmitted to any third party.
Response (in progress):
{
"job_id": "uuid",
"status": "IN_PROGRESS",
"summary": ""
}Response (ready):
{
"job_id": "uuid",
"status": "READY",
"summary": "Meeting discussed quarterly targets and agreed on..."
}Note: Summary generation is asynchronous. Poll approximately every minute until
statuschanges toREADY. Requires transcription to have been enabled during the session.
Get session transcripts.
Export session transcripts as txt or json.
Query Parameters: format (txt or json)
Request Body (optional):
| Field | Type | Description |
|---|---|---|
locale |
string | Export locale: en, it, de, es |
lang |
string | Export language: en, it, de, es |
End the specified live session.
Delete all chat messages for a session.
Delete all Q&A for a session.
Delete AI-generated summaries for a session.
Delete transcripts for a session.
Delete all polls for a session.
Delete all quizzes for a session.
Delete all recordings for a session.
Hard delete all stored resource data for a specific session.
Request Body (optional):
| Field | Type | Description |
|---|---|---|
delete_history |
boolean | Anonymise all participants PII for this session |
List all participants.
Get participant details.
List sessions for a participant.
Connect phone participants to rooms via SIP integration.
Connect the room to the phone bridge (SIP). Enables phone dial-in participants to join the meeting.
Disconnect the room from the phone bridge (SIP).
Mute a phone participant.
Unmute a phone participant.
Stream room video to external platforms like YouTube, Vimeo, or custom RTMP servers.
Start RTMP restreaming from the room.
Request Body:
{
"type": "youtube",
"stream_key": "your-stream-key"
}Or with custom RTMP server:
{
"server_url": "rtmps://rtmp-global.cloud.vimeo.com/live",
"stream_key": "your-stream-key"
}Parameters:
| Field | Description |
|---|---|
type |
Restreaming provider: youtube, vimeo, or cloudflare. Don't use with server_url. |
server_url |
Custom RTMP server URL. Don't use with type. |
stream_key |
(Required) Unique authentication token for your restreaming destination. |
Stop RTMP restreaming from the room.
List custom roles.
Create a custom role.
Request Body:
{
"name": "presenter",
"display_name": "Presenter",
"permissions": {
"broadcast": true,
"screenshare": true,
"chat": true,
"raise_hand": true,
"recording": false,
"emoji_reactions": true
}
}Get role details.
Update a role.
Delete a role.
List library folders.
Create a library folder.
List files in a library.
Upload a file to library.
Delete a library file.
Get live participant count for a room.
Get total live participants across all rooms.
Room usage statistics.
Participant statistics.
Session statistics.
Recording statistics.
List configured webhooks.
Create a webhook.
Request Body:
{
"endpoint": "https://your-server.com/webhook",
"events": [
"session.started",
"session.ended",
"participant.joined",
"participant.left",
"recording.started",
"recording.stopped"
],
"secret": "your-webhook-secret"
}Get webhook details.
Update a webhook.
Delete a webhook.
| Event | Triggered When |
|---|---|
session.started |
Meeting begins |
session.ended |
Meeting ends |
participant.joined |
User joins room |
participant.left |
User leaves room |
recording.started |
Recording begins |
recording.stopped |
Recording ends |
recording.ready |
Recording processed and available |
transcript.ready |
Transcript available |
Webhook Payload:
{
"event": "participant.joined",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"room_id": "uuid",
"session_id": "uuid",
"participant_id": "uuid",
"external_id": "user-123",
"name": "John Doe"
}
}Signature Verification: Webhooks are signed with HMAC-SHA256 using your webhook secret. Verify the X-Signature header matches the computed hash of the payload.