OOrchard

API Reference

Orchard exposes a REST API for programmatic management of groves.

Base URL

code
http://<your-orchard-host>:8080/api

When running locally via trowel dev-server start, the core API listens on port 7778 instead (http://localhost:7778/api).

Authentication

By default, authentication is disabled — all requests are accepted for local development. Pass your cultivator UUID via the X-Cultivator-Id header to identify yourself:

code
X-Cultivator-Id: <your-cultivator-uuid>

Requests without this header return 401. In production deployments with OAuth2 enabled, a JWT token is used instead. See the Authentication page for details.

Current Cultivator

code
GET /api/me

Returns the cultivator identified by the request's credentials — used by Canopy and the VS Code extension to show who you are signed in as.

code
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "username": "octocat",
  "email": "octocat@example.com"
}

Groves

List Groves

code
GET /api/groves

Headers: X-Cultivator-Id: <uuid>

Query params: all=true to include CLEARED groves.

Response:

code
[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "my-workspace",
    "repositoryUrl": "https://github.com/your-org/your-repo",
    "branch": "main",
    "commitSha": "a1b2c3d4e5f6",
    "state": "FLOURISHING",
    "sshConnectionString": "ssh -p 22 dev@203.0.113.10",
    "seedling": {
      "id": "661f9511-f30c-52e5-b827-557766551111",
      "state": "SAPLING",
      "ipAddress": "203.0.113.10",
      "sshPort": 22,
      "cpuCores": 2,
      "memoryMb": 2048,
      "diskGb": 20
    },
    "fruits": [
      {
        "id": "772a0622-041d-63f6-c938-668877662222",
        "state": "RIPENING",
        "containerId": "abc123def456",
        "containerName": "my-workspace_app_1",
        "serviceName": "app"
      }
    ],
    "plantedAt": "2026-05-01T12:00:00Z",
    "lastAccessedAt": "2026-05-01T13:00:00Z"
  }
]

Plant Grove

code
POST /api/groves

Headers: X-Cultivator-Id: <uuid>, Content-Type: application/json

Request body:

code
{
  "repositoryUrl": "https://github.com/your-org/your-repo",
  "branch": "main",
  "name": "my-workspace",
  "machineSize": "small"
}
FieldRequiredDescription
repositoryUrlYesGit repository URL
branchNoBranch to check out (default: main)
nameNoFriendly name for the grove
machineSizeNosmall, medium, or large (default: small)

Returns 201 Created with the grove object.

Get Grove

code
GET /api/groves/{groveId}

Clear Grove

code
DELETE /api/groves/{groveId}

Returns 204 No Content.

Get SSH Config

code
GET /api/groves/{groveId}/ssh-config

Returns a plain-text SSH config block for the grove's VM. Only available when the grove is in FLOURISHING state with an active seedling.

Stream Grove Events

code
GET /api/groves/{groveId}/events

A Server-Sent Events stream (text/event-stream) that emits a grove-state-changed event whenever the grove transitions between states. Canopy and the VS Code extension use this for live status updates.

code
event: grove-state-changed
data: {"groveId":"...","previousState":"GROWING","newState":"FLOURISHING"}

Stop Grove

code
POST /api/groves/{groveId}/actions/stop

Stops a grove by tearing down its containers and VM, then transitioning it to DORMANT state. Returns 200 OK with the updated grove object.

Start Grove

code
POST /api/groves/{groveId}/actions/start

Starts a dormant grove by re-provisioning its VM and containers. Returns 200 OK with the updated grove object. The grove must be in DORMANT state.

CLI subcommands for stop/start (trowel grove stop / trowel grove start) are coming soon.

Prebuilds

Prebuilds (Greenhouse) cache a repository's container image ahead of time so groves plant faster. This subsystem is still maturing.

code
POST /api/prebuilds        # body: { "repositoryUrl": "...", "branch": "main" }
GET  /api/prebuilds        # list prebuilds
GET  /api/prebuilds/{id}   # get a single prebuild

Grove States

StateDescription
PREPARINGInitial setup
PLANTINGVM and container provisioning in progress
GROWINGEnvironment starting up
FLOURISHINGReady — SSH access available
DORMANTSuspended
CLEARINGTeardown in progress
CLEAREDDeleted
BLIGHTEDError state

Health

code
GET /api/health
code
{
  "status": "healthy",
  "name": "Orchard",
  "version": "0.3.0"
}
code
GET /api/health/ready

Returns 200 when the configured seedling provider (QEMU, AWS, etc.) is available, 503 otherwise.

Error Responses

The API returns standard HTTP status codes. Error bodies follow Spring's default error format:

code
{
  "status": 404,
  "error": "Not Found",
  "message": "..."
}