Managing projects
Manager keeps the PaaS side: projects, keys, links, environment variables, removals, closings, usage and limits. You use it through Console or the management API. It is never on the path of what people exchange, which goes through Relay.
Console
Sign in to Console with GitHub; you see and manage the projects you own, in English or Japanese, on a desktop or a phone. Deleting a project, a key, a link or a variable, removing a participant and closing a range each ask for confirmation first.
| Screen | Shows | Does |
|---|---|---|
| Projects | Each project's name, state and bytes this month | Creates a project, opens one |
| Project | ID, the Relay URL, state, limits | Renames, deletes, sets the monthly byte limit and the connection limit |
| Keys | IDs and creation times | Creates a key (its secret shown once), deletes one |
| Links | ID, root, patterns, creation time | Creates a link, copies its ID, deletes one |
| Variables | Names and update times | Sets or replaces a value, deletes a variable |
| Participants | Removals: sub, path, time |
Removes a sub, optionally within a path |
| Ranges | Closings: path, time | Closes a path |
| Usage | Per day of a chosen month: bytes in and out, connected minutes, peak connections; the month's totals against the limits |
Paths and patterns are typed relative to the project root, as the API takes them.
The management API
The API is at /v1 on the Manager API address (Reference), with JSON bodies. A call authenticates with a key, Authorization: Basic base64({key id}:{secret}), and acts on that key's project; Console calls it with its session. Errors are HTTP statuses with {"code", "message"}: bad-request (400; message names the field at fault), unauthenticated (401), forbidden (403, a key listing or creating projects), not-found (404, also for a project the caller does not manage) and internal (500).
| Call | Body | Result |
|---|---|---|
GET /projects, POST /projects (Console only) |
{name} |
[Project], Project |
GET, PATCH, DELETE /projects/{p} |
{name?, limits?} |
Project |
GET /projects/{p}/keys, POST |
[{id, created}], {id, secret, created} |
|
DELETE /projects/{p}/keys/{id} |
||
GET /projects/{p}/links, POST |
{root, publish, subscribe} |
[Link], Link |
DELETE /projects/{p}/links/{id} |
||
GET /projects/{p}/variables |
[{name, updated}] |
|
PUT /projects/{p}/variables/{name}, DELETE |
{value} |
|
GET /projects/{p}/removals, POST |
{sub, path?} |
[{sub, path, at}], the removal |
GET /projects/{p}/closings, POST |
{path} |
[{path, at}], the closing |
GET /projects/{p}/usage?from={day}&to={day} |
[{day, bytesIn, bytesOut, seconds, peakConnections}] |
- Project:
{id, name, created, limits: {monthlyBytes, connections}, state}; a limit is a number ornull(none);stateisrunning,fullorstopped.idis 12 characters froma–z 0–9. - Link:
{id, root, publish, subscribe, created}. - Lists are oldest first (variables by name).
DELETEandPUTanswer 204 with no body.PATCHchanges only what it gives, andnullremoves a limit. Paths are literal (no wildcard), relative to the project root; an empty or omittedpathis the whole project. Times are RFC 3339 in UTC, anddayisYYYY-MM-DDin UTC;usagelists only days with usage.
// The management API with a project key: a link, a variable, a limit, a removal, a closing and this month's usage.
const auth = `Basic ${btoa(`${process.env.TABLEBOX_KEY_ID}:${process.env.TABLEBOX_KEY_SECRET}`)}`;
const project = `${process.env.TABLEBOX_MANAGER_URL}/v1/projects/${process.env.TABLEBOX_PROJECT}`;
async function call(method: string, path: string, body?: unknown) {
const reply = await fetch(project + path, {
method, headers: { authorization: auth, 'content-type': 'application/json' }, body: JSON.stringify(body),
});
if (!reply.ok) throw new Error(`${method} ${path}: ${reply.status} ${await reply.text()}`);
return reply.status === 204 ? undefined : reply.json();
}
const link = await call('POST', '/links', { root: 'rooms/42', publish: ['{id}/**'], subscribe: ['**'] });
console.log(`link ${link.id} for rooms/42`);
await call('PUT', '/variables/STORAGE_BUCKET', { value: 'my-bucket' });
await call('PATCH', '', { limits: { connections: 1_000 } });
await call('POST', '/removals', { sub: 'mallory', path: 'rooms/42' });
await call('POST', '/closings', { path: 'rooms/41' });
const today = new Date().toISOString().slice(0, 10);
console.log(await call('GET', `/usage?from=${today.slice(0, 8)}01&to=${today}`));Keys, links and variables
- Keys. An ID,
tb_and 20 characters fromA–Z a–z 0–9, and a secret of 43 characters, shown once at creation. A key signs tokens (Connecting) and authenticates API calls for its project. Deleting it closes the sessions it admitted withinvalid-token. - Links. An ID,
lk_and 22 characters fromA–Z a–z 0–9, which admits whoever holds it with the link's root and patterns until the link is deleted (Connecting). - Variables. Names of letters, digits and
_, starting with a letter, up to 70 characters; values up to 16 KiB; up to 100 per project. Values are set and replaced and never shown back; names are listed with their update time. Tablebox's programs read them.
Removals and closings
- Removing
subS within path X: within 5 s every session of S whose root is X or beneath it closes withremoved. For roots in X, Relay then refuses S's tokens issued at or before the removal and S's connections through links created before it; later tokens and links are admitted. Removing S again within the same path moves its time forward. - Closing path X: within 5 s every session whose root is X or beneath it closes with
closed. For roots in X, Relay then refuses tokens issued at or before the closing and links created before it; later ones are admitted. A session rooted above X stays, so a lobby or a backend keeps running when one range closes. - Tablebox's programs keep running through removals and closings. Deleting a project closes its sessions with
closed, and its programs stop serving it.
Limits and usage
You set a monthly byte limit (bytes in and out over the UTC calendar month) and a connection limit, each optional. Reaching the byte limit makes the project stopped until the month ends or the limit rises: every session, the programs' included, closes with limit, and new ones are refused. Reaching the connection limit makes it full while the count stays there: new sessions are refused with limit, and open ones continue. A limit can be passed by what Relays carry in one report interval (10 s) plus the time a change takes to reach them.
Usage is counted per project and UTC day: bytes into and out of Relays, connected seconds and peak connections, programs' sessions included, visible within a minute.
While Manager is down
Sessions in progress carry on. Relays admit, remove and limit with the last state they read, also after their own restart, and programs keep running with the last variables they read. Console and the API are unavailable; removals, closings and settings take effect once Manager is back, and the usage counted meanwhile is reported then.