action field determines the operation.
Add a Node
Creates a new node with an auto-generated ID.Parent rules
| Type | Parent required | Parent type |
|---|---|---|
| Goal | No | None |
| Need | Yes | Goal |
| Approach | Yes | Need |
| Job | Yes | Approach |
| Task | No | None |
Update a Node
PATCH semantics. Only include fields you want to change. Existing fields are preserved.status to null.
Delete a Node
Hard delete. The node is removed from the table, but the full node is kept in the changelog, so a delete is recoverable withrestore (below).
Restore a Node
Recover a hard-deleted node from the changelog. It returns with its original id, type, parentId, and data. Identify it bynodeId (restores the most recent deletion of that node) or by a specific changelogId.
409if a node with that id already exists (nothing to restore).404if no deletion is on record.- If the node’s original parent was also deleted, it comes back orphaned (dangling
parentId). Restore the parent too, or reparent. The response_meta._tipflags this. - Restore does not cascade. It brings back the single node, not its former children.
Batch Mutations
Multiple operations in a single request. All-or-nothing. If any mutation fails validation, the entire batch is rejected.Idempotency
Make anymutate call (single or batch) safe to retry by sending an Idempotency-Key header. An opaque per-operation string (a UUID is ideal):
- Replay. A second request with the same key and the same body returns the original response unchanged (with an
Idempotent-Replayed: trueheader) instead of applying again. An agent that retries after a timeout never double-creates. - Conflict. The same key with a different body returns
409(you reused a key for a new operation. Generate a fresh one). - In flight. If the first request is still running, a retry returns
409(“in progress, retry shortly”). - Window. Keys are remembered for 24 hours, then expire. Scope is per user.
Idempotency-Key, retries are not deduplicated, re-read with GET /api/v1/nodes or search and re-submit only what’s missing.
Validation
The API validates all mutations before applying them:- Label is required on all nodes
- Parent must exist and be the correct type (need under goal, approach under need, etc.)
- Fields must match node type, setting
iterationon a goal ormaturityon a task is rejected - Kano values:
must-have,performance,delighter - Size values:
skateboard,vespa,car,truck,antonov - Maturity values:
mvp,releasable - Approach status values:
development,validation,resolved,retired
{ "success": false, "errors": ["..."] }.
