I love that new feature smell
- 40,248 hours, or
- 1,677 days, or
- 55 months, or
- 4 years.
That’s how long we had to wait between OpenAPI 3.1 and OpenAPI 3.2.
Was it worth it? Let’s find out!
Upgraded tags
The Tag object can now operate hierarchically:
summaryfield to allow additional metadata to be supplied for a tag.parentfield that points to the parent tag.kindfield that provides the ability to categorize or group tags.
The kind field is freeform, but really the goal is to establish a
registry of known types like nav or badge.
Tags are a really important part of the specification. They are of little use to some folks, and to others, they form the foundation of metadata used to group and navigate the surface of the API.
I am really excited about this upgrade because with nested tags comes a much stronger ability to organize operations and create a custom and specific information architecture for our APIs.
ALL THE METHODS!
There is a new kid on the block when it comes to HTTP methods. QUERY is a new method that allows us to submit a body
as an idempotent, read-only operation.
In English, this means instead of using a hugely complex encoded query parameter for a
GETrequest, that query object can be passed as a request body using theQUERYmethod. It’s a read-only method but allows big, complex objects.
The QUERY method can now be used alongside all the other favorites.
But wait… there’s more…
A new additionalOperations property now exists, which allows you to ADD YOUR OWN METHODS.
Want a new SPICEGIRLS method? No problem. What about a new CHEESE method?
paths:
/crackers:
additionalOperations:
CHEESE:
description: cheddar.
...
/zig-a-zig-ahh:
additionalOperations:
SPICEGIRLS:
description: you gotta get with my friends.
...
And you know what? It gets even better. If you want, you can JUST ADD THEM INTO THE ROOT with libopenapi!
you can bypass additionalOperations (but you shouldn’t for the sake of correctness).
paths:
/crackers:
CHEESE:
description: cheddar.
...
/zig-a-zig-ahh:
SPICEGIRLS:
description: you gotta get with my friends.
...
You can do this in libopenapi, but it’s not a part of the standard and the correct way to do things is to use
additionalOperationsin order to maintain compatibility with other tools and the standard.
Document resolution and identity
A personal nightmare for me in the past. Literally, I would wake up exhausted in the morning after having nightmares about being stuck in recursive loops, trying to resolve references that loop around endlessly.
Well, some of these issues just got a little easier with the introduction of the $self property on the entry document.
The purpose of this new property is to create a ‘resolution’ starting point for references, as well as identify the document with a unique URI.
Essentially $self marks the location of the entry point of the document. All relative references in the document
should resolve from this point.
For example:
$self: https://api.pb33f.io/wiretap/giftshop-openapi.yaml
This tells the tool to resolve any relative references (from this root document) to resolve from /wiretap on the domain api.pb33f.io.
libopenapi already supported this capability, but now there is a standard for it!
Streaming support
Sequential media, server-sent events (SSE), and other streaming media types like text/event-stream, application/jsonl,
and application/json-seq are now officially supported.
When it comes to responses that operate on lines or sequences, there are new itemSchema,
itemEncoding, and prefixEncoding properties in the MediaType object that allow each item to be described correctly.
More encoding types allow more control over multipart media types versus a singular encoding property.
Streaming is useful for APIs that send chunked or real-time data that may not all arrive in one blob, or may be collections of many different objects. Traditionally, we have used WebSockets or SSE for these types of interfaces, but there are other options.
My mate, Phil Sturgeon, has written a great article on JSON Streaming in OpenAPI 3.2.
Parameter / Cookie / Header changes
A new in location for the Parameter object called queryString.
openapi: 3.2.0
paths:
/searchStore:
get:
parameters:
- name: productQuery
in: queryString
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
filters:
type: object
properties:
category:
type: string
price_min:
type: number
price_max:
type: number
sort:
type: string
limit:
type: integer
Essentially, it allows the entire query to be parsed as a single field versus individual parameters. Also, allowReserved
is now available on any Parameter with an in property set.
Cookie parameters can now use the style property to define cookie content using a semicolon as a delimiter.
Look who’s back, back again
It’s resurfacing again because AI is using it under the covers to build prompts.
What goes around comes around, and there is a new nodeType added that allows mapping to common XML node types like element, attribute, text, cdata, or none.
attribute and wrapped have become deprecated in favor of using a nodeType like nodeType: attribute or nodeType: element.
Upgraded examples
We all love them and need them. Now there are two new fields, dataValue and serializedValue, in any object that supports examples
dataValueis the structured format of the example.serializedValueis how the example will look when it’s handled by the API.
Here are a couple of examples I just made up.
openapi: 3.2.0
paths:
/api/data:
get:
parameters:
- name: X-Filter-Options
in: header
style: simple
explode: false
schema:
type: object
properties:
include:
type: array
items:
type: string
exclude:
type: array
items:
type: string
examples:
filter_header:
summary: Complex filter in header
description: Shows how objects are serialized in headers
dataValue:
include:
- posts
- comments
exclude:
- draft
- deleted
serializedValue: "include,posts,comments,exclude,draft,deleted"
openapi: 3.2.0
paths:
/search:
get:
parameters:
- name: tags
in: query
style: form
explode: true
schema:
type: array
items:
type: string
examples:
exploded_form:
summary: Form style with explode=true
dataValue: ["urgent", "bug", "high-priority"]
serializedValue: "tags=urgent&tags=bug&tags=high-priority"
- name: categories
in: query
style: form
explode: false
schema:
type: array
items:
type: string
examples:
comma_separated:
summary: Form style with explode=false
dataValue: ["electronics", "computers", "accessories"]
serializedValue: "categories=electronics,computers,accessories"
- name: keywords
in: query
style: spaceDelimited
schema:
type: array
items:
type: string
examples:
space_delimited:
summary: Space delimited array
dataValue: ["bish", "bash", "bosh"]
serializedValue: "keywords=bish%20bash%20bosh"
- name: ids
in: query
style: pipeDelimited
schema:
type: array
items:
type: integer
examples:
pipe_delimited:
summary: Pipe delimited integers
dataValue: [1, 2, 3, 4, 5]
serializedValue: "ids=1|2|3|4|5"
Security updates
The main update is that the OAuth2 Device Authorization Flow is supported
by the addition of the new deviceAuthorization field in the flows object.
For individual flows, there are new deviceAuthorizationUrl and tokenUrl properties.
A new oauth2MetadataUrl security scheme property has been added that defines the URL used for authentication server metadata.
Schemes can now also be deprecated.
Media Types added to Components
MediaType objects can now be added to the new mediaTypes section in the Components model, allowing clean re-use and referencing of common
media types used throughout the API.
Additional feature roundup
There are a number of smaller, but no less important, updates:
Serverobject now supportsnameproperty.- Formal ABNF syntax supported in URLs.
- The
propertyNamediscriminator value is now optional. - New
defaultMappingadded to discriminator that defines the schema to be used in casepropertyNameis unset or invalid.
v0.18+ and libopenapi v0.28+ both support OpenAPI 3.2 and all of the features mentioned above.Check out OpenAPI 3.2 release notes and the 3.2 Upgrade Guide to learn more about the spec updates and read more of the clarifications made across the board.
