Your API key is a project secret — it lives on your server and never ships to an app or browser. The server's only job for calling is to exchange that key for short-lived tokens.
Two token types
- Session token (
/v1/session) — lets a user connect to the signalling socket for call invitations + chat. Mint this at login; the client SDK’sconnect()uses it. - Room token (
/v1/token) — lets a participant join one specific media room. Use this if you skip signalling and join a room directly.
sk_live_… in an app, a mobile binary, or browser code. Anyone with it can mint tokens on your project. Keep it in a server env var.Mint a session token
Body { userId, userName } → { token, userId, userName }. A minimal endpoint your app calls:
1// Your backend — mint a SESSION token for the signalling socket.2// The app's client.connect({ sessionEndpoint }) calls this with { userId, userName }.3import express from "express";4const app = express();5app.use(express.json());67const SOCRITS = "https://api.socrits.com";8const KEY = process.env.SOCRITS_API_KEY; // sk_live_… — server-side only910app.post("/socrits/session", async (req, res) => {11 // 1) authenticate YOUR user first (session cookie / JWT / etc.)12 const { userId, userName } = req.body; // trust your own auth, not the client13 // 2) exchange your key for a Socrits user token14 const r = await fetch(SOCRITS + "/v1/session", {15 method: "POST",16 headers: { "x-api-key": KEY, "Content-Type": "application/json" },17 body: JSON.stringify({ userId, userName }),18 });19 res.json(await r.json()); // → { token, userId, userName }20});Mint a room token
Body { room, identity } → { token, url, room }. Hand the url + token to the app to join:
1// Your backend — mint a ROOM token (join a specific room directly, no signalling).2app.post("/socrits/token", async (req, res) => {3 const { room, identity } = req.body; // derive from YOUR authed user4 const r = await fetch(SOCRITS + "/v1/token", {5 method: "POST",6 headers: { "x-api-key": KEY, "Content-Type": "application/json" },7 body: JSON.stringify({ room, identity }),8 });9 res.json(await r.json()); // → { token, url, room }10});Managing keys
- Create/revoke keys per project via the Dashboard API (reference) — a raw key is shown once, then only its hash is stored.
- Use a separate key per environment (dev/staging/prod). Revoke a key the moment it leaks — revocation is instant.
- Rooms are namespaced to your project id, so your room names can never collide with another tenant's.
Room control
Manage a live room from your backend with the project key — the ZEGO KickoutUser / room-dismiss equivalent. Use remove to disconnect one participant (e.g. when their coins run out) while the others keep talking, or end to terminate the whole room.
POST /v1/rooms/:room/remove— body{ identity }; disconnects that one participant.POST /v1/rooms/:room/end— terminates the room, disconnecting everyone.GET /v1/rooms/:room/participants— who’s currently in the room.
1// Your backend — manage a live room with your project key.23// Kick ONE participant (e.g. their balance hit zero). Others stay connected.4await fetch(SOCRITS + "/v1/rooms/" + room + "/remove", {5 method: "POST",6 headers: { "x-api-key": KEY, "Content-Type": "application/json" },7 body: JSON.stringify({ identity }), // the identity you minted the token with8});910// End the WHOLE room — disconnects everyone.11await fetch(SOCRITS + "/v1/rooms/" + room + "/end", {12 method: "POST",13 headers: { "x-api-key": KEY },14});1516// Who's in the room right now.17const res = await fetch(SOCRITS + "/v1/rooms/" + room + "/participants", {18 headers: { "x-api-key": KEY },19}); // → { participants: [{ identity, joinedAt }] }:room is the same room name you pass to /v1/token (Socrits namespaces it to your project internally). For an intentional in-call hang up over hosted signalling, a client sends call:end and the peer receives call:ended (plus a call.ended webhook) — so you can tell a real hang-up from a network drop.Webhooks & metering
Socrits meters participant-minutes per project from LiveKit room events it receives internally — you don’t configure anything. Read current-month usage via GET /dashboard/projects/:id/usage.
CallbackSecret (verify the t=/v1=header). See the API reference for the event catalog.