Guides
Realtime changes
A Socket.IO namespace at /v1. Connect once with the same key and Octopus pushes a compact change event whenever something you can see moves, whoever moved it.
A session, start to finish
Step 3 is the mechanism worth understanding. On connect you are placed in one room per .read scope you hold, and change events are published to those rooms, so you receive exactly the resources you are allowed to see and nothing else. The filtering is structural, not a check applied per message.
Steps 4 and 5 answer the same question twice, deliberately. ready is pushed the instant you connect, which suits a client that registers handlers before connecting. A client that awaits connection first and subscribes afterwards would miss that packet entirely, nothing replays it, so describe asks for the same answer at any time.
Do not depend on ready if you subscribe late
This exact race cost the test suite three assertions before it could cost an integrator an afternoon. If your client connects and then attaches handlers, call describe instead.
Connecting
import { io } from "socket.io-client";
const socket = io("https://gateway.octopusoperations.co.za/v1", {
transports: ["websocket"],
auth: { apiKey: process.env.OCTOPUS_API_KEY },
});
socket.on("ready", (d) => console.log("subscribed to", d.subscribedTo));
socket.on("change", (c) => {
if (c.resource === "tasks") refreshTask(c);
});
// Request/response works too: <event> / <event>Success / <event>Error
socket.emit("listTasks", {});
socket.on("listTasksSuccess", (r) => console.log(r.populatedItem.length));This namespace is for applications only
A signed-in person is refused here on purpose. The guarantees of /v1 are written in terms of scopes, and a person holds roles instead. Letting one in would mean a different rule set than the contract describes.
What a change event carries
Deliberately small: enough to know what moved and to fetch it if you care, never a full record you did not ask for.
{
"v": 1,
"id": "b754d5dc-f1a5-45cc-9220-7571e992dd1f",
"type": "TASK_UPDATED",
"resource": "tasks",
"action": "updated",
"orgId": "4bca402b-e846-4bde-8489-ee894cd80d1c"
}v: the change schema version, currently 1.id: unique per change. Use it to deduplicate.resource: the family. The easiest thing to switch on.action: one ofcreated,updatedordeleted.
Which scope hears which changes
| Resource | Event prefix | Scope needed |
|---|---|---|
| tasks | TASK_ | tasks.read |
| projects | PROJECT_ | projects.read |
| risks | RISK_ | projects.read |
| issues | ISSUE_ | projects.read |
| calendar | CALENDAR_ | calendar.read |
| clients | CLIENT_ | clients.read |
| documents | DOCUMENT_ | documents.read |
| financials | FINANCIAL_ | financials.read |
| assets | ASSET_ | assets.read |
| personnel | PERSONNEL_ | personnel.read |
| certificates | CERTIFICATE_ | personnel.read |
| compliance | COMPLIANCE_ | personnel.read |
| organisation | ORGANISATION_ | organisation.read |
