Developer Docs

REST Reference

Canonical willaOS REST resources, request/response shapes, and generated reference artifacts.

The canonical REST namespace is /api/*. There is no public /api/v1 contract.

Response Envelope

Most JSON routes return:

{
  "data": {},
  "request_id": "req_..."
}

Validation and auth failures return an error envelope or simple error object depending on legacy route age:

{
  "error": {
    "message": "X-Version header is required"
  },
  "request_id": "req_..."
}

Some file routes return the file body directly instead of a JSON envelope.

Core Resources

ResourceMethodsNotes
/api/clientsGET, POSTList and create client records.
/api/clients/{id}GET, PATCH, DELETERead, update, and soft-delete one client. Mutations use X-Version.
/api/clients/{id}/{field}GET, PUTField-level client reads and writes guarded by field permissions.
/api/clients/{id}/projectsGET, POSTList or create projects under a client.
/api/projectsGETList visible projects.
/api/projects/{id}GET, PATCH, DELETERead, update, and soft-delete one project. Mutations use X-Version.
/api/projects/{id}/documentsGET, POSTProject document list and create.
/api/projects/{id}/workstreamsGET, PATCHFirst-class workstream state and blockers.
/api/projects/{id}/readiness-rollupGETCross-system readiness rollup.
/api/projects/{id}/qa-configGETQA extension project contract.
/api/projects/{id}/qa-itemsGET, POSTCanonical QA item intake and list.
/api/projects/{id}/qa-items/{itemId}PATCH, DELETEVersioned QA item update and delete. Requires X-Version.
/api/projects/{id}/qa-items/{itemId}/repliesGET, POSTQA item comment thread, oldest first. POST takes body (1–4000 chars) and optional author_name (defaults to the key name).
/api/projects/{id}/reviews/{reviewId}/roundsPOSTAdmin-key mutation. Open the next numbered review round. Send expected_current_round_id. If the current round is exactly its successor, a retry returns that round; other mismatches return 409.
/api/projects/{id}/reviews/{reviewId}/assets/{assetId}PATCHAdmin-key mutation. Change a review asset status. Send status and expected_updated_at; stale writes return 409. This route does not use X-Version.
/api/sopsGET, POSTSOP registry.
/api/skillsGET, POSTPublished release metadata by default; publisher view=library includes drafts. POST creates a skill.
/api/skills/{slug}GET, PATCHPublished bundle or publisher draft view. PATCH saves a draft or archives and requires X-Version.
/api/skills/{slug}/releasesPOSTPublish the current draft or restore from_version as a new release. Requires X-Version.
/api/skills/{slug}/versionsGETImmutable history, newest first; limit 1 to 5, default 5, and exclusive before_version cursor.
/api/skills/{slug}/usageGETSelection and invocation totals by version, plus up to 20 recent events.
/api/skills/invocationsPOSTIngest 1 to 100 events. Deduplicates by authenticated source and event ID.
/api/milestonesGETCross-project milestone list.
/api/meeting-proposalsGET, POSTMeeting availability proposal workflow.
/api/agent-sessionsGET, POSTList or create durable agent sessions within the caller's scope.
/api/agent-sessions/{id}GETRead one session with its event and artifact timeline.
/api/statusGETPublic JSON health check.

The full generated route inventory is in REST Route Inventory. The OpenAPI seed is docs/openapi/willaos-public.json and covers the stable core routes that should be exposed first in hosted reference navigation.

Query And Body Shapes

List routes commonly support limit, cursor, client_id, project_id, status, or route-specific filters. Invalid query params return 400.

GET /api/projects supports opt-in limit and offset query params. When limit is present, the response includes pagination: { total, limit, offset }; without limit, the route keeps the legacy { data, request_id } shape.

GET /api/record-work/blocked-on-you?team_member_id=tm_… and MCP list_blocked_on_you apply the key's record-work role, client_scope, and explicit project grants before selecting blocked QA and workstreams. Omitted project_ids add no project grant; a client-scoped key still sees that client's work. Explicit project IDs grant access alongside the client scope, and an explicit "*" retains wildcard access. Field redaction applies to the resulting list.

Write routes accept JSON bodies validated by local Zod schemas or route-specific domain parsers. Unknown or unsupported fields are ignored only on legacy routes; newer routes reject invalid input.

Deliverable-review mutations currently require the unrestricted admin API key, including content_production write access. They use existing record fields as optimistic tokens because those tables do not have integer versions. Round opening accepts a UUID expected_current_round_id; if another request already advanced exactly one round from that ID, the retry succeeds with the existing next round. Other round mismatches return 409. Asset status accepts the asset's exact timestamp-with-time-zone expected_updated_at in the JSON body and does not use X-Version. On conflict, refresh the resource returned by the failed operation: the current review for round opening or the current asset for asset status. Retry with that resource's current optimistic token.

Skill drafts do not change the published bundle. Publication and restoration create a new immutable version; archive withdraws the release. Creation and PATCH use installContent; responses use install_content. X-Version refers to the editable head returned by view=library, even when an older release is still published. See the skill library integration reference for bundle limits, permissions, MCP parity, and usage attribution.

Request IDs

When a route returns request_id, include it in support or incident reports. It is also the preferred correlation key for audits and logs.