IPA-123: Enums
By leveraging enumerations (enums) whenever a field only accepts a discrete set of values and documenting those values, an API communicates to consumers the expectation for that data field.
Guidance
API producers should use enumeration objects for sets of values for a field that are expected to remain relatively static.
components:
schemas:
Order:
type: object
properties:
status:
type: string
enum:
- PENDING
- SHIPPED
- DELIVEREDWhy:The set of order statuses is small and stable, so an enum documents the exact values a consumer can expect and lets tooling validate them.
components:
schemas:
Order:
type: object
properties:
status:
type: string
description: One of PENDING, SHIPPED, or DELIVERED.Why:The allowed values live only in prose, so nothing validates them and tooling cannot generate a typed value set from a fixed, stable list.
For each schema under
$.components.schemas, list the string properties that accept a fixed set of values.For each such property, check whether the allowed values are declared as an
enumor only described in thedescriptiontext.Decide whether the value set is expected to stay relatively static, using the property name, description, and any example.
Flag any property with a small, stable value set whose values are documented only in prose rather than as an
enum.
API producers may include additional documentation explaining each of the allowable values.
Enumeration values must be
UPPER_SNAKE_CASE.status:
type: string
enum:
- IN_PROGRESS
- ON_HOLD
- COMPLETEDWhy:Every value uses uppercase letters with underscores between words, so the casing is consistent across the whole API.
status:
type: string
enum:
- inProgress
- on-hold
- CompletedWhy:The values mix camelCase, kebab-case, and capitalized words, so casing is inconsistent and harder to predict across endpoints.
API producers should default to making enums extensible, so new values can be added freely.
priority:
type: string
description: >
Priority of the task. Additional values may be added over time; clients
should tolerate values they do not recognize.
enum:
- LOW
- MEDIUM
- HIGHWhy:Treating the enum as extensible means a later value such as
URGENTcan be added without forcing a breaking change on existing clients.priority:
type: string
description: >
Priority of the task. These are the only values that will ever exist and
clients may reject anything else.
enum:
- LOW
- MEDIUM
- HIGHWhy:Declaring the set permanently closed leaves no room to grow, so adding any future value becomes a breaking change.
For each enum-typed property in
$.components.schemas, read its description and any client-facing documentation.Determine whether the documentation treats the value set as fixed and closed or as open to future additions.
Flag enums that are documented as permanently closed without a stated reason that the set is genuinely fixed.
Enums must not be extended in a non-compatible fashion, such as splitting one existing value into two.
state:
type: string
enum:
- ACTIVE
- SUSPENDED
- ACTIVE_TRIALWhy:A new value is appended while the existing values keep their meaning, so a consumer that already handles
ACTIVEis unaffected.state:
type: string
enum:
- ACTIVE_PAID
- ACTIVE_TRIAL
- SUSPENDEDWhy:The previous
ACTIVEvalue was split intoACTIVE_PAIDandACTIVE_TRIAL, so a value a consumer relied on disappears and existing integrations break.Identify the enum and retrieve its previously published value set from version control history or the prior released spec.
Compare the current values against the previous set: list values that were added, removed, or renamed.
For each removed or renamed value, check whether its meaning was redistributed across two or more new values.
Report any change where a previously published value was removed, renamed, or split, since each breaks consumers that depended on the old value.
API producers should use a string field rather than an enum when the set of allowable values exceeds 20.
regionCode:
type: string
description: >
Identifier of the region. The list of allowed values is extensive (>20);
refer to the API documentation for the current list.
example: NORTH_AMERICA_EASTWhy:With more than 20 possible values, a free-form string with documented values avoids an unwieldy enum that must change every time a value is added.
regionCode:
type: string
enum:
- REGION_01
- REGION_02
- REGION_03
# ...continues past 20 entries
- REGION_25Why:An enum with more than 20 entries is hard to maintain and grows with every new region, so a documented string is the better fit.
API producers should use a string field rather than an enum when the set of allowable values changes often.
categoryCode:
type: string
description: >
Identifier of the document category. The list of allowed values changes
frequently; refer to the API documentation for the current list.
example: FINANCE_REPORTWhy:A frequently changing value set modeled as a documented string avoids a spec change for every new category, which an enum would require.
categoryCode:
type: string
enum:
- FINANCE_REPORT
- HR_POLICY
- LEGAL_NOTICEWhy:The category set turns over frequently, so pinning it to an enum forces a breaking spec change each time a category is added or retired.
For each enum-typed property in
$.components.schemas, gather how often its value set has changed across recent spec revisions.Use the property description and release history to judge whether the values turn over frequently.
Flag any enum whose value set changes often, since a documented string field is the better model for it.
When a string field is used in place of an enum, API producers must document the allowable values.
categoryCode:
type: string
description: >
Identifier of the document category. Refer to the API documentation for the
current list of allowed values.
example: FINANCE_REPORT
externalDocs:
description: Current list of allowed category codes
url: https://example.com/docs/category-codesWhy:The description and
externalDocspoint a consumer to the authoritative list, so the allowable values remain discoverable even though they are not enumerated.categoryCode:
type: stringWhy:The string carries no description, example, or link to the allowed values, so a consumer has no way to know which values are valid.
For each schema under
$.components.schemas, find string properties that stand in for an enum because the value set is large or changes often.For each such property, check that the allowable values are documented through the
description, anexample, or anexternalDocslink to the current list.Flag any such string property that omits documentation of its allowable values.
The API must not accept invalid enum values and silently modify them to make them valid; instead it returns a validation error (see Validation Errors).
# Request body sends status: "open"
# Response:
status: 400
body:
error: VALIDATION_ERROR
detail: "status must be one of: OPEN, CLOSED"Why:An invalid value is rejected with a validation error, so the caller learns the input was wrong rather than having it changed without notice.
# Request body sends status: "open"
# Response:
status: 200
body:
status: OPENWhy:The invalid
openis silently coerced toOPEN, so the caller never learns the input was wrong and the silent rewrite can mask real client bugs.Enumerate the enum-typed request fields and their declared value sets.
From the source or by exercising the endpoint, submit a value that is invalid only by casing or formatting, such as a lowercase variant of a valid value.
Inspect the response: confirm the request is rejected with a validation error rather than accepted and normalized to a valid value.
Report any endpoint that rewrites an invalid enum value into a valid one instead of returning a validation error.