Skip to content

API overview

Everything in Outflare is available through one REST API. The web app uses it, the SDK wraps it, and your scripts and agents call it directly. There is no private API.

Your instance serves the API under /v1, for example http://localhost:8080/v1 or https://outflare.example.com/v1. Workspace resources live under /v1/workspaces/{ws}/..., where {ws} is the workspace ID.

The API is described by an OpenAPI 3.1 document, api/openapi.yaml. Your instance serves the exact version it runs:

Terminal window
curl localhost:8080/v1/openapi.yaml

Use it to generate a client in any language, import it into Postman or Insomnia, or give it to an agent. The endpoint reference on this site is generated from the same file.

Two unauthenticated endpoints let tools and agents find out what an instance offers:

Terminal window
curl localhost:8080/v1/meta
curl localhost:8080/.well-known/outflare.json
{ "name": "Outflare", "version": "0.1.0", "api": { "rest": "/v1", "openapi": "/v1/openapi.yaml" }, "capabilities": [] }

Send an API token as a bearer token:

Terminal window
curl localhost:8080/v1/workspaces/$WS/mailboxes -H "Authorization: Bearer oft_..."

Tokens are scoped to one workspace and a list of scopes. Each endpoint’s description in the reference names the scope it needs. See Authentication.

Responses are JSON. Lists are wrapped in a data array:

{ "data": [ { "id": "…", "email": "[email protected]", "status": "active" } ] }

The audit log pages backwards in time: pass before= the next_before value from the previous page.

Every error uses the same shape, with a stable code, a readable message and the request_id to quote in bug reports:

{ "error": { "code": "not_found", "message": "workspace not found", "request_id": "…" } }
Status Codes Meaning
400 invalid_request The request is invalid. The message says why.
401 unauthenticated, invalid_credentials Missing or invalid credentials.
403 forbidden The token or member lacks the scope this endpoint needs.
404 not_found, invalid_invite Not found, including workspaces you cannot see.
409 conflict, already_set_up, last_owner Conflicts, such as running setup twice or removing the last owner.
413 invalid_request The upload is too large.
415 invalid_request Wrong content type, for example a mailbox import that is not text/csv.
429 rate_limited Too many attempts, for example repeated failed sign-ins.
500, 503 internal, unavailable A server problem. Quote the request_id.

GET /healthz reports that the process is up and GET /readyz that it can reach Postgres. Neither needs authentication.