Documentation menu

API reference

27 operations in projects. Raw spec: openapi.json.

GET/api/v1/project-templates

GET /api/project-templates

Responses

StatusDescription
200

Security: bearer

POST/api/v1/project-templates

POST /api/project-templates — stores a blueprint (spec validated); emits `project.template_updated`.

Request body

CreateTemplateRequest

Responses

StatusDescription
200
409template name already in use
422invalid template spec

Security: bearer

PATCH/api/v1/project-templates/{id}

PATCH /api/project-templates/{id} — emits `project.template_updated`.

Parameters

NameInTypeRequiredDescription
idpathstringYes

Request body

PatchTemplateRequest

Responses

StatusDescription
200
404template not visible in scope (rls_sparse)
422invalid template spec

Security: bearer

DELETE/api/v1/project-templates/{id}

DELETE /api/project-templates/{id} — blueprints are data, not live references: projects already instantiated are untouched; emits `project.template_removed`.

Parameters

NameInTypeRequiredDescription
idpathstringYes

Responses

StatusDescription
200
404template not visible in scope (rls_sparse)

Security: bearer

POST/api/v1/project-templates/{id}/instantiate

POST /api/project-templates/{id}/instantiate — expands the template into a REAL project: phases, tasks, dependencies, and every lifecycle event, all in ONE transaction (claim → expand → insert → events → record). Rollback on any failure leaves zero partial rows.

Parameters

NameInTypeRequiredDescription
idpathstringYes

Request body

InstantiateTemplateRequest

Responses

StatusDescription
200
404template not visible in scope (rls_sparse)
409version conflict or idempotency key reused
422invalid template spec or request

Security: bearer

GET/api/v1/project-views

GET /api/project-views — one project's views, or all org views when `project_id` is omitted.

Parameters

NameInTypeRequiredDescription
project_idquery—NoScope to one project's views; omit for the org's ENTIRE view set.

Responses

StatusDescription
200

Security: bearer

POST/api/v1/project-views

POST /api/project-views — saves a view; emits `project.view_updated`.

Request body

CreateViewRequest

Responses

StatusDescription
200
404project not visible in scope (rls_sparse)
409view name already in use in the scope
422validation failed

Security: bearer

PATCH/api/v1/project-views/{id}

PATCH /api/project-views/{id} — renames / respecs a view; emits `project.view_updated`.

Parameters

NameInTypeRequiredDescription
idpathstringYes

Request body

PatchViewRequest

Responses

StatusDescription
200
404view not visible in scope (rls_sparse)
422validation failed

Security: bearer

DELETE/api/v1/project-views/{id}

DELETE /api/project-views/{id} — emits `project.view_removed`.

Parameters

NameInTypeRequiredDescription
idpathstringYes

Responses

StatusDescription
200
404view not visible in scope (rls_sparse)

Security: bearer

GET/api/v1/projects

GET /api/projects — filtered, newest-first list.

Parameters

NameInTypeRequiredDescription
statusquerynull | ProjectStatusNo
client_idquery—No
limitqueryintegerNo
offsetqueryintegerNo

Responses

StatusDescription
200

Security: bearer

POST/api/v1/projects

POST /api/projects — creates the project and emits `project.created` in one transaction. Instant-first (IF1/IF2): idempotency-keyed, version-gated, read-your-write response.

Request body

CreateProjectRequest

Responses

StatusDescription
200
409version conflict or idempotency key reused
422validation failed

Security: bearer

GET/api/v1/projects/{id}

GET /api/projects/{id}

Parameters

NameInTypeRequiredDescription
idpathstringYes

Responses

StatusDescription
200
404not found

Security: bearer

PATCH/api/v1/projects/{id}

PATCH /api/projects/{id} — tri-state partial update. Instant-first (IF1/IF2): idempotency-keyed, version-gated, returns prior + new values.

Parameters

NameInTypeRequiredDescription
idpathstringYes

Request body

PatchProjectRequest

Responses

StatusDescription
200
404project not visible in scope (rls_sparse)
409version conflict or idempotency key reused
422validation failed

Security: bearer

GET/api/v1/projects/{id}/billing-releases

GET /api/projects/{id}/billing-releases — the release ledger: every staged milestone/fee for this project with its status (`pending` bills on the next run reaching its window; `billed` carries the consuming invoice; `cancelled` terminal).

Parameters

NameInTypeRequiredDescription
idpathstringYes

Responses

StatusDescription
200

Security: bearer

POST/api/v1/projects/{id}/billing-releases/{release_id}/cancel

POST /api/projects/{id}/billing-releases/{release_id}/cancel — cancel a PENDING release (admin correction; terminal). Billed releases are immutable — they ride an invoice, and invoices correct through credit notes.

Parameters

NameInTypeRequiredDescription
idpathstringYes
release_idpathstringYes

Responses

StatusDescription
200
404release not visible/already settled (rls_sparse)

Security: bearer

GET/api/v1/projects/{id}/gantt

GET /api/projects/{id}/gantt — the dated timeline plus its undated remainder, each phase carrying its budget burn.

Parameters

