- Get Started

API Reference

OpenFlows is a thin orchestration brain on top of a self-hosted Coder deployment. It exposes a small, versioned control-plane API for operator automation, consumes the Coder API for workspace lifecycle, and uses the GitHub REST API and MCP for repository operations. This page documents the full API surface: OpenFlows endpoints, Coder integration points, GitHub calls, authentication, and request/response examples.

The key architectural principle is that Coder is the only runtime. OpenFlows does not run agents locally; it provisions ephemeral Coder workspaces and drives them through the Coder control plane. LLM calls go through the Coder AI Gateway, and GitHub identity is provided by Coder external auth. Worker workspaces contain zero AI software, zero LLM keys, and zero GitHub tokens.

Base URL and Versioning

All OpenFlows control-plane endpoints are prefixed with /api/v1. When running the orchestrator from Docker Compose, the default base URL is http://localhost:8080. In production, route through your internal ingress or load balancer.

bash
# Default local base URL
OPENFLOWS_BASE_URL=http://localhost:8080/api/v1

# Coder deployment base URL
CODER_URL=https://coder.example.com

The API is versioned by URL path. /api/v1 is the current stable version. Breaking changes will be introduced under a new path (e.g. /api/v2) with a deprecation window for the previous version.

Authentication

OpenFlows uses three distinct credential types, each scoped to a different subsystem. None of them are stored inside worker workspaces.

CredentialScope
Authorization: Bearer <openflows-token>OpenFlows control-plane API. Set via OPENFLOWS_API_TOKEN or the bootstrap-created admin token.
CODER_SESSION_TOKENCoder API and Chats API. Scoped to provision workspaces, read users, and send chat messages.
GitHub external auth tokenGitHub REST and MCP. Managed by Coder external auth; OpenFlows never stores a PAT.

The GitHub token is never configured in OpenFlows directly. It is obtained by Coder external auth and injected into workspaces via the git-config module. OpenFlows GitHub calls use the same token through the Coder MCP server or a short-lived REST credential provided by Coder.

bash
# Example request to the OpenFlows control plane
curl -X GET   $OPENFLOWS_BASE_URL/health   -H "Authorization: Bearer $OPENFLOWS_API_TOKEN"   -H "Content-Type: application/json"

# Example request to the Coder API
curl -X GET   $CODER_URL/api/v2/users/me   -H "Authorization: Bearer $CODER_SESSION_TOKEN"   -H "Coder-Session-Token: $CODER_SESSION_TOKEN"

OpenFlows Control-Plane Endpoints

These endpoints are served by the openflows binary. They are intended for operators, dashboards, and external integrations. They are not required for normal autonomous operation; NEXUS drives the flow internally.

EndpointPurpose
GET /api/v1/healthHealth check for the orchestrator, Redis, Coder, and AI Gateway
GET /api/v1/tenantsList all configured tenants and their repository bindings
POST /api/v1/tenantsCreate or update a tenant repository binding
GET /api/v1/tenants/:idFetch tenant details, active workers, and current state
DELETE /api/v1/tenants/:idRemove a tenant and stop its workers
GET /api/v1/ticketsList all tickets in the SharedStore
GET /api/v1/tickets/:idFetch a ticket status, linked PR, and event history
POST /api/v1/tickets/:id/reassignReassign a stuck ticket to another idle worker
GET /api/v1/workersList all worker slots and their current state
POST /api/v1/workers/:id/pausePause a worker without deleting it
POST /api/v1/workers/:id/resumeResume a paused worker
GET /api/v1/eventsRead recent events from the event ring

Request and Response Examples

Health check:

bash
GET /api/v1/health
Authorization: Bearer $OPENFLOWS_API_TOKEN
json
{
  "status": "ok",
  "version": "1.2.0",
  "dependencies": {
    "redis": "ok",
    "coder": "ok",
    "ai_gateway": "ok"
  },
  "timestamp": "2026-07-20T15:42:00Z"
}

Create a tenant:

bash
POST /api/v1/tenants
Authorization: Bearer $OPENFLOWS_API_TOKEN
Content-Type: application/json
json
{
  "name": "my-team",
  "repository": "owner/repo",
  "coder_user": "openflows-nexus"
}
json
{
  "id": "tenant-2f8c1e",
  "name": "my-team",
  "repository": "owner/repo",
  "namespace": "my-team",
  "state": "active",
  "created_at": "2026-07-20T15:42:00Z"
}

