Skip to content

OpenAPI document ​

Every instance describes its own API in an OpenAPI 3.1 document, served at:

GET <PUBLIC_BASE_URL>/api/v1/openapi.json
GET <PUBLIC_BASE_URL>/api/v1/openapi.json?lang=fr

The route is public: no session or key is needed to read it. Texts (summaries, descriptions) are in English by default and in French with ?lang=fr. The document is cached for five minutes by the instance.

The reference of this documentation is generated from the same document, so the two never diverge.

What it is generated from ​

The document is not written by hand. The instance keeps a registry of its routes; for each one, the registry points at the validation schemas the route really uses to parse its parameters, its body and its responses. The document is derived from them at start-up, in the dialect OpenAPI 3.1 speaks natively, JSON Schema 2020-12.

Consequences:

  • a field that appears in the document is a field the route accepts or returns, with its real constraints (minimum, maxLength, enum…);
  • schemas are inlined in each operation, not shared under components/schemas: the same object (a workflow, an execution) appears in full wherever it is used. Code generators handle this; the generated types are merely longer;
  • info.title carries the brand of the instance and info.version its software version;
  • servers[0].url is the public address of the instance when it is configured, / otherwise (relative to where you fetched the document);
  • a few routes served by the instance are deliberately absent: the WebSocket of the interface and the OAuth redirections, which no HTTP client calls directly.

Authentication in the document ​

Two security schemes are declared under components.securitySchemes:

SchemeTypeMeaning
sessionCookieapiKey in cookie sessionThe session set by POST /api/v1/auth/login
apiKeyoauth2An API key sent as Authorization: Bearer mk_…

The API key is declared as oauth2 only because that is how OpenAPI names scopes: the scopes map of the scheme lists every scope a key can carry, and each operation lists the one it requires. There is no token endpoint and no authorisation flow: the key is the token. A client that follows the oauth2 scheme literally will not work; configure it instead to send a bearer token.

Each operation's security says who may call it: [{ "sessionCookie": [] }, { "apiKey": ["workflows:read"] }] for a route open to keys, [{ "sessionCookie": [] }] for a session-only route, [] for a public route or one authorised by a token in its URL.

Extensions ​

Three x- extensions carry what standard OpenAPI has no word for:

ExtensionWhereMeaning
x-required-scopeOperationThe scope an API key must cover, for example "workflows:write". Absent on session-only, public and token routes. See Scopes.
x-idempotency-keyOperationtrue when the operation accepts an Idempotency-Key header. The header is also declared among the operation's parameters. See Idempotency.
x-error-codesOperationThe error codes specific to the operation, for example ["workflow.not_found", "workflow.not_publishable"]. The common codes (request.bad_request, auth.unauthenticated, api_key.*) are implied. See Errors.

Every operation also has a stable operationId, derived from its method and path: GET /api/v1/workflows/{id} is getWorkflowsById, POST /api/v1/workflows is postWorkflows. Code generators use it to name methods.

Where an operation has an example, it is attached to the request body (requestBody.content.*.example) and to its first success response.

Importing the document ​

In an API client (Postman, Insomnia, Bruno, Hoppscotch…): import from URL with <PUBLIC_BASE_URL>/api/v1/openapi.json. Then set the authentication of the collection to Bearer token with your key; ignore the OAuth 2 flow the client may propose from the apiKey scheme. Re-import after an upgrade of the instance to pick up new routes.

With a code generator (openapi-generator, openapi-typescript, oapi-codegen, NSwag…): point the generator at the URL or at a saved copy. Inlined schemas produce one type per operation; if your generator supports it, enable its schema de-duplication. Example with openapi-typescript:

sh
curl -s <PUBLIC_BASE_URL>/api/v1/openapi.json -o openapi.json
npx openapi-typescript openapi.json -o api.d.ts

For validation: the document declares jsonSchemaDialect: https://json-schema.org/draft/2020-12/schema. Any JSON Schema 2020-12 validator can check a body against paths["/api/v1/workflows"].post.requestBody.content["application/json"].schema before sending it.

To diff two versions: save the document before and after an upgrade and compare them. A new route, a new field or a new error code shows up as a change in the document, which is the contract of the instance.