API action reference

Everything goes through one endpoint, POST /api/, with an action field naming what to do. For the shape of the request and the reasoning behind a single entrypoint, see The API. This page is the catalogue.

Authentication is bearer-only (no cookies, which removes CSRF). A magic-link flow issues the token: request_code → email → verify_code → token in Authorization: Bearer …. Each row lists the permission the action requires.

Response and error conventions

Success usually carries success: true. Queries return a single result (for resolve/byPath) or a plural results with a count. Error statuses you’ll meet:

Status Meaning
400 Validation / bad request
401 Not authenticated
402 Plan limit reached (carries limitType)
403 Permission, feature gate, or coming-soon
404 Not found
409 Conflict — path in use, lock held, connector slug clash
413 Body too large
422 Operation failed
429 Rate limited (Retry-After on auth backoff)

A global ceiling of 120 requests/hour per IP applies; health and log_client_error have their own limits.

Auth

| Action | Does | Permission | |—|—|—| | request_code | Request a six-digit login code by email | none (auth backoff) | | verify_code | Exchange the code for a bearer token | none | | revoke | Revoke the current session token | bearer |

Node lifecycle

| Action | Does | Permission | |—|—|—| | create | Create a node as a draft; routable when given a path | write + create.route/create.collection | | duplicate | Clone an existing node to a new draft | write | | save | Save one property on the draft | write | | approve | Publish draft → live; compile, propagate, invalidate caches | publish | | make_draft | Open a live node for editing | write | | discard | Drop the draft, revert to live | write | | unpublish | Take a live node offline (back to draft) | publish | | delete | Remove the node and its index entries | delete | | status | Full status: graph, draft, diff, lock | view | | submit | Public submission → draft for review | feature publicSubmit | | form_spec | Form spec + values for the drawer form | view | | atoms_spec | The declarative atom contract (types, formats, read-only keys) | view |

Editor locks

The advisory heartbeat trio (Concur\Lock) sits alongside the older lock/unlock actions kept for existing callers.

Action Does Permission
lock_acquire Claim an editor lock on {type, id} write (409 if held)
lock_renew Extend the 30-minute TTL (heartbeat) write
lock_release Release the lock write

Actors

| Action | Does | Permission | |—|—|—| | whoami | Your own actor data (token masked) | view | | list_actors / get_actor | List or fetch persons and API keys | manage.actors | | save_person | Create or update a person + permissions | manage.actors | | save_webapi | Create or update a WebAPI key | manage.actors | | rotate_token | Roll a WebAPI token (one-time reveal) | manage.actors | | remove_actor | Remove an actor (not yourself) | manage.actors |

Space configuration

| Action | Does | Permission | |—|—|—| | get_space | Organisation + plan + usage | manage.settings | | save_organisation | Name, URL, view gating, owner | manage.settings | | save_plan | Toggle features (publicSubmit, viewGating, customDomain, apiAccess) | manage.settings |

Files

| Action | Does | Permission | |—|—|—| | upload_file | Upload → ImageObject node; MIME whitelist (no SVG), 10 MB max, alt text required | write (402 over storage limit) | | delete_file | Remove a file and its node | delete | | list_files | List media files | bearer |

Registry, query and rendering

| Action | Does | Permission | |—|—|—| | index | The registry as an ItemList | bearer | | appears_in | Where a node is referenced | bearer | | set_routing | Set or change a node’s @path and @build | create.route | | query | byType / byIdentifier / byAppearsIn / resolve / byPath; fields selects columns | view | | resolve | Path → @id / @type / @build lookup | bearer | | build | Server-side render a form or block (menu/page reserved) | write | | collections | The type-picker vocabulary | view |

Worker

| Action | Does | Permission | |—|—|—| | rebuild | Rebuild registry/indexes and recompile all live nodes | manage.settings | | maintain | Run cron maintenance now (stale locks, sessions, rate files) | manage.settings | | cron_status | Cron state and log | manage.settings | | wipe | Clear .index / .sessions and stale lock backups | manage.settings |

Observability

| Action | Does | Permission | |—|—|—| | health | Per-subsystem status; 200 healthy / 503 otherwise | none (60/min) | | log_client_error | Browser error → runtime log | none (10/hour, 2 KB cap) |

Wizard

The wizard picks AnthropicLLMClient when an AI connector is active, otherwise the built-in CtxrLLMClient.

Action Does Permission
wizard.turn One chat cycle (ask → assess → execute) view (execution gated deeper)
wizard.confirm Typed confirmation for a destructive step view
wizard.sessions / wizard.session List sessions / fetch one view

Connectors

Secrets are always redacted in responses, and every mutation emits an audit event.

Action Does Permission
connector.list Instances, available kinds, categories, plan tier view
connector.install New instance (inactive) manage.settings
connector.configure Partial config update manage.settings
connector.test Run the kind’s test callable manage.settings (10/hour)
connector.activate / connector.deactivate Flip status; swap-confirmation on operation overlap manage.settings
connector.uninstall Remove the config manage.settings

Incoming and OAuth (edge routes)

These sit outside the action map, with their own authentication.

  • POST /api/incoming/{provider} — webhooks. Signature-verified (not bearer), routed to a synthetic actor with a whitelisted set of operations, then mapped to an operation invoke.
  • GET /oauth/callback/{kind} — OAuth return, bound through the state parameter, handled by the connector’s adapter.

The openai connector is registered but marked coming-soon, so it can’t be installed yet.