Reassign a ticket:

bash
POST /api/v1/tickets/OF-123/reassign
Authorization: Bearer $OPENFLOWS_API_TOKEN
Content-Type: application/json
json
{
  "target_worker": "forge-2",
  "reason": "Worker forge-1 timed out"
}
json
{
  "ticket_id": "OF-123",
  "worker_id": "forge-2",
  "state": "assigned",
  "reassigned_at": "2026-07-20T15:45:00Z"
}

Coder API Integration Points

OpenFlows uses the Coder API to provision, monitor, and destroy ephemeral workspaces. The orchestrator holds the Coder session token and acts as a Coder user. All workspace lifecycle calls are made from the OpenFlows control plane, not from inside the workspace.

EndpointPurpose
GET /api/v2/users/meResolve the authenticated Coder user for identity checks
GET /api/v2/workspacesList existing workspaces
POST /api/v2/workspacesProvision a new ephemeral workspace from a Coder template
GET /api/v2/workspaces/:idFetch workspace status, resources, and agent metadata
POST /api/v2/workspaces/:id/buildsStart or stop a workspace build
DELETE /api/v2/workspaces/:idTear down a workspace after merge or failure
POST /api/v2/chatsCoder Chats API - send a control-plane message to a Coder Agent
GET /api/v2/chats/:idRetrieve a chat session and its messages
POST /api/v2/chats/:id/messagesAppend a follow-up message to an existing chat

Coder Chats API vs. AgentAPI

OpenFlows drives Coder AI agents through the Coder Chats API, which is a control-plane API. The Chats API runs agents on Coder's servers and connects them to workspaces over the same secure tunnel used by IDEs. This is fundamentally different from the in-workspace AgentAPI, which runs inside a workspace and exposes local tools.

The Chats API is the correct integration point for OpenFlows because:

bash
# Start a control-plane chat with a Coder agent for a specific workspace
POST /api/v2/chats
Authorization: Bearer $CODER_SESSION_TOKEN
Content-Type: application/json
json
{
  "agent_id": "coder-agent-forge-1",
  "user_id": "openflows-nexus",
  "workspace_id": "workspace-uuid",
  "message": {
    "role": "user",
    "content": "Read the current plan in PLAN.md and implement segment 3."
  }
}
json
{
  "id": "chat-uuid",
  "agent_id": "coder-agent-forge-1",
  "workspace_id": "workspace-uuid",
  "status": "running",
  "messages": [
    { "role": "user", "content": "Read the current plan in PLAN.md and implement segment 3." }
  ]
}

Why not AgentAPI

The Coder AgentAPI requires the agent process to run inside the workspace with access to local tools and environment variables. OpenFlows deliberately avoids this: worker workspaces have no AI software, no API keys, and no GitHub tokens. The Chats API keeps the intelligence in the Coder control plane and the repository data in the ephemeral workspace.

Workspace Lifecycle Example

When NEXUS assigns a ticket to FORGE, it orchestrates the following Coder API calls. The sequence is fully deterministic and can be observed in the event ring.

  1. Provision: POST /api/v2/workspaces with the template ID and parameter values.
  2. Build: POST /api/v2/workspaces/:id/builds to start the workspace.
  3. Chat: POST /api/v2/chats to attach a Coder agent to the workspace.
  4. Observe: Poll GET /api/v2/workspaces/:id until the workspace is running.
  5. Destroy: DELETE /api/v2/workspaces/:id after merge or failure.
bash
# Provision an ephemeral FORGE workspace
POST /api/v2/workspaces
Authorization: Bearer $CODER_SESSION_TOKEN
Content-Type: application/json
json
{
  "template_id": "openflows-forge",
  "name": "forge-42-abc123",
  "parameter_values": [
    { "name": "repo", "value": "owner/repo" },
    { "name": "ticket_id", "value": "OF-42" },
    { "name": "coder_module", "value": "claude-code" }
  ],
  "auto_start": true
}
json
{
  "id": "workspace-uuid",
  "name": "forge-42-abc123",
  "template_id": "openflows-forge",
  "owner_id": "openflows-nexus",
  "status": "pending",
  "created_at": "2026-07-20T15:42:00Z"
}

GitHub MCP and REST

OpenFlows interacts with GitHub through two mechanisms: the Coder GitHub MCP server, which is the preferred path for high-level operations like opening PRs and posting comments, and the GitHub REST API for polling and read-only queries that do not require tool semantics.

EndpointPurpose
GET /repos/:owner/:repo/issuesIssue discovery and priority polling
GET /repos/:owner/:repo/issues/:numberFetch a single issue body and labels
POST /repos/:owner/:repo/issues/:number/commentsPost status updates back to the issue
POST /repos/:owner/:repo/pullsOpen a pull request
GET /repos/:owner/:repo/pulls/:numberRead PR state and mergeable status
PUT /repos/:owner/:repo/pulls/:number/mergeMerge a green PR
GET /repos/:owner/:repo/actions/runsPoll GitHub Actions CI status
GET /repos/:owner/:repo/git/ref/:refResolve branch or tag refs for rebase checks

The MCP server is configured in the Coder dashboard (AI Settings → MCP Servers) and is referenced by name in registry.json. REST calls are made from the orchestrator with the same token obtained through Coder external auth.

GitHub REST Example: Open a Pull Request

bash
POST https://api.github.com/repos/owner/repo/pulls
Authorization: Bearer $GITHUB_TOKEN
Accept: application/vnd.github+json
Content-Type: application/json
json
{
  "title": "feat(scope): implement feature described in #42",
  "head": "forge-42-abc123",
  "base": "main",
  "body": "Closes #42.

This PR was generated by OpenFlows FORGE. Review contract in CONTRACT.md.",
  "draft": false
}
json
{
  "number": 123,
  "html_url": "https://github.com/owner/repo/pull/123",
  "state": "open",
  "head": { "ref": "forge-42-abc123" },
  "base": { "ref": "main" }
}

GitHub MCP Example: Post a Comment

When using the MCP server, the Coder agent calls the tool with a structured JSON payload. The orchestrator does not construct HTTP requests directly; it instructs the agent to use the github MCP server.

json
{
  "tool": "github.create_issue_comment",
  "params": {
    "owner": "owner",
    "repo": "repo",
    "issue_number": 42,
    "body": "FORGE has opened PR #123. SENTINEL review is in progress."
  }
}

No GitHub PATs in OpenFlows

GitHub authentication is handled exclusively by Coder external auth. OpenFlows configuration files contain no GitHub client secrets or personal access tokens. The GITHUB_REPOSITORY environment variable only tells OpenFlows which repo to monitor; it is not a credential.

Status Codes and Error Envelope

All OpenFlows control-plane responses use a consistent JSON envelope. Errors include a machine-readable code and a human-readable message.

json
{
  "error": {
    "code": "TENANT_NOT_FOUND",
    "message": "Tenant 'my-team' does not exist.",
    "request_id": "req-uuid"
  }
}
StatusMeaning
200 OKRequest succeeded.
202 AcceptedAsync operation started (tenant creation, workspace build).
400 Bad RequestMalformed JSON or validation failure.
401 UnauthorizedMissing or invalid bearer token.
403 ForbiddenToken lacks required scope.
404 Not FoundUnknown tenant, ticket, or worker.
409 ConflictResource already exists or state transition illegal.
500 Internal Server ErrorOrchestrator error; check RUST_LOG.

Rate Limits and Retries

The orchestrator respects the rate limits of the upstream APIs it calls. Coder and GitHub rate limits are inherited from the Coder deployment and the GitHub token. OpenFlows retries transient failures with exponential backoff (up to 3 attempts) and surfaces persistent failures as FAILED or AwaitingHuman states.

Control-plane endpoints are not heavily throttled by default because they are intended for internal tooling. If you expose the OpenFlows API externally, place it behind a reverse proxy or API gateway with its own rate-limit policy.

Observing API calls

Set RUST_LOG=openflows=debug to see every Coder and GitHub API call in the orchestrator logs, including request IDs, status codes, and retry attempts. The event ring also captures high-level lifecycle events for the TUI dashboard.