Skip to main content
/api/entities is the legacy general read/write surface over workspace records. One endpoint serves every entity type — initiatives, workstreams, milestones, tasks, decisions, artifacts, runs, goals, and more — selected by a type parameter. Existing MCP and workspace integrations may still use it.
This endpoint lives outside the /api/v1 namespace and outside the published OpenAPI document. It is retained for compatibility only. New integrations should use the dedicated /api/v1 operation for the resource they need; the OpenAPI document is the machine contract.

Authentication

All three methods require a personal API key or an authenticated MCP connection:
With an API key, reads and writes are scoped to the key owner’s records. The user_id parameter must match the key’s identity; a mismatch returns 403.

Methods

There is no DELETE method on this endpoint. See deletion and terminal states.

Entity type vocabulary

The type parameter accepts these values. Each maps to one underlying table; the label and body columns show which field names the type actually stores (generic title/name and summary/description aliases are mapped for you on write). Two additional read-only types are served without a table lookup: agent (the built-in agent roster, filterable by domain) and video_template. The alias issue is accepted and normalized to blocker.

GET — list and fetch

Query parameters

Response envelope

POST — create

The body is flat: type plus the record’s fields. owner_id defaults to the API key’s identity.
Creation rules that matter:
  • Initiative idempotency. idempotency_key (up to 120 characters) replays the existing initiative with _dedup: true and _replayed: true instead of inserting a duplicate.
  • Hierarchy dedup. Creating a workstream, milestone, or task whose label already exists (case-insensitive) inside the same parent scope returns the existing row with _dedup: true rather than a sibling duplicate.
  • Hierarchy parents. workstream requires initiative_id; task and milestone resolve their parents from milestone_id / workstream_id / initiative_id.
  • Guarded types. blocker creation is refused here (blockers are raised by runs). decision creation may not set a non-pending status or any server-owned resolution field. run creation may not set status, started_at, completed_at, or cancelled_at. artifact creation may not set approved or rejected — those assert a human ruling; an automated reviewer writes eval_passed instead.
The success envelope is { "type": ..., "data": { ... } } with the created row in data (also spread at the top level for older clients). Its data.id is the UUID you use everywhere else.

PATCH — update

The body is flat: type, id, plus the fields to change.
Update guards, enforced per type:
  • Decision: proposal-field updates are available through the MCP decision tool while a decision is pending; a personal API key receives 403. Only proposal fields (title, summary, description, priority, due_at, recommended_action, blocks_task, estimate, urgency, urgency_score) are patchable, and only while pending (409 otherwise). Approving or declining is a human action — see the decision page.
  • Run: status and timestamp fields are rejected (403); control a run through POST /api/v1/runs/{runId}/actions/{action}.
  • Blocker: not patchable at all; blockers close through their resolve and dismiss lifecycle.
  • Artifact: approved and rejected are rejected (403); a machine reviewer writes eval_passed.
  • Task: done tasks are terminal for automated updates; a 409 tells you to reopen deliberately first.

Deletion and terminal states

/api/entities has no DELETE method, and hard deletion is not part of the API-key REST contract. Use terminal statuses for API-key workflows. The MCP orgx_act tool can perform the additional lifecycle actions available to an authenticated MCP connection. With an API key, use terminal statuses instead:

Lifecycle actions — POST /api/v1/lifecycle

One route pauses, resumes, retries, or cancels any node of the hierarchy. It takes exactly three fields, all required: Note the field names: this route takes level and id, not entity_type and entity_id (those belong to the artifact and receipt surfaces). There is no status or target-state field — the target state is implied by action, and cascades to child runs.
The response is a bare object — no { data, meta } envelope — returned with 200 when ok is true and 422 when it is false:
A refusal adds error and blockReasons to the lifecycle result. Lifecycle errors use the same structured error envelope as the rest of /api/v1.

Where the IDs come from

MCP equivalents