OpenAPI Enum Examples with Descriptions in YAML and JSON

OpenAPI enum examples with descriptions using x-enumDescriptions for clearer API references and self-documenting SDKs.

Jump to section

Jump to section

Jump to section

Adding descriptions to your OpenAPI enums is a low-effort way to make your generated SDKs clearer, safer, and easier for developers to use. Without descriptions, developers see enums as cryptic lists of strings, forcing them to guess meanings or dig through documentation.

This article covers how to use the x-enumDescriptions extension to transform basic enums into self-documenting code, including practical examples across multiple languages, handling nullable and reusable enums, and best practices for writing descriptions that actually help developers integrate faster.

Why enum descriptions matter for SDK quality

The standard OpenAPI Specification (OAS) does not have a built-in way to describe individual enum values. To add descriptions, you must use a vendor extension, with x-enumDescriptions being the most common. This extension lets you add a human-readable explanation for each value, which dramatically improves your API's clarity and the quality of any generated SDKs.

Without descriptions, a developer using your SDK sees an enum as just a list of strings. Consider a status property for a payment. The generated TypeScript SDK might look like this:

// Before: What do these statuses actually mean?
type Status = 'pending' | 'processing' | 'completed' | 'failed';

What does processing mean? Can the payment still be canceled? Is failed a final state? This ambiguity forces developers to guess or dig through your documentation, slowing them down and leading to bugs.

These small points of confusion create hidden costs that add up over time, reinforcing why your API isn't finished until the SDK ships.

  • Incorrect Integrations: A developer might misinterpret a status, leading to faulty logic in their application that you have to help debug.

  • Increased Support Load: Every question about what an enum value means is a support ticket that your team has to answer.

  • Slower Onboarding: New developers take longer to get up to speed because they have to constantly cross-reference your code with external documentation.

Adding enum descriptions is a simple fix with a high impact. Modern SDK generators can automatically read these descriptions and embed them as code comments, turning your SDK into self-documenting code.

How to use x-enumDescriptions in OpenAPI

The x-enumDescriptions field is a vendor extension, which is OpenAPI's mechanism for adding custom metadata that isn't part of the official specification. It has become the de-facto standard for documenting enum values and is supported by many popular tools.

You add it directly alongside your enum and type definitions in your OpenAPI spec. Here is a full example for a task_status property using YAML.

# components/schemas/Task.yaml
type: object
properties:
  status:
    type: string
    description: The current status of the task.
    enum:
      - pending
      - in_progress
      - completed
    x-enumDescriptions

And here is the same example in JSON format.

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "description": "The current status of the task.",
      "enum": ["pending", "in_progress", "completed"],
      "x-enumDescriptions": [
        "The task has been created but has not started.",
        "The task is actively being worked on.",
        "The task has been finished successfully."
      ]
    }
  }
}

Note for Stainless users: These same x-enumDescriptions flow directly into the generated SDK documentation. You’ll see them in the preview pane of your SDK Studio and as doc comments in your generated TypeScript, Python, and other language code.

When you feed this spec into documentation tools like Redocly or ReadMe, they will render these descriptions next to the values, making your API reference much more useful. You can also integrate SDK snippets with your API docs to provide copy-ready code examples.

Similarly, our SDK Studio gives you a live preview of how these descriptions will appear in your SDKs and documentation as you edit your spec.

Good tooling also helps you keep your spec consistent. For example, our generator will raise a diagnostic warning if the number of descriptions in x-enumDescriptions doesn't match the number of values in your enum array, preventing out-of-sync documentation.

Array vs map formats for enum descriptions

The x-enumDescriptions extension can be structured in two ways: as an array of strings or as a map (or object) of key-value pairs. The format you choose depends on your specific needs and maintenance preferences.

Select array format for full coverage

The array format is the most straightforward and common approach. You provide an array of strings where the order of descriptions must exactly match the order of values in the enum array. This format is ideal when every enum value requires a description and the order is unlikely to change.