NameInTypeRequiredDescription
idpathstringYes

Responses

StatusDescription
200

Security: bearer

GET/api/v1/projects/{id}/phase-burn

GET /api/projects/{id}/phase-burn — the burn read model (report P3): consumed approved billable minutes and card-priced value per phase against the phase's budget, with the typed `none | warn | over` alert state (`warn` at ≥80%, `over` at ≥100%).

Parameters

NameInTypeRequiredDescription
idpathstringYes

Responses

StatusDescription
200
404project not visible in scope (rls_sparse)

Security: bearer

GET/api/v1/projects/{id}/phases

GET /api/projects/{id}/phases — ordered by sort_order.

Parameters

NameInTypeRequiredDescription
idpathstringYes

Responses

StatusDescription
200

Security: bearer

POST/api/v1/projects/{id}/phases

POST /api/projects/{id}/phases — adds a phase; emits `project.phase_created`.

Parameters

NameInTypeRequiredDescription
idpathstringYes

Request body

CreatePhaseRequest

Responses

StatusDescription
200
404project not visible in scope (rls_sparse)
409version conflict or idempotency key reused
422validation failed

Security: bearer

PATCH/api/v1/projects/{id}/phases/{phase_id}

PATCH /api/projects/{id}/phases/{phase_id} — tri-state partial update.

Parameters

NameInTypeRequiredDescription
idpathstringYes
phase_idpathstringYes

Request body

PatchPhaseRequest

Responses

StatusDescription
200
404phase not visible in scope (rls_sparse)
409version conflict or idempotency key reused
422validation failed

Security: bearer

POST/api/v1/projects/{id}/phases/{phase_id}/complete

POST /api/projects/{id}/phases/{phase_id}/complete — stamps the phase completed and, when it is a billing milestone, emits `project.milestone_completed` in the same transaction (the core-billing seam). Instant-first: the idempotency key guarantees a retried completion can never double-emit the billing event.

Parameters

NameInTypeRequiredDescription
idpathstringYes
phase_idpathstringYes

Request body

MutationParams

Responses

StatusDescription
200
404phase not visible in scope (rls_sparse)
409already completed, version conflict, or idempotency key reused

Security: bearer

GET/api/v1/projects/{id}/tasks

GET /api/projects/{id}/tasks — filtered by phase/status/assignee and the milestone flag, sort_order-ordered.

Parameters

NameInTypeRequiredDescription
idpathstringYes
phase_idquery—No
statusquerynull | TaskStatusNo
assignee_idquery—No
milestonequery—No
limitqueryintegerNo
offsetqueryintegerNo

Responses

StatusDescription
200

Security: bearer

POST/api/v1/projects/{id}/tasks

POST /api/projects/{id}/tasks — creates the task (optionally with its dependency set) and emits `project.task_created` in one transaction.

Parameters

NameInTypeRequiredDescription
idpathstringYes

Request body

CreateTaskRequest

Responses

StatusDescription
200
404project not visible in scope (rls_sparse)
409version conflict or idempotency key reused
422validation failed

Security: bearer

PATCH/api/v1/projects/{id}/tasks/{task_id}

PATCH /api/projects/{id}/tasks/{task_id} — tri-state partial update. `status: "completed"` is rejected: completion runs through the complete endpoint (dependency gating + the billing seam).

Parameters

NameInTypeRequiredDescription
idpathstringYes
task_idpathstringYes

Request body

PatchTaskRequest

Responses

StatusDescription
200
404task not visible in scope (rls_sparse)
409version conflict or idempotency key reused
422validation failed

Security: bearer

POST/api/v1/projects/{id}/tasks/{task_id}/complete

POST /api/projects/{id}/tasks/{task_id}/complete — the guarded completion: every finish-to-start dependency must already be completed (typed 409 `task_dependencies_unsatisfied` naming the blockers), then `project.task_completed` fires — plus `project.milestone_completed` when the task is a billing milestone. Instant-first: the idempotency key makes retried completions replay instead of double-billing.

Parameters

NameInTypeRequiredDescription
idpathstringYes
task_idpathstringYes

Request body

MutationParams

Responses

StatusDescription
200
404task not visible in scope (rls_sparse)
409dependencies unsatisfied, already completed, version conflict, or idempotency key reused

Security: bearer

GET/api/v1/projects/{id}/tasks/{task_id}/dependencies

GET /api/projects/{id}/tasks/{task_id}/dependencies

Parameters

NameInTypeRequiredDescription
idpathstringYes
task_idpathstringYes

Responses

StatusDescription
200
404not found

Security: bearer

PUT/api/v1/projects/{id}/tasks/{task_id}/dependencies

PUT /api/projects/{id}/tasks/{task_id}/dependencies — replaces the whole dependency set, cycle-checked over the project graph BEFORE any write; emits `project.task_updated`.

Parameters

NameInTypeRequiredDescription
idpathstringYes
task_idpathstringYes

Request body

SetDependenciesRequest

Responses

StatusDescription
200
404task not visible in scope (rls_sparse)
422dependency set rejected (self-dep, cross-project, or cycle)

Security: bearer