Skip to content

OpenAPI and generated clients ​

Every module's JSON API (/api/**) is described by one OpenAPI document. View routes (Inertia pages) are not part of it.

Where the schema lives ​

Environment/api/openapi.json
developmentalways served, no login
anything elseserved only when openapi_public is on (SM_OPENAPI_PUBLIC=true)

The schema lists every endpoint, so production keeps it off unless you opt in. When it is served it is anonymous, like /health.

info.title, info.version and info.description come from the host settings api_title (default SimpleModule), api_version (default: the host package's version) and api_description. They are read at boot, so a change needs a restart.

Operation ids are <module>_<function> (users_list_users), which gives generated clients readable method names. A clash gets the method and path appended and logs a warning.

Breaking change

The bare /openapi.json is gone. It used to be served in production too; use /api/openapi.json.

Security schemes ​

The schema declares two components.securitySchemes: bearerAuth (http, bearer — personal access tokens, service keys and Keycloak access tokens) and sessionCookie (apiKey in a cookie named session). Every operation carries security: [] when anonymous callers are let through (a register_public_routes rule matched on the templated path with each {param} replaced by a placeholder segment, the auth provider's legacy public paths, or the schema URL itself), and [{bearerAuth: []}, {sessionCookie: []}] otherwise, so a generated client sends credentials only where needed. bearerAuth covers provider access tokens (e.g. Keycloak) on every protected route, while personal API tokens are accepted only on routes marked TokenAllowed(). Rules that need a specific path segment (a regex on a slug) can over- or under-report here; AuthMiddleware stays the authority.

Diagnostic SM031 warns at a dev boot about an /api route with no permission, TokenAllowed or Authenticated gate that is not public (see diagnostic codes).

Exporting without a server ​

bash
uv run smpy openapi export --out openapi.json          # or: make openapi
uv run smpy openapi export --module users --module audit_log

The command builds the app in process and does not start a server or need Redis. It reads host settings from the database when it is reachable; otherwise it warns and uses the environment and defaults.

TypeScript client (hey-api) ​

yaml
# .github/workflows/client.yml (excerpt)
- run: uv sync --all-packages
- run: uv run smpy openapi export --out openapi.json
- run: npx @hey-api/openapi-ts -i openapi.json -o src/client -c @hey-api/client-fetch

Dart client (openapi-generator dart-dio) ​

yaml
- run: uv sync --all-packages
- run: uv run smpy openapi export --out openapi.json
- run: >
    npx @openapitools/openapi-generator-cli generate
    -i openapi.json -g dart-dio -o packages/api_client
    --additional-properties=pubName=api_client
- run: cd packages/api_client && dart pub get && dart run build_runner build

Released under the MIT License.