Tags

The groups your operations are published under in the OpenAPI document — manifest.tags, a capability's tag field, and the naming rules enforced at publish.

A tag is a section header in the published API reference — the grouping a reader of the API Explorer scrolls through, and the grouping the generated SDKs use to organise their methods.

Declaring none is the normal case. Every operation is grouped under its capability namespace — the part of the key before the first dot — and that group is described from the manifest's top-level description. So an app whose capabilities are serials.list, serials.get and serials.create publishes one tidy serials section without you writing anything.

Declare tags only when one app's surface is too large to read as a single list.

Declaring them

Two halves. The manifest declares the tags that exist:

manifest.json
"tags": [
  { "name": "serials", "description": { "en": "Serial registry." } },
  { "name": "serials.service", "description": { "en": "Service history and warranty." } }
]
FieldRequiredDescription
nameYesThe tag name, as it appears in the published document.
descriptionNoWhat the group covers. String or locale map. Becomes the tag description in the OpenAPI document.

And each capability names one:

manifest.capabilities.json
{
  "type": "define",
  "capability": "serials.service.list",
  "version": "1.0.0",
  "summary": "List service events for a serial",
  "tag": "serials.service",
  "route": { "method": "GET", "path": "/serials/{id}/service" },
  "response": { "title": "ServiceEventPage", "type": "object" }
}

A capability with no tag falls back to its namespace, so you can tag part of a surface and leave the rest alone.

The naming rules

These are enforced, and two of them only fail at publish time rather than in your editor — the JSON Schema cannot see across the two files to check them.

A tag name is global in the published document. Your tenant's /v1/openapi.json merges the capabilities of every installed app, so tag names share one namespace across apps. That is why the rule below exists.

A tag must be a capability namespace this app defines, or a dotted refinement of one. If your capabilities are serials.*, then serials and serials.service are legal tag names and inventory is not. You cannot claim a section header for a namespace you do not own, and you cannot invent a marketing name for your group.

A capability may only name a tag declared in the manifest's top-level tags. Naming an undeclared tag is rejected at publish time. This is the one that bites: the capability file and the manifest are generated separately, so a tag added to one and not the other passes local validation and fails on the way out.

Getting it right

Group by what a reader is trying to do, not by your internal modules. serials and serials.service are two jobs an operator has. serials.internal and serials.v2helpers are your file layout leaking into a partner's reference.

Two or three sections, not ten. Tags exist to make a long list readable. A tag with one operation in it is noise.

Write the description for someone who has not met your app. It is the paragraph under the section header in the API Explorer — the only prose a partner reads before your operation summaries.

Keep the namespace and the tag consistent. If you tag serials.service.* capabilities as serials.service, tag all of them that way. A half-tagged namespace splits one group into two sections that look like different features.

Next steps

Was this page helpful?