Here’s an example for a priority enum where each value has a clear meaning.

priority:
  type: string
  enum:
    - low
    - medium
    - high
  x-enumDescriptions

In the generated SDK, these descriptions appear as JSDoc comments, providing instant context in the developer's IDE.

/**
 * An enumeration.
 *
 * - `low`: For non-urgent tasks that can be deferred.
 * - `medium`: Default priority for most tasks.
 * - `high`: For critical tasks that require immediate attention.
 */
export type Priority = 'low' | 'medium' | 'high';

When a developer hovers over Priority or one of its values in an editor like VS Code, the corresponding description will appear in a tooltip.

Select map format for flexible coverage

The map format, also known as an object format, links each enum value directly to its description. This is more verbose but offers more flexibility. It's the better choice when you only need to document a few complex values or if you anticipate the order of your enums might change over time.

Consider an enum for HTTP methods where you only want to explain the less common ones.

http_method:
  type: string
  enum:
    - GET
    - POST
    - PUT
    - PATCH
    - DELETE
  x-enumDescriptions:
    PUT: Creates or replaces the entire resource.
    PATCH

In this case, the generated SDK will still include all enum values, but only PUT and PATCH will have the extra documentation. The map format ensures that descriptions stay correctly associated even if you reorder the enum array.

Select format based on decision criteria

Choosing between the array and map formats comes down to a trade-off between conciseness and robustness. Here’s a quick guide to help you decide.

Criteria

Array Format

Map Format

Use Case

Best when all values need a description and the order is stable.

Best for documenting only a subset of values or when order may change.

Maintenance

Simpler to write, but risky if values are reordered.

More explicit and safer against reordering, but more verbose.

Tool Support

Universally supported by tools that recognize the extension.

Supported by most modern tools, including Stainless.

Ultimately, our SDK generator treats both formats identically, so you can choose the one that best fits your team's workflow without affecting the final SDK.

How enum descriptions transform your SDKs

Adding descriptions to your enums fundamentally changes the developer experience of using your SDK. It transforms a simple list of strings into a rich, self-documenting type that guides developers toward correct usage.

Let's look at the before-and-after in a few languages.

TypeScript

// Before
export type Status = 'active' | 'inactive' | 'archived';

// After
/**
 * - `active`: The resource is currently active.
 * - `inactive`: The resource is not active but can be reactivated.
 * - `archived`: The resource is permanently archived and cannot be changed.
 */
export type Status = 'active' | 'inactive' | 'archived';

In Stainless, the generated enum might look like this:

/**
 * This is an auto-generated enum from Stainless,
 * reflecting "x-enumDescriptions" in your OpenAPI spec.
 *
 * - `active`: The resource is currently active.
 * - `inactive`: The resource is not active but can be reactivated.
 * - `archived`: The resource is permanently archived and cannot be changed.
 */
export enum Status {
  Active = "active",
  Inactive = "inactive",
  Archived = "archived",
}

Python

# Before
class Status(str, Enum):
    ACTIVE = "active"
    INACTIVE = "inactive"
    ARCHIVED = "archived"

# After
class Status(str, Enum):
    """
    - `active`: The resource is currently active.
    - `inactive`: The resource is not active but can be reactivated.
    - `archived`: The resource is permanently archived and cannot be changed.
    """
    ACTIVE = "active"
    INACTIVE = "inactive"
    ARCHIVED = "archived"

This added context surfaces in several key places.

  • IDE Autocomplete: Descriptions appear directly in the autocomplete suggestions, helping developers choose the right value without leaving their editor.

  • Inline Documentation: Hovering over an enum member in the code instantly reveals its purpose.

  • Generated Documentation: The descriptions are automatically included in your API reference pages and README examples, ensuring your documentation is always in sync with your code.

