Skip to content

Commit 2ef9de7

Browse files
ConalMullanclaude
andcommitted
feat: add missing API endpoints for full OpenAPI coverage
New API client methods: - getRoomTranscripts, getSessionTranscripts, deleteRoomTranscripts, exportRoomTranscripts - raiseParticipantHand, lowerParticipantHand - raisePhoneParticipantHand, lowerPhoneParticipantHand - getRecordingBookmarks - deleteSessionRecordings, deleteSessionResources New MCP tools: - list-room-transcripts, list-session-transcripts, export-room-transcripts - raise-participant-hand, lower-participant-hand - raise-phone-participant-hand, lower-phone-participant-hand - get-recording-bookmarks - delete-session-recordings, delete-session-resources Also improved delete-room-transcripts to use direct API call instead of iterating sessions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 6f3b9be commit 2ef9de7

8 files changed

Lines changed: 1003 additions & 55 deletions

File tree

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
"eslint": "^9.28.0",
6868
"globals": "^16.2.0",
6969
"jest": "^30.0.0",
70+
"js-yaml": "^4.1.1",
7071
"prettier": "^3.2.5",
7172
"ts-jest": "^29.1.1",
7273
"tsx": "^4.7.0",

src/digital-samba-api.ts

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,58 @@ export class DigitalSambaApiClient {
885885
});
886886
}
887887

888+
/**
889+
* Raise participant's hand
890+
*/
891+
async raiseParticipantHand(
892+
roomId: string,
893+
participantId: string,
894+
): Promise<void> {
895+
await this.request<void>(
896+
`/rooms/${roomId}/participants/${participantId}/raise-hand`,
897+
{ method: "POST" },
898+
);
899+
}
900+
901+
/**
902+
* Lower participant's hand
903+
*/
904+
async lowerParticipantHand(
905+
roomId: string,
906+
participantId: string,
907+
): Promise<void> {
908+
await this.request<void>(
909+
`/rooms/${roomId}/participants/${participantId}/lower-hand`,
910+
{ method: "POST" },
911+
);
912+
}
913+
914+
/**
915+
* Raise phone participant's hand
916+
*/
917+
async raisePhoneParticipantHand(
918+
roomId: string,
919+
callId: string,
920+
): Promise<void> {
921+
await this.request<void>(
922+
`/rooms/${roomId}/phone-participants/${callId}/raise-hand`,
923+
{ method: "POST" },
924+
);
925+
}
926+
927+
/**
928+
* Lower phone participant's hand
929+
*/
930+
async lowerPhoneParticipantHand(
931+
roomId: string,
932+
callId: string,
933+
): Promise<void> {
934+
await this.request<void>(
935+
`/rooms/${roomId}/phone-participants/${callId}/lower-hand`,
936+
{ method: "POST" },
937+
);
938+
}
939+
888940
// Recordings
889941

890942
/**
@@ -965,6 +1017,29 @@ export class DigitalSambaApiClient {
9651017
);
9661018
}
9671019

1020+
/**
1021+
* Get bookmarks for a recording
1022+
*/
1023+
async getRecordingBookmarks(
1024+
recordingId: string,
1025+
): Promise<
1026+
Array<{
1027+
id: string;
1028+
timestamp: number;
1029+
label?: string;
1030+
created_at: string;
1031+
}>
1032+
> {
1033+
return this.request<
1034+
Array<{
1035+
id: string;
1036+
timestamp: number;
1037+
label?: string;
1038+
created_at: string;
1039+
}>
1040+
>(`/recordings/${recordingId}/bookmarks`);
1041+
}
1042+
9681043
/**
9691044
* Archive a recording
9701045
*/
@@ -1376,6 +1451,133 @@ export class DigitalSambaApiClient {
13761451
});
13771452
}
13781453

