OpenAPI

OpenAPI is a specification for describing RESTful HTTP APIs. The OpenAPI generator produces an OpenAPI specification in YAML from a LinkML schema. As of now it supports OpenAPI specification versions v3.0.3 and v3.1.0.

Note

This generator produces a complete OpenAPI spec by combining a user-provided template (containing the API header, endpoints, and security schemes) with JSON Schema components derived from the LinkML schema.

Overview

The generator works in two stages:

  1. The user provides an OpenAPI template — a valid OpenAPI YAML file that defines the API metadata (title, version, servers), paths (endpoints), and security schemes. It also specifies the version of the OpenAPI specification in its top-level attribute openapi.

  2. The generator fills the components/schemas section with JSON Schema definitions generated from the LinkML schema, keeping only those classes that are transitively reachable from the endpoints. A reference counts wherever it sits in an endpoint’s schema object, so a list endpoint (type: array with the $ref under items) and a polymorphic one (oneOf, anyOf, allOf) seed generation too.

Both the input template and the final output are automatically validated against the corresponding OpenAPI specification version using openapi-spec-validator.

To run:

gen-openapi personinfo.yaml --template api-template.yaml > personinfo.openapi.yaml

The template’s top-level attribute `openapi` MUST specify the supported OpenAPI version.

The --template / -t option is required when generating a concrete specification. If omitted, the generator prints a generic template that can be used as a starting point:

gen-openapi personinfo.yaml > api-template.yaml

OpenAPI Validation

The generator validates both the input template and the final output against the OpenAPI specification using openapi-spec-validator.

The template’s components/schemas section must declare each resource that is referenced by an endpoint, using two custom extension fields:

x-linkml-schema

The id of the LinkML schema being used. Must match exactly.

x-linkml-source

The name of the LinkML class that provides the schema for this resource.

Example template fragment:

components:
  schemas:
    Person:
      type: object
      x-linkml-schema: https://w3id.org/linkml/my_schema
      x-linkml-source: Person
    Organization:
      type: object
      x-linkml-schema: https://w3id.org/linkml/my_schema
      x-linkml-source: Organization

If the x-linkml-schema value does not match the schema being processed, the generator raises a ValueError. Any endpoint that references a resource not declared in components/schemas also raises an error.

Name Rewiring

If the name used for a resource in the OpenAPI template differs from the LinkML class name specified in x-linkml-source, the generator automatically rewires all $ref references and schema keys to use the template name.

For example, given this template:

components:
  schemas:
    PersonResource:
      type: object
      x-linkml-schema: https://w3id.org/linkml/my_schema
      x-linkml-source: Person

The generated spec will use PersonResource rather than Person throughout components/schemas and all $ref values.

Template Annotations

A template placeholder is normally read only for x-linkml-schema and x-linkml-source; the schema body is generated from the LinkML element. A placeholder may additionally declare annotations, which override the generated values for that resource:

  • description, title, example, externalDocs, deprecated

  • any x- vendor extension (x-linkml-* keys are never published)

The LinkML-derived value is the default; a key the template declares explicitly wins. Structural keys such as type, properties and enum are never taken from the template: placeholders conventionally carry type: object even for LinkML types and enums, which generate as type: string.

components:
  schemas:
    PersonResource:
      type: object
      description: A person, as exposed by this API.
      deprecated: true
      x-linkml-schema: https://w3id.org/linkml/my_schema
      x-linkml-source: Person

Overrides are applied by template name, so they also reach renamed resources (see Name Rewiring above). A placeholder whose schema is pruned is ignored. Annotations must have the type OpenAPI requires (for example deprecated must be a boolean); a wrongly typed value fails template validation before generation starts.

JSON Schema Transformations

The generator applies several compatibility transforms to the JSON Schema generated by JsonSchemaGenerator:

  • const values become single-element enum arrays (OpenAPI 3.0 does not support const).

  • type lists (e.g. ["string", "null"] for nullable fields) are rewritten as anyOf.

  • $ref paths are rewritten from #/$defs/ to #/components/schemas/.

  • Class-level title fields (redundant with the schema key) are stripped, unless the template declares a title for that resource.

Only classes transitively reachable from the endpoints are included in the output — unreferenced schemas are pruned automatically.

Advanced Usage

Keeping Unreferenced OpenAPI Schemas

By default, if the OpenAPI template declares schemas in components/schemas that are not referenced by any of the endpoints, they are removed.

