text field becomes a string, a number field a number, a select an enum, and so on. You rarely need to touch that. When you do, put a partial Schema Object under the field’s custom.openapi key.
Whatever you put there is deep-merged on top of the inferred schema, and your keys win. You only change what you name; everything else the plugin inferred stays intact. The merge applies wherever the field appears — the read, create, and update schemas alike.
Annotating a field
collections/Posts.ts
format, deprecated, length and range constraints, or a full type override:
Localized strings
description, title, and summary under custom.openapi are localizable. Give them a function or a locale-keyed object instead of a plain string, and they resolve against the request language — the same way Payload labels do:
{ t, i18n } for the active request language. A locale map is any object whose keys are your project’s locales and whose values are strings. Resolution happens per request: GET /api/openapi.json?lang=de returns the German descriptions. See i18n for how the language is picked.
Only
description, title, and summary are treated this way. Other keys keep their values as-is, so an object
under properties named en is never mistaken for a locale map.Entity-level metadata
Collections and globals accept acustom.openapi key too. At the entity level the plugin reads security — a per-operation override of the automatic public/secured marking:
collections/Posts.ts
{ read, create, update, delete } map. See Security marking for how this interacts with the access-function probe and securityWhen.
The title and description shown on an entity’s tag in the docs UI come from Payload’s own config: the tag description is the collection’s or global’s admin.description, which is also resolved against the request language.
Related
Security marking
How operations get their public/secured marking and every way to override it.
Custom endpoints
The same
custom.openapi convention on endpoints, as a full Operation Object.