>;];
+
+
+ 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 @@
+
+
+
+
+
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..a96c257
--- /dev/null
+++ b/specification/callbacks.md
@@ -0,0 +1,82 @@
+---
+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) 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 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.
+
+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:
+ 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
+ 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:
+ 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. 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 `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:
+ "{$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 status received
+```
+
+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 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
+
+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 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/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/links.md b/specification/links.md
new file mode 100644
index 0000000..bd47d21
--- /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. 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/security.md b/specification/security.md
index 0c0442c..4213dc9 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 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..11f428b
--- /dev/null
+++ b/specification/webhooks.md
@@ -0,0 +1,49 @@
+---
+layout: default
+title: Providing Webhooks
+parent: The OpenAPI Specification Explained
+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 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).
+
+
+
+ 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 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:
+
+```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"
+```
+
+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
+
+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.