This example shows a typical sequence of API calls for creating and evolving a shared metaverse world with multiple users, scene assets, and portals.
Imagine a virtual world with:
- a central lobby
- a few interactive assets (chairs, lamps, signs)
- a portal to another area
- multiple users entering and editing the world at the same time
The API is centered around a shared scene graph, so the main job is to create nodes, attach them to parents, update their positions or appearance, and watch for live changes from other users.
First, a client should load the current world summary.
curl http://localhost:3000/wow/worldExample response shape:
{
"content": {
"label": "OpenSpatialWorld",
"version": 1
},
"users": {
"active_user_count": 1,
"total_user_count": 1
},
"views": {
"view_count": 1
},
"portals": {
"portal_count": 1
}
}The root node is the top of the scene graph and is usually the starting point for building the world.
curl http://localhost:3000/wow/scene/node/0This returns the root node and any child references that define the scene structure.
Open a WebSocket connection to the event endpoint so the client can receive live updates from other users.
ws://localhost:3000/events
The server will broadcast messages such as:
user_joineduser_leftnode_creatednode_updatednode_deleted
Create a parent node that represents the lobby area.
curl -X POST http://localhost:3000/wow/scene/node/0 \
-H "Content-Type: application/json" \
-d '[{"label":"Lobby","children":[],"localTransform":[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}]'The server responds with the created node, including an assigned numeric id.
Create a portal node as a child of the lobby.
curl -X POST http://localhost:3000/wow/scene/node/1 \
-H "Content-Type: application/json" \
-d '[{"label":"Portal to Arena","children":[],"spatialAssetURI":"https://example.com/assets/portal.glb"}]'Here 1 is the id returned for the lobby node in the previous step.
Add a lamp or chair asset as another child node.
curl -X POST http://localhost:3000/wow/scene/node/1 \
-H "Content-Type: application/json" \
-d '[{"label":"Lamp","children":[],"spatialAssetURI":"https://example.com/assets/lamp.glb"}]'Once an asset exists, update it with placement or appearance details.
curl -X PUT http://localhost:3000/wow/scene/node/2 \
-H "Content-Type: application/json" \
-d '{"label":"Lobby Lamp","localTransform":[1,0,0,0,0,1,0,0,0,0,1,0,0,2,0,1]}'The nodeId in the URL should be replaced with the actual id returned by the create call.
If the scene includes special viewpoints or teleport destinations, fetch them explicitly.
curl http://localhost:3000/wow/view/1
curl http://localhost:3000/wow/portal/1As other users connect, create nodes, or update nodes, your client will receive event messages over the WebSocket connection.
Typical handling logic:
- on
user_joined, show presence - on
node_created, refresh the scene tree - on
node_updated, update the relevant node in the UI - on
node_deleted, remove the node from the local view
A typical authoring sequence is:
- GET /wow/world
- GET /wow/scene/node/0
- Open ws://localhost:3000/events
- POST /wow/scene/node/0 to create the main area
- POST /wow/scene/node/{lobbyId} to create child assets and portals
- PUT /wow/scene/node/{assetId} to refine placement and appearance
- GET /wow/view/{viewId} or /wow/portal/{portalId} as needed
- Continue listening to /events for concurrent changes from other users
sequenceDiagram
participant ClientA as Author Client A
participant Server as simpleWorlds API
participant ClientB as Author Client B
ClientA->>Server: GET /wow/world
Server-->>ClientA: world summary
ClientA->>Server: GET /wow/scene/node/0
Server-->>ClientA: root scene node
ClientA->>Server: Open WebSocket /events
Server-->>ClientA: user_joined
ClientA->>Server: POST /wow/scene/node/0
Server-->>ClientA: created lobby node
ClientA->>Server: POST /wow/scene/node/{lobbyId}
Server-->>ClientA: created portal node
ClientA->>Server: POST /wow/scene/node/{lobbyId}
Server-->>ClientA: created asset node
ClientA->>Server: PUT /wow/scene/node/{assetId}
Server-->>ClientA: updated node
ClientB->>Server: Open WebSocket /events
Server-->>ClientB: user_joined
Server-->>ClientA: user_joined
ClientB->>Server: POST /wow/scene/node/{lobbyId}
Server-->>ClientB: created node
Server-->>ClientA: node_created
ClientA->>Server: GET /wow/portal/1
Server-->>ClientA: portal data
This second example focuses on the live collaboration pattern: a user joins, a second user edits an existing node, and then one of them deletes it.
User A opens the app and connects to the event stream.
curl http://localhost:3000/wow/worldws://localhost:3000/events
The server creates a temporary user record and broadcasts a user_joined event.
Suppose User A wants to edit an existing node with id 7.
curl http://localhost:3000/wow/scene/node/7User B opens a second client, connects to the same event stream, and updates the node.
curl -X PUT http://localhost:3000/wow/scene/node/7 \
-H "Content-Type: application/json" \
-d '{"label":"Updated Sign","localTransform":[1,0,0,0,0,1,0,0,0,0,1,0,0,1,0,1]}'The server responds with the updated node, and both clients receive a node_updated event over /events.
User A decides to remove the node entirely.
curl -X DELETE http://localhost:3000/wow/scene/node/7The server removes the node and its subtree and broadcasts a node_deleted event.
Because User B is still listening to /events, it receives the deletion notice and should remove the node from its local UI immediately.
sequenceDiagram
participant UserA as User A
participant UserB as User B
participant Server as simpleWorlds API
UserA->>Server: GET /wow/world
Server-->>UserA: world summary
UserA->>Server: Open WebSocket /events
Server-->>UserA: user_joined
UserA->>Server: GET /wow/scene/node/7
Server-->>UserA: node data
UserB->>Server: Open WebSocket /events
Server-->>UserB: user_joined
Server-->>UserA: user_joined
UserB->>Server: PUT /wow/scene/node/7
Server-->>UserB: updated node
Server-->>UserA: node_updated
UserA->>Server: DELETE /wow/scene/node/7
Server-->>UserA: success
Server-->>UserB: node_deleted
- Multiple clients can participate in the same shared scene.
- Updates are broadcast to all connected clients over
/events. - A delete operation can race with an edit, so clients should treat the node as stale if they receive a delete event after a prior update.
This API does not include upload endpoints for assets. Each asset must already be available at a public or reachable URI before it is referenced by spatialAssetURI or appearanceURI.