Kubo Live
Sign in
RESOURCES / REFERENCE

Documentation

API reference · Session authentication · Live events

Authentication

Sign in through the configured identity provider. The console uses same-origin session cookies; every POST, PATCH, and DELETE includes the current session CSRF token.

API key secrets are revealed once. Keep long-lived credentials on your server. Restricted live tokens belong in memory, never localStorage or source code.

live:readLive read scopedata:readData read scopealerts:writeAlerts API access (including reads)

Connect to live events

Request an account-restricted token, then connect to the returned WebSocket endpoint. An open socket does not mean the creator is live; events and collector errors must be handled as received.

JavaScript / restricted live session
// Same-origin browser session after signing in.
// Tokens default to a 60-second lifetime and one connection.
// Expiration applies to handshakes only.
// Already connected sockets are not closed when the token expires.
const session = await fetch('/api/auth/session', {
  credentials: 'include'
}).then(r => r.json());
if (!session.authenticated || !session.csrf) {
  throw new Error('Sign in at /api/auth/login first');
}

const response = await fetch('/api/tokens', {
  method: 'POST',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
    'X-CSRF-Token': session.csrf
  },
  body: JSON.stringify({ account: 'YOUR_CREATOR' })
});
if (!response.ok) throw new Error(await response.text());
const { jwtKey, wsUrl } = await response.json();
const url = new URL(wsUrl, window.location.origin);
if (url.protocol === 'https:') url.protocol = 'wss:';
if (url.protocol === 'http:') url.protocol = 'ws:';
url.searchParams.set('jwtKey', jwtKey);
const socket = new WebSocket(url);
socket.onmessage = event => {
  const frame = JSON.parse(event.data);
  for (const { type, data } of frame.messages ?? []) {
    console.log(type, data);
  }
};
socket.onerror = () => console.error('Transport failure');
socket.onclose = event => console.log('Closed', event.code);

Tokens default to expiresInSeconds: 60 and maxConnections: 1. maxConnections has a hard cap of 100 and cannot exceed workspace concurrency (Free: 25). Expiration applies only to new handshakes, not existing sockets.

Webhooks

Create an alert with an account and a required public HTTPS webhook URL. Destinations must be public HTTPS endpoints on port 443; the backend validates network safety. An accepted test request is not proof of delivery. Inspect the test response and delivery history.

JSON / create alert
{
  "account": "YOUR_CREATOR",
  "webhook": "https://YOUR_SERVER/webhooks/live"
}

External alerts API

Server-to-server /v1/alerts requests use Authorization: Bearer with an alerts:write API key. Listing, creating, updating, and deleting are metered. GET /v1/account requires data:read and is not metered. Session-based /api mutations still require CSRF.

cURL / external alerts
# Server-side only. Keep KUBO_API_KEY private.
curl --fail-with-body "$KUBO_ORIGIN/v1/account" \
  -H "Authorization: Bearer $KUBO_API_KEY"

curl --fail-with-body "$KUBO_ORIGIN/v1/alerts" \
  -H "Authorization: Bearer $KUBO_API_KEY"

curl --fail-with-body -X POST "$KUBO_ORIGIN/v1/alerts" \
  -H "Authorization: Bearer $KUBO_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"account":"YOUR_CREATOR","webhook":"https://YOUR_SERVER/webhooks/live"}'

curl --fail-with-body -X PATCH "$KUBO_ORIGIN/v1/alerts/$ALERT_ID" \
  -H "Authorization: Bearer $KUBO_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"enabled":false}'

curl --fail-with-body -X DELETE "$KUBO_ORIGIN/v1/alerts/$ALERT_ID" \
  -H "Authorization: Bearer $KUBO_API_KEY"

Endpoint reference

MethodEndpointResponse / action
GET/api/auth/sessionSession, user, CSRF token
GET/api/auth/loginIdentity provider sign-in
POST/api/auth/logoutEnd current session
GET/api/overviewUsage, limits, collector health
GET / POST/api/keysList / create scoped keys
DELETE/api/keys/:idRevoke a key
PATCH/api/keys/:idRename / reduce scopes only
POST/api/keys/:id/rotateCreate a new secret; old key remains active
POST/api/tokensRestricted JWT and WebSocket URL
GET/api/connectionsCollector connections
DELETE/api/connections/:idStop collector connection
GET / POST/api/alertsList / create live alerts
PATCH / DELETE/api/alerts/:idEnable, disable / delete alert
POST/api/alerts/:id/testSend a test webhook
GET/api/deliveriesWebhook delivery history
GET/api/usageDaily usage and operations
GET/api/usage?period=6h|24h|7d|30dTime-window usage buckets
GET/api/logs/requestsMetadata only; filters, cursor, limit
GET/api/logs/connectionsConnection lifecycle metadata; filters, cursor, limit
GET/api/plansAvailable capacity plans
GET/api/billingSubscription and sandbox readiness
POST/api/billing/checkoutSandbox checkout; may return 503
GET/api/settingsIdentity configuration
PATCH/api/settingsUpdate workspaceName
GET/api/auth/capabilitiesProvider readiness and registration reasons
GET/api/auth/registerStart registration only when ready; otherwise 503
GET/api/auth/reauthReauthenticate the same identity before account management
GET/v1/accountBearer data:read · account capacity · not metered
POST/v1/prepareBearer data:read · anonymous direct parameters · 60-second initialization · metered
GET/webcast/fetchBearer data:read · original TikTok protobuf · self-hosted request context · accepted deployments only
GET/webcast/rooms/:room_id/connectRoom-ID alias for the same unmodified original response
GET / POST/v1/alertsBearer alerts:write · list / create · metered
PATCH / DELETE/v1/alerts/:idBearer alerts:write · update / delete · metered

Errors & availability

401
Session expired or missing. Sign in again.
403
Permission denied or CSRF token invalid. Refresh the session and verify access.
429
Rate or capacity limit reached. Reduce request volume before retrying.
503
Service unavailable, collector unreachable, or billing not ready. Do not treat this as success.

The server reports collector and connection failures using error codes.