Skip to content

API & OpenAPI

The backend is spec-first: backend/openapi.yaml is the source of truth for the REST API. The server handlers and the typed frontend client are generated from it — you change the spec first, then regenerate code, never the other way around.

The spec is split across multiple files so it stays maintainable:

backend/
openapi.yaml # root: info, servers, components, tags, and $ref index
paths/<domain>.yaml # operations, one file per tag/domain
schemas/<domain>.yaml # schemas, one file per domain

The convention is one tag = one paths/ file = one schemas/ file.

The API is organised into these domains (one paths/*.yaml file each):

GroupGroup
activitiesadmin
agentsapi-keys
artifactsattachments
authbackoffice
blueprintscomments
embedding-providersfeeds
githubgithub-app-config
healthinvitations
memoriesmetadata
model-providersnotifications
projectsprompts
relationssearch
supportteam-email-provider
team-settingsteams
typesuser
webhooks

Shared schema definitions live in schemas/common.yaml; other schemas/*.yaml files mirror the path domains.

The admin domain (paths/admin.yaml) is the instance-admin surface at /api/v1/admin/*: getAdminStats, listAdminUsers, getAdminUser, listAdminTeams, and getAdminTeam. It is instance-admin-only. The routes are mounted behind optional auth plus an instance-admin check, so non-admins and unauthenticated callers alike get 404. The surface is not advertised.

The comments domain (paths/comments.yaml) is new in v0.7.0 and REST-only (no MCP). It is team-scoped under /api/v1/{team_id}/comments and lets users comment on resources.

The relations domain (paths/relations.yaml) is team-scoped under /api/v1/{team_id}/relations and records typed links between prompts, blueprints, memories and artifacts. Unlike comments, it has both a REST and an MCP surface: AI tools create links through the vibexp_io_link_resources tool rather than through the endpoints.

Five operations: listRelations (a resource’s relations), createRelation, confirmRelation (promote an AI-suggested link to confirmed), deleteRelation, and seedRelations (backfill suggestions from embedding similarity).

Resource reads carry the result: a GET on a prompt, blueprint, memory or artifact gains related (typed links) and similar (embedding neighbours). See Relations for the relation types, the type-constraint matrix and the suggested-vs-confirmed trust tiers.

The multi-file source is bundled into a single artifact with Redocly before linting, docs, and code generation:

Terminal window
make backend-bundle-openapi
# → backend/dist/openapi.bundled.yaml

Always consume the bundle (dist/openapi.bundled.yaml), not the source tree.

Since v0.5.0 every running instance serves its own bundled spec at GET /openapi.yaml and GET /openapi.json. The bytes come from a committed, go:embed-ed bundle in internal/server/openapispec/:

Terminal window
make backend-generate-openapi-bundle # regenerate the embedded bundle (redocly)
make backend-openapi-bundle-check # regenerate, then fail on drift

CI and pre-commit run the drift check, so regenerate and commit the embedded bundle whenever the spec changes.

Terminal window
make backend-validate-openapi # structural validation (swagger-cli)
make backend-lint-openapi # ruleset linting (vacuum, Spectral-format ruleset)

CI runs both, so run them locally before committing.

The bundle drives oapi-codegen, which produces the strict-server bindings and shared types. The generated code is committed and must never be hand-edited:

Terminal window
make backend-generate-openapi-server

See Code Generation for the full set of generators (oapi-codegen, Wire, mockery) and the golden rules around them.

A change to the API ripples through the codebase in order:

  1. Update the spec. Edit backend/paths/*.yaml / backend/schemas/*.yaml, then regenerate the server (make backend-generate-openapi-server) and implement the handler/service/repository logic. Validate and lint the spec.
  2. The typed clients publish automatically. Merging a spec change to main triggers the publish-api-client.yml workflow (path-filtered to backend/openapi.yaml, backend/paths/**, and backend/schemas/**), which auto-publishes both generated clients from the spec: @vibexp/api-client (npm, source in api-client-js) and api-client-go (Go module, source in api-client-go). Each downstream repo computes its own next version and generates from vibexp/vibexp@main.
  3. Bump the frontend dependency. Update the frontend to the new @vibexp/api-client version and use the new endpoints/types.