From 802949ded21c6b7a8926d7b09d6357063735854d Mon Sep 17 00:00:00 2001 From: Chris Wood Date: Fri, 22 Mar 2024 17:21:08 +0000 Subject: [PATCH 1/7] feat: Callbacks and webhooks, spelling and invalid OpenAPI... --- .gitignore | 1 + examples/tictactoe.yaml | 63 ++++++++-- img/callback-object.dot | 77 ++++++++++++ img/callback-object.svg | 245 +++++++++++++++++++++++++++++++++++++ img/webhook-object.dot | 29 +++++ img/webhook-object.svg | 78 ++++++++++++ img/webhooks-object.svg | 0 index.md | 3 +- specification/callbacks.md | 91 ++++++++++++++ specification/index.md | 8 +- specification/security.md | 24 ++-- specification/webhooks.md | 47 +++++++ 12 files changed, 640 insertions(+), 26 deletions(-) create mode 100644 img/callback-object.dot create mode 100644 img/callback-object.svg create mode 100644 img/webhook-object.dot create mode 100644 img/webhook-object.svg create mode 100644 img/webhooks-object.svg create mode 100644 specification/callbacks.md create mode 100644 specification/webhooks.md diff --git a/.gitignore b/.gitignore index ee4bf43..8f6caf0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ _site/ *.swp .jekyll-metadata .ruby-version +.vscode diff --git a/examples/tictactoe.yaml b/examples/tictactoe.yaml index d27b80d..5cfa3cf 100644 --- a/examples/tictactoe.yaml +++ b/examples/tictactoe.yaml @@ -24,9 +24,9 @@ paths: schema: $ref: "#/components/schemas/status" security: - apiKey: [] - app2AppOauth: - - board:read + - defaultApiKey: [] + - app2AppOauth: + - board:read # Single square operations /board/{row}/{column}: @@ -54,9 +54,9 @@ paths: $ref: "#/components/schemas/errorMessage" example: "Illegal coordinates" security: - bearerHttpAuthentication: [] - user2AppOauth: - - board:read + - bearerHttpAuthentication: [] + - user2AppOauth: + - board:read put: summary: Set a single board square description: Places a mark on the board and retrieves the whole board and the winner (if any). @@ -76,6 +76,13 @@ paths: application/json: schema: $ref: "#/components/schemas/status" + "202": + description: Mark operation has not completed. Use callback to check for progress + headers: + Location: + description: Callback URL + schema: + type: string "400": description: The provided parameters are incorrect content: @@ -90,10 +97,31 @@ paths: invalidMark: value: "Invalid Mark (X or O)." security: - bearerHttpAuthentication: [] - user2AppOauth: - - board:write - + - bearerHttpAuthentication: [] + - user2AppOauth: + - board:write + callbacks: + statusCallback: + '{$response.header.Location}': + get: + summary: Status of mark operation + description: Provides the status of the ongoing mark operation + operationId: markOperationCallback + responses: + "200": + description: Mark operation has completed successfully + content: + application/json: + schema: + $ref: "#/components/schemas/status" + "202": + description: Mark operation has not completed + default: + description: Error returning information on mark operation progress + content: + application/json: + schema: + $ref: '#/components/schemas/errorMessage' components: parameters: rowParam: @@ -179,4 +207,17 @@ components: scopes: # Reads and writes permitted via authorization code flow board:read: Read the board - board:write: Write to the board \ No newline at end of file + board:write: Write to the board +webhooks: + markStatus: + post: + summary: Status of mark operation + description: Provides the status of the mark operation on completion + operationId: markOperationWebhook + responses: + "200": + description: Mark operation has completed successfully + content: + application/json: + schema: + $ref: "#/components/schemas/status" \ No newline at end of file diff --git a/img/callback-object.dot b/img/callback-object.dot new file mode 100644 index 0000000..db636c4 --- /dev/null +++ b/img/callback-object.dot @@ -0,0 +1,77 @@ +digraph componentsObject { + node [shape = none; fontname = monospace; tooltip = "Click to jump to the specification of this object";]; + rankdir = LR; + bgcolor = white; + + openapiObject [URL = "https://spec.openapis.org/oas/v3.1.0#oasObject";target = "_blank";label = < + + + + + + +
OpenAPI Object
openapi
info
components
security
paths
>;]; + + componentsObject [URL = "https://spec.openapis.org/oas/v3.1.0#componentsObject";target = "_blank";label = < + + +
Components Object
callbacks
>;]; + + pathsObject [URL = "https://spec.openapis.org/oas/v3.1.0#pathsObject";target = "_blank";label = < + + + + +
Paths Object
/endpoint1
/endpoint2
/endpoint3
>;]; + + pathItemObject [URL = "https://spec.openapis.org/oas/v3.1.0#pathItemObject";target = "_blank";label = < + + + + + + +
Path Item Object
delete
get
patch
post
put
>;]; + + operationObject [URL = "https://spec.openapis.org/oas/v3.1.0#operationObject";target = "_blank";label = < + + +
Operation Object
callbacks
>;]; + + + callbackPathItemObject [URL = "https://spec.openapis.org/oas/v3.1.0#pathItemObject";target = "_blank";label = < + + + + + + +
Path Item Object
delete
get
patch
post
put
>;]; + + + callbackObject [URL = "https://spec.openapis.org/oas/v3.1.0#callbackObject";target = "_blank";label = < + + +
Callback Object
{expression}
>;]; + + openapiObject:components -> componentsObject:header; + + componentsObject:callbacks -> callbackObject:header; + + openapiObject:paths -> pathsObject:header; + + pathsObject:endpoint1 -> pathItemObject:header; + pathsObject:endpoint2 -> pathItemObject:header; + pathsObject:endpoint3 -> pathItemObject:header; + + pathItemObject:delete -> operationObject:header; + pathItemObject:get -> operationObject:header; + pathItemObject:patch -> operationObject:header; + pathItemObject:post -> operationObject:header; + pathItemObject:put -> operationObject:header; + + operationObject:callbacks -> callbackObject:header; + + + callbackObject:expression -> callbackPathItemObject:header; +} \ No newline at end of file diff --git a/img/callback-object.svg b/img/callback-object.svg new file mode 100644 index 0000000..8408996 --- /dev/null +++ b/img/callback-object.svg @@ -0,0 +1,245 @@ + + + + + + +componentsObject + + + +openapiObject + + + +OpenAPI Object + + +openapi + + +info + + +components + + +security + + +paths + + + + + + + + +componentsObject + + + +Components Object + + +callbacks + + + + + + + + +openapiObject:components->componentsObject:header + + + + + +pathsObject + + + +Paths Object + + +/endpoint1 + + +/endpoint2 + + +/endpoint3 + + + + + + + + +openapiObject:paths->pathsObject:header + + + + + +callbackObject + + + +Callback Object + + +{expression} + + + + + + + + +componentsObject:callbacks->callbackObject:header + + + + + +pathItemObject + + + +Path Item Object + + +delete + + +get + + +patch + + +post + + +put + + + + + + + + +pathsObject:endpoint1->pathItemObject:header + + + + + +pathsObject:endpoint2->pathItemObject:header + + + + + +pathsObject:endpoint3->pathItemObject:header + + + + + +operationObject + + + +Operation Object + + +callbacks + + + + + + + + +pathItemObject:delete->operationObject:header + + + + + +pathItemObject:get->operationObject:header + + + + + +pathItemObject:patch->operationObject:header + + + + + +pathItemObject:post->operationObject:header + + + + + +pathItemObject:put->operationObject:header + + + + + +operationObject:callbacks->callbackObject:header + + + + + +callbackPathItemObject + + + +Path Item Object + + +delete + + +get + + +patch + + +post + + +put + + + + + + + + +callbackObject:expression->callbackPathItemObject:header + + + + + diff --git a/img/webhook-object.dot b/img/webhook-object.dot new file mode 100644 index 0000000..8c4b293 --- /dev/null +++ b/img/webhook-object.dot @@ -0,0 +1,29 @@ +digraph componentsObject { + node [shape = none; fontname = monospace; tooltip = "Click to jump to the specification of this object";]; + rankdir = LR; + bgcolor = white; + + openapiObject [URL = "https://spec.openapis.org/oas/v3.1.0#oasObject";target = "_blank";label = < + + + + + + + +
OpenAPI Object
openapi
info
components
security
paths
webhooks
>;]; + + + + pathItemObject [URL = "https://spec.openapis.org/oas/v3.1.0#pathItemObject";target = "_blank";label = < + + + + + + +
Path Item Object
delete
get
patch
post
put
>;]; + + + openapiObject:webhooks -> pathItemObject:header; +} \ No newline at end of file diff --git a/img/webhook-object.svg b/img/webhook-object.svg new file mode 100644 index 0000000..1defb96 --- /dev/null +++ b/img/webhook-object.svg @@ -0,0 +1,78 @@ + + + + + + +componentsObject + + + +openapiObject + + + +OpenAPI Object + + +openapi + + +info + + +components + + +security + + +paths + + +webhooks + + + + + + + + +pathItemObject + + + +Path Item Object + + +delete + + +get + + +patch + + +post + + +put + + + + + + + + +openapiObject:webhooks->pathItemObject:header + + + + + diff --git a/img/webhooks-object.svg b/img/webhooks-object.svg new file mode 100644 index 0000000..e69de29 diff --git a/index.md b/index.md index 40234c6..efd6565 100644 --- a/index.md +++ b/index.md @@ -5,6 +5,7 @@ nav_order: 1 --- # Getting started + ## Intended Audience This guide is directed at **HTTP-based API** designers and writers wishing to benefit from having their API formalized in an **OpenAPI Description** (**OAD**). @@ -29,7 +30,7 @@ Having your API formally described in a machine-readable format allows automated - **Documentation Generation**: Create traditional human-readable documentation based on the machine-readable description, which always stays up-to-date. - **Code Generation**: Create both server and client code in any programming language, freeing developers from having to perform data validation or write SDK glue code, for example. - **Graphical Editors**: Allow easy creation of description files using a GUI instead of typing them by hand. -- **Mock Servers**: Create fake servers providing example responses which you and your customers can start testing with before you write a single line of code. +- **Mock Servers**: Create fake servers providing example responses that you and your customers can start testing with before you write a single line of code. - **Security Analysis**: Discover possible vulnerabilities at the API design stage instead of much, much later. On top of this, the **OpenAPI Specification** also provides you with: diff --git a/specification/callbacks.md b/specification/callbacks.md new file mode 100644 index 0000000..d778fa2 --- /dev/null +++ b/specification/callbacks.md @@ -0,0 +1,91 @@ +--- +layout: default +title: Providing Callbacks +parent: The OpenAPI Specification Explained +nav_order: 9 +--- + +# Providing Callbacks + +Callbacks are a feature of OAS that provides a relationship between a given [Operation](https://spec.openapis.org/oas/v3.1.0#operation-object) and a [Path Item](https://spec.openapis.org/oas/v3.1.0#path-item-object). A callback allows an API provider to describe this relationship at design time, indicating that an API consumer can call a given URL based on the definition of the Callback and dynamic values they received in response to the first API call. These are described as "out-of-band" by the specification as the expectation is the API consumer can call these Operations independently of the Operation in which they are defined. + +
+ +
Callbacks are implemented in an Operation and also be described by reference using a Reference Object.
+
+ +A common use case for callbacks is to provide information on the success or failure of long-running operations that cannot be completed synchronously. An example is in the context of payments API, where payments backend systems are asynchronous and therefore cannot always return a definitive response within the typical timeout period for an HTTP request. Callbacks are therefore implemented to allow an immediate, synchronous response to be made so that the API consumer can check on the status of the payment out-of-band. + +A Callback object is defined as part of an Operation. In our Tic Tac Toe example we have defined a Response object that indicates an asynchronous response to a requested move on the board. A 202 HTTP response is returned - indicating the request has been accepted but the operation has yet to complete - along with the `Location` header that provides the callback URL: + +```yaml +put: + summary: Set a single board square + description: Places a mark on the board and retrieves the whole board and the winner (if any). + tags: + - Gameplay + operationId: put-square + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/mark" + responses: + "200": + description: "OK" + content: + application/json: + schema: + $ref: "#/components/schemas/status" + "202": + description: Mark operation has not completed. Use callback to check for progress + headers: + Location: + description: Callback URL + schema: + type: string +``` + +This operation also describes the callback, which is implemented as a Runtime Expression that points at the `Location` header from the 202 response. The `callbacks` object is defined as a Map. Each callback is defined with a name that uniquely identifies the Callback object, including the Expression value: + +```yaml +callbacks: + statusCallback: + "{$response.header.Location}": + get: + summary: Status of mark operation + description: Provides the status of the ongoing mark operation + operationId: markOperationCallback + responses: + "200": + description: Mark operation has completed successfully + content: + application/json: + schema: + $ref: "#/components/schemas/status" + "202": + description: Mark operation has not completed + default: + description: Error returning information on mark operation progress + content: + application/json: + schema: + $ref: "#/components/schemas/errorMessage" +``` + +The object defines or references a Path Item, qualified by the Runtime Expression. The API consumer will use this Runtime Expression to resolve the value of the URL to call. In the example OAD we've defined several response codes in the Path Item defined by the Callback object, namely: + +- A 200, indicating the move operation has been completed. This callback returns the same status information as a synchronous response. +- A 202, indicating the move operation is still ongoing. The API consumer will need to call the URL again to check on the status of the move. +- Any other responses returned by the callback URL are defined based on the `errorMessage` Schema Object, indicated using the `default` keyword. + +The behaviors that govern how frequently an API consumer should call a callback URL are largely based on the type of operation being supported and the specifics of the API provider's implementation. We therefore do not cover such considerations in this topic. + +## Summary + +In this topic we've learned that: + +- Callbacks provide the means to associate a given Operation with a that provides additional, out-of-band information. +- An API provider can use Callbacks to support features like long-running operations that are completed asynchronously. +- API consumers can resolve a Callback URL using a Runtime Expression, which resolves to attributes of the request or response messages. diff --git a/specification/index.md b/specification/index.md index a0f3e63..5fc8c31 100644 --- a/specification/index.md +++ b/specification/index.md @@ -10,12 +10,16 @@ has_toc: false The [OpenAPI Specification](https://spec.openapis.org/oas/v3.1.0) is the ultimate source of knowledge regarding this API description format. However, its length is daunting to newcomers and makes it hard for experienced users to find specific bits of information. This chapter provides a soft landing for readers not yet familiar with OpenAPI and is organized by topic, simplifying browsing. -The following pages introduce the syntax and structure of an OpenAPI Description (OAD), its main building blocks and a minimal API description. Afterwards, the different blocks are detailed, starting from the most common and progressing towards advanced ones. +The following pages introduce the syntax and structure of an OpenAPI Description (OAD), its main building blocks, and a minimal API description. The different blocks are then detailed, starting from the most common and progressing towards advanced ones. -- [Structure of an OpenAPI Description](structure): JSON, YAML, `openapi` and `info` +- [Structure of an OpenAPI Description](structure): JSON, YAML, `openapi`, and `info`. - [API Endpoints](paths): `paths` and `responses`. - [Content of Message Bodies](content): `content` and `schema`. - [Parameters and Payload of an Operation](parameters): `parameters` and `requestBody`. - [Reusing Descriptions](components): `components` and `$ref`. - [Providing Documentation and Examples](docs): `description` and `example`/`examples`. - [API Servers](servers): `servers`. +- [Describing API Security](security): `securitySchemes` and `security`. +- [Providing Callbacks](callbacks): `callbacks`. +- [Providing Webhooks](webhooks): `webhooks`. +- [Implementing Links](links): `links`. diff --git a/specification/security.md b/specification/security.md index 0c0442c..b132a3d 100644 --- a/specification/security.md +++ b/specification/security.md @@ -16,7 +16,7 @@ OpenAPI provides the [Security Scheme Object](https://spec.openapis.org/oas/late
Security Scheme objects are referenced as Security Requirements, either globally or by an Operation.
-A Security Requirement declared for a given Operation takes precedence over global Security Requirements. A number of security mechanisms are supported. Each mechanism is indicated using the `type` property, which is shown in the examples below. +A Security Requirement declared for a given Operation takes precedence over global Security Requirements. Several security mechanisms are supported. Each mechanism is indicated using the `type` property, which is shown in the examples below. There are currently five supported security types, namely: @@ -146,7 +146,7 @@ paths: /board: get: security: - oauth2Profiles: [] + - oauth2Profiles: [] ``` Note that if you want to segregate grant types - where, for example, Client Credentials is only supported for a specific Operation - you'll need to create a separate Security Scheme object that can be applied individually. This is also true if you want to differentiate the available scopes, for example: @@ -185,15 +185,15 @@ paths: /board: get: security: - app2AppOauth: - - board:read + - app2AppOauth: + - board:read ... /board/{row}/{column}: put: security: - user2AppOauth: - - board:read - - board:write + - user2AppOauth: + - board:read + - board:write ... ``` @@ -203,7 +203,7 @@ paths: The final Security Scheme type is OpenID Connect, which provides information for [OpenID Connect Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html). -OpenID Connect Core is obviously an OAuth 2.0 profile and is supported by some of properties the OAuth Flow Object. However, OpenID Connect is generally more complex than plain OAuth 2.0 and given OpenID Connect Discovery provides a machine-readable format at the discovery endpoint it makes sense to outsource this functionality entirely. +OpenID Connect Core is obviously an OAuth 2.0 profile and is supported by some of the properties of the OAuth Flow Object. However, OpenID Connect is generally more complex than plain OAuth 2.0 and given OpenID Connect Discovery provides a machine-readable format at the discovery endpoint it makes sense to outsource this functionality entirely. Specifying OpenID Connect is therefore straightforward in that you provide the discovery endpoint in the property `openIdConnectUrl`: @@ -226,16 +226,16 @@ info: and requesting the state of the board or of individual squares. version: 1.0.0 security: - openIdConnect: - - board:read - - board:write + - openIdConnect: + - board:read + - board:write ``` This approach allows OpenAPI to provide _just enough_ information for humans and tooling, whilst ensuring that OpenID Connect Discovery provides the system-or-record for security-related information. ## Summary -In this page we've learnt that: +In this page we've learned that: - API security can be described in OpenAPI. - Security properties must be described using a Security Scheme object. diff --git a/specification/webhooks.md b/specification/webhooks.md new file mode 100644 index 0000000..6830769 --- /dev/null +++ b/specification/webhooks.md @@ -0,0 +1,47 @@ +--- +layout: default +title: Providing Webhooks +parent: The OpenAPI Specification Explained +nav_order: 9 +--- + +# Providing Webhooks + +Webhooks are a style of API common in the API world. Their purpose is to provide bi-directional communications from the API provider to the API consumer, supporting out-of-band events that do not fit into the pattern of REST APIs. Webhooks fulfill similar purposes to Callbacks in that they support transmitting information about asynchronous or long-running communications. The example of payments APIs discussed in the Callbacks topic provides real-world implementations of Webhooks. Many payments API providers implement webhooks to communicate the result of payment operations as an alternative to callbacks. API consumers can implement a webhook at a URL of their choosing to receive out-of-band updates on a previously submitted, long-running request. + +API providers still need to define the shape of a given webhook, however. They can do this using the `webhooks` property which is found at the root of the [OpenAPI document](https://spec.openapis.org/oas/v3.1.0#openapi-object). + +
+ +
Webhooks are implemented at the root of the OpenAPI object
+
+ +A webhook is, in fact, simply a Path Item Object and can support one or more Operation objects. The key difference is that Webhooks are not encapsulated by a Paths Object, as the expectation is that an API consumer will host the webhook at a URL of their choosing. Webhooks therefore define a template, expressed as a Path Item, for API consumers to follow in how they validate incoming events. + +Our Tic Tac Toe example includes a webhook that communicates the status of the board. This is not linked to a specific Operation, but given asynchronous behaviors are supported it is implied that this may be received as a result of the API consumer receiving a 202 HTTP return code: + +```yaml +webhooks: + markStatus: + post: + summary: Status of mark operation + description: Provides the status of the mark operation on completion + operationId: markOperationWebhook + responses: + "200": + description: Mark operation has completed successfully + content: + application/json: + schema: + $ref: "#/components/schemas/status" +``` + +When events are sent over a webhook is, however, typically defined outside of the OAD and described in an API provider's documentation. That said, OpenAPI provides a convenient mechanism for describing webhooks alongside the description of the APIs. + +## Summary + +In this topic we've learned that: + +- Webhooks are a style of API that facilitates bi-directional communication between API providers and API consumers. +- OpenAPI provides the means for API providers to describe their webhooks for API consumers to use as a template for implementation. +- Webhooks in an OAD use Path Items but are not allied to a specific path through a Paths object. From 326170ae333eeb878f72d13b2e51100af30a817b Mon Sep 17 00:00:00 2001 From: Chris Wood Date: Fri, 22 Mar 2024 17:21:57 +0000 Subject: [PATCH 2/7] fix: Removed duplicate webhooks SVG --- img/webhooks-object.svg | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 img/webhooks-object.svg diff --git a/img/webhooks-object.svg b/img/webhooks-object.svg deleted file mode 100644 index e69de29..0000000 From 4772da7f07cd1b78282d424019f0d69413fb60c8 Mon Sep 17 00:00:00 2001 From: Chris Wood Date: Mon, 25 Mar 2024 14:23:08 +0000 Subject: [PATCH 3/7] feat: Added Links page and corrected typos --- examples/tictactoe.yaml | 7 + img/link-object.dot | 79 +++++++++++ img/link-object.svg | 267 +++++++++++++++++++++++++++++++++++++ specification/callbacks.md | 12 +- specification/links.md | 61 +++++++++ specification/webhooks.md | 6 +- 6 files changed, 423 insertions(+), 9 deletions(-) create mode 100644 img/link-object.dot create mode 100644 img/link-object.svg create mode 100644 specification/links.md diff --git a/examples/tictactoe.yaml b/examples/tictactoe.yaml index 5cfa3cf..6e64d30 100644 --- a/examples/tictactoe.yaml +++ b/examples/tictactoe.yaml @@ -46,6 +46,13 @@ paths: application/json: schema: $ref: "#/components/schemas/mark" + links: + markSquare: + description: Operation to use if the mark value returned indicates the square is empty + operationId: put-square + parameters: + row: $request.path.row + column: $request.path.column "400": description: The provided parameters are incorrect content: diff --git a/img/link-object.dot b/img/link-object.dot new file mode 100644 index 0000000..f141f2a --- /dev/null +++ b/img/link-object.dot @@ -0,0 +1,79 @@ +digraph componentsObject { + node [shape = none; fontname = monospace; tooltip = "Click to jump to the specification of this object";]; + rankdir = LR; + bgcolor = white; + + openapiObject [URL = "https://spec.openapis.org/oas/v3.1.0#oasObject";target = "_blank";label = < + + + + + + +
OpenAPI Object
openapi
info
components
security
paths
>;]; + + componentsObject [URL = "https://spec.openapis.org/oas/v3.1.0#componentsObject";target = "_blank";label = < + + +
Components Object
links
>;]; + + pathsObject [URL = "https://spec.openapis.org/oas/v3.1.0#pathsObject";target = "_blank";label = < + + + + +
Paths Object
/endpoint1
/endpoint2
/endpoint3
>;]; + + pathItemObject [URL = "https://spec.openapis.org/oas/v3.1.0#pathItemObject";target = "_blank";label = < + + + + + + +
Path Item Object
delete
get
patch
post
put
>;]; + + operationObject [URL = "https://spec.openapis.org/oas/v3.1.0#operationObject";target = "_blank";label = < + + +
Operation Object
responses
>;]; + + responsesObject [URL = "https://spec.openapis.org/oas/v3.1.0#responsesObject";target = "_blank";label = < + + +
Responses Object
*
>;]; + + responseObject [URL = "https://spec.openapis.org/oas/v3.1.0#responseObject";target = "_blank";label = < + + +
Response Object
links
>;]; + + linkObject [URL = "https://spec.openapis.org/oas/v3.1.0#linkObject";target = "_blank";label = < + + + + + + +
Link Object
operationRef
operationId
parameters
requestBody
description
server
>;]; + + openapiObject:components -> componentsObject:header; + + componentsObject:links -> linkObject:header; + + openapiObject:paths -> pathsObject:header; + + pathsObject:endpoint1 -> pathItemObject:header; + pathsObject:endpoint2 -> pathItemObject:header; + pathsObject:endpoint3 -> pathItemObject:header; + + pathItemObject:delete -> operationObject:header; + pathItemObject:get -> operationObject:header; + pathItemObject:patch -> operationObject:header; + pathItemObject:post -> operationObject:header; + pathItemObject:put -> operationObject:header; + + operationObject:responses -> responsesObject:header; + responsesObject:all -> responseObject:header; + responseObject:links -> linkObject:header; +} \ No newline at end of file diff --git a/img/link-object.svg b/img/link-object.svg new file mode 100644 index 0000000..1a9f4db --- /dev/null +++ b/img/link-object.svg @@ -0,0 +1,267 @@ + + + + + + +componentsObject + + + +openapiObject + + + +OpenAPI Object + + +openapi + + +info + + +components + + +security + + +paths + + + + + + + + +componentsObject + + + +Components Object + + +links + + + + + + + + +openapiObject:components->componentsObject:header + + + + + +pathsObject + + + +Paths Object + + +/endpoint1 + + +/endpoint2 + + +/endpoint3 + + + + + + + + +openapiObject:paths->pathsObject:header + + + + + +linkObject + + + +Link Object + + +operationRef + + +operationId + + +parameters + + +requestBody + + +description + + +server + + + + + +componentsObject:links->linkObject:header + + + + + +pathItemObject + + + +Path Item Object + + +delete + + +get + + +patch + + +post + + +put + + + + + + + + +pathsObject:endpoint1->pathItemObject:header + + + + + +pathsObject:endpoint2->pathItemObject:header + + + + + +pathsObject:endpoint3->pathItemObject:header + + + + + +operationObject + + + +Operation Object + + +responses + + + + + + + + +pathItemObject:delete->operationObject:header + + + + + +pathItemObject:get->operationObject:header + + + + + +pathItemObject:patch->operationObject:header + + + + + +pathItemObject:post->operationObject:header + + + + + +pathItemObject:put->operationObject:header + + + + + +responsesObject + + + +Responses Object + + +* + + + + + + + + +operationObject:responses->responsesObject:header + + + + + +responseObject + + + +Response Object + + +links + + + + + + + + +responsesObject:all->responseObject:header + + + + + +responseObject:links->linkObject:header + + + + + diff --git a/specification/callbacks.md b/specification/callbacks.md index d778fa2..5e8702e 100644 --- a/specification/callbacks.md +++ b/specification/callbacks.md @@ -7,16 +7,16 @@ nav_order: 9 # Providing Callbacks -Callbacks are a feature of OAS that provides a relationship between a given [Operation](https://spec.openapis.org/oas/v3.1.0#operation-object) and a [Path Item](https://spec.openapis.org/oas/v3.1.0#path-item-object). A callback allows an API provider to describe this relationship at design time, indicating that an API consumer can call a given URL based on the definition of the Callback and dynamic values they received in response to the first API call. These are described as "out-of-band" by the specification as the expectation is the API consumer can call these Operations independently of the Operation in which they are defined. +Callbacks are a feature of OAS that provides a relationship between a given [Operation](https://spec.openapis.org/oas/v3.1.0#operation-object) and a [Path Item](https://spec.openapis.org/oas/v3.1.0#path-item-object). A callback allows an API provider to describe this relationship at design time, indicating that an API consumer can call a given URL based on the definition of the Callback and dynamic values they receive in the response from a given Operation. These are described as "out-of-band" by the specification as the expectation is the API consumer can call such URLs independently of the Operation in which they are defined.
Callbacks are implemented in an Operation and also be described by reference using a Reference Object.
-A common use case for callbacks is to provide information on the success or failure of long-running operations that cannot be completed synchronously. An example is in the context of payments API, where payments backend systems are asynchronous and therefore cannot always return a definitive response within the typical timeout period for an HTTP request. Callbacks are therefore implemented to allow an immediate, synchronous response to be made so that the API consumer can check on the status of the payment out-of-band. +A common use case for callbacks is to provide information on the success or failure of long-running operations that cannot be completed synchronously. An example is in the context of payments API, where payments backend systems are asynchronous and therefore cannot always return a definitive response within the typical timeout period for an HTTP request. Callbacks are therefore implemented to allow an immediate, synchronous response to be made so that the API consumer can check on the status of the payment out-of-band. This supports polling patterns that are often implemented by API providers. -A Callback object is defined as part of an Operation. In our Tic Tac Toe example we have defined a Response object that indicates an asynchronous response to a requested move on the board. A 202 HTTP response is returned - indicating the request has been accepted but the operation has yet to complete - along with the `Location` header that provides the callback URL: +A Callback object is defined as part of an Operation. Our Tic Tac Toe example implements a Response object that indicates an asynchronous response to a requested move on the board. A 202 HTTP response is returned - indicating the request has been accepted but the operation has yet to complete - along with the `Location` header that provides the callback URL: ```yaml put: @@ -47,7 +47,7 @@ put: type: string ``` -This operation also describes the callback, which is implemented as a Runtime Expression that points at the `Location` header from the 202 response. The `callbacks` object is defined as a Map. Each callback is defined with a name that uniquely identifies the Callback object, including the Expression value: +This operation also describes the callback, which is implemented as a [Runtime Expression](https://spec.openapis.org/oas/v3.1.0#runtime-expressions) that points at the `Location` header from the 202 response. The `callbacks` object is defined as a Map. Each callback is defined with a name that uniquely identifies the Callback object, including the expression value: ```yaml callbacks: @@ -77,7 +77,7 @@ callbacks: The object defines or references a Path Item, qualified by the Runtime Expression. The API consumer will use this Runtime Expression to resolve the value of the URL to call. In the example OAD we've defined several response codes in the Path Item defined by the Callback object, namely: - A 200, indicating the move operation has been completed. This callback returns the same status information as a synchronous response. -- A 202, indicating the move operation is still ongoing. The API consumer will need to call the URL again to check on the status of the move. +- A 202, indicating the move operation is still ongoing. The API consumer will need to call the URL again to check on the state of the move. - Any other responses returned by the callback URL are defined based on the `errorMessage` Schema Object, indicated using the `default` keyword. The behaviors that govern how frequently an API consumer should call a callback URL are largely based on the type of operation being supported and the specifics of the API provider's implementation. We therefore do not cover such considerations in this topic. @@ -86,6 +86,6 @@ The behaviors that govern how frequently an API consumer should call a callback In this topic we've learned that: -- Callbacks provide the means to associate a given Operation with a that provides additional, out-of-band information. +- Callbacks provide the means to associate a given Operation with a Callback that provides additional, out-of-band information. - An API provider can use Callbacks to support features like long-running operations that are completed asynchronously. - API consumers can resolve a Callback URL using a Runtime Expression, which resolves to attributes of the request or response messages. diff --git a/specification/links.md b/specification/links.md new file mode 100644 index 0000000..759ac91 --- /dev/null +++ b/specification/links.md @@ -0,0 +1,61 @@ +--- +layout: default +title: Implementing Links +parent: The OpenAPI Specification Explained +nav_order: 10 +--- + +# Implementing Links + +As the API economy has grown the number of ways to indicate a relationship between one-or-more operations has grown with it. Most approaches equate to something loosely resembling the REST constraint of hypermedia as the engine of state (HATEOAS), and this has been replayed in many standards-based approaches like HAL and `json:api`. + +There has, however, always been a need to _describe_ how the relationships are manifested and how to process such information. This is because the promise of dynamically consuming links returned from an API has rarely been born out in the practicalities of both publishing APIs and software development for API consumers. The Link Object is a feature of OAS that attempts to address this, as Links are designed to describe a relationship between two operations _at design time_. + +
+ +
Links are implemented in an Response and also be described by reference using a Reference Object.
+
+ +A Link provides a reference to another operation through either an `operationRef` - which uses [References](../referencing/) to resolve a target operation - or through an unqualified `operationId` value that must be resolved to an Operation object locally. Links allow API providers to decouple the data they return in response payloads from properties specific to resolving a relationship, a pattern that is generally manifested in returning URLs in the response payload encapsulated in properties like `links`. The Link object instead uses [Runtime Expressions](https://spec.openapis.org/oas/v3.1.0#runtime-expressions) to provide the relationship, which can reference any part of the request, response, and the headers and parameters therein. Runtime Expressions are important in this context as they allow the binding of design-time information to runtime data in a very flexible way. A Link can also implement a specific [Server object](https://spec.openapis.org/oas/v3.1.0#server-object) that is only applicable to that Link. + +Our Tic Tac Toe description includes a very simple example of a Link object that indicates a relationship between the `get` and `put` Operations on the Path Item `/board/{row}/{column}`. The Link object is a property of a Response object, and is therefore always qualified by a specific HTTP return code from a given Operation: + +```yaml +/board/{row}/{column}: + parameters: + - $ref: "#/components/parameters/rowParam" + - $ref: "#/components/parameters/columnParam" + get: + summary: Get a single board square + description: Retrieves the requested square. + tags: + - Gameplay + operationId: get-square + responses: + "200": + description: "OK" + content: + application/json: + schema: + $ref: "#/components/schemas/mark" + links: + markSquare: + description: Operation to use if the mark value returned indicates the square is empty + operationId: put-square + parameters: + row: $request.path.row + column: $request.path.column +``` + +The Link object indicates a relationship to the `put-square` operation and identifies the required `row` and `column` parameters through Runtime Expressions referencing the same values in the request. This is (obviously) a trivial example as the API consumer would almost certainly understand this relationship without the additional information. However, it serves the purpose of showing how this information _could_ be used by an API consumer if they did not understand the link between the two operations. This is especially valuable _across Path Items_ where logical groupings by operation do not exist. + +It should be noted that API consumers are under no obligation to follow Links as doing so should be based on understanding its effect. The API consumer also needs to be aware of any constraints that may be applied, such as permission to access a given Operation. + +## Summary + +In this topic we've learned that: + +- There has long been a need to indicate relationships between the operations of an API. +- The Link object provides the means to indicate a relationship at design time. +- The relationship can be to an operation in the same OAD or a remote OAD. +- Links are expressed using Runtime Expressions that resolve to dynamic values at runtime. diff --git a/specification/webhooks.md b/specification/webhooks.md index 6830769..a0538d7 100644 --- a/specification/webhooks.md +++ b/specification/webhooks.md @@ -7,7 +7,7 @@ nav_order: 9 # Providing Webhooks -Webhooks are a style of API common in the API world. Their purpose is to provide bi-directional communications from the API provider to the API consumer, supporting out-of-band events that do not fit into the pattern of REST APIs. Webhooks fulfill similar purposes to Callbacks in that they support transmitting information about asynchronous or long-running communications. The example of payments APIs discussed in the Callbacks topic provides real-world implementations of Webhooks. Many payments API providers implement webhooks to communicate the result of payment operations as an alternative to callbacks. API consumers can implement a webhook at a URL of their choosing to receive out-of-band updates on a previously submitted, long-running request. +Webhooks are a style of communication common in the API economy. Their purpose is to provide bi-directional communications from the API provider to the API consumer to support out-of-band events that do not fit into the pattern of REST APIs. Webhooks fulfill similar purposes to Callbacks in that they support transmitting information about asynchronous or long-running communications. The example of payments APIs discussed in the Callbacks topic also provides an example of the real-world implementations of Webhooks. Many payments API providers implement webhooks to communicate the result of payment operations as an alternative to callbacks. API consumers can implement a webhook at a URL of their choosing to receive out-of-band updates on a previously submitted, long-running request. This avoids implementing polling patterns, which many API providers find onerous to support. API providers still need to define the shape of a given webhook, however. They can do this using the `webhooks` property which is found at the root of the [OpenAPI document](https://spec.openapis.org/oas/v3.1.0#openapi-object). @@ -16,7 +16,7 @@ API providers still need to define the shape of a given webhook, however. They c
Webhooks are implemented at the root of the OpenAPI object
-A webhook is, in fact, simply a Path Item Object and can support one or more Operation objects. The key difference is that Webhooks are not encapsulated by a Paths Object, as the expectation is that an API consumer will host the webhook at a URL of their choosing. Webhooks therefore define a template, expressed as a Path Item, for API consumers to follow in how they validate incoming events. +A webhook is, in fact, simply a Path Item Object and can support one or more Operation objects. The key difference is that Webhooks are not encapsulated by a Paths Object, as the expectation is that an API consumer will host the webhook at a URL of their choosing. Webhooks therefore define a template, expressed as a Path Item, for API consumers to follow in how they implement the webhook and validate incoming events. Our Tic Tac Toe example includes a webhook that communicates the status of the board. This is not linked to a specific Operation, but given asynchronous behaviors are supported it is implied that this may be received as a result of the API consumer receiving a 202 HTTP return code: @@ -36,7 +36,7 @@ webhooks: $ref: "#/components/schemas/status" ``` -When events are sent over a webhook is, however, typically defined outside of the OAD and described in an API provider's documentation. That said, OpenAPI provides a convenient mechanism for describing webhooks alongside the description of the APIs. +The timing and periodicity of events sent over a webhook are typically defined outside of the OAD and described in an API provider's documentation. That said, OpenAPI provides a convenient mechanism for describing webhooks alongside the description of the APIs. ## Summary From bc1dd56017bf8bafed4d6e8307007c0969edb8c4 Mon Sep 17 00:00:00 2001 From: Chris Wood Date: Tue, 26 Mar 2024 17:47:10 +0000 Subject: [PATCH 4/7] fix: Corrected Callback page and OpenAPI description --- examples/tictactoe.yaml | 32 +++++++++++----------- specification/callbacks.md | 55 ++++++++++++++++---------------------- specification/links.md | 2 +- 3 files changed, 40 insertions(+), 49 deletions(-) diff --git a/examples/tictactoe.yaml b/examples/tictactoe.yaml index 6e64d30..a7e58cc 100644 --- a/examples/tictactoe.yaml +++ b/examples/tictactoe.yaml @@ -70,6 +70,13 @@ paths: tags: - Gameplay operationId: put-square + parameters: + - name: progressUrl + in: header + description: Progress URL that should be called if asynchronous response is returned + required: false + schema: + type: string requestBody: required: true content: @@ -109,26 +116,19 @@ paths: - board:write callbacks: statusCallback: - '{$response.header.Location}': - get: + '{$request.header.progressUrl}': + post: summary: Status of mark operation - description: Provides the status of the ongoing mark operation + description: Provides the status of the mark operation operationId: markOperationCallback + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/status" responses: "200": - description: Mark operation has completed successfully - content: - application/json: - schema: - $ref: "#/components/schemas/status" - "202": - description: Mark operation has not completed - default: - description: Error returning information on mark operation progress - content: - application/json: - schema: - $ref: '#/components/schemas/errorMessage' + description: Mark operation status received components: parameters: rowParam: diff --git a/specification/callbacks.md b/specification/callbacks.md index 5e8702e..a96c257 100644 --- a/specification/callbacks.md +++ b/specification/callbacks.md @@ -7,16 +7,16 @@ nav_order: 9 # Providing Callbacks -Callbacks are a feature of OAS that provides a relationship between a given [Operation](https://spec.openapis.org/oas/v3.1.0#operation-object) and a [Path Item](https://spec.openapis.org/oas/v3.1.0#path-item-object). A callback allows an API provider to describe this relationship at design time, indicating that an API consumer can call a given URL based on the definition of the Callback and dynamic values they receive in the response from a given Operation. These are described as "out-of-band" by the specification as the expectation is the API consumer can call such URLs independently of the Operation in which they are defined. +Callbacks are a feature of OAS that provides a relationship between a given [Operation](https://spec.openapis.org/oas/v3.1.0#operation-object) and a [Path Item](https://spec.openapis.org/oas/v3.1.0#path-item-object) that can be implemented by an API consumer. A callback allows an API provider to describe this relationship at design time, indicating that they can call an API consumer at a given URL based on the definition of both the Callback and dynamic values received during a given Operation. These are described as "out-of-band" by the specification as the expectation is the API provider can call such URLs independently of the Operation in which they are defined.
Callbacks are implemented in an Operation and also be described by reference using a Reference Object.
-A common use case for callbacks is to provide information on the success or failure of long-running operations that cannot be completed synchronously. An example is in the context of payments API, where payments backend systems are asynchronous and therefore cannot always return a definitive response within the typical timeout period for an HTTP request. Callbacks are therefore implemented to allow an immediate, synchronous response to be made so that the API consumer can check on the status of the payment out-of-band. This supports polling patterns that are often implemented by API providers. +A common use case for callbacks is to provide information on the success or failure of long-running operations that cannot be completed synchronously. An example is in the context of payments API, where payments backend systems are asynchronous and therefore cannot always return a definitive response within the typical timeout period for an HTTP request. Callbacks are therefore implemented to allow an immediate, synchronous response to be made so that payment API providers can relay the status of the payment out-of-band. A Callback object is defined as part of an Operation. It differs from a [Webhook](webhooks.md) in that it is always allied to a specific Operation. Webhooks should be considered for more generic use cases as they define Path Items outside the context of a given Operation. -A Callback object is defined as part of an Operation. Our Tic Tac Toe example implements a Response object that indicates an asynchronous response to a requested move on the board. A 202 HTTP response is returned - indicating the request has been accepted but the operation has yet to complete - along with the `Location` header that provides the callback URL: +Our Tic Tac Toe example implements a Response object that indicates an asynchronous response to a requested move on the board. A 202 HTTP response is returned indicating the request has been accepted but the operation is not completed. The API consumer can send a URL in the HTTP header `progressUrl` so the API provider can send a notification when the move is complete. This header is optional, so if no value is supplied no callback will be made by the API provider: ```yaml put: @@ -25,6 +25,13 @@ put: tags: - Gameplay operationId: put-square + parameters: + - name: progressUrl + in: header + description: Progress URL that should be called if asynchronous response is returned + required: false + schema: + type: string requestBody: required: true content: @@ -39,48 +46,32 @@ put: schema: $ref: "#/components/schemas/status" "202": - description: Mark operation has not completed. Use callback to check for progress - headers: - Location: - description: Callback URL - schema: - type: string + description: Mark operation has not completed. Callback will be used to send notification once operation is complete ``` -This operation also describes the callback, which is implemented as a [Runtime Expression](https://spec.openapis.org/oas/v3.1.0#runtime-expressions) that points at the `Location` header from the 202 response. The `callbacks` object is defined as a Map. Each callback is defined with a name that uniquely identifies the Callback object, including the expression value: +This operation also describes the callback, which is implemented as a [Runtime Expression](https://spec.openapis.org/oas/v3.1.0#runtime-expressions) that points at the `progressUrl` header from the parameter above. The `callbacks` object is defined as a Map. Each callback is defined with a name that uniquely identifies the Callback object and the runtime expression value: ```yaml callbacks: statusCallback: - "{$response.header.Location}": - get: + "{$request.header.progressUrl}": + post: summary: Status of mark operation description: Provides the status of the ongoing mark operation operationId: markOperationCallback + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/status" responses: "200": - description: Mark operation has completed successfully - content: - application/json: - schema: - $ref: "#/components/schemas/status" - "202": - description: Mark operation has not completed - default: - description: Error returning information on mark operation progress - content: - application/json: - schema: - $ref: "#/components/schemas/errorMessage" + description: Mark operation status received ``` -The object defines or references a Path Item, qualified by the Runtime Expression. The API consumer will use this Runtime Expression to resolve the value of the URL to call. In the example OAD we've defined several response codes in the Path Item defined by the Callback object, namely: - -- A 200, indicating the move operation has been completed. This callback returns the same status information as a synchronous response. -- A 202, indicating the move operation is still ongoing. The API consumer will need to call the URL again to check on the state of the move. -- Any other responses returned by the callback URL are defined based on the `errorMessage` Schema Object, indicated using the `default` keyword. +The object defines or references a Path Item, qualified by the Runtime Expression. The API provider will use this Runtime Expression to resolve the value of the URL to call. The API consumer uses this object to define the implementation code for their callback API and perform activities like request payload schema validation. -The behaviors that govern how frequently an API consumer should call a callback URL are largely based on the type of operation being supported and the specifics of the API provider's implementation. We therefore do not cover such considerations in this topic. +The behaviors that govern when an API provider should call a callback URL are largely based on the type of operation being supported and the specifics of the implementation. We therefore do not cover such considerations in this topic. ## Summary @@ -88,4 +79,4 @@ In this topic we've learned that: - Callbacks provide the means to associate a given Operation with a Callback that provides additional, out-of-band information. - An API provider can use Callbacks to support features like long-running operations that are completed asynchronously. -- API consumers can resolve a Callback URL using a Runtime Expression, which resolves to attributes of the request or response messages. +- API providers can resolve a Callback URL using a Runtime Expression, which resolves to attributes of the request or response messages and allows them to call the API consumer at the resolved URL. diff --git a/specification/links.md b/specification/links.md index 759ac91..bd47d21 100644 --- a/specification/links.md +++ b/specification/links.md @@ -9,7 +9,7 @@ nav_order: 10 As the API economy has grown the number of ways to indicate a relationship between one-or-more operations has grown with it. Most approaches equate to something loosely resembling the REST constraint of hypermedia as the engine of state (HATEOAS), and this has been replayed in many standards-based approaches like HAL and `json:api`. -There has, however, always been a need to _describe_ how the relationships are manifested and how to process such information. This is because the promise of dynamically consuming links returned from an API has rarely been born out in the practicalities of both publishing APIs and software development for API consumers. The Link Object is a feature of OAS that attempts to address this, as Links are designed to describe a relationship between two operations _at design time_. +There has, however, always been a need to _describe_ how the relationships are manifested and how to process such information. This is because the promise of dynamically consuming links returned from an API has rarely been born out in the practicalities of both publishing APIs and software development for API consumers. The Link Object is a feature of OAS that attempts to address this. Links are designed to describe a relationship between two operations _at design time_.
From f8bf791a71b879743149acdea8ae9106c1533de1 Mon Sep 17 00:00:00 2001 From: Chris Wood Date: Tue, 26 Mar 2024 17:56:58 +0000 Subject: [PATCH 5/7] refactor: Added clarification on use of Webhooks --- specification/webhooks.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/specification/webhooks.md b/specification/webhooks.md index a0538d7..959c249 100644 --- a/specification/webhooks.md +++ b/specification/webhooks.md @@ -7,7 +7,9 @@ nav_order: 9 # Providing Webhooks -Webhooks are a style of communication common in the API economy. Their purpose is to provide bi-directional communications from the API provider to the API consumer to support out-of-band events that do not fit into the pattern of REST APIs. Webhooks fulfill similar purposes to Callbacks in that they support transmitting information about asynchronous or long-running communications. The example of payments APIs discussed in the Callbacks topic also provides an example of the real-world implementations of Webhooks. Many payments API providers implement webhooks to communicate the result of payment operations as an alternative to callbacks. API consumers can implement a webhook at a URL of their choosing to receive out-of-band updates on a previously submitted, long-running request. This avoids implementing polling patterns, which many API providers find onerous to support. +Webhooks are a style of communication common in the API economy. Their purpose is to provide bi-directional communications from the API provider to the API consumer to support out-of-band events that do not fit into the pattern of REST APIs or Callbacks. Webhooks fulfill similar purposes to Callbacks in that they support transmitting information about asynchronous or long-running communications. The example of payments APIs discussed in the Callbacks topic also provides an example of the real-world implementations of Webhooks. Many payments API providers implement webhooks to communicate the result of payment operations. API consumers can implement a webhook at a URL of their choosing to receive out-of-band updates on a previously submitted, long-running request. This avoids implementing polling patterns, which many API providers find onerous to support. + +Implementing Webhooks typically involves a registration step, which can be defined using regular Operations and allows API consumers to only consume the events they want to receive. [GitHub](https://docs.github.com/en/webhooks/using-webhooks/creating-webhooks) provides a great example of an API provider who makes extensive use of Webhooks and the means to register for specification events. API providers still need to define the shape of a given webhook, however. They can do this using the `webhooks` property which is found at the root of the [OpenAPI document](https://spec.openapis.org/oas/v3.1.0#openapi-object). From 58c425a48953b77f88cd92791b2a0b1bcc8a666d Mon Sep 17 00:00:00 2001 From: Chris Wood Date: Wed, 12 Jun 2024 15:20:05 +0100 Subject: [PATCH 6/7] fix: Remove the word "obviously" as its cruft Co-authored-by: Lorna Jane Mitchell --- specification/security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/security.md b/specification/security.md index b132a3d..4213dc9 100644 --- a/specification/security.md +++ b/specification/security.md @@ -203,7 +203,7 @@ paths: The final Security Scheme type is OpenID Connect, which provides information for [OpenID Connect Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html). -OpenID Connect Core is obviously an OAuth 2.0 profile and is supported by some of the properties of the OAuth Flow Object. However, OpenID Connect is generally more complex than plain OAuth 2.0 and given OpenID Connect Discovery provides a machine-readable format at the discovery endpoint it makes sense to outsource this functionality entirely. +OpenID Connect Core is an OAuth 2.0 profile and is supported by some of the properties of the OAuth Flow Object. However, OpenID Connect is generally more complex than plain OAuth 2.0 and given OpenID Connect Discovery provides a machine-readable format at the discovery endpoint it makes sense to outsource this functionality entirely. Specifying OpenID Connect is therefore straightforward in that you provide the discovery endpoint in the property `openIdConnectUrl`: From 136212f3fff8ebdf16cc932e085180c4018c6cb5 Mon Sep 17 00:00:00 2001 From: Chris Wood Date: Wed, 12 Jun 2024 15:20:39 +0100 Subject: [PATCH 7/7] fix: Reworded to reflect better vocabulisitics Co-authored-by: Lorna Jane Mitchell --- specification/webhooks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/webhooks.md b/specification/webhooks.md index 959c249..11f428b 100644 --- a/specification/webhooks.md +++ b/specification/webhooks.md @@ -18,7 +18,7 @@ API providers still need to define the shape of a given webhook, however. They c
Webhooks are implemented at the root of the OpenAPI object
-A webhook is, in fact, simply a Path Item Object and can support one or more Operation objects. The key difference is that Webhooks are not encapsulated by a Paths Object, as the expectation is that an API consumer will host the webhook at a URL of their choosing. Webhooks therefore define a template, expressed as a Path Item, for API consumers to follow in how they implement the webhook and validate incoming events. +A webhook is, in fact, simply a Path Item Object and can support one or more Operation objects. The key difference is that Webhooks are not encapsulated by a Paths Object, as the API consumer registers (via an out-of-band mechanism) to receive the webhook at a URL of their choosing. Webhooks therefore describe a template, expressed as a Path Item, for API consumers to follow in how they implement the webhook and validate incoming events. Our Tic Tac Toe example includes a webhook that communicates the status of the board. This is not linked to a specific Operation, but given asynchronous behaviors are supported it is implied that this may be received as a result of the API consumer receiving a 202 HTTP return code: