Skip to main content
The Fabro API is under active development and may be subject to change. Endpoints, request/response formats, and authentication mechanisms may evolve as the project matures.
The Fabro API is a REST API for managing workflow runs, interactive sessions, and related resources. All requests and responses use JSON.

Base URL

The API is served by fabro serve, which defaults to:
http://localhost:3000
The base URL is configurable via server.toml:
server.toml
[api]
base_url = "https://fabro.example.com"

Authentication

The API supports two authentication strategies, configured in server.toml:
server.toml
[api]
authentication_strategies = ["jwt"]

JWT (Bearer Token)

Send an Ed25519-signed JWT in the Authorization header:
Authorization: Bearer <token>
The token must include these claims:
ClaimDescription
issIssuer — must be fabro-web
iatIssued-at timestamp (Unix seconds)
expExpiration timestamp (Unix seconds)
subSubject — a URL identifying the user (e.g. https://github.com/username)
The username is extracted from the last path segment of the sub claim and checked against the allowed_usernames list in the web auth config. Set the verification key via the FABRO_JWT_PUBLIC_KEY environment variable (PEM format or base64-encoded PEM).

mTLS (Mutual TLS)

With mTLS, the client authenticates using a TLS client certificate. Configure both the strategy and TLS paths:
server.toml
[api]
authentication_strategies = ["mtls"]

[api.tls]
cert = "~/.fabro/certs/server.crt"
key = "~/.fabro/certs/server.key"
ca = "~/.fabro/certs/ca.crt"
The Common Name (CN) from the client certificate identifies the user.

Multiple Strategies

You can configure both strategies. They are tried in order — the first successful match wins:
server.toml
[api]
authentication_strategies = ["jwt", "mtls"]

Errors

Error Shape

All error responses share a consistent JSON structure:
{
  "errors": [
    {
      "status": "404",
      "title": "Not Found",
      "detail": "Run abc123 not found."
    }
  ]
}
Each entry in the errors array contains:
FieldTypeDescription
statusstringThe HTTP status code as a string
titlestringThe canonical reason phrase for the status code
detailstringA human-readable explanation of the error

HTTP Status Codes

StatusMeaningWhen It Occurs
400 Bad RequestThe request body or parameters are invalidMissing required fields, malformed JSON
401 UnauthorizedAuthentication is missing or invalidNo token, expired token, invalid certificate
403 ForbiddenThe authenticated user lacks accessUsername not in the allowed list
404 Not FoundThe requested resource does not existUnknown run ID, unknown workflow name
409 ConflictThe resource is in a conflicting stateAnswering a question on a run that isn’t running yet
410 GoneThe resource is no longer availableSSE event stream has closed
501 Not ImplementedThe endpoint exists but is not yet implementedPlaceholder routes
502 Bad GatewayAn upstream dependency failedGraphviz dot not installed or returned an error

Pagination

List endpoints that return large collections use offset-based pagination. Pass pagination parameters as query strings:
ParameterTypeDefaultDescription
page[limit]integer20Maximum number of items to return (clamped to 1–100)
page[offset]integer0Number of items to skip
Paginated responses include a meta object alongside the data array:
{
  "data": [...],
  "meta": {
    "has_more": true
  }
}
When has_more is true, increment the offset by the limit to fetch the next page.

Versioning

The Fabro API does not currently use versioning. All endpoints reflect the latest behavior of the running server. Breaking changes will be communicated in the changelog.

Discovery

The root endpoint (GET /) returns discovery URLs. The health endpoint (GET /health) can be used for liveness checks. The OpenAPI spec is available at GET /openapi.json.