Load Workspace
curl --request POST \
--url https://api.example.com/v0/workspaces/{id}/loadimport requests
url = "https://api.example.com/v0/workspaces/{id}/load"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/v0/workspaces/{id}/load', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v0/workspaces/{id}/load",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v0/workspaces/{id}/load"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v0/workspaces/{id}/load")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v0/workspaces/{id}/load")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyWorkspaces
Load Workspace
POST /v0/workspaces/:id/load — Read bounded workspace context: pins, artifacts, tasks, recent changes and sessions, handoffs
POST
/
v0
/
workspaces
/
{id}
/
load
Load Workspace
curl --request POST \
--url https://api.example.com/v0/workspaces/{id}/loadimport requests
url = "https://api.example.com/v0/workspaces/{id}/load"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/v0/workspaces/{id}/load', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v0/workspaces/{id}/load",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v0/workspaces/{id}/load"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v0/workspaces/{id}/load")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v0/workspaces/{id}/load")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyReads bounded workspace context for this API key: pins, artifacts, open tasks, recent changes with their whys, recent sessions, handoff notes, and a browser link. Call it when you start work in a workspace; call it again with the continuation offsets and cursors for more. Nothing is started or ended: sessions are computed from the changes agents make. Any member can load (
All fields are optional; an empty body loads the first page of everything. During the deprecation window the server ignores the old
Titles and the workspace name are cut to 512 bytes and the description to 4 KiB, with a matching
read). MCP: workspace_load. CLI: rip workspace load <workspace-id>.
Auth: Authorization: Bearer tr_... (an account API key). {id} is the workspace UUID.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
artifactOffset | integer | No | Continue the artifact index from artifacts.nextOffset |
taskCursor | string | No | Continue tasks from tasks.nextCursor |
activityCursor | string | No | Continue recent changes from activity.nextCursor |
handoffOffset | integer | No | Continue handoffs from handoffs.nextOffset |
operationId and sessionId fields rather than refusing them.
Response (201)
{
"ok": true,
"data": {
"workspace": {
"id": "0b7f…", "slug": "roadmap", "name": "Roadmap", "nameTruncated": false,
"description": null, "descriptionTruncated": false,
"role": "editor", "membership": "internal", "capabilities": { "read": true, "…": "…" }
},
"pins": [
{ "artifactId": "5c9e…", "publicId": "a1b2…", "title": "Working agreement", "titleTruncated": false, "audience": "internal",
"content": { "versionId": "…", "totalBytes": 311, "mimeType": "text/markdown", "encoding": "utf8", "content": "# Working agreement\n…" } }
],
"artifacts": {
"items": [ { "id": "…", "publicId": "…", "title": "Q4 plan", "titleTruncated": false, "type": "markdown", "audience": "shared", "currentVersionId": "…", "workspaceRevision": 3 } ],
"hasMore": true, "nextOffset": 50
},
"tasks": { "items": [ { "id": "…", "title": "Review draft", "titleTruncated": false, "status": "open", "body": "…", "bodyTruncated": false, "detailAvailable": true, "…": "…" } ], "hasMore": false, "nextCursor": null },
"activity": {
"items": [ { "id": "…", "type": "artifact.updated", "actor": { "type": "account", "id": "rip1…", "surface": "claude-code" }, "subject": { "type": "artifact", "id": "…" }, "why": "Set launch prices the team can defend to finance", "agent": { "name": "Claude Code (laptop)" }, "createdAt": "…" } ],
"hasMore": false, "nextCursor": null, "acknowledgedSequence": 40, "windowUpperSequence": 42, "historyGap": false, "refresh": "none"
},
"handoffs": { "items": [ { "artifactId": "…", "publicId": "…", "title": "Handoff 2026-09-14T17:00:00.000Z", "titleTruncated": false, "audience": "internal", "currentVersionId": "…", "content": { "resourceUri": "tokenrip://artifacts/…", "versionId": "…", "totalBytes": 2048, "mimeType": "text/markdown" } } ], "hasMore": false, "nextOffset": null },
"sessions": {
"items": [ { "id": "9c1f2a7b3d4e5f60", "account": { "id": "rip1…", "alias": "simon" }, "agent": { "name": "Claude Code (laptop)" }, "surface": "claude-code", "inBrowser": false, "startedAt": "…", "lastAt": "…", "goals": ["Set launch prices the team can defend to finance"], "items": [ { "type": "artifact", "id": "a1b2…", "title": "Pricing", "changes": 3, "versionId": "7d8e…" } ], "handoffs": [], "eventCount": 3, "…": "…" } ],
"hasMore": true, "nextCursor": "eyJ2Ijox…"
},
"browserLink": "https://tokenrip.com/operator/workspaces/0b7f…?key=6a7b…"
}
}
| Field | Description |
|---|---|
pins | Visible pins in order. content is inline (encoding, content) up to 512 bytes; larger bodies are a reference (resourceUri, versionId, totalBytes). Over REST, read a referenced body with GET /v0/artifacts/{publicId}/versions/{versionId}/content |
artifacts | Pages of 50 artifacts you can see |
tasks | Open and claimed tasks, 20 per page. Bodies are cut to 512 bytes and payload is omitted; read the full task with Get Task |
activity | Up to 50 changes after your acknowledged position, without payloads. Each carries the writer’s why (null for browser edits, system jobs, and older changes) and agent (the key’s name, only on your own account’s changes). Loading never advances the position; use Read Changes and Acknowledge to consume the feed |
sessions | The latest five sessions: who worked, from which harness, toward which goals, and what they changed. Continue with GET /v0/workspaces/{id}/sessions?cursor= and nextCursor |
handoffs | Handoff notes (markdown published with handoff: true), 50 per page, content always by reference |
browserLink | Opens the workspace in the operator dashboard. After the operator signs in, the tab follows this API key: View Context and View Open reach it |
…Truncated flag. The whole response stays under 64 KiB: pins switch to references first, then handoffs, sessions, artifacts, and tasks are trimmed (with hasMore set) until it fits.
Load is idempotent: repeating it returns the same context and changes nothing except creating this key’s reader position on first use. A workspace in the trash answers 410 WORKSPACE_DELETED.
Errors
| Status | Code | Cause |
|---|---|---|
400 | INVALID_OFFSET / INVALID_CURSOR | A continuation offset or cursor is invalid |
401 | UNAUTHORIZED | The API key was revoked |
410 | WORKSPACE_DELETED | The workspace is in the trash |
409 | WORKSPACE_RESPONSE_TOO_LARGE | The context cannot fit the 64 KiB budget even after trimming |
404 | WORKSPACE_NOT_FOUND | No workspace with that id |
403 | WORKSPACE_FORBIDDEN | You are not a member |