Identify your users
Only members read and write in a Komozu chat. Your server stays in charge: it creates each member once, and Komozu gives it a token for that member. The chat shows the member’s name and avatar, opens Members and Private channels to them, and lets you ban them. Without a token, the chat asks the visitor to sign in on your site.
Your server ── members.upsert({ id, name, avatarUrl }) ──▶ Komozu ──▶ { member, token } (once, at sign-up)Your server ── writes the stored token in the page ──▶ the chat (every page)1. Install the server SDK
Section titled “1. Install the server SDK”npm install @komozu/nodeimport { Komozu } from '@komozu/node';
const komozu = new Komozu({ secretKey: process.env.KOMOZU_SECRET_KEY });The secret key (kz_sec_…) is in the dashboard → API keys (shown once; rotate it to get a new one). Never put it
in a browser or a mobile app: the API refuses any server call that carries an Origin header
(403 SECRET_KEY_IN_BROWSER).
2. Create the member and store the token
Section titled “2. Create the member and store the token”When a user signs up:
const { token } = await komozu.members.upsert({ id: user.id, name: user.name, avatarUrl: user.avatarUrl ?? null });// Save it with the user in your database, next to their other fieldsawait saveUser({ ...user, komozuToken: token });idis the user id in your database (1–128 characters).- The name (1–64 characters) and avatar shown in the chat always come from here, never from the token. The avatar is
an
https://image URL. - The token doesn’t expire. Store it once and reuse it on every page.
- When the name or avatar changes, call
komozu.members.update(user.id, { name, avatarUrl }): the token stays the same. - Users who signed up before you added Komozu: run
upsertonce for each of them (a small script) and store their tokens.
3. Write the token in the page
Section titled “3. Write the token in the page”Your server writes the signed-in user’s token in the integration’s script (data-komozu-token), and leaves it empty
for a visitor who isn’t signed in (the chat then asks to sign in).
import { createServer } from 'node:http';
createServer(async (req, res) => { const user = await getSignedInUser(req); // your own session, null for a visitor res.setHeader('Content-Type', 'text/html; charset=utf-8'); res.end(`<!doctype html><h1>Club news</h1><script src="https://embed.komozu.com/komozu-embed.js" data-komozu-integration="int_…" data-komozu-token="${user?.komozuToken ?? ''}" defer></script>`);}).listen(3000);The token never goes in a URL: the script hands it to the chat with postMessage, so it doesn’t end up in the
browser history or in a Referer header.
The same token works with the developer SDKs:
- React:
<KomozuChat clientId="kz_live_…" channel="general" token={user?.komozuToken ?? null} /> - JavaScript:
new KomozuClient({ apiUrl, clientId, memberToken: user.komozuToken })
With the script, a user who signs in or out without reloading the page: window.Komozu.setUser({ token }), or
window.Komozu.setUser({ token: null }) to sign out of the chat (in React, change the token prop).
Revoke a token
Section titled “Revoke a token”A token leaked, or a user lost access to their account? Revoke their tokens:
const token = await komozu.members.revokeTokens(user.id);await saveUser({ ...user, komozuToken: token }); // store the new oneEvery token issued before stops working right away (401 TOKEN_REVOKED) and the member’s open chats are
disconnected. You can also do it from the dashboard: Members → Token → Revoke tokens.
From the dashboard
Section titled “From the dashboard”You can also create a member by hand in the dashboard (Members → New member), for example to open a private channel to a few people. Their token is shown right after, and any time from Members → Token: your server still writes it in the page.
Members → Edit changes a member’s name and avatar; open chats show the change right away. If your backend
syncs its users with members.upsert, its next call can replace them.
- A token is always required to read or write: without one, the API answers
401 MEMBER_TOKEN_REQUIREDand the chat asks to sign in, without loading any message. - A valid token for a member that was never created is refused (
401 MEMBER_NOT_FOUND). - Order of checks: signature (
401 INVALID_MEMBER_TOKEN) → expiry, only if the token has one (401 TOKEN_EXPIRED) → known member (401 MEMBER_NOT_FOUND) → not revoked (401 TOKEN_REVOKED) → not banned (403 MEMBER_BANNED) → channel access (403 CHANNEL_ACCESS_DENIED). - A token that is present but refused is never ignored: the chat says the session has ended.
- Rotating the secret key invalidates every token signed with the old one: create new ones with
upsert.
Private channels
Section titled “Private channels”const team = await komozu.channels.create({ name: 'U15 team', access: 'private' });await komozu.channels.addMembers(team.slug, ['user_42', 'user_43']);await komozu.channels.removeMembers(team.slug, ['user_43']); // their open chat is disconnected right awayMembers can also be added from the dashboard (channel page → Members). See server-api.md.