Zokai / Docs

Quickstart

5 min

Go from zero to receiving live events in your app in under five minutes.


1

Create a Zokai account

Head to the dashboard and register. It's free — no credit card required.

Once logged in, click + New App and give your app a name. You'll land on the app detail page where you can grab your credentials.

2

Get your API key and secret

Open the Credentials tab in your app. Copy the API Key (public, safe in the browser) and the API Secret (keep this server-side only).

⚠️ Never expose your API Secret in client-side code or public repositories. It's used to sign tokens on your backend.
3

Install the client SDK

bash
npm install @zokai/client
4

Connect and subscribe

Add this to your frontend. Replace YOUR_APP_KEY with the key from the dashboard.

javascript
import Zokai from '@zokai/client';

// 1. Connect using your app key
const client = new Zokai({ appKey: 'YOUR_APP_KEY' });

// 2. Subscribe to a channel
const channel = client.subscribe('orders');

// 3. Listen for events
channel.on('new-order', (data) => {
  console.log('New order:', data);
});
5

Publish an event from your backend

From your server, call the Zokai REST API to push an event to all subscribers.

node.js
// server.js
import Zokai from '@zokai/server';

const zokai = new Zokai({
  appKey:    process.env.ZOKAI_KEY,
  appSecret: process.env.ZOKAI_SECRET,
});

// When a new order is created in your app:
await zokai.publish('orders', 'new-order', {
  id:    'ORD-1042',
  total: 89.00,
  status: 'confirmed',
});
Your browser client will receive the event in milliseconds. That's it — you're live!

Installation

Client SDK (browser / React Native)

bash
npm install @zokai/client
# or
yarn add @zokai/client
# or
pnpm add @zokai/client

Server SDK — Node.js

bash
npm install @zokai/server

Server SDK — Python

bash
pip install zokai

Server SDK — Go

bash
go get github.com/zokai/zokai-go

Authentication

Zokai uses a two-credential system — a public API Key and a private API Secret.

CredentialWhere to useSafe in browser?
API Key Client SDK initialization, WebSocket URL ✅ Yes
API Secret Server SDK, REST API requests, token signing ❌ No — backend only

How it works

When a client connects to Zokai, it opens a WebSocket using the API Key. For public channels, that's enough. For private channels, the client must authenticate with a signed token generated by your backend:

flow
Browser                   Your Server                 Zokai
  │                            │                          │
  │── subscribe('private-x') ──▶                          │
  │                            │                          │
  │◀── GET /auth/zokai ────────│ (your auth endpoint)     │
  │                            │── sign token ────────▶   │
  │                            │◀─ token ──────────────   │
  │                            │                          │
  │── zok:auth(token) ─────────────────────────────────▶  │
  │◀── zok:auth_success ───────────────────────────────   │
  │◀── zok:subscribed ─────────────────────────────────   │
