Guides
SDK Guide
Integrate Synento into your application using the JavaScript/TypeScript SDK.
Integrate Synento into your application using the JavaScript/TypeScript SDK.
Installation
npm install @synento/nodeimport { createSynentoClient } from "@synento/node";
import type { Session, Project, ConnectionToken } from "@synento/node";Initialization
const synento = createSynentoClient({
apiKey: "sk_live_xxxxx",
baseUrl: "https://api.synento.com" // optional: SYNENTO_API_URL, then this
});This client holds your secret API key, so it belongs on the server only. In the
browser, use @synento/client and have your server
mint short-lived connection tokens for it.
Retry Configuration
Enable automatic retry for transient failures (network errors, 5xx responses):
synento.withRetry({ maxRetries: 3, baseDelayMs: 500 });The retry uses exponential backoff with jitter. Check the current config:
const options = synento.getRetryOptions(); // { maxRetries: 2, baseDelayMs: 500 }Session Methods
Create a Session
const session = await synento.createSession({ name: "My Meeting" });
console.log(session.id); // sess_abc123List Sessions
const sessions = await synento.listSessions();
for (const s of sessions) {
console.log(`${s.name} — ${s.startedAt ? "Started" : "Not started"} at ${s.createdAt}`);
}Get a Single Session
const session = await synento.getSession("sess_abc123");
if (session) {
console.log(`Session ended at: ${session.endedAt || "not yet"}`);
} else {
console.log("Session not found"); // returns null for 404
}Toggle Session Visibility
await synento.setSessionVisibility("sess_abc123", true); // make publicConnection Token Methods
Get a Live Streaming Token
const token = await synento.createConnectionToken("sess_abc123", { userId: "alice" });
// → { accessToken: "...", expiresIn: 300, session: "sess_abc123" }Get a Replay Token
const token = await synento.createConnectionToken("sess_abc123", {
userId: "viewer",
replay: true,
fromTs: 0, // start from beginning (use timeline API to find the right offset)
speed: 1.0, // playback speed (0.25 to 4)
});
// Connect WebSocket for replay
const wsUrl = synento.getWebSocketUrl("sess_abc123", token.accessToken, "viewer");
const ws = new WebSocket(wsUrl);
ws.onmessage = (event) => {
const data = JSON.parse(event.data as string);
if (data.stream_type.startsWith("media/")) {
// Decode and render video frame from data.body (base64 JPEG)
}
};Generate WebSocket URL
const wsUrl = synento.getWebSocketUrl(sessionId, accessToken, "alice");
// → wss://host/ws?session=sess_abc123&access_token=...&user_id=aliceProject Methods
Create a Project
const project = await synento.createProject("My App", "production");
// → { id: "...", name: "My App", orgId: "...", environment: "production" }List Projects
const projects = await synento.listProjects();
// → [{ id, name, orgId, environment }, ...]Webhook Methods
Create a Webhook
const webhook = await synento.createWebhook(
"https://example.com/webhooks/synento",
["session.created", "session.started", "session.ended"]
);
// Events: session.created, session.started, session.ended, recording.ready, export.completedList Webhooks
const webhooks = await synento.listWebhooks();
// → [{ id, projectId, url, events: string[], isActive }]Usage & Billing Methods
Check Billing Limits
const limits = await synento.getBillingLimits();
if (limits.isBlocked) {
console.error(`Blocked: ${limits.statusMessage}`);
}
// Access individual fields
console.log(`Minutes used: ${limits.streamingMinutesUsed}`);
console.log(`Has subscription: ${limits.hasActiveSubscription}`);Get Billing Summary with Cost Breakdown
const summary = await synento.getBillingSummary();
// → { streamingMinutesUsed, storageBytesUsed, costBreakdown?: { streamingCost, storageCost, totalDue } }Get Usage Records
const records = await synento.getUsage();
// → [{ id, projectId, sessionId, usageType: "streaming_minutes"|"storage_bytes", value, recordedAt }]API Key Management
List Keys (metadata only — no secrets)
const keys = await synento.listApiKeys();
// → [{ id, projectId, createdAt }]Create a New Key (returns the raw secret)
const result = await synento.createApiKey();
// → { id: "...", secret: "sk_live_xxxxx" } ← show this ONCERevoke a Key (deletes it)
await synento.revokeApiKey("key_id_here"); // deletes the key permanently
// → true (on success)Restricted keys
A restricted key (rk_live_…) works with the same client for everything an
integration does — createSession, createConnectionToken and
getSessionManifest — and nothing else. It is what a coding agent connected
over MCP writes into your environment:
SYNENTO_API_KEY=rk_live_…
SYNENTO_API_URL=https://api.synento.com
SYNENTO_PROJECT_ID=…Check that media arrived
const manifest = await synento.getSessionManifest(session.id);
// A participant whose tracks include "cam" and "mic" really published both.
const alice = manifest.participants.find((p) => p.user_id === "alice");
const kinds = alice?.tracks.map((t) => t.kind) ?? [];Advanced Patterns
Full Session Lifecycle in One Block
const project = await synento.createProject("Live Q&A");
const session = await synento.createSession({ name: "Q&A Session #5" });
await synento.setSessionVisibility(session.id, true); // make it public
const hostToken = await synento.createConnectionToken(session.id, { userId: "host" });
const guestToken = await synento.createConnectionToken(session.id, { userId: "guest-1" });
// Share URLs with participants (host token for broadcasting, guest for joining)
const hostWsUrl = synento.getWebSocketUrl(session.id, hostToken.accessToken, "host");
const guestWsUrl = synento.getWebSocketUrl(session.id, guestToken.accessToken, "guest-1");Error Handling
import { SynentoError } from "@synento/node";
try {
const session = await synento.createSession({ name: "Test" });
} catch (err) {
if (err instanceof SynentoError && err.statusCode === 401) {
console.error("Invalid or expired API key");
} else if (err instanceof SynentoError && err.statusCode === 403) {
console.error("Project access denied");
} else if (err instanceof SynentoError && err.statusCode === 429) {
console.error("Rate limited — retry after delay");
} else {
console.error("Unexpected error:", err.message);
}
}Reconnecting After Token Expiry
async function getReconnectToken(client: SynentoClient, sessionId: string): Promise<ConnectionToken> {
const token = await client.createConnectionToken(sessionId, { userId: "reconnect-user" });
// Token expires after `token.expiresIn` seconds — regenerate before expiry
setTimeout(async () => {
const newToken = await getReconnectToken(client, sessionId);
// Update your WebSocket URL or reconnect...
}, token.expiresIn * 800); // refresh at 80% of TTL
return token;
}