List Tasks
tasks:read scope. Returns Tasks created through this API key, newest
first. Optional query parameters: status (one of queued, running,
requires_action, waiting, completed, canceled), limit (1–200,
default 50), and cursor (opaque string from a previous next_cursor).
curl -sS \
"https://tycoon.us/api/public/tasks?status=completed&limit=20" \
-H "Authorization: Bearer $TYCOON_API_KEY"
{
"tasks": [
{
"task": {
"id": "cm...",
"reference": "growth-42",
"title": "Competitor research",
"status": "completed",
"created_at": "2026-08-01T12:00:00.000Z",
"started_at": "2026-08-01T12:00:03.000Z",
"completed_at": "2026-08-01T12:04:21.000Z",
"updated_at": "2026-08-01T12:04:21.000Z"
},
"outcome": null,
"playbook": null,
"result": null,
"required_actions": [],
"usage": null,
"poll_after_ms": null
}
],
"next_cursor": "eyJjcmVhdGVkQXQiOi..."
}
The list omits result, outcome, and usage. Call GET /tasks/{id}
to read the accepted result text and cost data for a specific Task.
Read a Task's message thread
tasks:read scope. Returns the Task's Comment thread in ascending
sequence order. This is the read side of POST /tasks/:id/messages; a
message sent to a running Task appears here once accepted. It is not a
separate comment system. Optional query parameters: limit (1–500,
default 100) and after_sequence (non-negative integer).
curl -sS "https://tycoon.us/api/public/tasks/cm.../messages" \
-H "Authorization: Bearer $TYCOON_API_KEY"
{
"messages": [
{
"id": "cm...",
"body": "Prioritize competitors under 50 employees.",
"created_at": "2026-08-01T12:02:00.000Z",
"sequence": 1,
"author": { "kind": "human" }
},
{
"id": "cm...",
"body": "Understood. Focusing on the SMB segment...",
"created_at": "2026-08-01T12:02:04.000Z",
"sequence": 2,
"author": { "kind": "agent", "slug": "astra" }
}
],
"next_cursor": 2
}
next_cursor is the sequence number of the last returned message. Pass
it as after_sequence to read messages that arrived later. null means
this response reached the current end of the thread.
List and read Docs
docs:read scope. The list omits the body; fetch GET /docs/{id} to
read it. Both endpoints accept limit (1–200, default 50) and cursor
(opaque string from next_cursor).
curl -sS https://tycoon.us/api/public/docs \
-H "Authorization: Bearer $TYCOON_API_KEY"
{
"docs": [
{
"id": "doc...",
"title": "Organic growth playbook",
"tags": ["growth", "seo"],
"created_at": "2026-07-01T09:00:00.000Z",
"updated_at": "2026-08-01T11:00:00.000Z"
}
],
"next_cursor": null
}
To read a Doc with its body:
curl -sS https://tycoon.us/api/public/docs/doc... \
-H "Authorization: Bearer $TYCOON_API_KEY"
{
"id": "doc...",
"title": "Organic growth playbook",
"tags": ["growth", "seo"],
"body": "# Organic growth playbook\n\n...",
"created_at": "2026-07-01T09:00:00.000Z",
"updated_at": "2026-08-01T11:00:00.000Z"
}
Upload a Doc
docs:write scope. Creates a Library Doc — the upload channel for a
local Claude Code or Codex session pushing findings, reports, and notes.
Requires an Idempotency-Key header; repeating the same key with the
same body returns the original Doc instead of creating a duplicate.
body is markdown (default) or a complete self-contained html
document, up to 200,000 characters. title (≤500 chars) and tags
(≤50, each ≤100 chars) are optional. The Doc lands in the key's own
workspace unless workspace_id names a workspace this key is explicitly
bound to (POST /workspaces/{id}/bind), so one key can sync each upload
to the right place.
curl -sS -X POST https://tycoon.us/api/public/docs \
-H "Authorization: Bearer $TYCOON_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: research-2026-08-26" \
-d '{
"title": "Competitor research findings",
"body": "# Findings\n\n...",
"tags": ["research"]
}'
{
"doc": {
"id": "doc...",
"title": "Competitor research findings",
"tags": ["research"],
"created_at": "2026-08-26T10:00:00.000Z",
"updated_at": "2026-08-26T10:00:00.000Z"
}
}
List and read Skills
skills:read scope. The list includes every workspace-scoped Skill in
your working set, including ones your workspace subscribes to from
another workspace. Subscribed Skills carry body_exportable: false; the
body endpoint returns 404 for them. Both endpoints accept limit
(1–200, default 50) and cursor (opaque string from next_cursor).
curl -sS https://tycoon.us/api/public/skills \
-H "Authorization: Bearer $TYCOON_API_KEY"
{
"skills": [
{
"id": "sk...",
"slug": "seo-experiment-method",
"name": "SEO experiment method",
"description": "Operating method for organic-growth experiments.",
"tags": ["seo", "experiment"],
"source_type": "LOCAL",
"updated_at": "2026-08-01T10:00:00.000Z",
"body_exportable": true
},
{
"id": "sk...",
"slug": "software-team",
"name": "Software Team",
"description": "Tycoon coding and delivery method.",
"tags": ["engineering"],
"source_type": "WORKSPACE",
"updated_at": "2026-08-01T09:00:00.000Z",
"body_exportable": false
}
],
"next_cursor": null
}
To read a Skill body:
curl -sS \
https://tycoon.us/api/public/skills/seo-experiment-method \
-H "Authorization: Bearer $TYCOON_API_KEY"
{
"id": "sk...",
"slug": "seo-experiment-method",
"name": "SEO experiment method",
"description": "Operating method for organic-growth experiments.",
"tags": ["seo", "experiment"],
"source_type": "LOCAL",
"markdown": "# SEO experiment method\n\n...",
"updated_at": "2026-08-01T10:00:00.000Z"
}
Fetching a Skill whose body is not yours returns 404. That response is
indistinguishable from a missing Skill: the endpoint never discloses the
existence of platform or other-workspace content.
Upload Skills
skills:write scope. Batch-upserts COMPANY Skills from SKILL.md bodies —
the sync channel for a local Claude Code or Codex session pushing its
skill library. Upserts are keyed by slug and idempotent: re-sending the
same batch updates in place. Up to 50 skills per request, markdown up
to 200,000 characters each. description is optional when the markdown
carries a frontmatter description: key. Skills your workspace
subscribes to from another workspace are refused per item — the learning
belongs upstream. The batch lands in the key's own workspace unless a
top-level workspace_id names a workspace this key is explicitly bound
to (POST /workspaces/{id}/bind), so one key can sync each library to
the right place.
curl -sS -X POST https://tycoon.us/api/public/skills \
-H "Authorization: Bearer $TYCOON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"skills": [
{ "slug": "deploy-runbook", "markdown": "---\ndescription: How we deploy\n---\n# Deploy\n..." }
]
}'
{
"results": [
{ "slug": "deploy-runbook", "id": "sk...", "action": "created" }
],
"upserted": 1,
"failed": 0
}
A batch where every item failed returns 422; a mixed batch returns
200 with each failure named in results.
Sync LLM traces
traces:write scope. POST /api/traces/llm also accepts a workspace
API key, so a local harness can auto-sync its raw LLM traces into the
workspace's write-only trace store. Send one harness-trace record as the
body, or batch up to 100 as { "traces": [...] } — the batch inserts
atomically. Records follow the harness-trace wire format (version-locked
schema; invalid records name their index). Traces are attributed to the
key's workspace and are never readable back through any customer-facing
endpoint.
Every harness class has an entry profile, chosen by
toolManifestAuthority.mode — a sync script maps each harness to one of
these rather than every harness needing full tool schemas:
exhaustive_schemas— the harness knows the exact tool schemas it exposed (Claude Code, Pi, DSH, Kimi Code, opencode class).named_allowlist— only tool names are known; tool calls are allowed within the list,toolsstays[](Codex class).provider_opaque— the harness cannot enumerate its tool surface; say why inopaqueReason(OpenClaw class).none— a text-only harness with no tools and no calls (Hermes class).
toolManifestSha256 binds the normalized tool list to the authority
object; compute it with the repository's exported toolManifestSha256
helper (lib/harness-trace.ts) or its canonical-JSON recipe — the
server recomputes and rejects a mismatch.
curl -sS -X POST https://tycoon.us/api/traces/llm \
-H "Authorization: Bearer $TYCOON_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "traces": [ { "formatVersion": "…", "traceSessionId": "local-session", "turnId": "turn-1", "...": "…" } ] }'
{ "ok": true, "ids": ["…"], "inserted": 1 }
Sync Vault credentials
vault:write scope, OWNER/ADMIN keys only. POST /api/public/vault
batch-upserts workspace Vault credentials — the provider keys the
workspace's agents run on. Values are encrypted at rest and are never
returned by any public endpoint; the response carries key names only.
Keys are UPPER_SNAKE_CASE (or app/<app-name>/UPPER_SNAKE_CASE), up
to 50 entries per request. Platform-reserved keys are refused per item.
Supports the same workspace_id routing as Doc and Skill uploads.
curl -sS -X POST https://tycoon.us/api/public/vault \
-H "Authorization: Bearer $TYCOON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"entries": [
{ "key": "OPENAI_API_KEY", "value": "sk-…", "description": "OpenAI provider key" }
]
}'
{
"results": [{ "key": "OPENAI_API_KEY", "ok": true }],
"upserted": 1,
"failed": 0
}