ℹ️ Public channels (names that don't start with private-) do not require authentication beyond the API Key.

Channels

Channels are named streams of events. Any number of clients can subscribe to a channel. Events published to a channel are delivered to all current subscribers.

TypePrefixAuth requiredUse case
Public news, global-feed No Public notifications, live scores, price tickers
Private private- Yes — server token Per-user feeds, DMs, order status, account data
Presence presence- Yes — server token Who's online, collaborative cursors, typing indicators

Naming rules

  • Max 200 characters
  • Allowed: letters, numbers, hyphens, underscores, dots
  • Use dots for namespacing: chat.room.42, user.1234.inbox

Events

Events are JSON messages sent over a channel. Each event has a name and optional data payload.

json
{
  "event":   "new-order",
  "channel": "orders",
  "data": {
    "id":     "ORD-1042",
    "total":  89.00,
    "status": "confirmed"
  }
}
  • Event names can be any string — use a consistent convention like kebab-case or past-tense verbs.
  • Data payload can be any JSON value — object, array, string, number.
  • Max payload size: 64 KB.

Presence

Presence channels let you track which users are currently subscribed. When a user joins or leaves, all other subscribers in the channel are notified automatically.

javascript
const ch = client.subscribe('presence-chat');

// Fires when the subscription succeeds — contains the current member list
ch.on('zokai:subscription_succeeded', ({ members }) => {
  console.log('Online now:', members);
});

// Member joined
ch.on('zokai:member_added', ({ id, info }) => {
  console.log(info.name, 'joined');
});

// Member left
ch.on('zokai:member_removed', ({ id }) => {
  console.log(id, 'left');
});

Client SDK

Installation

bash
npm install @zokai/client

Works in any modern browser and React Native. No additional bundler config needed.

Connecting

javascript
import Zokai from '@zokai/client';

const client = new Zokai({
  appKey:     'YOUR_APP_KEY',        // required
  authEndpoint: '/api/zokai/auth',  // required for private/presence channels
  cluster:    'us-east-1',          // optional, default: nearest
});

// Connection lifecycle events
client.on('connected',    () => console.log('Connected'));
client.on('disconnected', () => console.log('Disconnected — reconnecting…'));
client.on('error',        (err) => console.error('Error', err));
OptionTypeDefaultDescription
appKeystringrequiredYour public API key
authEndpointstring/zokai/authYour server endpoint for signing private channel tokens
clusterstringautoRegion hint for nearest gateway node
autoReconnectbooleantrueReconnect automatically on disconnect

Subscribing to channels

javascript
// Public channel — no auth required
const feed = client.subscribe('live-feed');

// Private channel — token fetched from your authEndpoint
const inbox = client.subscribe('private-user.1234.inbox');

// Unsubscribe when done
client.unsubscribe('live-feed');

Listening to events

javascript
const ch = client.subscribe('orders');

// Bind a specific event
ch.on('order-created', (data) => {
  console.log('New order:', data.id);
});

// Bind all events on the channel
ch.onAll((eventName, data) => {
  console.log(eventName, data);
});

// Remove a listener
const handler = (data) => { /* ... */ };
ch.on('order-created', handler);
ch.off('order-created', handler);

Presence channels

Presence channels require your backend's authEndpoint to include user identity in the signed token.

javascript
const room = client.subscribe('presence-chat.room.42');

// Once subscribed, you get the full member list
room.on('zokai:subscription_succeeded', ({ count, members }) => {
  renderUserList(members);
});

// Live updates
room.on('zokai:member_added',   ({ id, info }) => addUser(id, info));
room.on('zokai:member_removed', ({ id })       => removeUser(id));

// Access current members at any time
console.log(room.members);

Private channels

When a client subscribes to a private- channel, the SDK calls your authEndpoint to fetch a signed token. Your server verifies the user is authorized and returns the token.

Your auth endpoint (Node.js example)

node.js
// Express route — POST /api/zokai/auth
app.post('/api/zokai/auth', requireLogin, (req, res) => {
  const { channel, socket_id } = req.body;

  // Authorize: only allow users to access their own inbox
  if (channel !== `private-user.${req.user.id}.inbox`) {
    return res.status(403).json({ error: 'Forbidden' });
  }

  const token = zokai.auth({ channel, socket_id, userId: req.user.id });
  res.json({ token });
});

Client API reference

Zokai instance

MethodDescription
subscribe(channel)Subscribe to a channel. Returns a Channel object.
unsubscribe(channel)Unsubscribe and clean up listeners.
on(event, fn)Listen to connection lifecycle events: connected, disconnected, error.
disconnect()Close the WebSocket connection.
reconnect()Manually reconnect.

Channel object

Method / PropertyDescription
on(event, fn)Listen for a named event on this channel.
off(event, fn)Remove a listener.
onAll(fn)Listen for all events on this channel.
nameThe channel name string.
membersCurrent member map (presence channels only).

Server SDK — Node.js

Setup

javascript
import Zokai from '@zokai/server';

const zokai = new Zokai({
  appKey:    process.env.ZOKAI_KEY,
  appSecret: process.env.ZOKAI_SECRET,
});

Publish an event

javascript
// Single channel
await zokai.publish('orders', 'order-created', {
  id: 'ORD-1042', total: 89.00,
});

// Multiple channels at once
await zokai.publish(['orders', 'analytics'], 'order-created', { id: 'ORD-1042' });

Generate an auth token

javascript
// Use in your auth endpoint to sign channel tokens
const token = zokai.auth({
  channel:  'private-user.1234.inbox',
  socketId: req.body.socket_id,
  userId:   'user-1234',
  userInfo: { name: 'Jane Doe' },  // shown in presence member list
});

Server SDK — Python

python
import zokai, os

client = zokai.Client(
    key=os.environ["ZOKAI_KEY"],
    secret=os.environ["ZOKAI_SECRET"],
)

# Publish an event
client.publish(
    channel="orders",
    event="order-created",
    data={"id": "ORD-1042", "total": 89.00},
)

# Generate an auth token (for Flask/Django auth endpoints)
token = client.auth(
    channel="private-user.1234.inbox",
    socket_id=request.form["socket_id"],
    user_id="user-1234",
)

Server SDK — Go

go
import zokai "github.com/zokai/zokai-go"

client := zokai.New(zokai.Config{
    Key:    os.Getenv("ZOKAI_KEY"),
    Secret: os.Getenv("ZOKAI_SECRET"),
})

// Publish an event
err := client.Publish(ctx, zokai.Event{
    Channel: "orders",
    Name:    "order-created",
    Data:    map[string]any{"id": "ORD-1042", "total": 89.00},
})

// Generate a channel auth token
token, err := client.Auth(ctx, zokai.AuthParams{
    Channel:  "private-user.1234.inbox",
    SocketID: r.FormValue("socket_id"),
    UserID:   "user-1234",
})

REST API

Base URL: https://api.zokai.io/v1

Authentication

All REST API requests must include your API Key and API Secret as HTTP Basic Auth:

bash
curl https://api.zokai.io/v1/apps/YOUR_APP_KEY/events \
  -u YOUR_APP_KEY:YOUR_APP_SECRET \
  -H "Content-Type: application/json" \
  -d '{"channel":"orders","event":"order-created","data":{"id":"ORD-1042"}}'

Publish event

POST /apps/{appKey}/events

Publishes an event to one or more channels. All subscribers receive it instantly.

Request body

FieldTypeRequiredDescription
channelstringYes*Target channel name
channelsstring[]Yes*Publish to multiple channels at once
eventstringYesEvent name
dataanyNoJSON payload, max 64 KB

* Provide either channel or channels.

json — request
{
  "channel": "orders",
  "event":   "order-created",
  "data": {
    "id":     "ORD-1042",
    "total":  89.00,
    "status": "confirmed"
  }
}
json — response 200
{ "ok": true, "delivered_to": 24 }

Errors

All error responses follow the same shape:

json
{
  "ok":    false,
  "error": "Channel name is required",
  "code":  400
}
StatusMeaning
400Bad request — missing or invalid fields
401Authentication failed — check your key and secret
403Forbidden — your plan does not allow this operation
404App not found
413Payload too large — max 64 KB
429Rate limit exceeded
500Internal server error — contact support
💬 Need help? Open a ticket in the dashboard or email us at support@zokai.io.