Our diagnostics pane helps enforce this quality standard by flagging enums that are missing descriptions, encouraging you to maintain a high-quality, well-documented spec.

Nullable and reusable enums with descriptions

As your API grows, you'll encounter more advanced scenarios like enums that can be null or enums that are used across multiple endpoints. Your OpenAPI spec can handle these gracefully while preserving descriptions.

To create a nullable enum, the syntax depends on your OpenAPI version. In OAS 3.0, you add nullable: true. In OAS 3.1, you define a type union. To provide a description for the null case, you simply include null in your enum array and add its description at the corresponding position in the x-enumDescriptions array.

sort_order:
  type: string
  nullable: true # For OAS 3.0
  # For OAS 3.1, you would use: type: ["string", "null"]
  enum:
    - asc
    - desc
    - null
  x-enumDescriptions

To keep your spec DRY (Don't Repeat Yourself), you should define reusable enums in the components/schemas section and reference them using $ref. This is the best practice for any schema used in more than one place.

# In components/schemas/Currency.yaml
type: string
description: A three-letter ISO currency code.
enum:
  - USD
  - CAD
  - EUR
x-enumDescriptions:
  - United States Dollar
  - Canadian Dollar
  - Euro

# In an endpoint definition
requestBody:
  content:
    application/json:
      schema:
        type: object
        properties:
          currency:
            $ref: '#/components/schemas/Currency'

This ensures that Currency is the same type everywhere it's used, reducing code duplication and improving consistency. For language-specific concerns like making Java nullable fields backwards compatible, proper enum design becomes even more critical.

Best practices for descriptive enum design

Writing good enum descriptions is a craft. Here are a few best practices to ensure your enums are as clear and useful as possible.

  • Write concise, action-oriented descriptions. Avoid generic phrases. Explain what the value means and what its implications are.

    • Bad: "Status is pending."

    • Good: "The operation is awaiting final confirmation and can be canceled."

  • Keep naming predictable. While you can override generated code names with extensions like x-enum-varnames, it's better to use clear, consistent names in the enum values themselves (e.g., IN_PROGRESS instead of inprogress). This makes the generated SDK more intuitive.

  • Plan for evolution. When an enum value becomes obsolete, don't just remove it. Mark it as deprecated by adding (Deprecated) to its description. This provides a clear signal to developers to migrate their code. Our automated release process will even capture this change in the SDK's CHANGELOG.md.

  • Validate descriptions in CI. Treat your OpenAPI spec as a critical piece of source code. Integrating a linter into your CI/CD pipeline can catch issues early. You can also use our GitHub Action to generate SDK previews on every pull request, which will flag missing or mismatched descriptions before they get merged. This works especially well when you edit configs and OpenAPI specs with branches to safely test changes.

Frequently asked questions about enum descriptions

Can OpenAPI store descriptions for each enum value?

No, the base OpenAPI Specification does not support this directly. You must use a vendor extension like x-enumDescriptions, which has become the community standard for this purpose.

What is the difference between x-enumNames and x-enumDescriptions?

The x-enumNames (or x-enum-varnames) extension controls the programmatic name of the variable in the generated code, while x-enumDescriptions provides the human-readable documentation that appears in comments and IDE tooltips.

Do all SDK generators respect enum descriptions?

Support can vary, especially with older tools. However, modern generators like the Stainless SDK generator, Speakeasy, and Fern are designed to handle these extensions robustly and propagate the descriptions into idiomatic documentation for each language.

How do nullable enums work with descriptions?

You include null as a value in your enum array and add a corresponding description in the x-enumDescriptions array. The syntax for making the property nullable itself depends on your OpenAPI version.

How do I migrate existing enums to use descriptions without breaking clients?

Adding x-enumDescriptions is a non-breaking, additive change. You can start with your most critical enums and incrementally add descriptions over time. Using SDK previews allows you to verify the changes before publishing.

Ready to build SDKs that developers love? Get started for free.