1454+
// Transcripts
1455+
1456+
/**
1457+
* Get room transcripts (closed captioning data)
1458+
*/
1459+
async getRoomTranscripts(
1460+
roomId: string,
1461+
params?: PaginationParams & {
1462+
session_id?: string;
1463+
},
1464+
): Promise<
1465+
ApiResponse<{
1466+
id: string;
1467+
text: string;
1468+
participant_id: string;
1469+
participant_name: string;
1470+
session_id: string;
1471+
created_at: string;
1472+
}>
1473+
> {
1474+
const queryParams = new URLSearchParams();
1475+
if (params) {
1476+
Object.entries(params).forEach(([key, value]) => {
1477+
if (value !== undefined) {
1478+
queryParams.append(key, String(value));
1479+
}
1480+
});
1481+
}
1482+
1483+
const query = queryParams.toString() ? `?${queryParams.toString()}` : "";
1484+
return this.request<
1485+
ApiResponse<{
1486+
id: string;
1487+
text: string;
1488+
participant_id: string;
1489+
participant_name: string;
1490+
session_id: string;
1491+
created_at: string;
1492+
}>
1493+
>(`/rooms/${roomId}/transcripts${query}`);
1494+
}
1495+
1496+
/**
1497+
* Get session transcripts (closed captioning data)
1498+
*/
1499+
async getSessionTranscripts(
1500+
sessionId: string,
1501+
params?: PaginationParams,
1502+
): Promise<
1503+
ApiResponse<{
1504+
id: string;
1505+
text: string;
1506+
participant_id: string;
1507+
participant_name: string;
1508+
created_at: string;
1509+
}>
1510+
> {
1511+
const queryParams = new URLSearchParams();
1512+
if (params) {
1513+
Object.entries(params).forEach(([key, value]) => {
1514+
if (value !== undefined) {
1515+
queryParams.append(key, String(value));
1516+
}
1517+
});
1518+
}
1519+
1520+
const query = queryParams.toString() ? `?${queryParams.toString()}` : "";
1521+
return this.request<
1522+
ApiResponse<{
1523+
id: string;
1524+
text: string;
1525+
participant_id: string;
1526+
participant_name: string;
1527+
created_at: string;
1528+
}>
1529+
>(`/sessions/${sessionId}/transcripts${query}`);
1530+
}
1531+
1532+
/**
1533+
* Delete room transcripts
1534+
*/
1535+
async deleteRoomTranscripts(roomId: string): Promise<void> {
1536+
await this.request<void>(`/rooms/${roomId}/transcripts`, {
1537+
method: "DELETE",
1538+
});
1539+
}
1540+
1541+
/**
1542+
* Export room transcripts
1543+
*/
1544+
async exportRoomTranscripts(
1545+
roomId: string,
1546+
options?: {
1547+
format?: "txt" | "json";
1548+
},
1549+
): Promise<string> {
1550+
const queryParams = new URLSearchParams();
1551+
if (options) {
1552+
Object.entries(options).forEach(([key, value]) => {
1553+
if (value !== undefined) {
1554+
queryParams.append(key, String(value));
1555+
}
1556+
});
1557+
}
1558+
1559+
const query = queryParams.toString() ? `?${queryParams.toString()}` : "";
1560+
1561+
const apiKey = this.getApiKey();
1562+
const response = await fetch(
1563+
`${this.apiBaseUrl}/rooms/${roomId}/transcripts/export${query}`,
1564+
{
1565+
headers: {
1566+
Authorization: `Bearer ${apiKey}`,
1567+
},
1568+
},
1569+
);
1570+
1571+
if (!response.ok) {
1572+
const errorText = await response.text();
1573+
throw new Error(
1574+
`Digital Samba API error (${response.status}): ${errorText}`,
1575+
);
1576+
}
1577+
1578+
return response.text();
1579+
}
1580+
13791581
// Polls
13801582

13811583
/**
@@ -2325,4 +2527,30 @@ export class DigitalSambaApiClient {
23252527
},
23262528
);
23272529
}
2530+
2531+
/**
2532+
* Delete session recordings
2533+
*/
2534+
async deleteSessionRecordings(sessionId: string): Promise<void> {
2535+
if (this.cache) {
2536+
this.cache.invalidateNamespace("api");
2537+
}
2538+
2539+
await this.request<void>(`/sessions/${sessionId}/recordings`, {
2540+
method: "DELETE",
2541+
});
2542+
}
2543+
2544+
/**
2545+
* Delete session resources
2546+
*/
2547+
async deleteSessionResources(sessionId: string): Promise<void> {
2548+
if (this.cache) {
2549+
this.cache.invalidateNamespace("api");
2550+
}
2551+
2552+
await this.request<void>(`/sessions/${sessionId}/resources`, {
2553+
method: "DELETE",
2554+
});
2555+
}
23282556
}

0 commit comments

Comments
 (0)