custom.openapi Operation Object to each endpoint you add, and annotate the fields you add the same way.
custom.openapi is a plain convention on Payload’s own custom key — the same one Payload’s agent skills document.
Your plugin does not import anything from @seshuk/payload-plugin-openapi, so it adds zero dependencies and zero
bundle weight.A documented plugin
src/index.ts
Why plugin order does not matter
The OpenAPI plugin does not read your config when it runs. It builds the document lazily, on request, from the fully sanitized config. By the time a request hits/api/openapi.json, every plugin in the plugins array has already run — so your endpoints, collections, and fields are visible no matter where either plugin sits in the list. There is no ordering constraint to document and nothing for your users to get wrong.
The key is inert without the plugin
custom.openapi is data on Payload’s custom key, nothing more. If the OpenAPI plugin is not installed, the metadata sits there unused — no runtime cost, no behavior change, no errors. You can ship it unconditionally in your plugin and let each user decide whether they generate a spec.
Users can still drop your endpoints from their spec with
filters.includeCustom: false or entity/operation
filters — the metadata is an offer, not an obligation.Beyond single endpoints and fields
Anything not tied to one endpoint or field — shared components, extra tags, a post-build transform — belongs in an extension. Extensions are an opt-in that users wire into their ownopenapi({ extensions: [...] }) call; there is no implicit cross-plugin channel to maintain. Export an OpenApiExtension object from your package if you want to offer one, and document that users pass it themselves.
Related
Custom endpoints
The full Operation Object convention, path normalization, and collection sources.
Extensions
Shared components, extra tags, and document transforms.