Using the keep unreferenced option (object constructor boolean argument keep_unreferenced, CLI flag --keep-unreferenced) it’s possible to change that behavior so that all schemas provided in components/schemas are kept in the resulting OAD (OpenAPI Description) document.

Inlining Enums

By default enumerations are declared as separate schemas in the components/schemas of the resulting OAD (OpenAPI Description) document.

Using the inline_enums option (object constructor boolean argument inline_enums, CLI flag --inline-enums) it’s possible to change that behavior so that enumerations are inlined, instead of being referenced, into the schemas that use them in the resulting OAD (OpenAPI Description) document.

Docs

Command Line

gen-openapi

Generate an OpenAPI YAML with resources modelled with LinkML. If no OpenAPI template is provided, a generic one with one exemplary class/type schema is printed out.

gen-openapi [OPTIONS] YAMLFILE

Options

-t, --template <template>

OpenAPI template - includes the header, the endpoints and the security schemes

-k, --keep-unreferenced

Keep schemas listed in the template even if not referenced by any endpoint

-e, --inline-enums

Inline enum subschemas into their parent schemas instead of generating separate schema entries

-V, --version

Show the version and exit.

-f, --format <format>

Output format

Default:

'openapi'

Options:

openapi

--metadata, --no-metadata

Include metadata in output

Default:

True

--generation-date, --no-generation-date

Stamp output with the generation_date timestamp. Off by default so output is reproducible across runs.

Default:

False

--useuris, --metauris

Use class and slot URIs over model uris

Default:

True

-im, --importmap <importmap>

Import mapping file

--log_level <log_level>

Logging level

Default:

'WARNING'

Options:

CRITICAL | ERROR | WARNING | INFO | DEBUG

-v, --verbose

Verbosity. Takes precedence over –log_level.

--mergeimports, --no-mergeimports

Merge imports into source file (default=mergeimports)

--stacktrace, --no-stacktrace

Print a stack trace when an error occurs

Default:

False

Arguments

YAMLFILE

Required argument

Code

class linkml.generators.openapigen.OpenApiGenerator(schema: str | ~typing.TextIO | ~linkml_runtime.linkml_model.meta.SchemaDefinition | ~linkml.utils.generator.Generator | ~pathlib.Path, schemaview: ~linkml_runtime.utils.schemaview.SchemaView | None = None, format: str | None = None, metadata: bool = True, include_generation_date: bool = False, useuris: bool | None = None, log_level: int | None = 30, mergeimports: bool | None = True, source_file_date: str | None = None, source_file_size: int | None = None, logger: ~logging.Logger | None = None, verbose: bool | None = None, output: str | None = None, namespaces: ~linkml_runtime.utils.namespaces.Namespaces | None = <property object>, directory_output: bool = False, base_dir: str = None, metamodel_name_map: dict[str, str] = None, importmap: str | ~collections.abc.Mapping[str, str] | None = None, emit_prefixes: set[str] = <factory>, metamodel: ~linkml.utils.schemaloader.SchemaLoader = None, stacktrace: bool = False, include: str | ~pathlib.Path | ~linkml_runtime.linkml_model.meta.SchemaDefinition | None = None, keep_unreferenced: bool = False, inline_enums: bool = False)[source]

Generates OpenAPI YAML from a LinkML schema.

The generator composes a user-provided OpenAPI template (containing the API header, paths/endpoints, and security schemes) with JSON Schema components generated from the LinkML schema via JsonSchemaGenerator. Only data schemas referenced by the template’s endpoints (and their transitive dependencies) are included in the components/schemas section.

Currently following generation paths are supported (others might follow):

  • v3.0.3 — uses JsonSchemaGenerator and applies post-processing transforms (const → enum, nullable type lists → anyOf, $defs → components/schemas) required by OpenAPI 3.0.3.

  • v3.1.0 — uses PydanticGenerator to compile a Python module, then calls pydantic.BaseModel.model_json_schema() on each class. Because OpenAPI 3.1.0 is fully aligned with JSON Schema 2020-12, no post-processing transforms are needed beyond rewriting $defs references and stripping linkml_meta annotations.

The OpenAPI version to be generated is obtained from the template’s top-level attribute openapi.

serialize(template_file: str = '', **kwargs) → str[source]

Generate OpenAPI YAML from template_file and the loaded LinkML schema.