Enums in OpenAPI
The OpenAPI Specification (OAS) version 3.x supports the enum
(enumerated list) keyword for all schemaObject
object properties, including parameters, request bodies, and responses. The OAS defines an enum
according to the JSON Schema Specification. The enum
keyword restricts the value of a JSON property to a fixed set of values. It must be an array with at least one element, and each element must be unique.
For example, the following code defines a property called status
that must be one of the values pending
, approved
, or rejected
:
{ "type": "object", "properties": { "status": { "type": "string", "enum": ["pending", "approved", "rejected"] } }, "required": ["status"]}
Any JSON instance that validates against this schema must have a status
property with exactly one of the three allowed values, matching case-sensitively, or the validation will fail.
The enum
keyword can be used with any JSON data type, including strings, numbers, objects, arrays, booleans, and the null
type. The enum
keyword is however most used with the base string
and integer
types. The boolean
type is already constrained to the values true
and false
(and possibly null
for a tri-state boolean
). Using an enum
with floating point number types generally makes little sense.
Here is an OpenAPI schema that defines a status
parameter that must be one of the values pending
, approved
, or rejected
:
YAML
parameters: status: in: query name: status required: true schema: type: string enum: - pending - approved - rejected
Any API request that includes this status
parameter must have a value that is one of the three allowed values or the request will be rejected.
Defaults
Use default
to allow clients to omit a field when calling your service. Below, if the client orders a drink without specifying a size, they'll get a medium cup.
openapi: 3.1.0info: title: Bar API version: 1.0.0paths: /orderDrink: post: operationId: orderDrink requestBody: content: application/json: schema: type: object properties: cupSize: type: string enum: - small - medium - large default: medium responses: '200': description: Order placed successfully
If you use a default, remember to omit required: true
from the field.
Enums With Names and Values
A common requirement using enums is to specify a human-readable name for the enum label and a specific integer for the enum value. For example, in C#:
public enum CupSize{ SMALL = 10 MEDIUM = 20 LARGE = 50}
This is not possible using the enum
keyword in OpenAPI. OpenAPI enums allow only a list of values. If you want your schema's enums to have both names and values, you can combine oneOf
and const
. This works only in OpenAPI version 3.1 and later. OpenAPI version 3.0 does not support const
.
Below is an example where a client can order a drink with one of three cup sizes:
openapi: 3.1.0info: title: Bar API version: 1.0.0paths: /orderDrink: post: summary: Order a drink with a specified cup size operationId: orderDrink requestBody: required: true content: application/json: schema: type: object properties: cupSize: $ref: '#/components/schemas/CupSize' responses: '200': description: Order placed successfullycomponents: schemas: CupSize: description: Size of the cup to order, represented by a code and label. oneOf: - description: Small cup size type: object properties: size: type: integer const: 10 label: type: string const: 'Small' - description: Medium cup size type: object properties: size: type: integer const: 20 label: type: string const: 'Medium' - description: Large cup size type: object properties: size: type: integer const: 50 label: type: string const: 'Large'
Below is an example call to this API:
{ "cupSize": { "size": 20, "label": "Medium" }}
Note that the client has to send both the label and the value. This defeats the purpose of using an enum, where a label is a human-readable alias for the actual value. But this oneOf
solution makes clear what options are allowed and their exact values. You'll need to decide in your design whether you want a simple enum
or a more descriptive oneOf
.
If you are using OpenAPI 3.0 or want to use enum
, you can use an extension attribute to give labels to enum values. Different code generators and OpenAPI tools use different extension names. Below is an example using the Speakeasy extension field:
components: schemas: CupSize: description: Size of the cup to order, represented by a numeric code with a corresponding label. type: integer enum: - 10 - 20 - 50 x-speakeasy-enums: - Small - Medium - Large
Or you can simply use a text description, for human understanding and not tooling support:
components: schemas: CupSize: type: integer enum: - 10 - 20 - 50 description: Small Medium Large
Constants for Single Value Enums
Before JSON Schema 2019 was included in OpenAPI 3.1, using an enum with a single value was the only way to specify a constant. If you are still using OpenAPI 3.0, the example below is how to specify that a constant string is returned in a response:
openapi: 3.0.0info: title: Bar API version: 1.0.0paths: /orderDrink: get: operationId: orderDrink responses: '200': description: Get a drink content: application/json: schema: enum: - Here is your beverage
When using OpenAPI 3.1, you can use the const
keyword whose name more clearly matches its intention than enum
did:
openapi: 3.1.0info: title: Bar API version: 1.0.0paths: /orderDrink: get: operationId: orderDrink responses: '200': description: Get a drink content: application/json: schema: const: Here is your beverage
Nullable Enums
OpenAPI 3.0
In OpenAPI 3.0 you can use the nullable
keyword to specify null
as an accpeted value in an enum. Below is an example where a client can order a drink with one of three cup sizes, or no cup siz specified at all:
components: schemas: CupSize: description: Size of the cup to order, represented by a numeric code with a corresponding label. type: string nullable: true enum: - SMALL - MEDIUM - LARGE
OpenAPI 3.1
OpenAPI 3.1 was intended to more closely align with the JSON Schema standard, and as such, the way to specify nullable types is different from 3.0. Instead of using the nullable
attribute, OpenAPI 3.1 uses JSON Schema's approach of using an array of types including the null
type. Here's the same example adapted for OpenAPI 3.1:
components: schemas: CupSize: description: Size of the cup to order, represented by a numeric code with a corresponding label. type: [string, null] enum: - SMALL - MEDIUM - LARGE - null
Open Enums
Traditionally enums are closed, meaning that only the values listed in the enum are allowed. By contrast, open enums allow additional values beyond those explicitly defined in the spec. Open Enums can be useful in cases where your API is evolving to support new use cases. In that scenario, you may want to allow clients to send additional values that are not yet defined where their usage is on the frontier of your API's capabilities.
OpenAPI 3.x currently does not natively support the description open enums directly. However, check to see if your tooling supports x-
extension attributes. For example, the Speakeasy extension x-speakeasy-unknown-values
allows you to define an enum with additional values beyond those listed.
components: schemas: CupSize: description: Size of the cup to order, represented by a numeric code with a corresponding label. type: [string, null] x-speakeasy-unknown-values: allow enum: - SMALL - MEDIUM - LARGE - null
Examples
Below is an example from the components
of an API for ordering drinks showing all the different data types you can use with enum
:
components: schemas: Orders: type: object properties: cupSize: type: string enum: - small - medium - large sugarNumbers: type: integer enum: - 0 - 1 - 2 - 3 strength: type: number enum: - 0.25 - 0.5 - 0.75 - 1.0 decaffeinated: type: boolean enum: - true - false teaOrigin: type: object enum: - { country: India, region: Assam, address: { name: "The farm"} } - { country: China, region: Fujian } - { country: Japan, region: Shizuoka } - { country: Sri Lanka, region: Nuwara Eliya } sizeRange: type: array enum: - [1,10] - [11,20]
Date objects are not directly supported. Export your dates to ISO strings before using them in an API.
Best Practices
Enums are simple, so there are only a few things to consider when using them in your schema:
- Naming conventions: Be consistent throughout your schema. If you use uppercase, like
NEW
, then stick to uppercase for all values in all enums. - Document values: Ensure that your description field explains exactly what the purpose of each enum value is. If any two values are similar, differentiate them carefully. A few extra explanatory lines in your schema can save you days of customer support queries.
- Plan for extension: When you need to add new values to an enum, have you designed your schema and your server to easily adapt? How much work will clients have to do to use the new values? What about removing values or renaming them? Consider how this affects the versioning of your API and how it will be explained to clients.
- Tool support: What tools will you use with your schema, such as code generators? Do they support
enum
andconst
? Do they require extension attributes? Research this before writing your schema. - Default value: Provide default values for enums with an obvious default, but avoid them where you need the client to put thought into their choice. For example, for an API that creates a web server, you would want the client to think carefully about the server size as it costs the client money. But the operating system version could easily default to the latest.