documentation
06 api reference

Projects API

The projects API lives under /api/projects and gives you programmatic control over the top-level containers for agent work — projects and their goals. Issue routes live here too but are covered on their own page.

Authentication

All endpoints require the internal API auth model — either a dashboard session cookie or a personal API key (Authorization: Bearer exou_...). Minimum role: Viewer or above for reads, Editor or above for writes.

See API overview for the full context on the two auth surfaces.

Projects

GET /api/projects

List all projects visible to the caller.

Query parameters:

ParameterTypeDescription
orgIdstringFilter to a specific organisation
statusstringFilter by status (Active, Paused, Archived)

Response: a JSON array of project objects. Each project includes id, name, description, status, team, budget cap, and timestamps.

POST /api/projects

Create a new project.

Request body: a project create request with at least name. Optional fields include description, teamId, budgetCap, workspacePath, and metadata.

Response: 201 Created with the new project object in the body and a Location header pointing at /api/projects/{id}.

GET /api/projects/{id}

Get a single project by id.

Response: the full project object, or 404 Not Found.

PUT /api/projects/{id}

Update an existing project. Request body is a project update request with the fields you want to change — unset fields are left unchanged.

Response: the updated project object.

DELETE /api/projects/{id}

Delete a project. Destructive: all goals, issues, comments, attachments, and data store entries inside this project go too.

Query parameters:

ParameterTypeDescription
confirmboolMust be true — safety guard to prevent accidental deletes

Response: 204 No Content on success. 400 Bad Request if confirm=true wasn’t provided.

Goals

GET /api/projects/{projectId}/goals

List goals inside a project.

Response: a JSON array of goal objects. Each goal includes id, description, status, parent goal (if any), and linked issue count.

POST /api/projects/{projectId}/goals

Create a new goal inside the project.

Request body: a goal create request with at least description. Optional: parentGoalId for hierarchical goals.

Response: 201 Created with the new goal object.

PUT /api/projects/goals/{goalId}

Update an existing goal.

Request body: fields to change (description, status, etc.).

Response: the updated goal object.

DELETE /api/projects/goals/{goalId}

Delete a goal. Linked issues are not deleted; they lose their goal reference and become orphaned (still visible under the project, just without a parent goal).

Response: 204 No Content.

GET /api/projects/goals/{goalId}/ancestry

Get the full hierarchy of a goal — its parent, grandparent, and so on, up to the root. Useful when you want to render a goal with its breadcrumb trail.

Response: an ordered array of goal objects from root to the target goal.

Example — create a project and a goal

# Create the project
curl -X POST https://your-exolvra.example/api/projects \
  -H "Authorization: Bearer exou_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q2 launch prep",
    "description": "Preparing for the Q2 launch — copy, design, implementation, QA.",
    "budgetCap": 50.00
  }'

# Response includes the new project's id, e.g. "proj_abc123"

# Create a goal inside it
curl -X POST https://your-exolvra.example/api/projects/proj_abc123/goals \
  -H "Authorization: Bearer exou_..." \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Launch the new pricing page by end of quarter."
  }'

The Project Manager agent reads newly-created goals on its next heartbeat and starts breaking them into issues — no further API calls required.

Issues, comments, attachments, and issue links live under /api/projects/ too but have their own page:

  • Issues API/api/projects/{projectId}/issues, /api/projects/issues/{issueId}/*, attachments, links

Where to go next