Talk (chat)

A conversation, on one machine, reached through the network.

This page covers creating a conversation, who may join, the SDK, and what happens when a connection drops.

01

Create a conversation

Create a conversation
curl -X POST https://dash.yunzheng.space/api/v1/talk/rooms \
  -H "Authorization: Bearer $ORBIT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Support","kind":"room"}'
FieldWhat it sets
kindroom keeps history for retention_days; live keeps the last few hundred messages in memory and nothing on disk.
cityWhere it lives. A pack feature; omit it and the city with the most room takes it. Its history lives there too, so it does not move.
max_peers, max_kbps, retention_daysCeilings for this conversation, up to what the packs allow. Asking for more is refused rather than quietly reduced.
public_joinfalse means the link answers nothing and only tokens from your backend get in.

The reply carries key (the link) and join_url (the hosted page). Set a passcode with PUT /talk/rooms/{id}/passcode; what is stored is a hash, and there is nothing to read back.

02

The SDK

Join from your own page
<script src="https://talk.yunzheng.space/v1.js"></script>
<script>
  var chat = OrbitTalk.join({
    room: "<room key>",
    label: "Ada",
    passcode: "",
    onMessage: function (m) { console.log(m.seq, m.label, m.body); },
    onState: function (s, d) { if (s === "open") console.log("in, " + d.members + " here"); },
    onPresence: function (p) { console.log(p.members + " here"); },
    onError: function (e) { console.error(e.code, e.message); }
  });
  chat.send("Hello");
  // later: chat.leave();
</script>

send returns an id at once and the message goes out when the connection allows; if the connection is down it waits in an outbox and goes on the next one. Your application never has to write that buffer.

For a backend that decides who may enter — your users, under your names — turn public_join off, mint the token on your server with POST /talk/rooms/{id}/join (its peer_id is your user's id, its label is their name), and hand it to the SDK through fetchJoin. The SDK calls it again on every reconnect, because a token is good for two minutes.

The backend door
OrbitTalk.join({
  fetchJoin: function () {
    // your server calls POST /talk/rooms/{id}/join with the caller's own id and name
    return fetch("/my-api/chat-token", { method: "POST", credentials: "same-origin" })
      .then(function (r) { return r.json(); });
  },
  onMessage: function (m) { /* m.peer is YOUR user id; m.label is the name you gave */ }
});
With link access off, the room key alone opens nothing: a leaked link is worth nothing to anyone, and every seat in the room is one your server issued.
03

Reading a conversation back

Messages live on the machine that carries the conversation and are never copied here. Your account can read them back a page at a time with GET /talk/rooms/{id}/history, using your API key — so this call belongs on your server, next to the one that mints join tokens.

Read a conversation, page by page
var page = await OrbitTalk.history({ room: 12, key: process.env.ORBIT_TOKEN });
page.messages.forEach(function (m) { console.log(m.seq, m.at, m.label, m.body); });

// Walk forward: pass the page's "next" back as the cursor until it comes back null.
while (page.next != null) {
  page = await OrbitTalk.history({ room: 12, key: process.env.ORBIT_TOKEN, cursor: page.next });
}
FieldWhat it is
cursorRead what came after this sequence number. Start with none; pass back the next of the page you just read.
limitMessages per page, 1 to 500. The default is 200, which is a screenful rather than everything.
nextThe cursor for the next page, or null when that was everything. A short page is proof there is no more, so it never carries one.
messages[].peerWho sent it. Through the backend door this is your own user id, which is what makes a record of a conversation mean anything a year later.
Every read is written to your account's audit log with the conversation, the cursor, the page size and how many messages came back. A live chat keeps nothing on disk, so it answers with an empty page and a sentence saying why.
04

When a connection drops

Every message carries a sequence number the conversation assigned, and the SDK remembers the last one it saw. On reconnect it asks for everything after that, so nothing is repeated and nothing is missed. Every message you send carries your own id, so a resend after a reset is answered with the number the first copy already has rather than stored twice.

History that has aged out is reported as a gap rather than silently skipped: the first frame after reconnecting says the earliest number still available.
05

What is counted

LimitMeaning
Conversationshow many you may have
Connections at oncepeople connected across all conversations
Messages per monthcounted once each, however many times a client resends
GB per monthbytes in and out
Days of historythe ceiling for a conversation; a live chat keeps none
Next

Related

Getting started

How an Orbit account is organised, what lives where in the console, and the shortest path from signing in to serving a name from our network.

DNS hosting

Add a zone, point your registrar at our name servers, manage records: weighted answers, health-checked records, ALIAS at the apex, zone-file import.

Connect a hostname

Delegate the whole domain, delegate one hostname, or add a CNAME and leave your DNS where it is. What each one costs you and when to pick it.

← All documentation