diff --git a/README.md b/README.md
index 52b4bd4..062c23b 100644
--- a/README.md
+++ b/README.md
@@ -6,32 +6,32 @@
- [OPEN QUESTIONS (REMOVE BEFORE PUBLISHING)](#open-questions-remove-before-publishing)
- [Introduction](#introduction)
- [What is OpenAPI and why use it?](#what-is-openapi-and-why-use-it)
- - [What versions of OpenAPI does this documentation cover?](#what-versions-of-openapi-does-this-documentation-cover)
- [How does this documentation differ from the official OpenAPI documentation?](#how-does-this-documentation-differ-from-the-official-openapi-documentation)
- - [Document Structure](#document-structure)
- - [Format \& File Structure](#format--file-structure)
+ - [Which versions of the OpenAPI Specification does this documentation cover?](#which-versions-of-the-openapi-specification-does-this-documentation-cover)
+ - [OpenAPI Document Structure](#openapi-document-structure)
+ - [Format and File Structure](#format-and-file-structure)
- [Document Schema](#document-schema)
- [Info Object](#info-object)
- [Contact Object](#contact-object)
- [License Object](#license-object)
- - [SDK Generation](#sdk-generation)
+ - [The Info Object in Generated SDKs](#the-info-object-in-generated-sdks)
- [External Documentation Object](#external-documentation-object)
- - [SDK Generation](#sdk-generation-1)
+ - [External Documentation in Generated SDKs](#external-documentation-in-generated-sdks)
- [Servers](#servers)
- [Server Object](#server-object)
- - [Server Variables \& Templating](#server-variables--templating)
+ - [Server Variables and Templating](#server-variables-and-templating)
- [Server Variable Object](#server-variable-object)
- - [SDK Generation](#sdk-generation-2)
+ - [Servers in Generated SDKs](#servers-in-generated-sdks)
- [Security](#security)
- [Security Requirement Object](#security-requirement-object)
- [Security Scheme Object](#security-scheme-object)
- - [OAuth2 Flow Object](#oauth2-flow-object)
+ - [OAuth2.0 Flow Object](#oauth20-flow-object)
- [Example Security Scheme Schema](#example-security-scheme-schema)
- - [SDK Generation](#sdk-generation-3)
+ - [Security Schemes in Generated SDKs](#security-schemes-in-generated-sdks)
- [Tags](#tags)
- [Tag Object](#tag-object)
- [SDK Creation](#sdk-creation)
- - [x-speakeasy-group](#x-speakeasy-group)
+ - [The x-speakeasy-group Extension](#the-x-speakeasy-group-extension)
- [Multiple Namespaces](#multiple-namespaces)
- [Define Multi-Level Namespaces](#define-multi-level-namespaces)
- [Paths Object](#paths-object)
@@ -51,30 +51,30 @@
- [Content](#content)
- [Media Type Object](#media-type-object)
- [Encoding Object](#encoding-object)
- - [SDK Generation](#sdk-generation-4)
+ - [Operation Objects in Generated SDKs](#operation-objects-in-generated-sdks)
- [Parameters](#parameters)
- [Parameter Object](#parameter-object)
- [Parameter Serialization](#parameter-serialization)
- [Query Parameters](#query-parameters)
- - [Primitive Types](#primitive-types)
- - [Simple Arrays](#simple-arrays)
- - [Simple Objects](#simple-objects)
- - [Complex Objects and Arrays](#complex-objects-and-arrays)
+ - [Primitive Types As Query Parameters](#primitive-types-as-query-parameters)
+ - [Simple Arrays As Query Parameters](#simple-arrays-as-query-parameters)
+ - [Simple Objects As Query Parameters](#simple-objects-as-query-parameters)
+ - [Complex Objects and Arrays As Query Parameters](#complex-objects-and-arrays-as-query-parameters)
- [Path Parameters](#path-parameters)
- - [Primitive Types](#primitive-types-1)
- - [Simple Arrays](#simple-arrays-1)
- - [Simple Objects](#simple-objects-1)
- - [Complex Objects and Arrays](#complex-objects-and-arrays-1)
+ - [Primitive Types As Path Parameters](#primitive-types-as-path-parameters)
+ - [Simple Arrays As Path Parameters](#simple-arrays-as-path-parameters)
+ - [Simple Objects As Path Parameters](#simple-objects-as-path-parameters)
+ - [Complex Objects and Arrays As Path Parameters](#complex-objects-and-arrays-as-path-parameters)
- [Header Parameters](#header-parameters)
- - [Primitive Types](#primitive-types-2)
- - [Simple Arrays](#simple-arrays-2)
- - [Simple Objects](#simple-objects-2)
- - [Complex Objects and Arrays](#complex-objects-and-arrays-2)
+ - [Primitive Types As Headers](#primitive-types-as-headers)
+ - [Simple Arrays As Headers](#simple-arrays-as-headers)
+ - [Simple Objects As Headers](#simple-objects-as-headers)
+ - [Complex Objects and Arrays As Headers](#complex-objects-and-arrays-as-headers)
- [Cookie Parameters](#cookie-parameters)
- - [Primitive Types](#primitive-types-3)
- - [Simple Arrays](#simple-arrays-3)
- - [Simple Objects](#simple-objects-3)
- - [Complex Objects and Arrays](#complex-objects-and-arrays-3)
+ - [Primitive Types As Cookies](#primitive-types-as-cookies)
+ - [Simple Arrays As Cookies](#simple-arrays-as-cookies)
+ - [Simple Objects As Cookies](#simple-objects-as-cookies)
+ - [Complex Objects and Arrays As Cookies](#complex-objects-and-arrays-as-cookies)
- [Schema Object](#schema-object)
- [Composition and Inheritance](#composition-and-inheritance)
- [Discriminator Object](#discriminator-object)
@@ -84,7 +84,9 @@
- [Extensions](#extensions)
- [References](#references)
- [OpenAPI Reference Object](#openapi-reference-object)
- - [JSON Schema Reference Object](#json-schema-reference-object)
+ - [JSON Schema References](#json-schema-references)
+ - [Absolute References](#absolute-references)
+ - [Relative References](#relative-references)
- [Expression](#expression)
- [Data Type Formats](#data-type-formats)
@@ -99,7 +101,7 @@
- TODO: Go through and update all examples of yaml and generated code once full documentation and example spec is complete.
- TODO: Ensure we refer to API, Endpoint, etc consistently throughout the documentation.
- TODO: Determine the best way to link back to the generator? Should we talk directly about it in this documentation, or leave it to links and/or expandable sections that go into more detail?
-- TODO: make the difference between OpenAPI references and JSON Schema references clear. I think this is a common point of confusion for people.
+- ~~TODO~~DONE: make the difference between OpenAPI references and JSON Schema references clear. I think this is a common point of confusion for people.
- TODO: do we want to add comments into our examples explaining them more?
- TODO: in some cases the smart bear docs document different sections of the spec in a lot of detail, almost as "how-to" guides ie. I think we should have the equivelant but should that be done inline in this documentation or as separate linked pages from here? List of potential candidates:
- callbacks
@@ -115,21 +117,60 @@
## Introduction
+Whether creating or consuming web services, developers understand the importance of API design. An API that developers enjoy interacting with can turn a SaaS business into a platform.
+
+But even if we spend years polishing the perfectly RESTful API, it is unlikely to lead anywhere without clear and accurate documentation, supported by SDKs that delight developer-users.
+
+However, the quest of keeping documentation up to date and maintaining usable SDKs in multiple programming languages is beyond the reach of most startups.
+
+One way to overcome this bump in the road to growth is to adopt a formal specification for APIs. Instead of creating documentation and multiple SDKs by hand, a formal API specification allows anyone to generate documentation, SDKs, and even server-side API endpoints.
+
+OpenAPI fits the bill, and we'd like to help you understand this powerful tool.
+
### What is OpenAPI and why use it?
-`TODO`
+When we refer to OpenAPI, we most often mean the **OpenAPI Specification** - a standardized document structure for describing HTTP APIs in a way that humans and computers can understand.
+
+To use OpenAPI, you create a JSON or YAML file that describes your API using the vocabulary provided by the OpenAPI Specification - we'll call this JSON or YAML file an **OpenAPI document**.
+
+A valid OpenAPI document can serve as a blueprint when generating documentation and SDKs. An app or library that reads an OpenAPI document to generate SDKs or documentation is called a **generator**.
-### What versions of OpenAPI does this documentation cover?
+Here's how these concepts fit together:
-This documentation will cover versions `3.1.x` and `3.0.x` of the OpenAPI specification. Where there is a important difference between the two versions, we will call it out specifically, otherwise the documentation will be applicable to both versions.
+
+
+At the center of the OpenAPI workflow, we have the OpenAPI document - the blueprint for our API, a recipe for creating SDKs, and a source of truth for our documentation.
+
+To create and maintain an OpenAPI document, we need to understand the OpenAPI Specification.
+
+This documentation will help you understand the OpenAPI Specification.
### How does this documentation differ from the official OpenAPI documentation?
-`TODO`
+Official documentation for the OpenAPI Specification, while thorough and complete, focuses on formal definition before usability. We aim to provide a gentler and more practical introduction without sacrificing accuracy.
+
+This documentation combines a simpler description of the specification with examples from a working API.
+
+We've structured the documentation according to the needs of OpenAPI users of any skill level.
+
+Instead of jumping head-first into the specification, find an entry point that suites your current understanding and goals:
-## Document Structure
+- To **learn about OpenAPI by building an API** work through our [OpenAPI tutorials](./tutorial/README.md), where we create an OpenAPI document from scratch, then generate server endpoint stubs, SDKs, and documentation.
+- Follow [step-by-step guides](./guides/README.md) on **how to accomplish specific tasks using OpenAPI**.
+- Reference a **detailed description** of the [OpenAPI Specification](./specification/README.md).
+- Understand OpenAPI terminology by referencing the [OpenAPI Glossary](./glossary/README.md).
+- Understand **OpenAPI best practices** by reading our [OpenAPI tips and advice](./tips/README.md).
+- See our detailed **OpenAPI document example** in the [Speakeasy Bar API](./example/README.md).
-An OpenAPI document is made up of a number of different sections, each of which is described in detail below.
+If you have no idea where to start, we recommend working through our [OpenAPI tutorial](./tutorials/README.md) to get the wheels turning.
+
+### Which versions of the OpenAPI Specification does this documentation cover?
+
+This documentation will cover versions `3.0.x` and `3.1.x` of the OpenAPI specification. Where there is an important difference between the two versions, we will call it out specifically, otherwise the documentation will apply to both versions.
+
+## OpenAPI Document Structure
+
+An OpenAPI document is made up of several different sections, each of which is described in detail below.
Example:
@@ -176,41 +217,41 @@ components:
| Field | Type | Required | Description |
| ------------------- | :-------------------------------------------------------------: | :----------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `openapi` | *string* | :heavy_check_mark: | The version of the OpenAPI specification that the document conforms to, this should be one of the [Supported Versions](https://github.com/OAI/OpenAPI-Specification/tree/main/versions) of the OpenAPI specification.
*Note:* Speakeasy tooling currently only supports versions `3.0.x` and `3.1.x` of the OpenAPI specification. |
-| `jsonSchemaDialect` | *string* | :heavy_minus_sign: | **(Available in OpenAPI 3.1.x ONLY)**
The version of the JSON Schema specification that the document conforms to (if not provided by the `$schema` field within a [Schema Object](#schema-object)), this is a URI to one of the [Supported Versions](https://json-schema.org/specification-links.html#published-drafts) of the JSON Schema specification.
*Note:* Currently **not** supported by Speakeasy tooling. |
-| `info` | [Info Object](#info-object) | :heavy_check_mark: | Contains information about the document including fields like `title`, `version`, `description` that help to identify the purpose and owner of the document. |
-| `externalDocs` | [External Documentation Object](#external-documentation-object) | :heavy_minus_sign: | Optional documentation available externally about the API. |
-| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the document (for example: [`x-speakeasy-name-overrides`](https://speakeasyapi.dev/docs/using-speakeasy/create-client-sdks/customize-sdks/methods/#change-method-names) that allows the default generated method names of operations to be overridden) that can be used by tooling and vendors to add additional metadata and functionality to the OpenAPI Specification. When provide at the global level here the extensions generally apply to the entire document. |
-| `servers` | [Servers](#servers) | :heavy_minus_sign: | Contains an optional list of servers the API is available on, if not provided the default URL is assumed to be `/` a path relative to where the OpenAPI document is hosted. |
-| `security` | [Security](#security) | :heavy_minus_sign: | Contains an optional list of security requirements that apply to all operations in the API. If not provided, the default security requirements are assumed to be `[]` an empty array. |
+| `openapi` | String | :heavy_check_mark: | The version of the OpenAPI Specification that the document conforms to, should be one of the [supported versions](https://github.com/OAI/OpenAPI-Specification/tree/main/versions).
**Note:** Speakeasy tooling currently only supports versions `3.0.x` and `3.1.x` of the OpenAPI Specification. |
+| `jsonSchemaDialect` | String | :heavy_minus_sign: | **(Available in OpenAPI 3.1.x ONLY)**
The version of the JSON Schema specification the document conforms to (if not provided by the `$schema` field in a [Schema Object](#schema-object)), in the form of a URI to one of the [supported versions](https://json-schema.org/specification-links.html#published-drafts).
**Note:** Currently **not** supported by Speakeasy tooling. |
+| `info` | [Info Object](#info-object) | :heavy_check_mark: | Contains information about the document including fields like `title`, `version`, and `description` that help to identify the purpose and owner of the document. |
+| `externalDocs` | [External Documentation Object](#external-documentation-object) | :heavy_minus_sign: | Optional documentation about the API available externally. |
+| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the document (for example, [`x-speakeasy-name-overrides`](https://speakeasyapi.dev/docs/using-speakeasy/create-client-sdks/customize-sdks/methods/#change-method-names) that allows the default generated method names of operations to be overridden) that can be used by tooling and vendors to add additional metadata and functionality to the OpenAPI Specification. When provided at the global level, the extensions generally apply to the entire document. |
+| `servers` | [Servers](#servers) | :heavy_minus_sign: | Contains an optional list of servers the API is available on. If not provided, the default URL is assumed to be `/`, a path relative to where the OpenAPI document is hosted. |
+| `security` | [Security](#security) | :heavy_minus_sign: | Contains an optional list of security requirements that apply to all operations in the API. If not provided, the default security requirements are assumed to be `[]`, an empty array. |
| `tags` | [Tags](#tags) | :heavy_minus_sign: | Contains an optional list of tags that are generally used to group or categorize a set of [Operations](#operation-object). |
| `paths` | [Paths Object](#paths-object) | :heavy_minus_sign: | Contains the paths and operations available within the API. |
| `webhooks` | [Webhooks](#webhooks) | :heavy_minus_sign: | **(Available in OpenAPI 3.1.x ONLY)**
Contains an optional list of incoming webhooks that the API consumer can subscribe to. |
| `components` | [Components Object](#components-object) | :heavy_minus_sign: | Contains an optional list of reusable components that can be referenced from other parts of the document. |
-The above order of fields is recommended (but is not required by the OpenAPI specification), as it allows the stage to be set in terms of calling out key information like details about the API, where it is available, what security is required to access it, and then flows into defining the available endpoints before getting into the details of the components that make up the API.
+The above order of fields is recommended (but is not required by the OpenAPI Specification) as it allows the stage to be set in terms of calling out key information like details about the API, where it is available, what security is required to access it, and then flows into defining the available endpoints before getting into the details of the components that make up the API.
-## Format & File Structure
+## Format and File Structure
-An OpenAPI document is either a JSON or YAML file that contains either an entire API definition or a partial definition of an API and/or its components. All fields names in the specification are case sensitive unless otherwise specified.
+An OpenAPI document is a JSON or YAML file that contains either an entire API definition or a partial definition of an API and/or its components. All field names in the specification are case-sensitive unless otherwise specified.
A document can be split into multiple files, and the files can be in different formats. For example, you can have a JSON file that contains the API definition and a YAML file that contains the components, or a collection of files that contain partial definitions of the API and its components.
-Generally the main API definition file is called `openapi.json` or `openapi.yaml`, and the component files are called `components.json` or `components.yaml`, though this is not a requirement.
+Generally, the main API definition file is called `openapi.json` or `openapi.yaml`, and the component files are called `components.json` or `components.yaml`, though this is not a requirement.
Some common organizational patterns for OpenAPI documents are:
- A single file that contains the entire API definition.
- A main file that contains the API definition and a components file that contains the components.
- - This is normally achieved by using the `$ref` keyword to reference the components file from the main file. [Click here for more information on references.](#references)
+ - This is normally achieved by using the `$ref` keyword to reference the components file from the main file. [Click here for more information on references](#references).
- A collection of files that contain partial definitions of the API and its components.
- - Some tools support this pattern by allowing multiple files to be provided others such as the Speakeasy Generator require the individual files to be merged into a single file before being passed to the tool, which can be achieved using Speakeasy's CLI tool. [Click here for more information on Speakeasy's CLI merge tool.](https://speakeasyapi.dev/docs/speakeasy-cli/merge/)
+ - Some tools support this pattern by allowing multiple files to be provided. Others, such as the Speakeasy Generator, require the individual files to be merged into a single file before being passed to the tool, which can be achieved using the Speakeasy CLI tool. [Click here for more information on the Speakeasy CLI merge tool](https://speakeasyapi.dev/docs/speakeasy-cli/merge/).
## Document Schema
### Info Object
-The document's `info` object contains information about the document including fields like `title`, `version`, `description` that help to identify the purpose and owner of the document.
+The document's `info` object contains information about the document, including fields like `title`, `version`, and `description` that help to identify the purpose and owner of the document.
Example:
@@ -233,13 +274,13 @@ info:
| Field | Type | Required | Description |
| ---------------- | :-------------------------------: | :----------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `title` | *string* | :heavy_check_mark: | A name for the API contained within the document. |
-| `version` | *string* | :heavy_check_mark: | The version of this OpenAPI document. *Not* the version of the API or the OpenAPI specification used. This is recommended to be a [Semantic Version.](https://semver.org/) |
-| `summary` | *string* | :heavy_minus_sign: | **(Available in OpenAPI 3.1.x ONLY)**
A short sentence summarizing the API contained with the document. |
-| `description` | *string* | :heavy_minus_sign: | A longer description of the API contained within the document. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
-| `contact` | [Contact Object](#contact-object) | :heavy_minus_sign: | Contact information for the maintainer of the API.
*Note:* Currently not supported by Speakeasy tooling. |
+| `title` | String | :heavy_check_mark: | A name for the API contained within the document. |
+| `version` | String | :heavy_check_mark: | The version of this OpenAPI document, *not* the version of the API or the OpenAPI Specification used. This is recommended to be a [Semantic Version](https://semver.org/). |
+| `summary` | String | :heavy_minus_sign: | **(Available in OpenAPI 3.1.x ONLY)**
A short sentence summarizing the API contained with the document. |
+| `description` | String | :heavy_minus_sign: | A longer description of the API contained within the document. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+| `contact` | [Contact Object](#contact-object) | :heavy_minus_sign: | Contact information for the maintainer of the API.
**Note:** Currently not supported by Speakeasy tooling. |
| `license` | [License Object](#license-object) | :heavy_minus_sign: | The license the API is made available under. |
-| `termsOfService` | *string* | :heavy_minus_sign: | A URL to the terms of service for the API. |
+| `termsOfService` | String | :heavy_minus_sign: | A URL to the terms of service for the API. |
| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the info object that can be used by tooling and vendors to add additional metadata and functionality to the OpenAPI Specification. |
The above order of fields is recommended (but is not required by the OpenAPI specification) as it puts the most important information first and allows the reader to get a quick overview of the document and API.
@@ -250,9 +291,9 @@ Contact information for the maintainer of the API.
| Field | Type | Required | Description |
| ------- | :-----------------------: | :----------------: | ---------------------------------------------------------------------------------------------------------- |
-| `name` | *string* | :heavy_minus_sign: | The name of a contact that could be approached for support for example. |
-| `url` | *string* | :heavy_minus_sign: | A URL to a website or similar providing contact information. |
-| `email` | *string* | :heavy_minus_sign: | An email address for the contact. |
+| `name` | String | :heavy_minus_sign: | The name of a contact that could be approached, for example, for support. |
+| `url` | String | :heavy_minus_sign: | A URL to a website or similar providing contact information. |
+| `email` | String | :heavy_minus_sign: | An email address for the contact. |
| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the contact object that can be used by tooling and vendors. |
#### License Object
@@ -261,14 +302,14 @@ The license the API is made available under.
| Field | Type | Required | Description |
| ------------ | :-----------------------: | :----------------: | ------------------------------------------------------------------------------------------------------------------------------------------- |
-| `name` | *string* | :heavy_check_mark: | The name of the license. |
-| `identifier` | *string* | :heavy_minus_sign: | **(Available in OpenAPI 3.1.x ONLY)**
An [SPDX identifier](https://spdx.org/licenses/) for the license. Provided only if url isn't set. |
-| `url` | *string* | :heavy_minus_sign: | A URL to the license information. Provided only if identifier isn't set. |
+| `name` | String | :heavy_check_mark: | The name of the license. |
+| `identifier` | String | :heavy_minus_sign: | **(Available in OpenAPI 3.1.x ONLY)**
An [SPDX identifier](https://spdx.org/licenses/) for the license. Provided only if `url` isn't set. |
+| `url` | String | :heavy_minus_sign: | A URL to the license information. Provided only if `identifier` isn't set. |
| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the license object that can be used by tooling and vendors. |
-#### SDK Generation
+#### The Info Object in Generated SDKs
-Speakeasy's SDK Generator will use the `info` object to produce code comments and documentation for the generated SDKs. If [External Documentation](#external-documentation-object) is also provided at the document level, this will be included in the generated comments as well.
+The Speakeasy SDK Generator uses the `info` object to produce code comments and documentation for the generated SDKs. If [external documentation](#external-documentation-object) is also provided at the document level, this will be included in the generated comments, too.
For example:
@@ -284,13 +325,13 @@ Allows for providing information about external documentation available for the
| Field | Type | Required | Description |
| ------------- | :-----------------------: | :----------------: | ----------------------------------------------------------------------------------------------------------------------------------------- |
-| `url` | *string* | :heavy_check_mark: | A URL to the external documentation. |
-| `description` | *string* | :heavy_minus_sign: | A description of the external documentation. [CommonMark syntax](https://spec.commonmark.org/) can be used to provide a rich description. |
+| `url` | String | :heavy_check_mark: | A URL to the external documentation. |
+| `description` | String | :heavy_minus_sign: | A description of the external documentation. [CommonMark syntax](https://spec.commonmark.org/) can be used to provide a rich description. |
| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the external documentation object that can be used by tooling and vendors. |
-#### SDK Generation
+#### External Documentation in Generated SDKs
-Speakeasy's SDK Generator will use the `externalDocs` object to produce code comments and documentation for the generated SDKs. This will be included alongside comments for any of the Methods ([Operations](#operation-object)), Classes/Enums ([Object Schemas](#schema-object)) or SDKs ([Tags](#tags)) that reference the `externalDocs` object.
+The Speakeasy SDK Generator uses the `externalDocs` object to produce code comments and documentation for the generated SDKs. These will be included alongside comments for any of the Methods ([Operations](#operation-object)), Classes or Enums ([Object Schemas](#schema-object)), or SDK ([Tags](#tags)) that reference the `externalDocs` object.
For example:
@@ -303,11 +344,11 @@ type Speakeasy struct {
### Servers
-A list of [Server Objects](#server-object) either the entire API or a specific path or operation is available on. Server's can be defined at the [Document](#document-structure) level, the [Path](#paths-object) level, or the [Operation](#operation-object) level.
+A list of [Server Objects](#server-object) that either the entire API or a specific path or operation is available on. Servers can be defined at the [Document](#document-structure) level, the [Path](#paths-object) level, or the [Operation](#operation-object) level.
-Servers are optional in the OpenAPI specification, if not provided the default URL is assumed to be `/` a path relative to where the OpenAPI document is hosted.
+Servers are optional in the OpenAPI specification. If not provided, the default URL is assumed to be `/`, a path relative to where the OpenAPI document is hosted.
-Generally the first server in the list is considered to be the default server to use, with logic to select other servers to use left up to tooling or the API consumer.
+Generally, the first server in the list is considered to be the default server to use, with logic to select other servers to use left up to tooling or the API consumer.
Example:
@@ -319,7 +360,7 @@ servers:
description: The staging server
```
-If a list of servers is provided at the `paths` level, the servers will override any servers provided at the document level. If a list of servers is provided at the `operation` level, the servers will override any servers provided at the `paths` & document levels.
+If a list of servers is provided at the `paths` level, the servers will override any servers provided at the document level. If a list of servers is provided at the `operation` level, the servers will override any servers provided at the `paths` and document levels.
#### Server Object
@@ -327,18 +368,18 @@ A Server Object describes a single server that is available for the API.
| Field | Type | Required | Description |
| ------------- | :-----------------------------------------------: | :----------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `url` | *string* | :heavy_check_mark: | A URL to the server. This can either be a absolute URL or a relative URL to the hosted location of the OpenAPI document. The URL also supports variable substitutions via [Templating](#server-variables--templating) |
-| `description` | *string* | :heavy_minus_sign: | A description of the server. [CommonMark syntax](https://spec.commonmark.org/) can be used to provide a rich description. |
+| `url` | String | :heavy_check_mark: | A URL to the server. This can be an absolute URL or a relative URL to the hosted location of the OpenAPI document. The URL also supports variable substitutions via [Templating](#server-variables--templating). |
+| `description` | String | :heavy_minus_sign: | A description of the server. [CommonMark syntax](https://spec.commonmark.org/) can be used to provide a rich description. |
| `variables` | [Server Variables](#server-variables--templating) | :heavy_minus_sign: | A map of variable names to [Server Variable Objects](#server-variable-object) that can be used for variable substitution via [Templating](#server-variables--templating). |
-| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the server object (for example: [`x-speakeasy-server-id`](https://speakeasyapi.dev/docs/archive/server-urls/#speakeasy-server-extensions) that allows IDs to be assigned to each server for easier selection via Speakeasy's SDKs) that can be used by tooling and vendors. |
+| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the Server Object (for example, [`x-speakeasy-server-id`](https://speakeasyapi.dev/docs/archive/server-urls/#speakeasy-server-extensions) that allows IDs to be assigned to each server for easier selection via Speakeasy SDKs) that can be used by tooling and vendors. |
-If the URL is an absolute path it ***must*** conform to [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) ie `schema://host{:port}{/path}`, and not include the query string and ***must*** be URL encoded (except for the templating delimiters `{}` if not part of the URL).
+If the URL is an absolute path, it ***must*** conform to [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) (`schema://host{:port}{/path}`) and not include the query string, and ***must*** be URL encoded (except for the templating delimiters `{}` if not part of the URL).
-But can also just be a relative path to where the OpenAPI document is hosted ie `/api` which will for a document hosted at `https://speakeasy.bar/openapi.yaml` result in the URL being `https://speakeasy.bar/api`.
+The URL can also be a relative path to where the OpenAPI document is hosted (`/api`). For a document hosted at `https://speakeasy.bar/openapi.yaml`, the resulting URL will be `https://speakeasy.bar/api`.
-The URL may also contain fragments ie `https://speakeasy.bar/drinks#mocktails` and can be used to allow repeated URLs with different fragments to be defined in the same document, allowing the definition of multiple operations with the same URL and HTTP method but different operation definitions.
+The URL may also contain fragments (for example, `https://speakeasy.bar/drinks#mocktails`) allowing for repeated URLs with different fragments to be defined in the same document and the definition of multiple operations with the same URL and HTTP method but different operation definitions.
-For example the below document is not valid as it defines two operations with the same URL and HTTP method:
+For example, the below document is not valid as it defines two operations with the same URL and HTTP method:
```yaml
paths:
@@ -382,7 +423,7 @@ paths:
$ref: "#/components/schemas/Mocktail"
```
-However the below document is valid as it defines two operations with the same URL and HTTP method but different fragments making the paths unique:
+However, the below document is valid as it defines two operations with the same URL and HTTP method but different fragments, making the paths unique:
```yaml
paths:
@@ -426,11 +467,11 @@ paths:
$ref: "#/components/schemas/Mocktail"
```
-*Note:* the above API can also be achieved using [`oneOf`](#oneof) in a single operation definition, but depending on the use case this may not be desirable.
+**Note:** The above API can also be achieved using [`oneOf`](#composition-and-inheritance) in a single operation definition, but depending on the use case, this may not be desirable.
-#### Server Variables & Templating
+#### Server Variables and Templating
-Server variables are a map of variable names (*string*) to [Server Variable Objects](#server-variable-object) that can be used for variable substitution via Templating.
+Server variables are a map of variable names (string) to [Server Variable Objects](#server-variable-object) that can be used for variable substitution via Templating.
Example:
@@ -455,22 +496,22 @@ Any variable delimited by `{}` in the `url` field declares a part of the URL tha
#### Server Variable Object
-A Server Variable Object describes a single variable that is optionally part of the URL in a [Server Object](#server-object). The value of a variable can be any arbitrary *string* value unless a list of allowed values is provided via the `enum` field.
+A Server Variable Object describes a single variable that is optionally part of the URL in a [Server Object](#server-object). The value of a variable can be any arbitrary string value unless a list of allowed values is provided via the `enum` field.
| Field | Type | Required | Description |
| ------------- | :-----------------------: | :----------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `description` | *string* | :heavy_minus_sign: | A description of the variable. [CommonMark syntax](https://spec.commonmark.org/) can be used to provide a rich description. |
-| `default` | *string* | :heavy_check_mark: | The default value of the variable. A variable is always of type *string*. If `enum` is provided this ***must*** be one of the values in the `enum` list. |
-| `enum` | *list\* | :heavy_minus_sign: | A list of allowed *string* values for the variable. |
-| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the server variable object that can be used by tooling and vendors. |
+| `description` | String | :heavy_minus_sign: | A description of the variable. [CommonMark syntax](https://spec.commonmark.org/) can be used to provide a rich description. |
+| `default` | String | :heavy_check_mark: | The default value of the variable. A variable is always of type *string*. If `enum` is provided this ***must*** be one of the values in the `enum` list. |
+| `enum` | List\ | :heavy_minus_sign: | A list of allowed string values for the variable. |
+| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the Server Variable Object that can be used by tooling and vendors. |
-#### SDK Generation
+#### Servers in Generated SDKs
-The Speakeasy SDK Generator generally requires at least one absolute URL to be provided to ensure the out of the box experience is as smooth as possible for developers using the generated SDKs. If not present in the OpenAPI document this can be provided via configuration. [Click here for more details](https://speakeasyapi.dev/docs/using-speakeasy/create-client-sdks/customize-sdks/servers/#declare-base-server-url).
+The Speakeasy SDK Generator generally requires at least one absolute URL to be provided to ensure the out-of-the-box experience is as smooth as possible for developers using the generated SDKs. If not present in the OpenAPI document, an absolute URL can be provided via configuration. [Click here for more details](https://speakeasyapi.dev/docs/using-speakeasy/create-client-sdks/customize-sdks/servers/#declare-base-server-url).
-The generated SDKs will contain a list of available servers that can be used with the SDK. The first server in the list is considered to be the default server to use, and will be used if no other server is provided when initializing the SDK (in the case of global servers) or when using a method (in the case of path or operation servers).
+Generated SDKs will contain a list of available servers that can be used with the SDK. The first server in the list is considered to be the default server to use and will be used if no other server is provided when initializing the SDK (in the case of global servers) or when using a method (in the case of path or operation servers).
-For globals servers some of the generated code will look like:
+For global servers, some of the generated code will look like this:
```go
// speakeasy.go
@@ -513,7 +554,7 @@ func WithServerIndex(serverIndex int) SDKOption {
}
```
-and used like:
+The code above is used like this:
```go
// Create a new Speakeasy SDK Instance using the default server
@@ -558,7 +599,7 @@ s := speakeasy.New(
)
```
-For path and operation servers the default server will be used if no other URL is provided when using a method. For example:
+For path and operation servers, the default server will be used when using a method if no other URL is provided. For example:
```go
// Create a new Speakeasy SDK Instance
@@ -572,7 +613,7 @@ s := speakeasy.New(
res := s.GetDrink(ctx, operations.GetDrinkRequest{ Name: "Old Fashioned" }, operations.WithServerURL("http://localhost:8080"))
```
-The Developer Experience of the SDKs can be improved when providing multiple servers that can be selected by using [`x-speakeasy-server-id`](https://speakeasyapi.dev/docs/archive/server-urls/#speakeasy-server-extensions) to assign IDs to each server. This will allow the generator to instead generate a map of servers and provide methods for selecting a server by ID. For example:
+The developer experience of SDKs can be improved when providing multiple servers that can be selected by using [`x-speakeasy-server-id`](https://speakeasyapi.dev/docs/archive/server-urls/#speakeasy-server-extensions) to assign IDs to each server. This allows the generator to generate a map of servers and provide methods for selecting a server by ID. For example:
```go
// speakeasy.go
@@ -603,7 +644,7 @@ func WithServer(server string) SDKOption {
}
```
-and used like:
+The code above is used like this:
```go
// Create a new Speakeasy SDK Instance using the staging server via ID
@@ -615,7 +656,7 @@ s := speakeasy.New(
)
```
-When server variables are used the SDK Generator will generate methods for setting the values of the variables. For example:
+When server variables are used, the SDK Generator will generate methods for setting the values of the variables. For example:
```go
// speakeasy.go
@@ -680,7 +721,7 @@ func WithOrganization(organization string) SDKOption {
}
```
-and used like:
+This code is used as follows:
```go
// Create a new Speakeasy SDK Instance setting the environment and organization variables
@@ -695,11 +736,11 @@ s := speakeasy.New(
### Security
-`security` is a list of [Security Requirement Objects](#security-requirement-object) that apply to either all operations in the API if defined at the [document](#document-structure) level or to a specific operation if defined at the [Operation](#operation-object) level.
+The `security` section is a list of [Security Requirement Objects](#security-requirement-object) that apply to all operations in the API (if defined at the [document](#document-structure) level) or to a specific operation (if defined at the [operation](#operation-object) level).
-Operation level security requirements override any security requirements defined at the document level.
+Operation-level security requirements override any security requirements defined at the document level.
-If not provided at the document level, the default security requirements are assumed to be `[]` an empty array, meaning no security is required to access the API.
+If not provided at the document level, the default security requirements are assumed to be `[]`, an empty array, meaning no security is required to access the API.
Example:
@@ -714,7 +755,7 @@ components:
in: header
```
-The named security schemes referenced ***must*** be [Security Scheme Object](#security-scheme-object) defined in the [Components Object](#components-object) under the `securitySchemes` field.
+The named security schemes referenced ***must*** be [Security Scheme Objects](#security-scheme-object) defined in the [Components Object](#components-object) under the `securitySchemes` field.
Security can also be made optional by providing an empty object (`{}`) in the list of security requirements. For example:
@@ -756,7 +797,7 @@ paths:
type: string
```
-or made completely optional for a specific operation by providing an empty object (`{}`) in the list of security requirements. For example:
+Security can be made completely optional for a specific operation by providing an empty object (`{}`) in the list of security requirements. For example:
```yaml
paths:
@@ -801,12 +842,12 @@ components:
write: Write access to the API
```
-The above example allows for the API to be accessed via an API Key **OR** OAuth2 with either the `read` or `write` scopes.
+The above example allows for the API to be accessed via an API Key **OR** OAuth2.0 with either the `read` or `write` scopes.
-If multiple schemes are required together then the [Security Requirement Object](#security-requirement-object) can define multiple schemes. For example:
+If multiple schemes are required together, then the [Security Requirement Object](#security-requirement-object) can define multiple schemes. For example:
```yaml
-security: # both apiKey AND basic are required
+security: # both apiKey AND basic is required
- apiKey: []
basic: []
components:
@@ -820,17 +861,17 @@ components:
scheme: basic
```
-The above example requires both an API Key **AND** Basic Auth to be provided.
+The above example requires both an API Key **AND** basic auth to be provided.
This **AND**/**OR** logic along with optional (`{}`) security can be used in any combination to express complex authorization scenarios.
#### Security Requirement Object
-A Security Requirement Object defines a map of security schemes names to scopes that are required to access the API. The names ***must*** match the names of [Security Scheme Objects](#security-scheme-object) defined in the [Components Object](#components-object) under the `securitySchemes` field.
+A Security Requirement Object defines a map of security scheme names to scopes that are required to access the API. The names ***must*** match the names of [Security Scheme Objects](#security-scheme-object) defined in the [Components Object](#components-object) under the `securitySchemes` field.
| Field | Type | Required | Description |
| ---------------------- | :--------------: | :----------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `{securitySchemeName}` | *list\* | :heavy_minus_sign: | A list of scopes/roles required for the security scheme. If the security scheme type is `oauth2` or `openIdConnect`, this is a list of scopes names required by the API consumer to be able to access/use the API, for any other types this could contain a list of roles or similar required for the API consumer to obtain to authenticate with the API. |
+| `{securitySchemeName}` | List\ | :heavy_minus_sign: | A list of scopes/roles required for the security scheme. If the security scheme type is `oauth2` or `openIdConnect`, this is a list of scope names required by the API consumer to be able to access or use the API. For any other type, this could contain a list of roles or similar required for the API consumer to obtain to authenticate with the API. |
#### Security Scheme Object
@@ -849,41 +890,41 @@ components:
scheme: basic
```
-The type field is the overall category of authentication. The value of type determines the other fields the security object needs.
+The `type` field is the overall category of authentication. The value of `type` determines the other fields the security object needs.
-Below are the string fields that do not depend on type and can be used in any security scheme.
+Below are the string fields that do not depend on `type` and can be used in any security scheme.
-Field | Required | Description
----|---|---
-`type` | :heavy_check_mark: | The type of the security scheme.
Allowed values: `apiKey`, `http`, `mutualTLS`, `oauth2`, or `openIdConnect`.
`mutualTLS` is for OpenApi version 3.1 only.
-`description` | | Human readable information. [CommonMark syntax](https://spec.commonmark.org/) may be used.
-`x-...` | | Extension fields
+| Field | Required | Description |
+| ---|---|--- |
+| `type` | :heavy_check_mark: | The type of the security scheme.
Allowed values: `apiKey`, `http`, `mutualTLS`, `oauth2`, or `openIdConnect`.
`mutualTLS` is for OpenAPI version 3.1 only. |
+| `description` | | Human-readable information. [CommonMark syntax](https://spec.commonmark.org/) may be used. |
+| `x-...` | | Extension fields |
To decide which authentication type to choose, please review this [article](https://www.speakeasyapi.dev/post/openapi-tips-auth).
Below are the fields that are required for each value of `type`. They are all strings, except for the OAuth flows, which are discussed in the next section.
-Field | Applies to | Description
----|---|---
-`in:` `query`, `header`, or `cookie` | `type: apiKey` | The location of the API key in the request.
-`name:` | `type: apiKey` | The name of the key parameter in the location.
-`scheme:` `basic`, `bearer`, or `digest` | `type: http` | The name of the HTTP Authorization scheme to be used in the Authorization header. [More values](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml) are theoretically allowed, but not supported in practice.
-`bearerFormat:` | `type: http`
`scheme: bearer` | A hint to the client to identify how the bearer token is formatted. Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes.
-_ | `type: mutualTLS` | No extra fields are required. Mutual TLS means the server will ask the client for a public security certificate after the server has sent its certificate.
-`openIdConnectUrl: https://...` | `type: openIdConnect` | Used to discover configuration values. The URL must point to a JSON OpenID Connect Discovery document.
-`flows:`
`authorizationCode: ...`
`clientCredentials: ...`
`implicit: ...`
`password: ...` | `type: oauth2` | Flows is an object containing four possible authentication flow objects. At least one must be present and you can use all four. The structure of a flow is detailed in the next section.
+| Field | Applies to | Description |
+| ---|---|--- |
+| `in:` (`query`, `header`, or `cookie`) | `type: apiKey` | The location of the API key in the request. |
+| `name:` | `type: apiKey` | The name of the key parameter in the location. |
+| `scheme:` (`basic`, `bearer`, or `digest`) | `type: http` | The name of the HTTP authorization scheme to be used in the Authorization header. [More values](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml) are theoretically allowed, but not supported in practice. |
+| `bearerFormat:` | `type: http`
`scheme: bearer` | A hint to the client to identify how the bearer token is formatted. Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation purposes. |
+| _ | `type: mutualTLS` | No extra fields are required. Mutual TLS means the server will ask the client for a public security certificate after the server has sent its certificate. |
+| `openIdConnectUrl: https://...` | `type: openIdConnect` | Used to discover configuration values. The URL must point to a JSON OpenID Connect Discovery document. |
+| `flows:`
`authorizationCode: ...`
`clientCredentials: ...`
`implicit: ...`
`password: ...` | `type: oauth2` | The `flows` object contains four possible authentication flow objects. At least one must be present and you can use all four. The structure of a flow is detailed in the next section. |
-#### OAuth2 Flow Object
+#### OAuth2.0 Flow Object
-Below are the required fields comprising a flow object used as a value for `flows: ...`.
+Below are the required fields comprising a flow object used as a **value** for `flows: ...`.
-Field | Applies to | Description | Required
----|---|---|---
-`scopes` | All flows | The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. The map may be empty. | :heavy_check_mark:
-`authorizationUrl` | `flows:` `implicit` or `authorizationCode` | The authorization URL to be used for this flow. E.g. `https://...` | :heavy_check_mark:
-`tokenUrl` | `flows:` `authorizationCode`, `clientCredentials`, or `password` | The token URL to be used for this flow. E.g. `https://...` | :heavy_check_mark:
-`refreshUrl` | All flows | The URL to be used for obtaining refresh tokens. E.g. `https://...` |
-`x-...` | Extension fields | |
+| Field | Applies to | Description | Required |
+| ---|---|---|--- |
+| `scopes` | All flows | The available scopes for the OAuth2.0 security scheme. A map between the scope name and a short description of it. The map may be empty. | :heavy_check_mark: |
+| `authorizationUrl` | `flows:`, `implicit`, or `authorizationCode` | The authorization URL to be used for this flow, for example, `https://...` | :heavy_check_mark: |
+| `tokenUrl` | `flows:`, `authorizationCode`, `clientCredentials`, or `password` | The token URL to be used for this flow, for example, `https://...` | :heavy_check_mark: |
+| `refreshUrl` | All flows | The URL to be used for obtaining refresh tokens, for example, `https://...` | |
+| `x-...` | Extension fields | | |
#### Example Security Scheme Schema
@@ -964,11 +1005,11 @@ components:
refreshUrl: https://test.com/oauth/refresh
```
-#### SDK Generation
+#### Security Schemes in Generated SDKs
-Speakeasy does not support mutualTLS, the HTTP digest security type, and some programming languages and flows for OAuth. For details, please see this [article](https://www.speakeasyapi.dev/docs/customize-sdks/authentication). Using OAuth requires you to [write your own callback function](https://www.speakeasyapi.dev/docs/customize-sdks/authentication#step-2-add-your-callback-function-to-your-sdks).
+Speakeasy does not support `mutualTLS`, the HTTP digest security type, and some programming languages and flows for OAuth. For details, please see this [article](https://www.speakeasyapi.dev/docs/customize-sdks/authentication). Using OAuth requires you to [write your own callback function](https://www.speakeasyapi.dev/docs/customize-sdks/authentication#step-2-add-your-callback-function-to-your-sdks).
-Below is a list showing how to call each supported authentication shown in the previous section's example schema, once Speakeasy has created an SDK:
+Below is a list showing how to call each supported authentication type illustrated in the previous section's example schema once Speakeasy has created an SDK:
- auth1 — apiKey · query
@@ -976,18 +1017,21 @@ Below is a list showing how to call each supported authentication shown in the p
const operationSecurity: Drinks1Security = "";
const result = await sdk.drinks1(operationSecurity);
```
+
- auth2 — apiKey · header
```ts
const operationSecurity: Drinks2Security = "";
const result = await sdk.drinks2(operationSecurity);
```
+
- auth3 — apiKey · cookie
```ts
const operationSecurity: Drinks3Security = "";
const result = await sdk.drinks3(operationSecurity);
```
+
- auth4 — http · basic
```ts
@@ -997,12 +1041,14 @@ Below is a list showing how to call each supported authentication shown in the p
};
const result = await sdk.drinks4(operationSecurity);
```
+
- auth5 — http · bearer
```ts
const operationSecurity: Drinks5Security = "";
const result = await sdk.drinks5(operationSecurity);
```
+
- auth6 — openIdConnect
```ts
@@ -1011,6 +1057,7 @@ Below is a list showing how to call each supported authentication shown in the p
});
const result = await sdk.drinks6();
```
+
- auth7 — oauth2
```ts
@@ -1019,7 +1066,7 @@ Below is a list showing how to call each supported authentication shown in the p
// custom work to be done: https://www.speakeasyapi.dev/docs/customize-sdks/authentication#step-2-add-your-callback-function-to-your-sdks
```
-Depending on whether global or operation level security is used, the Speakeasy SDK Generator will generate the correct code to handle the security requirements.
+Depending on whether global- or operation-level security is used, the Speakeasy SDK Generator will generate the correct code to handle the security requirements.
For global security requirements, the generator may generate code like the following, which is used when configuring the SDK instance:
@@ -1077,7 +1124,7 @@ type Security struct {
}
```
-and used like:
+The above is used like this:
```go
// Create a new Speakeasy SDK Instance
@@ -1088,7 +1135,7 @@ s := speakeasy.New(
)
```
-For operation level security requirements the generator may generate code like the following which is used when calling a method:
+For operation-level security requirements, the generator may generate code like the following, which is used when calling a method:
```go
// drinks.go
@@ -1099,7 +1146,7 @@ func (s *drinks) GetDrink(ctx context.Context, request operations.GetDrinkReques
}
```
-and used like:
+The above is used like this:
```go
// Create a new Speakeasy SDK Instance
@@ -1112,9 +1159,9 @@ res := s.Drinks.GetDrink(ctx, operations.GetDrinkRequest{Name: "Long Island Ice
### Tags
-The document-level `tags` field contains a list of [tag](#tag-object) definitions that may be used to categorize or group operations in the API. Tags can be referenced by [Operations](#operation-object) via the operations-level `tags` field.
+The document-level `tags` field contains a list of [tag](#tag-object) definitions that may be used to categorize or group operations in the API. Tags can be referenced by [operations](#operation-object) via the operations-level `tags` field.
-Tag definitions at the document level are optional, even if an undefined tag is referenced within an [Operation](#operation-object), but it is recommended that all tags used are defined here to provide useful documentation and intent for the tags.
+Tag definitions at the document level are optional, even if an undefined tag is referenced in an [operation](#operation-object), but it is recommended that all tags used are defined here to provide useful documentation and intent for the tags.
Tag names ***must*** be unique in the document.
@@ -1134,8 +1181,8 @@ A Tag Object defines a single tag that can be used to categorize or group operat
| Field | Type | Required | Description |
| -------------- | :-------------------------------------------------------------: | :----------------: | --------------------------------------------------------------------------------------------------------------------------- |
-| `name` | *string* | :heavy_check_mark: | The name of the tag. ***Must*** be unique in the document. |
-| `description` | *string* | :heavy_minus_sign: | A description of the tag. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+| `name` | String | :heavy_check_mark: | The name of the tag. ***Must*** be unique in the document. |
+| `description` | String | :heavy_minus_sign: | A description of the tag. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
| `externalDocs` | [External Documentation Object](#external-documentation-object) | :heavy_minus_sign: | Additional external documentation for this tag. |
| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the tag object that can be used by tooling and vendors. |
@@ -1160,11 +1207,11 @@ The created TypeScript can be called like this:
await sdk.drinks.listDrinks(type);
```
-##### x-speakeasy-group
+##### The x-speakeasy-group extension
Add the `x-speakeasy-group` field to an endpoint to tell Speakeasy to ignore the endpoint's tag and group it under the custom group instead.
-For example, if you add x-speakeasy-group to the drinks endpoint, the YAML will look like this:
+For example, if you add `x-speakeasy-group` to the `drinks` endpoint, the YAML will look like this:
```yaml
paths:
@@ -1183,13 +1230,14 @@ The created TypeScript can now be called like this:
await sdk.beverages.listDrinks(type);
```
-You will no longer be able to use the code below, even though the tag for drinks is still there:
+You will no longer be able to use the code below, even though the tag for `drinks` is still there:
```ts
await sdk.drinks.listDrinks(type);
```
##### Multiple Namespaces
+
If you want to add a method to multiple namespaces, list multiple values in tags or the `x-speakeasy-group` extension. Both accept an array of values:
```yaml
@@ -1202,7 +1250,7 @@ paths:
- beverages
```
-You can call either:
+You can call either of the following:
```ts
await sdk.drinks.listDrinks(type);
@@ -1210,6 +1258,7 @@ await sdk.beverages.listDrinks(type);
```
##### Define Multi-Level Namespaces
+
You can use tags or the `x-speakeasy-group` extension to define nested namespaces for your operations using `.` notation. There is no limit to the number of levels you can define.
For instance:
@@ -1233,9 +1282,9 @@ Note that the files `drinks.ts`, `wine.ts`, and `champagne.ts` will be created,
### Paths Object
-The `paths` object is a map of [Path Item Objects](#path-item-object) that describe the available paths and operations for the API.
+The `paths` object is a map of [Path Item Objects](#path-item-object) that describes the available paths and operations for the API.
-Each path is a relative path to the servers defined in the [Servers](#servers) object, either at the document level, path or operation level. For example if a server is defined as `https://speakeasy.bar/api` and a path is defined as `/drinks` the full URL to the path would be `https://speakeasy.bar/api/drinks`, where the path is appended to the server URL.
+Each path is a relative path to the servers defined in the [Servers](#servers) object, either at the document, path, or operation level. For example, if a server is defined as `https://speakeasy.bar/api` and a path is defined as `/drinks`, the full URL to the path would be `https://speakeasy.bar/api/drinks`, where the path is appended to the server URL.
Example:
@@ -1257,16 +1306,16 @@ paths:
| Field | Type | Required | Description |
| --------- | :-----------------------------------: | :----------------: | -------------------------------------------------------------------------------------------------------- |
-| `/{path}` | [Path Item Object](#path-item-object) | :heavy_minus_sign: | A relative path to an individual endpoint, where the path ***must*** begin with a `/` |
+| `/{path}` | [Path Item Object](#path-item-object) | :heavy_minus_sign: | A relative path to an individual endpoint, where the path ***must*** begin with a `/`. |
| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the paths object that can be used by tooling and vendors. |
#### Path Item Object
-A Path Item Object describes the operations available on a single path, this is generally a map of HTTP methods to [Operation Objects](#operation-object) that describe the operations available.
+A Path Item Object describes the operations available on a single path. This is generally a map of HTTP methods to [Operation Objects](#operation-object) that describe the operations available.
-It is also possible to override the [Servers](#servers) defined at the document level for a specific path by providing a list of [Server Objects](#server-object) at the path level.
+It is possible to override the [Servers](#servers) defined at the document level for a specific path by providing a list of [Server Objects](#server-object) at the path level.
-And to provide a list of [Parameters](#parameters) that are common to all operations defined on the path.
+It is also possible to provide a list of [Parameters](#parameters) that are common to all operations defined on the path.
Example:
@@ -1294,7 +1343,7 @@ paths:
... # operation definition
```
-or
+Or:
```yaml
paths:
@@ -1324,26 +1373,28 @@ components:
| Field | Type | Required | Description |
| ------------- | :-----------------------------------: | :----------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `$ref` | *string* | :heavy_minus_sign: | Allows for referencing a [Path Item Object](#path-item-object) defined in the [Components Object](#components-object) under the `pathItems` field. If used then no other fields should be set. |
-| `summary` | *string* | :heavy_minus_sign: | A short summary of what the path item represents. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
-| `description` | *string* | :heavy_minus_sign: | A description of the path item. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
-| `servers` | [Servers](#servers) | :heavy_minus_sign: | A list of [Server Objects](#server-object) that override the servers defined at the document level, and applies to all operations defined on this path. |
+| `$ref` | String | :heavy_minus_sign: | Allows for referencing a [Path Item Object](#path-item-object) defined in the [Components Object](#components-object) under the `pathItems` field. If used, no other fields should be set. |
+| `summary` | String | :heavy_minus_sign: | A short summary of what the path item represents. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+| `description` | String | :heavy_minus_sign: | A description of the path item. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+| `servers` | [Servers](#servers) | :heavy_minus_sign: | A list of [Server Objects](#server-object) that override the servers defined at the document level. Applies to all operations defined on this path. |
| `parameters` | [Parameters](#parameters) | :heavy_minus_sign: | A list of [Parameter Objects](#parameter-object) that are common to all operations defined on this path. |
-| `get` | [Operation Object](#operation-object) | :heavy_minus_sign: | A operation associated with the [`GET` HTTP method.](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) |
-| `put` | [Operation Object](#operation-object) | :heavy_minus_sign: | A operation associated with the [`PUT` HTTP method.](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) |
-| `post` | [Operation Object](#operation-object) | :heavy_minus_sign: | A operation associated with the [`POST` HTTP method.](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) |
-| `delete` | [Operation Object](#operation-object) | :heavy_minus_sign: | A operation associated with the [`DELETE` HTTP method.](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE) |
-| `options` | [Operation Object](#operation-object) | :heavy_minus_sign: | A operation associated with the [`OPTIONS` HTTP method.](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS) |
-| `head` | [Operation Object](#operation-object) | :heavy_minus_sign: | A operation associated with the [`HEAD` HTTP method.](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) |
-| `patch` | [Operation Object](#operation-object) | :heavy_minus_sign: | A operation associated with the [`PATCH` HTTP method.](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) |
-| `trace` | [Operation Object](#operation-object) | :heavy_minus_sign: | A operation associated with the [`TRACE` HTTP method.](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/TRACE) |
-| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the path item object that can be used by tooling and vendors. |
-
-The above order is a recommendation for how the fields should be ordered, but is not significant to the order in which the endpoints should be used.
+| `get` | [Operation Object](#operation-object) | :heavy_minus_sign: | An operation associated with the [`GET` HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET). |
+| `put` | [Operation Object](#operation-object) | :heavy_minus_sign: | An operation associated with the [`PUT` HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT). |
+| `post` | [Operation Object](#operation-object) | :heavy_minus_sign: | An operation associated with the [`POST` HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST). |
+| `delete` | [Operation Object](#operation-object) | :heavy_minus_sign: | An operation associated with the [`DELETE` HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE). |
+| `options` | [Operation Object](#operation-object) | :heavy_minus_sign: | An operation associated with the [`OPTIONS` HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS). |
+| `head` | [Operation Object](#operation-object) | :heavy_minus_sign: | An operation associated with the [`HEAD` HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD). |
+| `patch` | [Operation Object](#operation-object) | :heavy_minus_sign: | An operation associated with the [`PATCH` HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH). |
+| `trace` | [Operation Object](#operation-object) | :heavy_minus_sign: | An operation associated with the [`TRACE` HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/TRACE). |
+| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the Path Item Object that can be used by tooling and vendors. |
+
+The order of fields above is recommended but is not significant to the order in which the endpoints should be used.
### Webhooks
-**(Available in OpenAPI 3.1.x ONLY)** Webhooks represents a possible list of incoming requests that form part of the documented API, that a consumer can subscribe to.
+**(Available in OpenAPI 3.1.x ONLY)**
+
+Webhooks represent a possible list of incoming requests that form part of the documented API that a consumer can subscribe to.
Webhooks are represented by a map of [Path Item Objects](#path-item-object) or [OpenAPI Reference Objects](#openapi-reference-object) that are keyed by the unique name of the webhook.
@@ -1354,7 +1405,7 @@ webhooks:
stockUpdate:
post:
summary: Receive stock updates.
- description: Receive stock updates from the bar, this will be called whenever the stock levels of a drink or ingredient changes.
+ description: Receive stock updates from the bar, this will be called whenever the stock levels of a drink or ingredient change.
tags:
- drinks
- ingredients
@@ -1384,21 +1435,23 @@ The Components Object is a container for reusable objects that can be referenced
| Field | Type | Required | Description |
| ----------------- | :-----------------------------------------------------------------------------------------------------------------------: | :----------------: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `schemas` | *map[string, [Schema Object](#schema-object)]* | :heavy_minus_sign: | A map of [Schema Objects](#schema-object) that can be referenced by other parts of the API.
**Note: OpenAPI `3.0.X` does support [OpenAPI Reference Objects](#openapi-reference-object) here as the value, but `3.1.x` uses the [JSON Schema Referencing](#json-schema-reference-object) format.** |
-| `securitySchemes` | *map[string, [Security Scheme Object](#security-scheme-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Security Scheme Objects](#security-scheme-object) that can be referenced by other parts of the API. |
-| `pathItems` | *map[string, [Path Item Object](#path-item-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Path Item Objects](#path-item-object) that can be referenced by other parts of the API. |
-| `parameters` | *map[string, [Parameter Object](#parameter-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Parameter Objects](#parameter-object) that can be referenced by other parts of the API. |
-| `requestBodies` | *map[string, [Request Body Object](#request-body-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Request Body Objects](#request-body-object) that can be referenced by other parts of the API. |
-| `responses` | *map[string, [Response Object](#response-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Response Objects](#response-object) that can be referenced by other parts of the API. |
-| `headers` | *map[string, [Header Object](#header-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Header Objects](#header-object) that can be referenced by other parts of the API. |
-| `examples` | *map[string, [Example Object](#example-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Example Objects](#example-object) that can be referenced by other parts of the API. |
-| `callbacks` | *map[string, [Callback Object](#callback-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Callback Objects](#callback-object) that can be referenced by other parts of the API. |
-| `links` | *map[string, [Link Object](#link-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Link Objects](#link-object) that can be referenced by other parts of the API. |
-| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the components object that can be used by tooling and vendors. |
+| `schemas` | Map[string, [Schema Object](#schema-object)]* | :heavy_minus_sign: | A map of [Schema Objects](#schema-object) that can be referenced by other parts of the API.
**Note: OpenAPI 3.0.x does support [OpenAPI Reference Objects](#openapi-reference-object) as the value here, but `3.1.x` uses the [JSON Schema Referencing](#json-schema-references) format.** |
+| `securitySchemes` | Map[string, [Security Scheme Object](#security-scheme-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Security Scheme Objects](#security-scheme-object) that can be referenced by other parts of the API. |
+| `pathItems` | Map[string, [Path Item Object](#path-item-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Path Item Objects](#path-item-object) that can be referenced by other parts of the API. |
+| `parameters` | Map[string, [Parameter Object](#parameter-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Parameter Objects](#parameter-object) that can be referenced by other parts of the API. |
+| `requestBodies` | Map[string, [Request Body Object](#request-body-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Request Body Objects](#request-body-object) that can be referenced by other parts of the API. |
+| `responses` | Map[string, [Response Object](#response-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Response Objects](#response-object) that can be referenced by other parts of the API. |
+| `headers` | Map[string, [Header Object](#header-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Header Objects](#header-object) that can be referenced by other parts of the API. |
+| `examples` | Map[string, [Example Object](#example-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Example Objects](#example-object) that can be referenced by other parts of the API. |
+| `callbacks` | Map[string, [Callback Object](#callback-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Callback Objects](#callback-object) that can be referenced by other parts of the API. |
+| `links` | Map[string, [Link Object](#link-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | A map of [Link Objects](#link-object) that can be referenced by other parts of the API. |
+| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the Components Object that can be used by tooling and vendors. |
## Operation Object
-An Operation describes a single endpoint within the API, including all its possible inputs/outputs and configuration required to make a successful request.
+An operation object describes a single API operation within a path, including all its possible inputs and outputs and the configuration required to make a successful request.
+
+Each operation object corresponds to an HTTP verb, such as `get`, `post`, or `delete`.
Example:
@@ -1406,6 +1459,7 @@ Example:
paths:
/drinks:
get:
+ # The Operation Object
operationId: listDrinks
summary: Get a list of drinks.
description: Get a list of drinks, if authenticated this will include stock levels and product codes otherwise it will only include public information.
@@ -1433,19 +1487,19 @@ paths:
| Field | Type | Required | Description |
| ------------- | :-----------------------------------------: | :----------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `operationId` | *string* | :heavy_minus_sign: | A unique identifier for the operation, this ***must*** be unique within the document, and is ***case sensitive***. It is ***recommended*** to always define an `operationId`, but is not required. |
-| `deprecated` | *boolean* | :heavy_minus_sign: | Whether the operation is deprecated or not. Defaults to `false`. |
-| `summary` | *string* | :heavy_minus_sign: | A short summary of what the operation does. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
-| `description` | *string* | :heavy_minus_sign: | A details description of the operation, what it does and how to use it. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
-| `servers` | [Servers](#servers) | :heavy_minus_sign: | A list of [Server Objects](#server-object) that override the servers defined at the document and path level, and apply to this operation. |
-| `security` | [Security](#security) | :heavy_minus_sign: | A list of [Security Requirement Objects](#security-requirement-object) that override the security requirements defined at the document and path levels, and apply to this operation. |
+| `operationId` | String | :heavy_minus_sign: | A unique identifier for the operation, this ***must*** be unique within the document, and is ***case sensitive***. It is ***recommended*** to always define an `operationId`, but is not required. |
+| `deprecated` | Boolean | :heavy_minus_sign: | Whether the operation is deprecated or not. Defaults to `false`. |
+| `summary` | String | :heavy_minus_sign: | A short summary of what the operation does. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+| `description` | String | :heavy_minus_sign: | A detailed description of the operation, what it does, and how to use it. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+| `servers` | [Servers](#servers) | :heavy_minus_sign: | A list of [Server Objects](#server-object) that override the servers defined at the document and path levels and apply to this operation. |
+| `security` | [Security](#security) | :heavy_minus_sign: | A list of [Security Requirement Objects](#security-requirement-object) that override the security requirements defined at the document and path levels and apply to this operation. |
| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the operation object that can be used by tooling and vendors. |
| `parameters` | [Parameters](#parameters) | :heavy_minus_sign: | A list of [Parameter Objects](#parameter-object) that are available to this operation. The parameters defined here merge with any defined at the path level, overriding any duplicates. |
-| `requestBody` | [Request Body Object](#request-body-object) | :heavy_minus_sign: | The request body for this operation, where the [HTTP Method supports](https://httpwg.org/specs/rfc7231.html) a request body otherwise this field is ignored. |
+| `requestBody` | [Request Body Object](#request-body-object) | :heavy_minus_sign: | The request body for this operation where the [HTTP method supports a request body](https://httpwg.org/specs/rfc7231.html). Otherwise, this field is ignored. |
| `responses` | [Responses](#responses) | :heavy_check_mark: | A map of [Response Objects](#response-object) that define the possible responses from executing this operation. |
| `callbacks` | [Callbacks](#callbacks) | :heavy_minus_sign: | A map of [Callback Objects](#callback-object) that define possible callbacks that may be executed as a result of this operation. |
-The above order of fields is a recommendation for how the fields should be defined in the document, and help to set the stage for the operation, and provide a clear understanding of what the operation does.
+The above order of fields is recommended for defining the fields in the document to help set the stage for the operation and provide a clear understanding of what it does.
### Request Body Object
@@ -1453,24 +1507,24 @@ The request body is used to describe the body of the request for operations that
| Field | Type | Required | Description |
| ------------- | :-----------------------: | :----------------: | ------------------------------------------------------------------------------------------------------------------------------------ |
-| `description` | *string* | :heavy_minus_sign: | A description of the request body. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
-| `content` | [Content](#content) | :heavy_check_mark: | A map of [Media Type Objects](#media-type-object) that define the possible media types that can be used for the request body. |
-| `required` | *boolean* | :heavy_minus_sign: | Whether the request body is required or not. Defaults to `false`. |
-| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the request body object that can be used by tooling and vendors. |
+| `description` | String | :heavy_minus_sign: | A description of the request body. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+| `content` | [Content](#content) | :heavy_check_mark: | A map of [Media Type Objects](#media-type-object) that defines the possible media types that can be used for the request body. |
+| `required` | Boolean | :heavy_minus_sign: | Whether the request body is required. Defaults to `false`. |
+| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the Request Body Object that can be used by tooling and vendors. |
### Responses
-The Responses object is a map of [Response Objects](#response-object) or [References](#references) to [Response Objects](#response-object) that define the possible responses that can be returned from executing the operation.
+The Responses Object is a map of [Response Objects](#response-object) or [References](#references) to [Response Objects](#response-object) that define the possible responses that can be returned from executing the operation.
The keys in the map represent any known HTTP status codes that the API may return. The HTTP status codes can be defined like below:
-- Numeric Status Code - ie `200`, `404` or `500` etc. HTTP status codes defined in [RFC 9110](https://httpwg.org/specs/rfc9110.html#overview.of.status.codes).
-- Status Code Wildcards - ie `1XX`, `2XX`, `3XX`, `4XX` or `5XX` etc. A wildcard that matches any status code in the range of its significant digit, for example `2XX` represents status codes `200` to `299` inclusive.
-- `default` - A catch all identifier for any other status codes not defined in the map.
+- Numeric Status Code - for example, `200`, `404`, or `500`. HTTP status codes are defined in [RFC 9110](https://httpwg.org/specs/rfc9110.html#overview.of.status.codes).
+- Status Code Wildcards - for example, `1XX`, `2XX`, `3XX`, `4XX`, or `5XX`. A wildcard that matches any status code in the range of its significant digit, for example, `2XX` represents status codes `200` to `299` inclusive.
+- `default` - A catch-all identifier for any other status codes not defined in the map.
The map ***must*** contain at least one successful response code.
-All values ***must*** be defined as explicit strings ie `"200"` to allow for compatibility between JSON and YAML.
+All values ***must*** be defined as explicit strings (for example,`"200"`) to allow for compatibility between JSON and YAML.
For example:
@@ -1521,15 +1575,15 @@ The Response Object describes a single response that can be returned from execut
| Field | Type | Required | Description |
| ------------- | :-----------------------: | :----------------: | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `description` | *string* | :heavy_check_mark: | A description of the response. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
-| `headers` | [Headers](#headers) | :heavy_minus_sign: | A map of [Header Objects](#header-object) that define the headers that can be returned from executing this operation. |
-| `content` | [Content](#content) | :heavy_minus_sign: | A map of [Media Type Objects](#media-type-object) that define the possible media types that can be returned from executing this operation. |
+| `description` | String | :heavy_check_mark: | A description of the response. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+| `headers` | [Headers](#headers) | :heavy_minus_sign: | A map of [Header Objects](#header-object) that defines the headers that can be returned from executing this operation. |
+| `content` | [Content](#content) | :heavy_minus_sign: | A map of [Media Type Objects](#media-type-object) that defines the possible media types that can be returned from executing this operation. |
| `links` | [Links](#links) | :heavy_minus_sign: | A map of [Link Objects](#link-object) or [References](#references) that define the possible links that can be returned from executing this operation. |
| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the response object that can be used by tooling and vendors. |
#### Links
-The Links object is a map of [Link Objects](#link-object) or [References](#references) to [Link Objects](#link-object) that allow for describing possible API usage scenarios between different operations. For example if a response returns a `Drink` object, and the `Drink` object has a `ingredients` property that is a list of `Ingredient` objects, then a link can be defined to the `listIngredients` operation showing how the ingredients can be used as an input to the `listIngredients` operation.
+The Links object is a map of [Link Objects](#link-object) or [References](#references) to [Link Objects](#link-object) that allows for describing possible API-use scenarios between different operations. For example, if a response returns a `Drink` object, and the `Drink` object has an `ingredients` property that is a list of `Ingredient` objects, then a link can be defined to the `listIngredients` operation showing how the ingredients can be used as an input to the `listIngredients` operation.
For example:
@@ -1600,15 +1654,15 @@ The Link Object represents a possible link that can be followed from the respons
| Field | Type | Required | Description |
| -------------- | :-----------------------------------------------: | :----------------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `operationId` | *string* | :heavy_check_mark: | The `operationId` of an [Operation](#operation-object) that exists in the document. Use either this field or the `operationRef` field not both. |
-| `operationRef` | *string* | :heavy_check_mark: | Either a [Relative Reference](#references) or [Absolute Reference](#references) to an [Operation](#operation-object) that exists in the document. Use either this field or the `operationId` field not both. |
-| `description` | *string* | :heavy_minus_sign: | A description of the link and intentions for it use. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
-| `parameters` | *map[string, any \| [{Expression}](#expression)]* | :heavy_minus_sign: | A map of parameters to pass to the linked operation. The key is the name of the parameter and the value is either a constant value or an [Expression](#expression) that will be evaluated.
The parameter name can also be qualified with the location of the parameter, for example `path.parameter_name` or `query.parameter_name` |
-| `requestBody` | *any \| [{Expression}](#expression)* | :heavy_minus_sign: | A constant value or [Expression](#expression) that will be used as the request body when calling the linked operation. |
+| `operationId` | String | :heavy_check_mark: | The `operationId` of an [operation](#operation-object) that exists in the document. Use either this field or the `operationRef` field, not both. |
+| `operationRef` | String | :heavy_check_mark: | Either a [Relative Reference](#references) or [Absolute Reference](#references) to an [operation](#operation-object) that exists in the document. Use either this field or the `operationId` field, not both. |
+| `description` | String | :heavy_minus_sign: | A description of the link and intentions for its use. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+| `parameters` | Map[string, any \| [{Expression}](#expression)]* | :heavy_minus_sign: | A map of parameters to pass to the linked operation. The key is the name of the parameter and the value is either a constant value or an [Expression](#expression) that will be evaluated.
The parameter name can also be qualified with the location of the parameter, for example, `path.parameter_name` or `query.parameter_name` |
+| `requestBody` | Any \| [{Expression}](#expression) | :heavy_minus_sign: | A constant value or [Expression](#expression) that will be used as the request body when calling the linked operation. |
| `server` | [Server Object](#server-object) | :heavy_minus_sign: | An optional server to be used by the linked operation. |
| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the link object that can be used by tooling and vendors. |
-OperationRef Example:
+An example of `OperationRef`:
```yaml
links:
@@ -1632,7 +1686,7 @@ A map of header names to [Header Objects](#header-object) or [References](#refer
In this simplified example, the server returns three [Header Objects](#header-object) with the names `X-RateLimit-Remaining`, `Last-Modified`, and `Cache-Control`:
-```
+```yaml
paths:
/drinks/{productCode}:
get:
@@ -1670,18 +1724,18 @@ The name of a header is determined by the header's key in a `headers` map.
| Field | Type | Required | Description |
| ------------- | ------------------------------------------------------ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `description` | *string* | :heavy_minus_sign: | A description of the header. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
-| `required` | *boolean* | :heavy_minus_sign: | Whether the header is required or not. Defaults to `false`. |
-| `deprecated` | *boolean* | :heavy_minus_sign: | Whether the header is deprecated or not. Defaults to `false`. |
-| `schema` | [Schema Object](#schema-object) | :heavy_minus_sign: | A schema or reference to a schema that defines the type of the header. This is ***required*** unless `content` is defined.
**Note: OpenAPI `3.0.X` does support [OpenAPI Reference Objects](#openapi-reference-object) here as the value, but `3.1.x` uses the [JSON Schema Referencing](#json-schema-reference-object) format.** |
-| `content` | *map[string, [Media Type Object](#media-type-object)]* | :heavy_minus_sign: | A map of [Media Type Objects](#media-type-object) that define the possible media types that can be used for the header. This is ***required*** unless `schema` is defined. |
-| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the header object for use by tooling and vendors. |
+| `description` | String | :heavy_minus_sign: | A description of the header. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+| `required` | Boolean | :heavy_minus_sign: | Whether the header is required. Defaults to `false`. |
+| `deprecated` | Boolean | :heavy_minus_sign: | Whether the header is deprecated. Defaults to `false`. |
+| `schema` | [Schema Object](#schema-object) | :heavy_minus_sign: | A schema or reference to a schema that defines the type of the header. This is ***required*** unless `content` is defined.
**Note: OpenAPI 3.0.x supports [OpenAPI Reference Objects](#openapi-reference-object) here as a value. OpenAPI 3.1.x uses the [JSON Schema Referencing](#json-schema-references) format.** |
+| `content` | Map[string, [Media Type Object](#media-type-object)] | :heavy_minus_sign: | A map of [Media Type Objects](#media-type-object) that define the possible media types that can be used for the header. This is ***required*** unless `schema` is defined. |
+| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the header object to be used by tooling and vendors. |
### Callbacks
-A map of [Callback Objects](#callback-object) or [References](#references) that define incoming requests that may be triggered by the parent operation, and the expected responses to be returned. The key is a unique identifier for the collection of callbacks contained within.
+A map of [Callback Objects](#callback-object) or [References](#references) that define incoming requests that may be triggered by the parent operation and the expected responses to be returned. The key is a unique identifier for the collection of callbacks contained within.
-**Note: Callbacks are only valid on operations that also pass the required URL to call the callback on, in either the parameters or the request body of the parent operation. In the event that a request from the API is sent in reaction to calling the parent operation but the callback URL is provided elsewhere, use [Webhooks](#webhooks) to document the callback instead (Webhooks only available in `3.1.x`)**
+**Note: Callbacks are only valid on operations that also pass the required URL to call the callback on, in either the parameters or the request body of the parent operation. In the event that a request from the API is sent in reaction to calling the parent operation but the callback URL is provided elsewhere, use [webhooks](#webhooks) to document the callback instead (webhooks only available in OpenAPI 3.1.x)**
For example:
@@ -1745,9 +1799,9 @@ For example:
#### Callback Object
-A map of [Runtime Expressions](#expression) (that represent a URL the callback request is sent to) to a [Path Item Object](#path-item-object) or [Reference](#references) that defines a request to be initiated by the API provider and a potential response to be returned.
+A map of [Runtime Expressions](#expression) (that represent URLs the callback request is sent to) to a [Path Item Object](#path-item-object) or [Reference](#references) that defines a request to be initiated by the API provider and a potential response to be returned.
-The expression when evaluated at runtime will resolve to a URL either represented in the parameters, request body or response body of the parent operation.
+The expression when evaluated at runtime will resolve to a URL either represented in the parameters, request body, or response body of the parent operation.
Examples:
@@ -1763,7 +1817,7 @@ Any number of [extension](#extensions) fields can be added to the Callback Objec
A map of Media Types (including wildcards) to a [Media Type Object](#media-type-object) that describes the content of the request or response as it relates to the media type consumed or produced.
-The key in the map is a [Media/MIME Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) that determines how the content is encoded. This media type can include wildcards indicating a range of media types it covers. For example, `application/*` would match `application/json`, `application/xml`, etc. `*/*` would match any media type. Or it can be explicitly defined to match only a single media type. For example, `application/json; charset=utf-8`.
+The key in the map is a [media or MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) that determines how the content is encoded. This media type can include wildcards indicating a range of media types it covers. For example, `application/*` would match `application/json`, `application/xml`, and so on, and `*/*` would match any media type. It can be explicitly defined to match only a single media type, for example, `application/json; charset=utf-8`.
Where both a wildcard and a specific media type are defined, the specific media type definition takes precedence.
@@ -1778,7 +1832,7 @@ content:
schema:
type: string
format: binary
- text/*: # Upload any text based description of a drink
+ text/*: # Upload any text-based description of a drink
schema:
type: string
text/csv: # Upload a CSV file (this will take precedence over text/*)
@@ -1793,9 +1847,9 @@ A Media Type Object describes the request or response for a media type, with opt
| Field | Type | Required | Description |
| ---------- | --------------------------------------------------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `schema` | [Schema Object](#schema-object) | :heavy_minus_sign: | A schema that describes the request or response content. |
-| `example` | *any* | :heavy_minus_sign: | An optional example of the media type. This example overrides any examples from the [Schema Object](#schema-object) in the `schema` field. Mutually exclusive of the `examples` field. |
-| `examples` | *map[string, [Example Object](#example-object) \| [OpenAPI Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | Optional examples of the media type. These examples override any examples from the [Schema Object](#schema-object) in the `schema` field. Mutually exclusive of the `example` field. |
-| `encoding` | *map[string, [Encoding Object](#encoding-object)]* | :heavy_minus_sign: | An optional map of [Encoding Objects](#encoding-object). Each Encoding Object's key should match one of the properties from the [Schema Object](#schema-object) in the `schema` field. Only applies to [Request Body Objects](#request-body-object) when the media type is `multipart` or `application/x-www-form-urlencoded`. |
+| `example` | Any | :heavy_minus_sign: | An optional example of the media type. This example overrides any examples from the [Schema Object](#schema-object) in the `schema` field. Mutually exclusive with the `examples` field. |
+| `examples` | Map[string, [Example Object](#example-object) \| [OpenAPI Reference Object](#openapi-reference-object)] | :heavy_minus_sign: | Optional examples of the media type. These examples override any examples from the [Schema Object](#schema-object) in the `schema` field. Mutually exclusive with the `example` field. |
+| `encoding` | Map[string, [Encoding Object](#encoding-object)] | :heavy_minus_sign: | An optional map of [Encoding Objects](#encoding-object). Each Encoding Object's key should match one of the properties from the [Schema Object](#schema-object) in the `schema` field. Only applies to [Request Body Objects](#request-body-object) when the media type is `multipart` or `application/x-www-form-urlencoded`. |
| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields as required by tooling and vendors. |
#### Encoding Object
@@ -1804,11 +1858,11 @@ Only applicable to `requestBody` where the media type is `multipart` or `applica
| Field | Type | Required | Description |
| --------------- | ----------------------------------------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `contentType` | *string* | :heavy_minus_sign: | The Content-Type of the field. If the field is an `object`, the default is `application/json`. If the field is an array, the default is based on the inner type. Otherwise, the default is `application/octet-stream`. Valid values are either a media type (e.g. `application/json`), a wildcard media type (e.g. `image/*`), or a comma-separated list of media types and wildcard media types (e.g. `image/png, application/*`). |
-| `headers` | *map[string, [Header Object](#header-object) \| [Reference Object](#openapi-reference-object)]* | :heavy_minus_sign: | Only applies to `multipart` requests. Allows additional headers related to the field. For example, if the client needs to add a `Content-Disposition` for an uploaded file. A `Content-Type` header in this map will be ignored, in favour of the `contentType` field of the encoding object. |
-| `style` | *string* | :heavy_minus_sign: | Can take one of the following values: `form`, `spaceDelimited`, `pipeDelimited`, `deepObject`. Specifies the style of the field's serialization only in requests with media type `multipart/form-data` or `application/x-www-form-urlencoded`. See the description of `style` under [Query Parameters](#query-parameters). |
-| `explode` | *boolean* | :heavy_minus_sign: | Only applies to requests with media type `multipart/form-data` or `application/x-www-form-urlencoded` and fields with `array` or `object` types. If `style` is `form`, the default is `true`, otherwise the default is `false`. |
-| `allowReserved` | *boolean* | :heavy_minus_sign: | Only applies to requests with media type `application/x-www-form-urlencoded`. Determines whether reserved characters (those allowed in literals but with reserved meanings) are allowed in the parameter's content. The default is `false`. When `true`, it allows reserved characters as defined by [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-2.2) to be included without percent-encoding. This can be useful for parameters with content such as URLs. |
+| `contentType` | String | :heavy_minus_sign: | The content type of the field. If the field is an `object`, the default is `application/json`. If the field is an array, the default is based on the inner type. Otherwise, the default is `application/octet-stream`. Valid values are either a media type (for example, `application/json`), a wildcard media type (for example, `image/*`), or a comma-separated list of media types and wildcard media types (for example, `image/png, application/*`). |
+| `headers` | Map[string, [Header Object](#header-object) \| [Reference Object](#openapi-reference-object)] | :heavy_minus_sign: | Only applies to `multipart` requests. Allows additional headers related to the field. For example, if the client needs to add a `Content-Disposition` for an uploaded file. A `Content-Type` header in this map will be ignored, in favor of the `contentType` field of the encoding object. |
+| `style` | String | :heavy_minus_sign: | Can take one of the following values: `form`, `spaceDelimited`, `pipeDelimited`, or `deepObject`. Specifies the style of the field's serialization only in requests with media type `multipart/form-data` or `application/x-www-form-urlencoded`. See the description of `style` under [Query Parameters](#query-parameters). |
+| `explode` | Boolean | :heavy_minus_sign: | Only applies to requests with media type `multipart/form-data` or `application/x-www-form-urlencoded` and fields with `array` or `object` types. If `style` is `form`, the default is `true`, otherwise the default is `false`. |
+| `allowReserved` | Boolean | :heavy_minus_sign: | Only applies to requests with media type `application/x-www-form-urlencoded`. Determines whether reserved characters (those allowed in literals but with reserved meanings) are allowed in the parameter's content. The default is `false`. When `true`, it allows reserved characters as defined by [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-2.2) to be included without percent-encoding. This can be useful for parameters with content such as URLs. |
```yaml
paths:
@@ -1838,19 +1892,59 @@ paths:
# explode: false - not applicable to strings
```
-### SDK Generation
+### Operation Objects in Generated SDKs
+
+The Speakeasy SDK generator creates a complete self-contained file per operation.
+
+For our Speakeasy Bar example, this modular approach would lead to the following TypeScript files.
+
+```bash
+src/models/operations/
+├── authenticate.ts
+├── createorder.ts
+├── deletedrink.ts
+├── getdrink.ts
+├── index.ts
+├── listdrinks.ts
+├── searchdrinks.ts
+├── subscribetowebhooks.ts
+├── updatedrinkjson.ts
+├── updatedrinkmultipart.ts
+├── updatedrinkraw.ts
+└── updatedrinkstring.ts
+```
+
+Each operation is presented as a function with the `operationId` as the function name. When using tags to structure the SDK, each operation function is bundled in a module named after its tag.
+
+Speakeasy generates the following usage example as part of the TypeScript SDK:
+
+```typescript
+import { SDK } from "openapi";
+
+async function run() {
+ const sdk = new SDK();
+
+ const productCode = "NAC-3F2D1";
+ const operationSecurity = "";
+
+ const result = await sdk.drinks.getDrink(operationSecurity, productCode);
+
+ // Handle the result
+ console.log(result)
+}
-`TODO`
+run();
+```
## Parameters
-Parameters are used to describe inputs to an operation, they can be defined at the path or operation level, and are merged together with any duplicates at the operation level overriding any defined at the path level.
+Parameters are used to describe inputs to an operation. Parameters can be defined at the path or operation level and are merged with any duplicates at the operation level, overriding any defined at the path level.
-Each parameter needs to be uniquely identified by a combination of its `name` and `in` fields, within an [Operation](#operation-object).
+Each parameter needs to be uniquely identified by a combination of its `name` and `in` fields in an [operation](#operation-object).
A parameter in the list can either be a [Parameter Object](#parameter-object) or a [Reference](#references) to a [Parameter Object](#parameter-object) defined in the [Components Object](#components-object) under the `parameters` field.
-Parameters can represent an number of different input types including:
+Parameters can represent a number of different input types, including:
- Path Parameters
- Query Parameters
@@ -1917,86 +2011,86 @@ paths:
| Field | Type | Required | Description |
| ----------------- | :-----------------------------: | :----------------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `name` | *string* | :heavy_check_mark: | The **case sensitive** name of the parameter. This ***must*** be unique when combined with the `in` field.
If the `in` field is `path` then this field ***must*** be referenced in the owning path. |
-| `in` | *string* | :heavy_check_mark: | The type/location of the parameter. The available types are:
- `path` - a templated parameter defined within the path.
- `query` - a query parameter passed via the URL.
- `header` - a header parameter passed via HTTP headers.
- `cookie` - a cookie parameter passed via HTTP cookies.
|
-| `description` | *string* | :heavy_minus_sign: | A description of the parameter. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
-| `required` | *boolean* | :heavy_minus_sign: | Whether the parameter is required or not. If the `in` field is `path` then this field is **always** required and ***must*** be `true`. Defaults to `false`. |
-| `deprecated` | *boolean* | :heavy_minus_sign: | Whether the parameter is deprecated or not. Defaults to `false`. |
-| `style` | *string* | :heavy_minus_sign: | Describes how the parameter value will be serialized depending on the `in` field. The available styles are `matrix`, `label`, `form`, `simple`, `spaceDelimited`, `pipeDelimited`, `deepObject`.
The default style depends on the `in` field:
- `path` - `simple`
- `query` - `form`
- `header` - `simple`
- `cookie` - `form`
See [Parameter Serialization](#parameter-serialization) for more details. |
-| `explode` | *boolean* | :heavy_minus_sign: | Whether the parameter value will be exploded or not, based on the parameter type. Defaults to `true` when `style` is `form` otherwise `false`.
See [Parameter Serialization](#parameter-serialization) for more details. |
-| `schema` | [Schema Object](#schema-object) | :heavy_minus_sign: | A schema or reference to a schema that defines the type of the parameter. This is ***required*** unless `content` is defined.
**Note: OpenAPI `3.0.X` does support [OpenAPI Reference Objects](#openapi-reference-object) here as the value, but `3.1.x` uses the [JSON Schema Referencing](#json-schema-reference-object) format.** |
-| `content` | [Content](#content) | :heavy_minus_sign: | A map of [Media Type Objects](#media-type-object) that define the possible media types that can be used for the parameter. This is ***required*** unless `schema` is defined. |
-| `allowEmptyValue` | *boolean* | :heavy_minus_sign: | Whether the parameter value can be empty or not. Only used if `in` is `query`. Defaults to `false`. |
-| `allowReserved` | *boolean* | :heavy_minus_sign: | Whether the parameter value can contain reserved characters or not as defined by [RFC3986](https://www.rfc-editor.org/rfc/rfc3986). Only used if `in` is `query`. Defaults to `false`. |
-| `example` | *any* | :heavy_minus_sign: | An example of the parameter's value. This is ignored if the `examples` field is defined. |
+| `name` | String | :heavy_check_mark: | The **case sensitive** name of the parameter. This ***must*** be unique when combined with the `in` field.
If the `in` field is `path`, then this field ***must*** be referenced in the owning path. |
+| `in` | String | :heavy_check_mark: | The type or location of the parameter. The available types are:
- `path` - A templated parameter defined within the path.
- `query` - A query parameter passed via the URL.
- `header` - A header parameter passed via HTTP headers.
- `cookie` - A cookie parameter passed via HTTP cookies.
|
+| `description` | String | :heavy_minus_sign: | A description of the parameter. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+| `required` | Boolean | :heavy_minus_sign: | Whether the parameter is required. If the `in` field is `path`, then this field is **always** required and ***must*** be `true`. Defaults to `false`. |
+| `deprecated` | Boolean | :heavy_minus_sign: | Whether the parameter is deprecated. Defaults to `false`. |
+| `style` | String | :heavy_minus_sign: | Describes how the parameter value will be serialized depending on the `in` field. The available styles are `matrix`, `label`, `form`, `simple`, `spaceDelimited`, `pipeDelimited`, and `deepObject`.
The default style depends on the `in` field:
- `path` - `simple`
- `query` - `form`
- `header` - `simple`
- `cookie` - `form`
See [Parameter Serialization](#parameter-serialization) for more details. |
+| `explode` | Boolean | :heavy_minus_sign: | Whether the parameter value will be exploded, based on the parameter type. Defaults to `true` when `style` is `form`, otherwise `false`.
See [Parameter Serialization](#parameter-serialization) for more details. |
+| `schema` | [Schema Object](#schema-object) | :heavy_minus_sign: | A schema or reference to a schema that defines the type of the parameter. This is ***required*** unless `content` is defined.
**Note: OpenAPI 3.0.x supports [OpenAPI Reference Objects](#openapi-reference-object) here as the value. OpenAPI 3.1.x uses the [JSON Schema Referencing](#json-schema-references) format.** |
+| `content` | [Content](#content) | :heavy_minus_sign: | A map of [Media Type Objects](#media-type-object) that defines the possible media types that can be used for the parameter. This is ***required*** unless `schema` is defined. |
+| `allowEmptyValue` | Boolean | :heavy_minus_sign: | Whether the parameter value can be empty. Only used if `in` is `query`. Defaults to `false`. |
+| `allowReserved` | Boolean | :heavy_minus_sign: | Whether the parameter value can contain reserved characters as defined by [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986). Only used if `in` is `query`. Defaults to `false`. |
+| `example` | Any | :heavy_minus_sign: | An example of the parameter's value. This is ignored if the `examples` field is defined. |
| `examples` | [Examples](#examples) | :heavy_minus_sign: | A map of [Example Objects](#example-object) and/or [OpenAPI Reference Objects](#openapi-reference-object) that define the possible examples of the parameter's value. |
| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the parameter object that can be used by tooling and vendors. |
-The above order of fields is a recommendation for how the fields should be defined in the document.
+The order of fields above is recommended for defining fields in the document.
### Parameter Serialization
-Depending on the `in`, `style` and `explode` fields the parameter value will be serialized in different ways depending on its schema type. Some combinations of schema type and parameter serialization are not valid and should be avoided.
+Depending on the parameter's `in`, `style`, and `explode` fields and schema type, the parameter value will be serialized in different ways. Some combinations of schema type and parameter serialization are not valid and should be avoided.
-`content` can also be used instead to define complex serialization scenarios for a parameter such as serializing an object to a JSON string for including in a query parameter in the URL.
+The `content` field can be used instead to define complex serialization scenarios for a parameter such as serializing an object to a JSON string for including in a query parameter in the URL.
#### Query Parameters
-Query parameters are serialized at run-time to the query string of the URL, this means they are generally serialized to a string representation and must adhere to the [RFC3986](https://www.rfc-editor.org/rfc/rfc3986) specification. By default reserved characters are percent encoded (for example `?` becomes `%3F`), but this can be disabled by setting `allowReserved` to `true`.
+Query parameters are serialized at runtime to the query string of the URL, meaning they are generally serialized to a string representation and must adhere to the [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) specification. By default, reserved characters are percent-encoded (for example, `?` becomes `%3F`) but this can be disabled by setting `allowReserved` to `true`.
-By default query parameters are serialized using `style: form` and `explode: true`. but there are a number of different serialization options available:
+By default, query parameters are serialized using `style: form` and `explode: true` but there are a number of different serialization options available:
-- `style: form` - Form style serialization is the default serialization for query parameters, it generally uses ampersands (`&`) to separate multiple values and equals (`=`) to separate the key and value. Defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.8).
-- `style: pipeDelimited` - Pipe delimited serialization uses pipes (`|`) to separate multiple values.
-- `style: spaceDelimited` - Space delimited serialization uses percent encoded spaces (`%20`) to separate multiple values.
-- `style: deepObject` - Deep object serialization uses nested objects to represent the parameter value.
+- `style: form` - Form style serialization is the default serialization for query parameters. It generally uses ampersands (`&`) to separate multiple values and equals (`=`) to separate the key and value. Defined by [RFC 6570](https://tools.ietf.org/html/rfc6570#section-3.2.8).
+- `style: pipeDelimited` - Pipe-delimited serialization uses pipes (`|`) to separate multiple values.
+- `style: spaceDelimited` - Space-delimited serialization uses percent-encoded spaces (`%20`) to separate multiple values.
+- `style: deepObject` - Deep-object serialization uses nested objects to represent the parameter value.
-##### Primitive Types
+##### Primitive Types As Query Parameters
-For primitive types such as `string`, `number`, `integer` and `boolean` the serialization is straight forward and the value is serialized as a string, the `style` and `explode` fields have little effect on the serialization.
+For primitive types such as `string`, `number`, `integer,` and `boolean`, the serialization is straightforward and the value is serialized as a string. The `style` and `explode` fields have little effect on the serialization.
-For the examples below we will use a query parameter named `limit` with a value of `10`.
+For the examples below, we will use a query parameter named `limit` with a value of `10`.
| Style | Explode == `true` | Explode == `false` |
| ---------------- | :---------------------------: | :----------------: |
-| `form` | `/query?limit=10` *(default)* | `/query?limit=10` |
+| `form` | `/query?limit=10` (default) | `/query?limit=10` |
| `pipeDelimited` | `/query?limit=10` | `/query?limit=10` |
| `spaceDelimited` | `/query?limit=10` | `/query?limit=10` |
| `deepObject` | **NOT VALID** | **NOT VALID** |
-##### Simple Arrays
+##### Simple Arrays As Query Parameters
-For simple arrays of primitive types such as `string`, `number`, `integer` and `boolean` serialization will vary depending on the `style` and `explode` fields.
+For simple arrays of primitive types such as `string`, `number`, `integer`, and `boolean`, serialization will vary depending on the `style` and `explode` fields.
-For the examples below we will use a query parameter named `terms` with a value of `["gin", "vodka", "rum"]`.
+For the examples below, we will use a query parameter named `terms` with a value of `["gin", "vodka", "rum"]`.
| Style | Explode == `true` | Explode == `false` |
| ---------------- | :--------------------------------------------------: | :------------------------------: |
-| `form` | `/query?terms=gin&terms=vodka&terms=rum` *(default)* | `/query?terms=gin,vodka,rum` |
+| `form` | `/query?terms=gin&terms=vodka&terms=rum` (default) | `/query?terms=gin,vodka,rum` |
| `pipeDelimited` | `/query?terms=gin&terms=vodka&terms=rum` | `/query?terms=gin\|vodka\|rum` |
| `spaceDelimited` | `/query?terms=gin&terms=vodka&terms=rum` | `/query?terms=gin%20vodka%20rum` |
| `deepObject` | **NOT VALID** | **NOT VALID** |
-##### Simple Objects
+##### Simple Objects As Query Parameters
-For simple objects whose fields are primitive types such as `string`, `number`, `integer` and `boolean` serialization will vary depending on the `style` and `explode` fields.
+For simple objects whose fields are primitive types such as `string`, `number`, `integer`, and `boolean`, serialization will vary depending on the `style` and `explode` fields.
-For the examples below we will use a query parameter named `filter` with a value of `{"type": "cocktail", "strength": 5}`.
+For the examples below, we will use a query parameter named `filter` with a value of `{"type": "cocktail", "strength": 5}`.
| Style | Explode == `true` | Explode == `false` |
| ---------------- | :-----------------------------------------------: | :--------------------------------------------: |
-| `form` | `/query?type=cocktail&strength=5` *(default)* | `/query?filter=type,cocktail,strength,5` |
+| `form` | `/query?type=cocktail&strength=5` (default) | `/query?filter=type,cocktail,strength,5` |
| `pipeDelimited` | `/query?type=cocktail&strength=5` | `/query?filter=type\|cocktail\|strength\|5` |
| `spaceDelimited` | `/query?type=cocktail&strength=5` | `/query?filter=type%20cocktail%20strength%205` |
| `deepObject` | `/query?filter[type]=cocktail&filter[strength]=5` | **NOT VALID** |
-There is a special case for simple objects with fields that are an array of primitive types such as `string`, `number`, `integer` and `boolean` that can be handled by `style: deepObject` and `explode: true`. For example for a query parameter named `filter` with a value of `{"type": ["cocktail", "mocktail"], "strength": [5, 10]}`, this will be serialized like `/query?filter[type]=cocktail&filter[type]=mocktail&filter[strength]=5&filter[strength]=10`.
+There is a special case for simple objects with fields that are an array of primitive types such as `string`, `number`, `integer`, and `boolean` that can be handled by `style: deepObject` and `explode: true`. For example, for a query parameter named `filter` with a value of `{"type": ["cocktail", "mocktail"], "strength": [5, 10]}`, this will be serialized like `/query?filter[type]=cocktail&filter[type]=mocktail&filter[strength]=5&filter[strength]=10`.
-##### Complex Objects and Arrays
+##### Complex Objects and Arrays As Query Parameters
For complex objects and arrays, serialization in a query parameter is only really possible using `content` and not any `style` options.
-For example serializing using JSON:
+For example, to serialize using JSON, the following:
```yaml
parameters:
@@ -2017,23 +2111,23 @@ parameters:
type: integer
```
-would serialize to `/query?filter=%7B%22type%22%3A%5B%22cocktail%22%2C%22mocktail%22%5D%2C%22strength%22%3A%5B5%2C10%5D%7D` which is the equivalent of `/query?filter={"type":["cocktail","mocktail"],"strength":[5,10]}` unencoded.
+Would serialize to `/query?filter=%7B%22type%22%3A%5B%22cocktail%22%2C%22mocktail%22%5D%2C%22strength%22%3A%5B5%2C10%5D%7D`, which is the equivalent of `/query?filter={"type":["cocktail","mocktail"],"strength":[5,10]}` unencoded.
#### Path Parameters
-Path parameters are serialized at run-time to the path of the URL, this means they are generally serialized to a string representation and must adhere to the [RFC3986](https://www.rfc-editor.org/rfc/rfc3986) specification. Reserved characters are percent encoded (for example `?` becomes `%3F`).
+Path parameters are serialized at runtime to the path of the URL, meaning they are generally serialized to a string representation and must adhere to the [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) specification. Reserved characters are percent-encoded (for example, `?` becomes `%3F`).
-By default path parameters are serialized using `style: simple` and `explode: false`, but there are a number of different serialization options available:
+By default, path parameters are serialized using `style: simple` and `explode: false` but there are a number of different serialization options available:
-- `style: simple` - Simple style serialization is the default serialization for path parameters, using commas (`,`) to separate multiple values. Defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.7).
-- `style: label` - Label style serialization uses dots (`.`) to separate multiple values. Defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.6).
-- `style: matrix` - Matrix style serialization uses semicolons (`;`) to separate multiple values. Defined by [RFC6570](https://tools.ietf.org/html/rfc6570#section-3.2.5).
+- `style: simple` - Simple style serialization is the default serialization for path parameters, using commas (`,`) to separate multiple values. Defined by [RFC 6570](https://tools.ietf.org/html/rfc6570#section-3.2.7).
+- `style: label` - Label-style serialization uses dots (`.`) to separate multiple values. Defined by [RFC 6570](https://tools.ietf.org/html/rfc6570#section-3.2.6).
+- `style: matrix` - Matrix-style serialization uses semicolons (`;`) to separate multiple values. Defined by [RFC 6570](https://tools.ietf.org/html/rfc6570#section-3.2.5).
-##### Primitive Types
+##### Primitive Types As Path Parameters
-For primitive types such as `string`, `number`, `integer` and `boolean` they are serialized as a string, the `style` and `explode` fields determine the prefix for the value generally.
+Primitive types such as `string`, `number`, `integer`, and `boolean` are serialized as a string. The `style` and `explode` fields determine the prefix for the value generally.
-For the examples below we will use a path parameter named `type` with a value of `cocktail` for a path templated URL of `/drinks/{type}`.
+For the examples below, we will use a path parameter named `type` with a value of `cocktail` for a path-templated URL of `/drinks/{type}`.
| Style | Explode == `true` | Explode == `false` |
| -------- | :----------------------: | :----------------------: |
@@ -2041,35 +2135,35 @@ For the examples below we will use a path parameter named `type` with a value of
| `label` | `/drinks/.cocktail` | `/drinks/.cocktail` |
| `matrix` | `/drinks/;type=cocktail` | `/drinks/;type=cocktail` |
-##### Simple Arrays
+##### Simple Arrays As Path Parameters
-For simple arrays of primitive types such as `string`, `number`, `integer` and `boolean` serialization will vary depending on the `style` and `explode` fields.
+For simple arrays of primitive types such as `string`, `number`, `integer`, and `boolean`, serialization will vary depending on the `style` and `explode` fields.
-For the examples below we will use a path parameter named `types` with a value of `["gin", "vodka", "rum"]` for a path templated URL of `/drinks/{types}`.
+For the examples below, we will use a path parameter named `types` with a value of `["gin", "vodka", "rum"]` for a path-templated URL of `/drinks/{types}`.
| Style | Explode == `true` | Explode == `false` |
| -------- | :----------------------------------------: | :---------------------------------: |
-| `simple` | `/drinks/gin,vodka,rum` | `/drinks/gin,vodka,rum` *(default)* |
+| `simple` | `/drinks/gin,vodka,rum` | `/drinks/gin,vodka,rum` (default) |
| `label` | `/drinks/.gin.vodka.rum` | `/drinks/.gin,vodka,rum` |
| `matrix` | `/drinks/;types=gin;types=vodka;types=rum` | `/drinks/;types=gin,vodka,rum` |
-##### Simple Objects
+##### Simple Objects As Path Parameters
-For simple objects whose fields are primitive types such as `string`, `number`, `integer` and `boolean` serialization will vary depending on the `style` and `explode` fields.
+For simple objects whose fields are primitive types such as `string`, `number`, `integer`, and `boolean`, serialization will vary depending on the `style` and `explode` fields.
-For the examples below we will use a path parameter named `filter` with a value of `{"type": "cocktail", "strength": 5}` for a path templated URL of `/drinks/{filter}`.
+For the examples below, we will use a path parameter named `filter` with a value of `{"type": "cocktail", "strength": 5}` for a path-templated URL of `/drinks/{filter}`.
| Style | Explode == `true` | Explode == `false` |
| -------- | :---------------------------------: | :--------------------------------------------: |
-| `simple` | `/drinks/type=cocktail,strength=5` | `/drinks/type,cocktail,strength,5` *(default)* |
+| `simple` | `/drinks/type=cocktail,strength=5` | `/drinks/type,cocktail,strength,5` (default) |
| `label` | `/drinks/.type=cocktail.strength=5` | `/drinks/.type,cocktail,strength,5` |
| `matrix` | `/drinks/;type=cocktail;strength=5` | `/drinks/;filter=type,cocktail,strength,5` |
-##### Complex Objects and Arrays
+##### Complex Objects and Arrays As Path Parameters
For complex objects and arrays, serialization in a path parameter is only really possible using `content` and not any `style` options.
-For example serializing using JSON:
+For example, to serialize using JSON, the following:
```yaml
parameters:
@@ -2090,57 +2184,57 @@ parameters:
type: integer
```
-would serialize to `/drinks/%7B%22type%22%3A%5B%22cocktail%22%2C%22mocktail%22%5D%2C%22strength%22%3A%5B5%2C10%5D%7D` which is the equivalent of `/drinks/{"type":["cocktail","mocktail"],"strength":[5,10]}` unencoded.
+Would serialize to `/drinks/%7B%22type%22%3A%5B%22cocktail%22%2C%22mocktail%22%5D%2C%22strength%22%3A%5B5%2C10%5D%7D`, which is the equivalent of `/drinks/{"type":["cocktail","mocktail"],"strength":[5,10]}` unencoded.
#### Header Parameters
-Header parameters are serialized at run-time to the HTTP headers of the request, types are generally serialized to a string representation, and only `simple` style is available.
+Header parameters are serialized at runtime to the HTTP headers of the request. Types are generally serialized to a string representation, and only `simple` style is available.
Explode defaults to `false`.
There are a few reserved headers that cannot be used as parameter names and are enabled by other OpenAPI features:
-- `Accept` - Defining content types in the [Response Object](#response-object) `content` field, documents that available values for the `Accept` header.
+- `Accept` - Defining content types in the [Response Object](#response-object) `content` field, documents the available values for the `Accept` header.
- `Authorization` - Defining security requirements in the [Security Requirement Object](#security-requirement-object) `security` field, documents that the `Authorization` header is required.
- `Content-Type` - Defining content types in the [Request Body Object](#request-body-object) `content` field, documents that the `Content-Type` header is required and the acceptable values.
If using headers for authentication, it is recommended to use the OpenAPI [`security`](#security) field to document a security scheme instead of a header parameter.
-##### Primitive Types
+##### Primitive Types As Headers
-For primitive types such as `string`, `number`, `integer` and `boolean` they are serialized as a string.
+Primitive types such as `string`, `number`, `integer`, and `boolean` are serialized as a string.
-For the examples below we will use a header parameter named `X-Drink-Limit` with a value of `5`.
+For the example below, we will use a header parameter named `X-Drink-Limit` with a value of `5`.
| Style | Explode == `true` | Explode == `false` |
| -------- | :---------------: | :---------------------------: |
-| `simple` | `X-Drink-Type: 5` | `X-Drink-Type: 5` *(default)* |
+| `simple` | `X-Drink-Type: 5` | `X-Drink-Type: 5` (default) |
-##### Simple Arrays
+##### Simple Arrays As Headers
-For simple arrays of primitive types such as `string`, `number`, `integer` and `boolean` the `style` and `explode` fields have little effect on the serialization.
+For simple arrays of primitive types such as `string`, `number`, `integer`, and `boolean`, the `style` and `explode` fields have little effect on the serialization.
-For the examples below we will use a header parameter named `X-Drink-Types` with a value of `["gin", "vodka", "rum"]`.
+For the example below, we will use a header parameter named `X-Drink-Types` with a value of `["gin", "vodka", "rum"]`.
| Style | Explode == `true` | Explode == `false` |
| -------- | :---------------------------: | :---------------------------------------: |
-| `simple` | `X-Drink-Type: gin,vodka,rum` | `X-Drink-Type: gin,vodka,rum` *(default)* |
+| `simple` | `X-Drink-Type: gin,vodka,rum` | `X-Drink-Type: gin,vodka,rum` (default) |
-##### Simple Objects
+##### Simple Objects As Headers
-For simple objects whose fields are primitive types such as `string`, `number`, `integer` and `boolean` serialization will vary depending on the `explode` field.
+For simple objects whose fields are primitive types such as `string`, `number`, `integer`, and `boolean`, serialization will vary depending on the `explode` field.
-For the examples below we will use a header parameter named `X-Drink-Filter` with a value of `{"type": "cocktail", "strength": 5}`.
+For the example below, we will use a header parameter named `X-Drink-Filter` with a value of `{"type": "cocktail", "strength": 5}`.
| Style | Explode == `true` | Explode == `false` |
| -------- | :--------------------------------------: | :--------------------------------------------------: |
-| `simple` | `X-Drink-Type: type=cocktail,strength=5` | `X-Drink-Type: type,cocktail,strength,5` *(default)* |
+| `simple` | `X-Drink-Type: type=cocktail,strength=5` | `X-Drink-Type: type,cocktail,strength,5` (default) |
-##### Complex Objects and Arrays
+##### Complex Objects and Arrays As Headers
For complex objects and arrays, serialization in a header parameter is only really possible using `content` and not any `style` options.
-For example serializing using JSON:
+For example, to serialize using JSON, the following:
```yaml
parameters:
@@ -2161,53 +2255,53 @@ parameters:
type: integer
```
-would serialize to `X-Drink-Filter: {"type":["cocktail","mocktail"],"strength":[5,10]}`.
+Would serialize to `X-Drink-Filter: {"type":["cocktail","mocktail"],"strength":[5,10]}`.
#### Cookie Parameters
-Cookie parameters are serialized at run-time to a HTTP cookie header, types are generally serialized to a string representation, and only `form` style is available.
+Cookie parameters are serialized at runtime to an HTTP cookie header. Types are generally serialized to a string representation, and only `form` style is available.
-Currently cookies are not well supported by OpenAPI and this may change in the future, so using the default `style: form` and `explode: true` values results in serialization incompatible with most cookie parsers.
+Currently, cookies are not well supported by OpenAPI and this may change in the future, so using the default `style: form` and `explode: true` values results in serialization incompatible with most cookie parsers.
-Therefore it is only really recommended to use cookies for primitive types or arrays with `explode: false` but the current serialization behaviors are included below for completeness.
+Therefore, it is recommended to only use cookies for primitive types or arrays with `explode: false`, but the current serialization behaviors are included below for completeness.
If using cookies for authentication, it is recommended to use the OpenAPI [`security`](#security) field to document a security scheme instead of a cookie parameter.
-##### Primitive Types
+##### Primitive Types As Cookies
-For primitive types such as `string`, `number`, `integer` and `boolean` they are serialized as a string.
+Primitive types such as `string`, `number`, `integer`, and `boolean` are serialized as a string.
-For the examples below we will use a cookie parameter named `drink-limit` with a value of `5`.
+For the example below, we will use a cookie parameter named `drink-limit` with a value of `5`.
| Style | Explode == `true` | Explode == `false` |
| ------ | :----------------------------------: | :---------------------: |
-| `form` | `Cookie: drink-limit=5` *(default)* | `Cookie: drink-limit=5` |
+| `form` | `Cookie: drink-limit=5` (default) | `Cookie: drink-limit=5` |
-##### Simple Arrays
+##### Simple Arrays As Cookies
-For simple arrays of primitive types such as `string`, `number`, `integer` and `boolean` serialization will vary depending on the `explode` field.
+For simple arrays of primitive types such as `string`, `number`, `integer`, and `boolean`, serialization will vary depending on the `explode` field.
-For the examples below we will use a cookie parameter named `drink-types` with a value of `["gin", "vodka", "rum"]`.
+For the example below, we will use a cookie parameter named `drink-types` with a value of `["gin", "vodka", "rum"]`.
| Style | Explode == `true` | Explode == `false` |
| ------ | :---------------------------------------------------------------------: | :---------------------------------: |
-| `form` | `Cookie: drink-types=gin&drink-types=vodka&drink-types=rum` *(default)* | `Cookie: drink-types=gin,vodka,rum` |
+| `form` | `Cookie: drink-types=gin&drink-types=vodka&drink-types=rum` (default) | `Cookie: drink-types=gin,vodka,rum` |
-##### Simple Objects
+##### Simple Objects As Cookies
-For simple objects whose fields are primitive types such as `string`, `number`, `integer` and `boolean` serialization will vary depending on the `explode` field.
+For simple objects whose fields are primitive types such as `string`, `number`, `integer`, and `boolean`, serialization will vary depending on the `explode` field.
-For the examples below we will use a cookie parameter named `drink-filter` with a value of `{"type": "cocktail", "strength": 5}`.
+For the example below, we will use a cookie parameter named `drink-filter` with a value of `{"type": "cocktail", "strength": 5}`.
| Style | Explode == `true` | Explode == `false` |
| ------ | :--------------------------------------------: | :---------------------------------------------: |
-| `form` | `Cookie: type=cocktail&strength=5` *(default)* | `Cookie: drink-filter=type,cocktail,strength,5` |
+| `form` | `Cookie: type=cocktail&strength=5` (default) | `Cookie: drink-filter=type,cocktail,strength,5` |
-##### Complex Objects and Arrays
+##### Complex Objects and Arrays As Cookies
For complex objects and arrays, serialization in a cookie parameter is only really possible using `content` and not any `style` options.
-For example serializing using JSON:
+For example, to serialize using JSON, the following:
```yaml
parameters:
@@ -2228,13 +2322,13 @@ parameters:
type: integer
```
-would serialize to `Cookie: drink-filter={"type":["cocktail","mocktail"],"strength":[5,10]}`.
+Would serialize to `Cookie: drink-filter={"type":["cocktail","mocktail"],"strength":[5,10]}`.
## Schema Object
-The Schema Object represents any data type used as input our output in OpenAPI. Data types can be objects, arrays, or primitives such as `string`, `number`, `integer` and `boolean`.
+The Schema Object represents any data type used as input or output in OpenAPI. Data types can be objects, arrays, or primitives such as `string`, `number`, `integer`, and `boolean`.
-Schema objects are sometimes referred to as *models*, *data types*, or simply, *schemas*. This is because Schema types are used to model complex data types used by an API.
+Schema objects are sometimes referred to as *models*, *data types*, or simply, *schemas*. This is because schema types are used to model complex data types used by an API.
The Schema Object is based on and extends the [JSON Schema Specification Draft 2020-12](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00).
@@ -2244,19 +2338,19 @@ For an overview of all JSON Schema properties, see [JSON Schema Docs > JSON Sche
OpenAPI 3.1 changes the definition of two JSON Schema properties:
-* `description` - In OpenAPI this property may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description.
-* `format` - OpenAPI extends JSON Schema's data types by adding additional formats. See [Data Type Formats](#data-type-formats).
+- `description` - In OpenAPI this property may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description.
+- `format` - OpenAPI extends JSON Schema data types by adding additional formats. See [Data Type Formats](#data-type-formats).
-OpenAPI adds an additional vocabulary to JSON Schema with the following properties:
+OpenAPI adds another vocabulary to JSON Schema with the following properties:
| Field Name | Type | Description |
| -------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `discriminator` | [Discriminator Object](#discriminator-object) | A discriminator object describes how to differentiate between related schemas based on the value of a field in a request or response. See [Composition and Inheritance](#composition-and-inheritance). |
| `xml` | [XML Object](#xml-object) | Adds details about how the schema should be represented as XML. |
| `externalDocs` | [External Documentation Object](#external-documentation-object) | Points to external documentation for this schema. |
-| `example` | *any* | An example that satisfies this schema. **Deprecated:** Although valid, the use of `example` is discouraged. Use [Examples](#examples) instead. |
+| `example` | Any | An example that satisfies this schema. **Deprecated:** Although valid, the use of `example` is discouraged. Use [Examples](#examples) instead. |
| `x-` | [Extensions](#extensions) | Any number of extension fields can be added to the schema that can be used by tooling and vendors. |
-| Arbitrary properties | *any* | The schema object supports arbitrary properties without the `x-` prefix. This is discouraged in favour of [Extensions](#extensions). |
+| Arbitrary properties | Any | The schema object supports arbitrary properties without the `x-` prefix. This is discouraged in favor of [Extensions](#extensions). |
The example below illustrates three schema objects: `IngredientProductCode`, `Ingredient`, and `IngredientType`.
@@ -2355,38 +2449,396 @@ components:
### Discriminator Object
-`TODO`
+When using `oneOf` to indicate that a request body or response contains exactly one of multiple [Schema Objects](#schema-object), a discriminator object can help the client or server figure out which schema is included in the request or response.
+
+The discriminator object in OpenAPI tells a client or server which field can be used to discriminate between different schemas.
+
+| Field | Type | Required | Description |
+| -------------- | ------------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------- |
+| `propertyName` | String | :heavy_check_mark: | The property name used to discriminate between schemas. |
+| `mapping` | Map[string, string] | :heavy_minus_sign: | An optional map of values and schema reference strings. |
+| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the discriminator object that can be used by tooling and vendors. |
+
+In the example below, the Speakeasy Bar can receive one of two order types: A drink order with a bar-counter reference or an ingredient order with a delivery address:
+
+```yaml
+components:
+ responses:
+ OrderResponse:
+ oneOf:
+ - $ref: "#/components/schemas/DrinkOrder"
+ - $ref: "#/components/schemas/IngredientOrder"
+```
+
+If we include a discriminator object, the client can indicate the order type so that the server does not need to figure that out:
+
+```yaml
+components:
+ responses:
+ OrderResponse:
+ oneOf:
+ - $ref: "#/components/schemas/DrinkOrder"
+ - $ref: "#/components/schemas/IngredientOrder"
+ discriminator:
+ propertyName: orderType
+```
+
+In the previous example, the value of the `orderType` property will determine the order type. The value of `orderType` must match one of the schema components, so must be either `DrinkOrder` or `IngredientOrder`.
+
+To use values that don't match a schema key, a discriminator object can include a `mapping` property that maps values to schemas. Here's an example:
+
+```yaml
+components:
+ responses:
+ OrderResponse:
+ oneOf:
+ - $ref: "#/components/schemas/DrinkOrder"
+ - $ref: "#/components/schemas/IngredientOrder"
+ discriminator:
+ propertyName: orderType
+ mapping:
+ drink: "#/components/schemas/DrinkOrder"
+ ingredient: "#/components/schemas/IngredientOrder"
+```
### XML Object
-`TODO`
+The XML Object allows us to add details about how the schema should be represented as XML.
+
+This is useful because XML has different data types and structures compared to JSON.
+
+For example, in JSON, an array is a list of values only, while in XML, array values are represented as elements with names.
+
+| Field | Type | Required | Description |
+| ----------- | ------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `name` | String | :heavy_minus_sign: | The name of the element when the property is represented in XML. When used in `items`, the name applies to each element in the XML array. |
+| `namespace` | String | :heavy_minus_sign: | The absolute URL of the XML namespace. |
+| `prefix` | String | :heavy_minus_sign: | A prefix for the element's name. |
+| `attribute` | Boolean | :heavy_minus_sign: | Whether the property should be represented as an XML attribute (``) instead of an XML element (`3`). Defaults to `false`, so each property is represented as an element by default. |
+| `wrapped` | Boolean | :heavy_minus_sign: | Whether array elements should be wrapped in a container element. Defaults to `false`, so array elements are not wrapped by default. Only applies to arrays. |
+| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the XML object that can be used by tooling and vendors. |
+
+The examples below illustrate how XML Objects can be used:
+
+```yaml
+components:
+ schemas:
+ Drink:
+ type: object
+ properties:
+ name:
+ type: string
+ xml:
+ name: drinkName
+ namespace: http://speakeasy.bar/schemas
+ prefix: se
+ ingredients:
+ type: array
+ items:
+ $ref: "#/components/schemas/Ingredient"
+ xml:
+ name: ingredients
+ wrapped: true
+ namespace: http://speakeasy.bar/schemas
+ prefix: se
+ Ingredient:
+ type: object
+ properties:
+ id:
+ type: number
+ xml:
+ name: ingredientId
+ namespace: http://speakeasy.bar/schemas
+ prefix: se
+ attribute: true
+ name:
+ type: string
+ xml:
+ name: ingredientName
+ namespace: http://speakeasy.bar/schemas
+ prefix: se
+```
+
+The example above translates to the following XML example:
+
+```xml
+
+ Mojito
+
+
+ Sugar
+
+
+ Lime
+
+
+ Mint
+
+
+
+```
### Examples
-`TODO`
+OpenAPI examples improve your API's documentation and SDK developer experience. We can add examples to objects, parameters, or properties using either the `example` or `examples` keyword.
+
+Here's how these keywords differ:
+
+- `example`: A single [Example Object](#example-object).
+- `examples`: A map of strings to [Example Objects](#example-object).
+
+In OpenAPI 3.1, the `examples` keyword from JSON Schema is preferred.
+
+Unlike JSON Schema, the OpenAPI `examples` keyword expects an object instead of an array.
+
+It is recommended to add reusable [Example Objects](#example-object) to the `components` object under the `examples` keyword.
#### Example Object
-`TODO`
+We can use the Example Object to add an example of a schema, parameter, or response.
+
+| Field | Type | Required | Description |
+| --------------- | ------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
+| `summary` | String | :heavy_minus_sign: | A brief summary of the example. |
+| `description` | String | :heavy_minus_sign: | A detailed description of the example. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+| `value` | Any | :heavy_minus_sign: | The example value. Mutually exclusive with the `externalValue` field. |
+| `externalValue` | String | :heavy_minus_sign: | A URL that points to the example. This is useful if the example is too large to include inline. Mutually exclusive with the `value` field. |
+| `x-*` | [Extensions](#extensions) | :heavy_minus_sign: | Any number of extension fields can be added to the Example Object that can be used by tooling and vendors. |
+
+The example below illustrates how to add an example to a schema:
+
+```yaml
+components:
+ examples:
+ SugarSyrup:
+ summary: An example of a sugar syrup ingredient.
+ value:
+ name: Sugar Syrup
+ type: long-life
+ stock: 10
+ photo: https://speakeasy.bar/ingredients/sugar_syrup.jpg
+```
+
+The example below illustrates how to add an example to an object property:
+
+```yaml
+components:
+ schemas:
+ Ingredient:
+ type: object
+ properties:
+ name:
+ type: string
+ examples:
+ - value: Sugar Syrup
+ summary: An example of a sugar syrup ingredient.
+ description: A sugar syrup used to sweeten cocktails.
+ type:
+ $ref: "#/components/schemas/IngredientType"
+ stock:
+ type: integer
+ readOnly: true
+ examples:
+ - value: 10
+ summary: An example of the number of units in stock.
+ description: The number of units of the ingredient in stock, only available when authenticated.
+ productCode:
+ $ref: "#/components/schemas/IngredientProductCode"
+ photo:
+ type: string
+ format: uri
+ examples:
+ - value: https://example.com/sugarsyrup.jpg
+```
## Extensions
-`TODO`
+Extensions allow us to add extra keywords not included in the OpenAPI Specification. This enables tooling such as SDK generators to access vendor-specific functionality directly in an OpenAPI document.
+
+Extension fields always start with `x-`.
+
+Although optional, it is conventional for vendors to further prefix their extensions with the name of the vendor. For example, Speakeasy uses extensions that start with `x-speakeasy-`. This makes it easier to track vendor extensions over time and remove unused vendor extensions in the future.
+
+The value of an extension field can be an object, array, `null`, or any primitive value. Vendors determine the values they expect for the extensions they use.
+
+| Field | Type | Description |
+| ------- | ------------------------- | ---------------------------------------------------------------------------------------------------------- |
+| `^x-` | Any | An extension's value can be an object, array, primitive, or `null`. Expected values are determined by tooling vendors. |
+
+Here's an example of a Speakeasy extension that adds retries to requests made by Speakeasy-managed SDKs:
+
+```yaml
+x-speakeasy-retries:
+ strategy: backoff
+ backoff:
+ initialInterval: 500 # 500 milliseconds
+ maxInterval: 60000 # 60 seconds
+ maxElapsedTime: 3600000 # 5 minutes
+ exponent: 1.5
+ statusCodes:
+ - 5XX
+ retryConnectionErrors: true
+```
## References
-`TODO`
+References are a useful way to define common schemas as components and reference them elsewhere in an API description.
+
+This reduces duplication in an API description, which makes an API easier to maintain.
+
+References also allow us to split an API description into multiple files to help keep individual parts of an API separate and easier to maintain.
### OpenAPI Reference Object
-`TODO`
+Any object supported by the [Components Object](#components-object) can be replaced by an OpenAPI Reference Object. A Reference Object points to a component using the `$ref` field, which is itself a [JSON Schema Reference](#json-schema-references) and can optionally override the `summary` or `description` of the referenced object.
+
+| Field | Type | Required | Description |
+| ------------ | ------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
+| `$ref` | String | :heavy_check_mark: | A [JSON Schema reference](#json-schema-references) to a component. |
+| `summary` | String | :heavy_minus_sign: | A brief summary that overrides the referenced component's `summary` field. This field is ignored if the referenced component's type does not support the `summary` field. |
+| `description`| String | :heavy_minus_sign: | A detailed description that overrides the referenced component's `description` field. This field is ignored if the referenced component's type does not support the `description` field. This may contain [CommonMark syntax](https://spec.commonmark.org/) to provide a rich description. |
+
+In the example below, we define a `Drink` schema in the `components` section:
+
+```yaml
+# Drink Schema
+components:
+ schemas:
+ Drink:
+ type: object
+ properties:
+ name:
+ type: string
+ ingredients:
+ type: array
+ items:
+ $ref: "#/components/schemas/Ingredient"
+ instructions:
+ type: string
+```
-### JSON Schema Reference Object
+This component schema can be referenced in API paths:
+
+```yaml
+paths:
+ /drinks:
+ post:
+ summary: Create a new drink
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ name:
+ type: string
+ ingredients:
+ type: array
+ items:
+ $ref: "#/components/schemas/Drink"
+ instructions:
+ type: string
+ responses:
+ '200':
+ description: OK
+```
+
+### JSON Schema References
+
+OpenAPI inherits the flexible JSON Schema `$ref` keyword. A JSON Schema reference is an absolute or relative URI that points to a property in the current schema or an external schema. Relative references are resolved using the current document's location as the base URI.
+
+JSON Schema `$ref` can reference elements within the same schema or external schemas, while OpenAPI Reference Objects are focused on referencing components defined within the `components` section of an OpenAPI document and allows us to override the `summary` and `description` metadata of the referenced component.
+
+#### Absolute References
+
+Absolute references include a protocol like `http://` or `https://` followed by the rest of the URI.
+
+The example below references an `Ingredient` component in a remote OpenAPI document:
+
+```yaml
+paths:
+ /drinks:
+ get:
+ summary: Get ingredients
+ responses:
+ '200':
+ description: OK
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: 'https://speakeasy.bar/schemas/ingredients.yaml#/components/schemas/Ingredient'
+```
+
+#### Relative References
+
+Relative references specify a location based on the current document. They are useful for referencing elements within the same API description.
+
+In the example below, the reference points to the `Drink` schema defined within the `components` section of the current OpenAPI document:
+
+```yaml
+paths:
+ /order:
+ post:
+ summary: Place an order for a drink
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Drink'
+
+```
### Expression
-`TODO`
+Runtime expressions allow us to dynamically determine values during API execution. These expressions add flexibility and reduce the need for hard coding details in an API description.
+
+Expressions in OpenAPI are enclosed in curly braces `{}` and always begin with the dollar sign `$`.
+
+Runtime expressions are commonly used in [Link Objects](#link-object) and [Callbacks Objects](#callback-object) to pass dynamic values to linked operations or callbacks.
+
+```yaml
+paths:
+ /orders/{orderId}:
+ get:
+ # ...
+ links:
+ viewItems:
+ operationId: getOrderItems
+ parameters:
+ orderId: $request.path.orderId # Pass orderId from the parent operation
+```
## Data Type Formats
-`TODO`
+Data type formats in OpenAPI 3.1 provide a standardized way to define the types and formats of data in an API. Below is a list of the standard formats available in OpenAPI:
+
+| Type | Format | Description | Example |
+|-----------|-------------------|-----------------------------------------------------------------------------------------------|------------------------------------------|
+| String | `date-time` | Date and time together, adhering to RFC 3339. | `2023-02-24T18:25:43.511Z` |
+| String | `date` | A calendar date (full-date) as per RFC 3339. | `2023-02-24` |
+| String | `time` | A time of day, with or without time zone information, as per RFC 3339. | `18:25:43.511Z` |
+| String | `duration` | A duration as per ISO 8601. | `P3Y6M4DT12H30M5S` |
+| String | `email` | An email address, conforming to the syntax defined in RFC 5322. | `contact@speakeasy.bar` |
+| String | `idn-email` | An internationalized email address. | `联络@speakeasy.bar` |
+| String | `hostname` | A hostname, following the requirements of RFC 1034 and RFC 1123. | `speakeasy.bar` |
+| String | `idn-hostname` | An internationalized hostname. | `国際化.speakeasy.bar` |
+| String | `ipv4` | An IPv4 address, adhering to the dot-decimal notation as defined in RFC 2673. | `192.0.2.1` |
+| String | `ipv6` | An IPv6 address, as defined in RFC 4291. | `2001:0db8:85a3:0000:0000:8a2e:0370:7334`|
+| String | `uri` | A Uniform Resource Identifier (URI) as per RFC 3986. | `https://speakeasy.bar/menu` |
+| String | `uri-reference` | A URI Reference, which can be a relative or absolute URI, as per RFC 3986. | `/menu/drinks` |
+| String | `iri` | An Internationalized Resource Identifier (IRI) as per RFC 3987. | `https://speakeasy.bar/メニュー` |
+| String | `iri-reference` | An IRI Reference, which can be a relative or absolute IRI, as per RFC 3987. | `/メニュー/ドリンク` |
+| String | `uri-template` | A URI Template as per RFC 6570. | `https://speakeasy.bar/orders/{order}` |
+| String | `json-pointer` | A JSON Pointer as per RFC 6901. | `/drinks/4` |
+| String | `relative-json-pointer` | A relative JSON Pointer. | `1/drinks/7` |
+| String | `regex` | A regular expression, which should be valid according to the ECMA 262 regular expression dialect. | `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$` |
+| Integer | `int32` | signed 32 bits | `2147483647` |
+| Integer | `int64` | signed 64 bits (long) | `9223372036854775807` |
+| Number | `float` | A single-precision 32-bit IEEE 754 floating point. | `3.4028235E38` |
+| Number | `double` | A double-precision 64-bit IEEE 754 floating point. | `1.7976931348623157E308` |
+| String | `password` | A hint to UIs to obscure input. | `p@ssw0rd` |
+
+Tools are not required to implement validation or generation based on these formats and will often use only the most common formats. It is best not to rely on the validation of formats based on generated code, as these values are often used for documentation rather than validation.
diff --git a/bun.lockb b/bun.lockb
index 1d7ffd0..5b60d0c 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/example/README.md b/example/README.md
new file mode 100644
index 0000000..d03abb3
--- /dev/null
+++ b/example/README.md
@@ -0,0 +1,13 @@
+# The Speakeasy Bar API
+
+## Introduction
+
+TODO: Introduction to the Speakeasy Bar API example
+
+## Installing The Speakeasy Bar API
+
+TODO: Installing The Speakeasy Bar API
+
+## Overview Of The Speakeasy Bar API
+
+TODO: Overview Of The Speakeasy Bar API, discuss endpoints and components one by one with inline snippets.
diff --git a/glossary/README.md b/glossary/README.md
new file mode 100644
index 0000000..47d068d
--- /dev/null
+++ b/glossary/README.md
@@ -0,0 +1,11 @@
+# OpenAPI Glossary
+
+TODO: Write short definitions for OpenAPI terms, link to our reference docs. Examples:
+
+## OpenAPI specification
+
+## OpenAPI document
+
+## JSON-Schema
+
+## SDK generator
diff --git a/guides/README.md b/guides/README.md
new file mode 100644
index 0000000..540e758
--- /dev/null
+++ b/guides/README.md
@@ -0,0 +1,20 @@
+# OpenAPI Guides
+
+## Introduction
+
+TODO: OpenAPI Guides Introduction
+
+## Guides
+
+TODO: Guides, categorised/structured according to e.g. documentation, SDKs, CI/CD, etc.
+
+Some examples:
+
+- How to add a webhook using OpenAPI.
+- How to add a list as a path parameter in OpenAPI.
+- Add SDK generation to your CI/CD workflows.
+- Lint and edit documentation strings in your OpenAPI documents.
+- How to generate API documentation using Redoc.
+- How to add Redoc-generated OpenAPI documentation to Docusaurus.
+- How to validate your OpenAPI document as part of CI/CD.
+- etc.
diff --git a/images/openapi-diagram.excalidraw b/images/openapi-diagram.excalidraw
new file mode 100644
index 0000000..7f0acfd
--- /dev/null
+++ b/images/openapi-diagram.excalidraw
@@ -0,0 +1,3253 @@
+{
+ "type": "excalidraw",
+ "version": 2,
+ "source": "https://excalidraw.com",
+ "elements": [
+ {
+ "type": "line",
+ "version": 2297,
+ "versionNonce": 889934367,
+ "isDeleted": false,
+ "id": "0Sp8sF-OeA1qOfbeK5nRL",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 836.5199479807073,
+ "y": 483.11743486842795,
+ "strokeColor": "#000000",
+ "backgroundColor": "#000000",
+ "width": 71.13384147098816,
+ "height": 66.90830545967371,
+ "seed": 221146689,
+ "groupIds": [
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 1.062361923620693,
+ 32.00749589815401
+ ],
+ [
+ 9.120599151341644,
+ 59.86119083449851
+ ],
+ [
+ 38.849653239029394,
+ 66.90830545967371
+ ],
+ [
+ 71.13384147098816,
+ 64.62986364920746
+ ],
+ [
+ 48.86597679010843,
+ 41.21171914817367
+ ],
+ [
+ 22.384140726805057,
+ 17.087388026514688
+ ],
+ [
+ 0,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 360,
+ "versionNonce": 1906418513,
+ "isDeleted": false,
+ "id": "0Y9K4tUu2EOmkReSmtp7L",
+ "fillStyle": "cross-hatch",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 836.4180584165914,
+ "y": 483.2593253174088,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 206.34074596883596,
+ "height": 0,
+ "seed": 1017708065,
+ "groupIds": [
+ "pdPnff0YmK5r9iajzNFZf",
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -206.34074596883596,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 416,
+ "versionNonce": 758756927,
+ "isDeleted": false,
+ "id": "rABl-qakxFPCyz52nPVTO",
+ "fillStyle": "cross-hatch",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 630.5585901945354,
+ "y": 483.26118667686865,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 0,
+ "height": 398.4859394289134,
+ "seed": 1644597761,
+ "groupIds": [
+ "pdPnff0YmK5r9iajzNFZf",
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 398.4859394289134
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 371,
+ "versionNonce": 622006577,
+ "isDeleted": false,
+ "id": "RHc80pujmW3yxcKek4nYo",
+ "fillStyle": "cross-hatch",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 630.1874079366612,
+ "y": 881.6744375542422,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 278.8341374256796,
+ "height": 0,
+ "seed": 1380362721,
+ "groupIds": [
+ "pdPnff0YmK5r9iajzNFZf",
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 278.8341374256796,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 374,
+ "versionNonce": 910595679,
+ "isDeleted": false,
+ "id": "Cxdn8FSvoZegmQF4yptoV",
+ "fillStyle": "cross-hatch",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 908.6672771399102,
+ "y": 883.0819645768958,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 0.22518584308543868,
+ "height": 335.97708704803824,
+ "seed": 377013697,
+ "groupIds": [
+ "pdPnff0YmK5r9iajzNFZf",
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0.22518584308543868,
+ -335.97708704803824
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 329,
+ "versionNonce": 668713745,
+ "isDeleted": false,
+ "id": "135pGusT9mMSzN66lRIub",
+ "fillStyle": "cross-hatch",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 834.671560632666,
+ "y": 482.6689397231678,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 73.78130588702145,
+ "height": 66.95934579309397,
+ "seed": 1773954465,
+ "groupIds": [
+ "pdPnff0YmK5r9iajzNFZf",
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 73.78130588702145,
+ 66.95934579309397
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 1496,
+ "versionNonce": 654471807,
+ "isDeleted": false,
+ "id": "u_fuzLYfe7g0Ul-hBhk8l",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 638.6654536851789,
+ "y": 715.7348591496311,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fff",
+ "width": 348.3540053081163,
+ "height": 108.52424902118653,
+ "seed": 2000750977,
+ "groupIds": [
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 129.34663488233835,
+ 0
+ ],
+ [
+ 276.3314472486323,
+ 0.9776959371278322
+ ],
+ [
+ 299.84901722723924,
+ 7.332719528458476
+ ],
+ [
+ 309.1580553437715,
+ 30.79742201952584
+ ],
+ [
+ 309.6480047183255,
+ 73.32719528458549
+ ],
+ [
+ 302.29876410001043,
+ 100.21383355560015
+ ],
+ [
+ 276.3314472486322,
+ 107.54655308405856
+ ],
+ [
+ 130.81648300600153,
+ 108.52424902118653
+ ],
+ [
+ -1.9597974982173039,
+ 107.5465530840588
+ ],
+ [
+ -27.927114349595772,
+ 99.23613761847217
+ ],
+ [
+ -38.70600058979076,
+ 75.282587158841
+ ],
+ [
+ -37.726101840682134,
+ 31.286269988089657
+ ],
+ [
+ -25.96731685137868,
+ 6.843871559894628
+ ],
+ [
+ 0,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 333,
+ "versionNonce": 376649969,
+ "isDeleted": false,
+ "id": "Ear82iups2ZS0i93Nlq0m",
+ "fillStyle": "cross-hatch",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 669.015186811921,
+ "y": 705.998048567473,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 203.76666259765625,
+ "height": 121.55333340874198,
+ "seed": 1480995169,
+ "groupIds": [
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [
+ {
+ "id": "lqy-s-QViuCL_uzCHt1D4",
+ "type": "arrow"
+ },
+ {
+ "id": "93GAVamdVhP2b81Bmqae2",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "fontSize": 77.50710975666918,
+ "fontFamily": 1,
+ "text": "JSON",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "JSON",
+ "lineHeight": 1.5682862358092613,
+ "baseline": 81
+ },
+ {
+ "type": "line",
+ "version": 186,
+ "versionNonce": 674089631,
+ "isDeleted": false,
+ "id": "Kq-m_0rXaRT9u2wETiEN0",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 659.6217542209372,
+ "y": 553.2789237510643,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ffffff",
+ "width": 152.20557681248553,
+ "height": 0,
+ "seed": 1377525057,
+ "groupIds": [
+ "8_VdqzlNYESqGjJrdCeUe",
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 152.20557681248553,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 431,
+ "versionNonce": 308343505,
+ "isDeleted": false,
+ "id": "3JjjW0lV5T6VxaO42ceSc",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 659.813906808278,
+ "y": 581.3534396925372,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ffffff",
+ "width": 197.3650494136525,
+ "height": 0,
+ "seed": 1411386657,
+ "groupIds": [
+ "8_VdqzlNYESqGjJrdCeUe",
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 197.3650494136525,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 445,
+ "versionNonce": 1987649215,
+ "isDeleted": false,
+ "id": "C69E1kJAlePhtD4qVhrae",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 659.8831882130464,
+ "y": 609.98680059863,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ffffff",
+ "width": 197.3650494136525,
+ "height": 0,
+ "seed": 902021377,
+ "groupIds": [
+ "8_VdqzlNYESqGjJrdCeUe",
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 197.3650494136525,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 490,
+ "versionNonce": 540831921,
+ "isDeleted": false,
+ "id": "hgakODYjhCBstDryt-ibb",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 659.8987147753032,
+ "y": 638.6455473533395,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ffffff",
+ "width": 197.3650494136525,
+ "height": 0,
+ "seed": 881195233,
+ "groupIds": [
+ "8_VdqzlNYESqGjJrdCeUe",
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 197.3650494136525,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "line",
+ "version": 507,
+ "versionNonce": 1686433503,
+ "isDeleted": false,
+ "id": "Ey3agQIYhjuXd7Zs8i4lf",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 659.6604544459931,
+ "y": 670.6631481822227,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ffffff",
+ "width": 197.3650494136525,
+ "height": 0,
+ "seed": 838218945,
+ "groupIds": [
+ "8_VdqzlNYESqGjJrdCeUe",
+ "PkOiniSNfdaYw97NiLpTh",
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 197.3650494136525,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 592,
+ "versionNonce": 256180479,
+ "isDeleted": false,
+ "id": "ZkcnFIryEFtwbzEKQzBfE",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 579.9051236666671,
+ "y": 244.5,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 387.73333740234375,
+ "height": 210.00000000000014,
+ "seed": 1539019631,
+ "groupIds": [
+ "7GwKqMHlLyNLMGd4IQKpt"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "lqy-s-QViuCL_uzCHt1D4",
+ "type": "arrow"
+ },
+ {
+ "id": "WiwCsA7fH0R7us5NMfDDN",
+ "type": "arrow"
+ },
+ {
+ "id": "8Hiexhf8TWdPZkQf-99vd",
+ "type": "arrow"
+ },
+ {
+ "id": "I7LRbi-gK7LZFQzD79CF2",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121247808,
+ "link": null,
+ "locked": false,
+ "fontSize": 84.00000000000006,
+ "fontFamily": 1,
+ "text": "OpenAPI\nDocument",
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "OpenAPI\nDocument",
+ "lineHeight": 1.25,
+ "baseline": 179
+ },
+ {
+ "type": "ellipse",
+ "version": 2054,
+ "versionNonce": 1544768607,
+ "isDeleted": false,
+ "id": "fD9I9Gm1V_dmkbCIvja3Q",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 0,
+ "angle": 0,
+ "x": -117.8786615818355,
+ "y": 641.288005084831,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 414.25732316367123,
+ "height": 414.25732316367123,
+ "seed": 1462034175,
+ "groupIds": [
+ "ERowcqIJG0kL-ISRNJDQI"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "lqy-s-QViuCL_uzCHt1D4",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121319427,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "line",
+ "version": 2436,
+ "versionNonce": 549033151,
+ "isDeleted": false,
+ "id": "QlSGIvwBwEejREQO79adn",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -12.551627823928584,
+ "y": 924.5631663961851,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 192.8271764417473,
+ "height": 171.70706293354758,
+ "seed": 1917757215,
+ "groupIds": [
+ "I3q17Ri2pJnSlrT5ihcS9",
+ "ERowcqIJG0kL-ISRNJDQI"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121319428,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 21.59664376147569,
+ -113.78178869090506
+ ],
+ [
+ 92.55704469203873,
+ -171.70706293354758
+ ],
+ [
+ 163.51744562260177,
+ -126.19434745718544
+ ],
+ [
+ 192.8271764417473,
+ -11.814796909425738
+ ],
+ [
+ 0,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "ellipse",
+ "version": 2176,
+ "versionNonce": 457614559,
+ "isDeleted": false,
+ "id": "nhJN3V7KwZP5Xg78jdBWT",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 36.21861830797562,
+ "y": 663.3094907396614,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 98.72751433817469,
+ "height": 86.38657504590316,
+ "seed": 1900702527,
+ "groupIds": [
+ "I3q17Ri2pJnSlrT5ihcS9",
+ "ERowcqIJG0kL-ISRNJDQI"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1709121319428,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 3402,
+ "versionNonce": 1039970559,
+ "isDeleted": false,
+ "id": "JZzzwvuNsgR-pZvL05OHX",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -80.68428712059244,
+ "y": 944.8233414304684,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 332.5333251953125,
+ "height": 177.4010023264076,
+ "seed": 7908191,
+ "groupIds": [
+ "a42ig6Vi_M-19xM_Fnpzv",
+ "ERowcqIJG0kL-ISRNJDQI"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "zyYYyw8oUspA7HUQi2xgr",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121319428,
+ "link": null,
+ "locked": false,
+ "fontSize": 70.96040093056304,
+ "fontFamily": 1,
+ "text": "API\nDeveloper",
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "API\nDeveloper",
+ "lineHeight": 1.25,
+ "baseline": 151
+ },
+ {
+ "id": "lqy-s-QViuCL_uzCHt1D4",
+ "type": "arrow",
+ "x": 310.41358944081355,
+ "y": 802.2940940405077,
+ "width": 243.72533913592213,
+ "height": 333.62495544849844,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "seed": 820115249,
+ "version": 1333,
+ "versionNonce": 2126839967,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "8piTPccs6PuVWJtfpqwJ-"
+ }
+ ],
+ "updated": 1709121319428,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 243.72533913592213,
+ -333.62495544849844
+ ]
+ ],
+ "lastCommittedPoint": null,
+ "startBinding": {
+ "elementId": "fD9I9Gm1V_dmkbCIvja3Q",
+ "focus": 0.7299030316251229,
+ "gap": 18.793061587938382
+ },
+ "endBinding": {
+ "elementId": "ZkcnFIryEFtwbzEKQzBfE",
+ "focus": 0.4899801175607359,
+ "gap": 29.405123666666896
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow"
+ },
+ {
+ "id": "8piTPccs6PuVWJtfpqwJ-",
+ "type": "text",
+ "x": 260.78333282470726,
+ "y": 537.1666666666667,
+ "width": 141.93333435058594,
+ "height": 45,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "seed": 659170911,
+ "version": 21,
+ "versionNonce": 33165361,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "text": "Creates",
+ "fontSize": 36,
+ "fontFamily": 1,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "baseline": 32,
+ "containerId": "lqy-s-QViuCL_uzCHt1D4",
+ "originalText": "Creates",
+ "lineHeight": 1.25
+ },
+ {
+ "type": "ellipse",
+ "version": 1570,
+ "versionNonce": 1837818385,
+ "isDeleted": false,
+ "id": "YgKGbgM71VUiMWEXnGewC",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 0,
+ "angle": 0,
+ "x": 1702.1213384181642,
+ "y": 383.7880050848312,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 334.25732316367146,
+ "height": 334.25732316367146,
+ "seed": 1917941809,
+ "groupIds": [
+ "cT1lYjXNN51M95HpwiGkL"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "WiwCsA7fH0R7us5NMfDDN",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 1998,
+ "versionNonce": 781763455,
+ "isDeleted": false,
+ "id": "6EnXbtHQp5gNASWQ97CYd",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1787.335278760687,
+ "y": 433.29650442225807,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 166.4483856088345,
+ "height": 110.96559040588984,
+ "seed": 783632913,
+ "groupIds": [
+ "gxVN5plA-sf_mjMTBT18e",
+ "cT1lYjXNN51M95HpwiGkL"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 1
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 2109,
+ "versionNonce": 921073649,
+ "isDeleted": false,
+ "id": "fS_-kT-m5CRoi7gJH3K-t",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1771.459956823248,
+ "y": 556.6131599607396,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 195.58008635350393,
+ "height": 26.771418664357462,
+ "seed": 914612209,
+ "groupIds": [
+ "gxVN5plA-sf_mjMTBT18e",
+ "cT1lYjXNN51M95HpwiGkL"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 1
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 2278,
+ "versionNonce": 1792146335,
+ "isDeleted": false,
+ "id": "WBt3eAkVQBzpOFLUxwsCy",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1915.65483974665,
+ "y": 566.4167780631813,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 35.0458399260337,
+ "height": 6.755698371874781,
+ "seed": 1472510417,
+ "groupIds": [
+ "gxVN5plA-sf_mjMTBT18e",
+ "cT1lYjXNN51M95HpwiGkL"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 1
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 2380,
+ "versionNonce": 1611944401,
+ "isDeleted": false,
+ "id": "BFqQ76CLxq0IvEfnH67T7",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1853.5652584311906,
+ "y": 545.9925736830936,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 35.0458399260337,
+ "height": 6.755698371874781,
+ "seed": 865032113,
+ "groupIds": [
+ "gxVN5plA-sf_mjMTBT18e",
+ "cT1lYjXNN51M95HpwiGkL"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 1
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 2709,
+ "versionNonce": 393162687,
+ "isDeleted": false,
+ "id": "JvGcnLUCtOC0cDy4cf6nU",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1801.629909770832,
+ "y": 446.1341180481726,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 138.07161035020977,
+ "height": 86.60293262828154,
+ "seed": 1544239505,
+ "groupIds": [
+ "gxVN5plA-sf_mjMTBT18e",
+ "cT1lYjXNN51M95HpwiGkL"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 1
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "text",
+ "version": 2652,
+ "versionNonce": 1043066801,
+ "isDeleted": false,
+ "id": "LpJORiJnM2ikblbl4Goay",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1665.4166717529292,
+ "y": 596.9658742791532,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 407.6666564941406,
+ "height": 214.71286389576645,
+ "seed": 846192497,
+ "groupIds": [
+ "sf1JV6oYtWyABzhDrqWtg",
+ "cT1lYjXNN51M95HpwiGkL"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "WiwCsA7fH0R7us5NMfDDN",
+ "type": "arrow"
+ },
+ {
+ "id": "71J6Cu2nsuvHNr1AFonQP",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "fontSize": 57.256763705537715,
+ "fontFamily": 1,
+ "text": "API\nDocumentation\nGenerator",
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "API\nDocumentation\nGenerator",
+ "lineHeight": 1.25,
+ "baseline": 194
+ },
+ {
+ "id": "WiwCsA7fH0R7us5NMfDDN",
+ "type": "arrow",
+ "x": 1679.7125013788364,
+ "y": 521.9443524243961,
+ "width": 701.7125013788364,
+ "height": 135.76650579974898,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "seed": 566766897,
+ "version": 541,
+ "versionNonce": 2123423711,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "Waah73DAFg7c5I_sKTF_b"
+ }
+ ],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -701.7125013788364,
+ -135.76650579974898
+ ]
+ ],
+ "lastCommittedPoint": null,
+ "startBinding": {
+ "elementId": "YgKGbgM71VUiMWEXnGewC",
+ "focus": -0.04440336304481718,
+ "gap": 24.61037559140263
+ },
+ "endBinding": {
+ "elementId": "ZkcnFIryEFtwbzEKQzBfE",
+ "focus": -0.019900384200122058,
+ "gap": 10.361538930989127
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow"
+ },
+ {
+ "id": "Waah73DAFg7c5I_sKTF_b",
+ "type": "text",
+ "x": 1136.433334350586,
+ "y": 317.16666666666686,
+ "width": 108.13333129882812,
+ "height": 45,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "seed": 97245823,
+ "version": 16,
+ "versionNonce": 391434641,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false,
+ "text": "Reads",
+ "fontSize": 36,
+ "fontFamily": 1,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "baseline": 32,
+ "containerId": "WiwCsA7fH0R7us5NMfDDN",
+ "originalText": "Reads",
+ "lineHeight": 1.25
+ },
+ {
+ "type": "ellipse",
+ "version": 1544,
+ "versionNonce": 1380420607,
+ "isDeleted": false,
+ "id": "x4ZNSBz9y-VXW0kI4tR_i",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 0,
+ "angle": 0,
+ "x": 1162.1213384181642,
+ "y": 545.9045654375834,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 334.25732316367146,
+ "height": 334.25732316367146,
+ "seed": 983289585,
+ "groupIds": [
+ "Z-ZU2NujtCJ9--q9ZQwUa"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "8Hiexhf8TWdPZkQf-99vd",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 1972,
+ "versionNonce": 13006705,
+ "isDeleted": false,
+ "id": "lZhP58Dj6-7DwBw7STch0",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1247.3352787606873,
+ "y": 595.4130647750103,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 166.4483856088345,
+ "height": 110.96559040588984,
+ "seed": 285657297,
+ "groupIds": [
+ "1hnawX8znPKWrRQNlrdoc",
+ "Z-ZU2NujtCJ9--q9ZQwUa"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 1
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 2083,
+ "versionNonce": 781431839,
+ "isDeleted": false,
+ "id": "fjMAXGyMllG9Nw19NxLTM",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1231.4599568232484,
+ "y": 718.7297203134918,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 195.58008635350393,
+ "height": 26.771418664357462,
+ "seed": 934774449,
+ "groupIds": [
+ "1hnawX8znPKWrRQNlrdoc",
+ "Z-ZU2NujtCJ9--q9ZQwUa"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 1
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 2252,
+ "versionNonce": 2093506897,
+ "isDeleted": false,
+ "id": "8zuccq6ZijeEEeKARw3hD",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1375.65483974665,
+ "y": 728.5333384159335,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 35.0458399260337,
+ "height": 6.755698371874781,
+ "seed": 693471377,
+ "groupIds": [
+ "1hnawX8znPKWrRQNlrdoc",
+ "Z-ZU2NujtCJ9--q9ZQwUa"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 1
+ },
+ "boundElements": [],
+ "updated": 1709121062018,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 2354,
+ "versionNonce": 1533401151,
+ "isDeleted": false,
+ "id": "fOPavhPLRA64K2PEvcmZT",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1313.5652584311906,
+ "y": 708.1091340358458,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 35.0458399260337,
+ "height": 6.755698371874781,
+ "seed": 530075249,
+ "groupIds": [
+ "1hnawX8znPKWrRQNlrdoc",
+ "Z-ZU2NujtCJ9--q9ZQwUa"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 1
+ },
+ "boundElements": [],
+ "updated": 1709121062019,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "rectangle",
+ "version": 2815,
+ "versionNonce": 1240619615,
+ "isDeleted": false,
+ "id": "iMeV2TGBD1sXcEbcz1prw",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1261.629909770832,
+ "y": 608.2506784009248,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 138.07161035020977,
+ "height": 86.60293262828154,
+ "seed": 826759249,
+ "groupIds": [
+ "1hnawX8znPKWrRQNlrdoc",
+ "Z-ZU2NujtCJ9--q9ZQwUa"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 1
+ },
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "YNGgRinIN7QHwfbNZPl5w"
+ }
+ ],
+ "updated": 1709121066963,
+ "link": null,
+ "locked": false
+ },
+ {
+ "id": "YNGgRinIN7QHwfbNZPl5w",
+ "type": "text",
+ "x": 1280.3990485335835,
+ "y": 639.0521447150655,
+ "width": 100.53333282470703,
+ "height": 25,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [
+ "1hnawX8znPKWrRQNlrdoc",
+ "Z-ZU2NujtCJ9--q9ZQwUa"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "seed": 1872039217,
+ "version": 15,
+ "versionNonce": 674507985,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1709121083742,
+ "link": null,
+ "locked": false,
+ "text": "Speakeasy",
+ "fontSize": 20,
+ "fontFamily": 1,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "baseline": 18,
+ "containerId": "iMeV2TGBD1sXcEbcz1prw",
+ "originalText": "Speakeasy",
+ "lineHeight": 1.25
+ },
+ {
+ "type": "text",
+ "version": 2628,
+ "versionNonce": 638816671,
+ "isDeleted": false,
+ "id": "DKX28bbcxdnCt9Rhj5jd0",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1185.5666656494136,
+ "y": 759.0824346319055,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 287.3666687011719,
+ "height": 143.1419092638443,
+ "seed": 809117233,
+ "groupIds": [
+ "b6ElxKjMbweLJFMNEjNzq",
+ "Z-ZU2NujtCJ9--q9ZQwUa"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "FIL8NP_3SCFOpTfzhml0m",
+ "type": "arrow"
+ },
+ {
+ "id": "aP7pyEn5-lbrXtdlir5SD",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121138572,
+ "link": null,
+ "locked": false,
+ "fontSize": 57.256763705537715,
+ "fontFamily": 1,
+ "text": "SDK\nGenerator",
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "SDK\nGenerator",
+ "lineHeight": 1.25,
+ "baseline": 122
+ },
+ {
+ "id": "8Hiexhf8TWdPZkQf-99vd",
+ "type": "arrow",
+ "x": 1181.2866631007983,
+ "y": 589.2748251447329,
+ "width": 203.50442511785434,
+ "height": 120.07318024004303,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "seed": 757824607,
+ "version": 197,
+ "versionNonce": 1256915217,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "iODvqL4wj5AIHxjANV63A"
+ }
+ ],
+ "updated": 1709121062019,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -203.50442511785434,
+ -120.07318024004303
+ ]
+ ],
+ "lastCommittedPoint": null,
+ "startBinding": {
+ "elementId": "x4ZNSBz9y-VXW0kI4tR_i",
+ "focus": 0.19083260693500598,
+ "gap": 25.768438191393187
+ },
+ "endBinding": {
+ "elementId": "ZkcnFIryEFtwbzEKQzBfE",
+ "focus": -0.0030544306466994595,
+ "gap": 17.8615389309889
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow"
+ },
+ {
+ "id": "iODvqL4wj5AIHxjANV63A",
+ "type": "text",
+ "x": 1172.6833343505857,
+ "y": 525.9166666666667,
+ "width": 108.13333129882812,
+ "height": 45,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "seed": 639313073,
+ "version": 14,
+ "versionNonce": 1846416511,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1709121062019,
+ "link": null,
+ "locked": false,
+ "text": "Reads",
+ "fontSize": 36,
+ "fontFamily": 1,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "baseline": 32,
+ "containerId": "8Hiexhf8TWdPZkQf-99vd",
+ "originalText": "Reads",
+ "lineHeight": 1.25
+ },
+ {
+ "type": "ellipse",
+ "version": 2058,
+ "versionNonce": 1357559537,
+ "isDeleted": false,
+ "id": "W35b4LxnZhCkjwQFpUv3r",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 0,
+ "angle": 0,
+ "x": 549.6213384181644,
+ "y": 1198.7880050848312,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 411.7573231636713,
+ "height": 411.7573231636713,
+ "seed": 2103648945,
+ "groupIds": [
+ "JO6xSXcYPUIdivvrhqh9S"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "zyYYyw8oUspA7HUQi2xgr",
+ "type": "arrow"
+ },
+ {
+ "id": "93GAVamdVhP2b81Bmqae2",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121062019,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "line",
+ "version": 2352,
+ "versionNonce": 292891807,
+ "isDeleted": false,
+ "id": "NyPx4YU1utiZ0Vdobxps5",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 663.2013323676829,
+ "y": 1447.656419371337,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 264.24419967074635,
+ "height": 184.05229196150296,
+ "seed": 1865262225,
+ "groupIds": [
+ "JO6xSXcYPUIdivvrhqh9S"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121062019,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 190.07038923685263,
+ -1.8405229196148813
+ ],
+ [
+ 225.61200673642674,
+ -40.49150423153057
+ ],
+ [
+ 179.25337521524315,
+ -92.02614598075121
+ ],
+ [
+ 182.3439506499887,
+ -141.72026481035726
+ ],
+ [
+ 143.7117577156691,
+ -184.05229196150296
+ ],
+ [
+ 89.62668760762155,
+ -176.69020028304288
+ ],
+ [
+ 67.9926595644025,
+ -147.24183356920244
+ ],
+ [
+ 37.08690521694674,
+ -156.44444816727733
+ ],
+ [
+ 13.907589456355055,
+ -136.19869605151206
+ ],
+ [
+ 13.907589456355055,
+ -104.90980641805672
+ ],
+ [
+ -20.088740325846256,
+ -97.54771473959639
+ ],
+ [
+ -38.632192934319626,
+ -64.41830218652586
+ ],
+ [
+ -33.9963297822013,
+ -20.245752115765285
+ ],
+ [
+ 0,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 3075,
+ "versionNonce": 1295560913,
+ "isDeleted": false,
+ "id": "4c5jRE4MtHhO2WtGqoT2l",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 686.3100076847047,
+ "y": 1472.3002147869865,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 132.1999969482422,
+ "height": 88.16520283410125,
+ "seed": 739043953,
+ "groupIds": [
+ "V88eXyGKRJpgNvow6E59e",
+ "ia2RDO0O_vOC8nKrl34B7",
+ "JO6xSXcYPUIdivvrhqh9S"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1709121062019,
+ "link": null,
+ "locked": false,
+ "fontSize": 70.532162267281,
+ "fontFamily": 1,
+ "text": "API",
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "API",
+ "lineHeight": 1.25,
+ "baseline": 62
+ },
+ {
+ "id": "zyYYyw8oUspA7HUQi2xgr",
+ "type": "arrow",
+ "x": 268.00000000000017,
+ "y": 1114.128643680457,
+ "width": 290.93605705216174,
+ "height": 193.64831077279155,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1300024575,
+ "version": 567,
+ "versionNonce": 500546879,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "Fcvtjo3u1d1uMMwsTJnyL"
+ }
+ ],
+ "updated": 1709121319428,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 290.93605705216174,
+ 193.64831077279155
+ ]
+ ],
+ "lastCommittedPoint": null,
+ "startBinding": {
+ "elementId": "JZzzwvuNsgR-pZvL05OHX",
+ "focus": -0.20668133533338645,
+ "gap": 16.150961925280058
+ },
+ "endBinding": {
+ "elementId": "W35b4LxnZhCkjwQFpUv3r",
+ "focus": -0.13725099334664437,
+ "gap": 13.267408426275694
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow"
+ },
+ {
+ "id": "Fcvtjo3u1d1uMMwsTJnyL",
+ "type": "text",
+ "x": 242.03333282470726,
+ "y": 1038.4166666666667,
+ "width": 141.93333435058594,
+ "height": 45,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "seed": 2055037457,
+ "version": 32,
+ "versionNonce": 1701605041,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1709121062019,
+ "link": null,
+ "locked": false,
+ "text": "Creates",
+ "fontSize": 36,
+ "fontFamily": 1,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "baseline": 32,
+ "containerId": "zyYYyw8oUspA7HUQi2xgr",
+ "originalText": "Creates",
+ "lineHeight": 1.25
+ },
+ {
+ "id": "93GAVamdVhP2b81Bmqae2",
+ "type": "arrow",
+ "x": 773,
+ "y": 842.1666666666669,
+ "width": 2.5,
+ "height": 344.99999999999966,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "seed": 905488465,
+ "version": 123,
+ "versionNonce": 1222365407,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "cchIiTGRS4n7lSSwEj7my"
+ }
+ ],
+ "updated": 1709121062019,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -2.5,
+ 344.99999999999966
+ ]
+ ],
+ "lastCommittedPoint": null,
+ "startBinding": {
+ "elementId": "Ear82iups2ZS0i93Nlq0m",
+ "focus": -0.025876696138663703,
+ "gap": 14.615284690451858
+ },
+ "endBinding": {
+ "elementId": "W35b4LxnZhCkjwQFpUv3r",
+ "focus": 0.06520132057172914,
+ "gap": 12.13796622439429
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow"
+ },
+ {
+ "id": "cchIiTGRS4n7lSSwEj7my",
+ "type": "text",
+ "x": 688.6166687011719,
+ "y": 969.6666666666667,
+ "width": 166.26666259765625,
+ "height": 90,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "seed": 805228529,
+ "version": 48,
+ "versionNonce": 539848849,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1709121062019,
+ "link": null,
+ "locked": false,
+ "text": "Formally\nDescribes",
+ "fontSize": 36,
+ "fontFamily": 1,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "baseline": 77,
+ "containerId": "93GAVamdVhP2b81Bmqae2",
+ "originalText": "Formally\nDescribes",
+ "lineHeight": 1.25
+ },
+ {
+ "id": "FIL8NP_3SCFOpTfzhml0m",
+ "type": "arrow",
+ "x": 1303.7149564695146,
+ "y": 919.6666666666667,
+ "width": 75.53463995629863,
+ "height": 314.9999999999998,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1642598737,
+ "version": 610,
+ "versionNonce": 184108049,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "NQif4MnOxfRnMDiqB2eLM"
+ }
+ ],
+ "updated": 1709121097038,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ -75.53463995629863,
+ 314.9999999999998
+ ]
+ ],
+ "lastCommittedPoint": null,
+ "startBinding": {
+ "elementId": "DKX28bbcxdnCt9Rhj5jd0",
+ "focus": 0.026099060249046062,
+ "gap": 17.442322770916917
+ },
+ "endBinding": {
+ "elementId": "VqwYMmB6w1vAtV5YjlSY1",
+ "focus": 0.012764041285976446,
+ "gap": 16.34806050615464
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow"
+ },
+ {
+ "id": "NQif4MnOxfRnMDiqB2eLM",
+ "type": "text",
+ "x": 1233.6833343505857,
+ "y": 1020.9166666666667,
+ "width": 183.63333129882812,
+ "height": 45,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "seed": 358485919,
+ "version": 18,
+ "versionNonce": 1127429745,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1709121062019,
+ "link": null,
+ "locked": false,
+ "text": "Generates",
+ "fontSize": 36,
+ "fontFamily": 1,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "baseline": 32,
+ "containerId": "FIL8NP_3SCFOpTfzhml0m",
+ "originalText": "Generates",
+ "lineHeight": 1.25
+ },
+ {
+ "type": "rectangle",
+ "version": 3445,
+ "versionNonce": 193420017,
+ "isDeleted": false,
+ "id": "VqwYMmB6w1vAtV5YjlSY1",
+ "fillStyle": "cross-hatch",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 0,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1101.3186339070824,
+ "y": 1251.0147271728213,
+ "strokeColor": "#000000",
+ "backgroundColor": "#ced4da",
+ "width": 195.86273218583085,
+ "height": 195.67517515409816,
+ "seed": 536845009,
+ "groupIds": [
+ "wCQ2YGj6v_H59CFAz8xzm",
+ "aKP9W7wo_yCoR2aZtHNlr",
+ "9CA-0EpB_qH4gp4N5Oqv5",
+ "6fAWMcrmn2cY1cM9PTfMX",
+ "gmd9ZOLpKIMOIM3mmC3km"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "FIL8NP_3SCFOpTfzhml0m",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121097005,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "ellipse",
+ "version": 1399,
+ "versionNonce": 2128385169,
+ "isDeleted": false,
+ "id": "h-XAaLymVKZ7-jhaIBmVS",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 0,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1120.4285054096651,
+ "y": 1270.3764979690177,
+ "strokeColor": "#000000",
+ "backgroundColor": "#868e96",
+ "width": 157.64298918066467,
+ "height": 157.64298918066467,
+ "seed": 1405491377,
+ "groupIds": [
+ "bQO_CCkruZLNoS_Z-2N0Q",
+ "gmd9ZOLpKIMOIM3mmC3km"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1709121097005,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "line",
+ "version": 4946,
+ "versionNonce": 1214110321,
+ "isDeleted": false,
+ "id": "mUu8EO1okcFpXETRdfHVs",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 0,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1168.2774804298272,
+ "y": 1302.0009594365217,
+ "strokeColor": "#000000",
+ "backgroundColor": "#fff",
+ "width": 85.38879544311153,
+ "height": 98.6208945550448,
+ "seed": 700570257,
+ "groupIds": [
+ "bQO_CCkruZLNoS_Z-2N0Q",
+ "gmd9ZOLpKIMOIM3mmC3km"
+ ],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "boundElements": [],
+ "updated": 1709121097005,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 7.664165054406105,
+ 2.6971498212440865
+ ],
+ [
+ 12.829145851940686,
+ 8.236938280841004
+ ],
+ [
+ 19.867784086498194,
+ 5.92344791773095
+ ],
+ [
+ 39.50830317185993,
+ 6.1906803774006205
+ ],
+ [
+ 45.63422762371787,
+ 6.795231383246021
+ ],
+ [
+ 50.372447132944515,
+ 3.0206678710566948
+ ],
+ [
+ 56.953632342706285,
+ -1.547434775419201
+ ],
+ [
+ 58.758598750446914,
+ 4.736633809360634
+ ],
+ [
+ 58.59198646665541,
+ 10.836844076527454
+ ],
+ [
+ 64.61779739711241,
+ 16.612781851426213
+ ],
+ [
+ 67.31136265174064,
+ 33.14769303816077
+ ],
+ [
+ 65.20094039038247,
+ 50.46497985672207
+ ],
+ [
+ 59.06405460406455,
+ 57.193230083875875
+ ],
+ [
+ 50.7056717005274,
+ 60.79736210827851
+ ],
+ [
+ 41.68083966182454,
+ 62.788601304843866
+ ],
+ [
+ 44.068949062835216,
+ 65.03244863512255
+ ],
+ [
+ 46.7625143174634,
+ 70.0074434734677
+ ],
+ [
+ 47.31788859676813,
+ 85.6123817249515
+ ],
+ [
+ 47.206813740907236,
+ 95.06037839943252
+ ],
+ [
+ 44.26333006059189,
+ 96.6955591305901
+ ],
+ [
+ 21.99976363896106,
+ 97.0734597796256
+ ],
+ [
+ 19.21595006394575,
+ 94.34826146861697
+ ],
+ [
+ 18.438426072919118,
+ 83.23254364738314
+ ],
+ [
+ 13.301213989349744,
+ 84.66044649392407
+ ],
+ [
+ 4.803987515986411,
+ 85.2044094830826
+ ],
+ [
+ -3.1378646780720714,
+ 80.64871944888039
+ ],
+ [
+ -8.080695763884666,
+ 72.69326073243768
+ ],
+ [
+ -12.884683279871066,
+ 67.7975938300115
+ ],
+ [
+ -18.077432791370896,
+ 64.35249489867451
+ ],
+ [
+ -11.024179444200065,
+ 65.03244863512255
+ ],
+ [
+ -6.025810930456929,
+ 68.88551980832838
+ ],
+ [
+ -0.3609932815481261,
+ 74.25715432626839
+ ],
+ [
+ 6.525647781831324,
+ 77.61159275941215
+ ],
+ [
+ 14.162044122272158,
+ 76.65965752838494
+ ],
+ [
+ 17.938589221544767,
+ 73.69052621256165
+ ],
+ [
+ 18.29958250309285,
+ 69.02151055561797
+ ],
+ [
+ 20.3266986225554,
+ 64.96445326147781
+ ],
+ [
+ 22.96472644925312,
+ 63.128578173067815
+ ],
+ [
+ 12.995758135732096,
+ 60.56741909911355
+ ],
+ [
+ 3.4710892456549374,
+ 57.426464856723136
+ ],
+ [
+ -1.3884356982619728,
+ 50.35165423398071
+ ],
+ [
+ -5.026137227708354,
+ 33.31077233736416
+ ],
+ [
+ -2.138190975323453,
+ 17.277031211918313
+ ],
+ [
+ 2.0271161194625082,
+ 12.883288813236305
+ ],
+ [
+ -0.3609932815481261,
+ 6.919446514586806
+ ],
+ [
+ 0,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 2310,
+ "versionNonce": 1098605649,
+ "isDeleted": false,
+ "id": "VH_CIvzKAYSrxXo-m49Xv",
+ "fillStyle": "hachure",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1121.6500019999999,
+ "y": 1462.5146906508855,
+ "strokeColor": "#000000",
+ "backgroundColor": "transparent",
+ "width": 155.1999969482422,
+ "height": 75.96153846153845,
+ "seed": 850026609,
+ "groupIds": [
+ "gmd9ZOLpKIMOIM3mmC3km"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1709121097005,
+ "link": null,
+ "locked": false,
+ "fontSize": 60.76923076923077,
+ "fontFamily": 1,
+ "text": "SDKs",
+ "textAlign": "left",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "SDKs",
+ "lineHeight": 1.25,
+ "baseline": 53
+ },
+ {
+ "type": "ellipse",
+ "version": 1895,
+ "versionNonce": 1682850321,
+ "isDeleted": false,
+ "id": "TCwz7ZPr5HU5MR_j4rJbJ",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 0,
+ "angle": 0,
+ "x": 1954.6213384181644,
+ "y": 1011.2880050848312,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 331.7573231636714,
+ "height": 331.7573231636714,
+ "seed": 402921855,
+ "groupIds": [
+ "qmYJsuHurC0ADYIdvLbgC"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "71J6Cu2nsuvHNr1AFonQP",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121151117,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "line",
+ "version": 2543,
+ "versionNonce": 522932145,
+ "isDeleted": false,
+ "id": "mTLrZ4668S8-Vw4itRx5Y",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 2059.36751712532,
+ "y": 1070.3660582096536,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 108.88499043658123,
+ "height": 133.3841132848123,
+ "seed": 2019725727,
+ "groupIds": [
+ "qmYJsuHurC0ADYIdvLbgC"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1709121151118,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 133.3841132848123
+ ],
+ [
+ 108.88499043658123,
+ 133.3841132848123
+ ],
+ [
+ 108.88499043658123,
+ 38.10974665280347
+ ],
+ [
+ 73.84154523860086,
+ 38.10974665280347
+ ],
+ [
+ 73.84154523860086,
+ 1.3610623804572137
+ ],
+ [
+ 108.8849904365809,
+ 38.10974665280365
+ ],
+ [
+ 72.58999362438685,
+ 3.4940278687265176e-13
+ ],
+ [
+ 0,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 3232,
+ "versionNonce": 1634218385,
+ "isDeleted": false,
+ "id": "igtieq1D_Reqi6xiRlbpD",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1918.516662597656,
+ "y": 1216.0492896149713,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 403.9666748046875,
+ "height": 142.07131260563915,
+ "seed": 310183359,
+ "groupIds": [
+ "oQgCqjCoKF7QT9iG98F4S",
+ "-eEHbKe0wmjYkFZaNqdoJ",
+ "GCxhlRHG6H9WsK2xfWeqD",
+ "qmYJsuHurC0ADYIdvLbgC"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1709121151118,
+ "link": null,
+ "locked": false,
+ "fontSize": 56.828525042255656,
+ "fontFamily": 1,
+ "text": "API\nDocumentation",
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "API\nDocumentation",
+ "lineHeight": 1.25,
+ "baseline": 121
+ },
+ {
+ "id": "71J6Cu2nsuvHNr1AFonQP",
+ "type": "arrow",
+ "x": 1930.9242510244037,
+ "y": 832.1666666666669,
+ "width": 96.73730356979513,
+ "height": 187.381717257692,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "seed": 302561969,
+ "version": 173,
+ "versionNonce": 1165996497,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "5-cVXOoREha_Px734Dw54"
+ }
+ ],
+ "updated": 1709121151117,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 96.73730356979513,
+ 187.381717257692
+ ]
+ ],
+ "lastCommittedPoint": null,
+ "startBinding": {
+ "elementId": "LpJORiJnM2ikblbl4Goay",
+ "focus": 0.013978514091284915,
+ "gap": 20.48792849174714
+ },
+ "endBinding": {
+ "elementId": "TCwz7ZPr5HU5MR_j4rJbJ",
+ "focus": -0.06142476104647964,
+ "gap": 17.048919717431716
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow"
+ },
+ {
+ "id": "5-cVXOoREha_Px734Dw54",
+ "type": "text",
+ "x": 1777.4333343505857,
+ "y": 908.4166666666667,
+ "width": 183.63333129882812,
+ "height": 45,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "seed": 1636905535,
+ "version": 18,
+ "versionNonce": 416157649,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1709121062019,
+ "link": null,
+ "locked": false,
+ "text": "Generates",
+ "fontSize": 36,
+ "fontFamily": 1,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "baseline": 32,
+ "containerId": "71J6Cu2nsuvHNr1AFonQP",
+ "originalText": "Generates",
+ "lineHeight": 1.25
+ },
+ {
+ "type": "ellipse",
+ "version": 1965,
+ "versionNonce": 1605630271,
+ "isDeleted": false,
+ "id": "QP-X_3vdTVqBv1ymg_ZIL",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 0,
+ "angle": 0,
+ "x": 1467.121338418165,
+ "y": 1083.750368098777,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 331.7573231636714,
+ "height": 331.7573231636714,
+ "seed": 578065105,
+ "groupIds": [
+ "jrdSlNlDMjIiG_cF7OAdv"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "aP7pyEn5-lbrXtdlir5SD",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121148566,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "line",
+ "version": 2612,
+ "versionNonce": 1737158047,
+ "isDeleted": false,
+ "id": "4_WKTaqwRskxPYQbGw46h",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1571.86751712532,
+ "y": 1142.8284212235994,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 108.88499043658123,
+ "height": 133.3841132848123,
+ "seed": 752619697,
+ "groupIds": [
+ "jrdSlNlDMjIiG_cF7OAdv"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1709121148566,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 133.3841132848123
+ ],
+ [
+ 108.88499043658123,
+ 133.3841132848123
+ ],
+ [
+ 108.88499043658123,
+ 38.10974665280347
+ ],
+ [
+ 73.84154523860086,
+ 38.10974665280347
+ ],
+ [
+ 73.84154523860086,
+ 1.3610623804572137
+ ],
+ [
+ 108.8849904365809,
+ 38.10974665280365
+ ],
+ [
+ 72.58999362438685,
+ 3.4940278687265176e-13
+ ],
+ [
+ 0,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 3304,
+ "versionNonce": 876208575,
+ "isDeleted": false,
+ "id": "Z-CeI1zG6xoSzGYPE6B0_",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": 1431.0166625976565,
+ "y": 1288.511652628917,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 403.9666748046875,
+ "height": 142.07131260563915,
+ "seed": 1566102161,
+ "groupIds": [
+ "N-_J3fKWo5Ytm-RWDdI4f",
+ "5XVg__TrluBC9TIJYBlEU",
+ "se5WdgLHqwQZNmB-a6Opd",
+ "jrdSlNlDMjIiG_cF7OAdv"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1709121148566,
+ "link": null,
+ "locked": false,
+ "fontSize": 56.828525042255656,
+ "fontFamily": 1,
+ "text": "SDK\nDocumentation",
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "SDK\nDocumentation",
+ "lineHeight": 1.25,
+ "baseline": 121
+ },
+ {
+ "id": "aP7pyEn5-lbrXtdlir5SD",
+ "type": "arrow",
+ "x": 1375.2475942440462,
+ "y": 912.1666666666667,
+ "width": 162.37256122635245,
+ "height": 175.99792814071156,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1496317105,
+ "version": 116,
+ "versionNonce": 2080896383,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "UhtnPOl4d1Kp-tjz0Ft_u"
+ }
+ ],
+ "updated": 1709121148566,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 162.37256122635245,
+ 175.99792814071156
+ ]
+ ],
+ "lastCommittedPoint": null,
+ "startBinding": {
+ "elementId": "DKX28bbcxdnCt9Rhj5jd0",
+ "focus": 0.14237720496161724,
+ "gap": 9.94232277091703
+ },
+ "endBinding": {
+ "elementId": "QP-X_3vdTVqBv1ymg_ZIL",
+ "focus": 0.237424700224968,
+ "gap": 21.65287835591434
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow"
+ },
+ {
+ "id": "UhtnPOl4d1Kp-tjz0Ft_u",
+ "type": "text",
+ "x": 1356.1833343505857,
+ "y": 1030.9166666666667,
+ "width": 183.63333129882812,
+ "height": 45,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "seed": 693783071,
+ "version": 12,
+ "versionNonce": 661451679,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1709121144212,
+ "link": null,
+ "locked": false,
+ "text": "Generates",
+ "fontSize": 36,
+ "fontFamily": 1,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "baseline": 32,
+ "containerId": "aP7pyEn5-lbrXtdlir5SD",
+ "originalText": "Generates",
+ "lineHeight": 1.25
+ },
+ {
+ "type": "ellipse",
+ "version": 2033,
+ "versionNonce": 1783312945,
+ "isDeleted": false,
+ "id": "xMpXS1m8f5h1jsRCMVxRl",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 0,
+ "angle": 0,
+ "x": -192.87866158183527,
+ "y": -48.71199491516859,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 321.7573231636712,
+ "height": 321.7573231636712,
+ "seed": 1937049919,
+ "groupIds": [
+ "AC0xNQdZAz_5pTiJs3ozq"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1709121290995,
+ "link": null,
+ "locked": false
+ },
+ {
+ "type": "line",
+ "version": 2682,
+ "versionNonce": 862438417,
+ "isDeleted": false,
+ "id": "rTp2ZKHVaE8MU6kc6qvLF",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -91.28979610919419,
+ "y": 8.585297123163087,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 105.60292300855146,
+ "height": 129.3635806854758,
+ "seed": 1604290911,
+ "groupIds": [
+ "AC0xNQdZAz_5pTiJs3ozq"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [],
+ "updated": 1709121290995,
+ "link": null,
+ "locked": false,
+ "startBinding": null,
+ "endBinding": null,
+ "lastCommittedPoint": null,
+ "startArrowhead": null,
+ "endArrowhead": null,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 0,
+ 129.3635806854758
+ ],
+ [
+ 105.60292300855146,
+ 129.3635806854758
+ ],
+ [
+ 105.60292300855146,
+ 36.96102305299305
+ ],
+ [
+ 71.61577537361515,
+ 36.96102305299305
+ ],
+ [
+ 71.61577537361515,
+ 1.3200365376068433
+ ],
+ [
+ 105.60292300855116,
+ 36.96102305299322
+ ],
+ [
+ 70.40194867236701,
+ 3.388709082228991e-13
+ ],
+ [
+ 0,
+ 0
+ ]
+ ]
+ },
+ {
+ "type": "text",
+ "version": 3384,
+ "versionNonce": 852957681,
+ "isDeleted": false,
+ "id": "Szt9fxuZolNOQzbYMHtaU",
+ "fillStyle": "solid",
+ "strokeWidth": 1,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "angle": 0,
+ "x": -198.30000305175747,
+ "y": 149.87726958003992,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "width": 332.6000061035156,
+ "height": 137.78892597281865,
+ "seed": 1053099391,
+ "groupIds": [
+ "4WjGbkBK39srbtCf_Lmx0",
+ "OpWrl3MebtARTMjKMMAlF",
+ "VSZfQrELP8Ry4I1IUCCNR",
+ "AC0xNQdZAz_5pTiJs3ozq"
+ ],
+ "frameId": null,
+ "roundness": null,
+ "boundElements": [
+ {
+ "id": "I7LRbi-gK7LZFQzD79CF2",
+ "type": "arrow"
+ }
+ ],
+ "updated": 1709121290995,
+ "link": null,
+ "locked": false,
+ "fontSize": 55.11557038912746,
+ "fontFamily": 1,
+ "text": "OpenAPI\nSpecification",
+ "textAlign": "center",
+ "verticalAlign": "top",
+ "containerId": null,
+ "originalText": "OpenAPI\nSpecification",
+ "lineHeight": 1.25,
+ "baseline": 117
+ },
+ {
+ "id": "I7LRbi-gK7LZFQzD79CF2",
+ "type": "arrow",
+ "x": 107.41806293567606,
+ "y": 301.3661925011007,
+ "width": 445.58193706432417,
+ "height": 97.01090692267098,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": {
+ "type": 2
+ },
+ "seed": 1282921105,
+ "version": 450,
+ "versionNonce": 2004919167,
+ "isDeleted": false,
+ "boundElements": [
+ {
+ "type": "text",
+ "id": "Xn7Bjt1w7D1ABH1rlG1v5"
+ }
+ ],
+ "updated": 1709121300387,
+ "link": null,
+ "locked": false,
+ "points": [
+ [
+ 0,
+ 0
+ ],
+ [
+ 445.58193706432417,
+ 97.01090692267098
+ ]
+ ],
+ "lastCommittedPoint": null,
+ "startBinding": {
+ "elementId": "Szt9fxuZolNOQzbYMHtaU",
+ "focus": 0.4989512524952957,
+ "gap": 13.699996948242188
+ },
+ "endBinding": {
+ "elementId": "ZkcnFIryEFtwbzEKQzBfE",
+ "focus": -0.6585433952288602,
+ "gap": 26.905123666666896
+ },
+ "startArrowhead": null,
+ "endArrowhead": "arrow"
+ },
+ {
+ "id": "Xn7Bjt1w7D1ABH1rlG1v5",
+ "type": "text",
+ "x": 237.50903451959596,
+ "y": 282.3716459624362,
+ "width": 185.39999389648438,
+ "height": 135,
+ "angle": 0,
+ "strokeColor": "#1e1e1e",
+ "backgroundColor": "transparent",
+ "fillStyle": "solid",
+ "strokeWidth": 2,
+ "strokeStyle": "solid",
+ "roughness": 1,
+ "opacity": 100,
+ "groupIds": [],
+ "frameId": null,
+ "roundness": null,
+ "seed": 1637472593,
+ "version": 45,
+ "versionNonce": 419967025,
+ "isDeleted": false,
+ "boundElements": null,
+ "updated": 1709121298809,
+ "link": null,
+ "locked": false,
+ "text": "Provides\nvocabulary\nfor",
+ "fontSize": 36,
+ "fontFamily": 1,
+ "textAlign": "center",
+ "verticalAlign": "middle",
+ "baseline": 122,
+ "containerId": "I7LRbi-gK7LZFQzD79CF2",
+ "originalText": "Provides\nvocabulary\nfor",
+ "lineHeight": 1.25
+ }
+ ],
+ "appState": {
+ "gridSize": null,
+ "viewBackgroundColor": "#ffffff"
+ },
+ "files": {}
+}
\ No newline at end of file
diff --git a/images/openapi-diagram.png b/images/openapi-diagram.png
new file mode 100644
index 0000000..04bfca1
Binary files /dev/null and b/images/openapi-diagram.png differ
diff --git a/openapi.yaml b/openapi.yaml
index 24b48d1..d516580 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -20,22 +20,19 @@ servers:
description: The production server.
- url: https://staging.speakeasy.bar
description: The staging server.
- # TODO: Wat for OAS3.1 bug fix - Variables in server URLs are not currently supported.
- # https://github.com/OAI/OpenAPI-Specification/pull/3455
- # We can uncomment this when the bug is fixed, but for now this will not validate.
- # - url: "https://{organization}.{environment}.speakeasy.bar"
- # description: A per-organization and per-environment API.
- # variables:
- # organization:
- # description: The organization name. Defaults to a generic organization.
- # default: api
- # environment:
- # description: The environment name. Defaults to the production environment.
- # default: prod
- # enum:
- # - prod
- # - staging
- # - dev
+ - url: "https://{organization}.{environment}.speakeasy.bar"
+ description: A per-organization and per-environment API.
+ variables:
+ organization:
+ description: The organization name. Defaults to a generic organization.
+ default: api
+ environment:
+ description: The environment name. Defaults to the production environment.
+ default: prod
+ enum:
+ - prod
+ - staging
+ - dev
security:
- apiKey: []
tags:
@@ -159,6 +156,7 @@ paths:
$ref: "#/components/examples/drink_csv"
multipart/form-data:
schema:
+ type: object
properties:
name:
description: The name of the drink.
@@ -308,6 +306,7 @@ paths:
$ref: "#/components/examples/drink_csv"
multipart/form-data:
schema:
+ type: object
properties:
name:
description: The name of the drink.
@@ -486,33 +485,34 @@ paths:
content:
application/json:
schema:
- $ref: "#/components/schemas/Order"
- examples:
- old_fashioned:
- summary: An order for one Old Fashioned
- value:
- { "type": "drink", "productCode": "AC-A2DF3", "quantity": 1 }
- sugar_syrup:
- summary: An order for three units of Sugar Syrup
- value:
- {
- "type": "ingredient",
- "productCode": "NAC-3F2D1",
- "quantity": 3,
- }
+ oneOf:
+ - $ref: "#/components/schemas/DrinkOrder"
+ - $ref: "#/components/schemas/IngredientOrder"
+ discriminator:
+ propertyName: orderType
+ mapping:
+ drink: "#/components/schemas/DrinkOrder"
+ ingredient: "#/components/schemas/IngredientOrder"
responses:
"200":
description: The order was created successfully.
content:
application/json:
schema:
- $ref: "#/components/schemas/Order"
+ oneOf:
+ - $ref: "#/components/schemas/DrinkOrder"
+ - $ref: "#/components/schemas/IngredientOrder"
+ discriminator:
+ propertyName: orderType
+ mapping:
+ drink: "#/components/schemas/DrinkOrder"
+ ingredient: "#/components/schemas/IngredientOrder"
examples:
- old_fashioned:
+ pending_order:
summary: Pending order
description: The order was created successfully but is still pending.
value: '{"type": "drink", "productCode": "AC-A2DF3", "quantity": 1, "status": "pending"}'
- sugar_syrup:
+ completed_order:
summary: Completed order
description: The order was completed immediately as there was enough stock to fulfill it.
value: '{"type": "ingredient", "productCode": "NAC-3F2D1", "quantity": 3, "status": "complete"}'
@@ -767,8 +767,12 @@ components:
description: An order for a drink or ingredient.
type: object
properties:
- type:
- $ref: "#/components/schemas/OrderType"
+ orderType:
+ description: The type of order.
+ type: string
+ enum:
+ - drink
+ - ingredient
productCode:
description: The product code of the drink or ingredient.
type: string
@@ -789,16 +793,41 @@ components:
- complete
readOnly: true
required:
- - type
+ - orderType
- productCode
- quantity
- status
- OrderType:
- description: The type of order.
- type: string
- enum:
- - drink
- - ingredient
+ DrinkOrder:
+ allOf:
+ - $ref: "#/components/schemas/Order"
+ - type: object
+ properties:
+ orderType:
+ type: string
+ enum:
+ - drink
+ barCounter:
+ description: The bar counter to collect the drink from.
+ type: string
+ enum:
+ - upstairs
+ - outside
+ - lounge
+ IngredientOrder:
+ allOf:
+ - $ref: "#/components/schemas/Order"
+ - type: object
+ properties:
+ orderType:
+ type: string
+ enum:
+ - ingredient
+ deliveryAddress:
+ description: The address to deliver the ingredient to.
+ type: string
+ examples:
+ - "123 Main St, Anytown, USA"
+ - "456 Elm St, Anytown, USA"
securitySchemes:
apiKey:
type: apiKey
diff --git a/proposal.md b/proposal.md
new file mode 100644
index 0000000..db63761
--- /dev/null
+++ b/proposal.md
@@ -0,0 +1,75 @@
+# Speakeasy OpenAPI Documentation Proposal
+
+We'd like to propose an implementation plan for the Speakeasy OpenAPI Documentation project.
+
+We recommend creating a static Docusaurus site structured as follows:
+
+```bash
+├── Home page and introduction
+├── example/
+│ ├── Overview of the Speakeasy Bar API example app.
+│ ├── Links to hosted documentation.
+│ └── Working online dummy server.
+├── glossary/
+│ └── Glossary generated from a YAML file.
+├── guides/
+│ └── List of step-by-step guides.
+├── specification/
+│ └── Detailed specification reference document.
+├── tips/
+│ └── Best practices, tips, advice on using OpenAPI.
+└── tutorials/
+ ├── OpenAPI design-first tutorial.
+ └── API-first OpenAPI tutorial.
+```
+
+## Complete Example API
+
+Based on the [`openapi.yaml`](./openapi.yaml) document, we can generate server-side stubs with minimal logic as an open-source TypeScript app to run in a serverless environment.
+
+Speakeasy could host a working example that allows users to make API calls as they explore the documentation and generated SDKs.
+
+This could live under a separate GitHub org, called "The Speakeasy Bar" or similar, and welcome fixes from other developers.
+
+In the docs, we should add an [overview of this example](./example/README.md).
+
+## Glossary
+
+We propose creating a glossary of OpenAPI concepts as a YAML file that we use to generate a [glossary page](./glossary/README.md) in the documentation.
+
+Create a [Remark plugin](https://github.com/remarkjs/remark/blob/main/doc/plugins.md#create-plugins) and mark up glossary terms in the documentation to provide hover-for-definition interaction. There is also the option of using `@grnet/docusaurus-terminology` for this.
+
+For an example, see [Stripe's docs](https://docs.stripe.com/no-code/payment-links) (hover the "Payment Links" link):
+
+
+
+Tooling could improve consistency, finding keywords to mark up.
+
+## Guides
+
+We propose creating [multiple step-by-step guides](./guides/README.md) for specific actions a developer might search for. For example:
+
+- How to add a webhook using OpenAPI.
+- How to add a list as a path parameter in OpenAPI.
+- Add SDK generation to your CI/CD workflows.
+- Lint and edit documentation strings in your OpenAPI documents.
+- How to generate API documentation using Redoc.
+- How to add Redoc-generated OpenAPI documentation to Docusaurus.
+- How to validate your OpenAPI document as part of CI/CD.
+
+To start with, two guides would be enough.
+
+## Specification
+
+A detailed [reference document](./specification/README.md), most of which is already written in [README.md](./README.md).
+
+## Tips and Best Practices
+
+Repurpose content from the blog and write more best practices and tips articles. Or simply link to the blog posts and keep publishing there.
+
+## Tutorials
+
+Two detailed [tutorials](./tutorials/README.md):
+
+1. OpenAPI Design-First Tutorial: Design a small API using OpenAPI, and generate SDKs, server stubs, and documentation.
+2. API-first OpenAPI Tutorial: Create an OpenAPI document to describe an existing API.
diff --git a/specification/README.md b/specification/README.md
new file mode 100644
index 0000000..96bf855
--- /dev/null
+++ b/specification/README.md
@@ -0,0 +1,13 @@
+# OpenAPI Specification
+
+## Introduction to the OpenAPI Specification
+
+TODO: Specification introduction
+
+TODO: We recommend moving the specification from [/README.md](../README.md) here as one long document, much like the official OpenAPI Specification, but with:
+
+- Inline examples from Speakeasy Bar API.
+- Outbound links to guides.
+- Outbound links to tutorial steps.
+- Outbound links to best-practices and tips.
+- Outbound links to SDK generation explanations.
diff --git a/temp-image/hover-term.png b/temp-image/hover-term.png
new file mode 100644
index 0000000..6ef5f8e
Binary files /dev/null and b/temp-image/hover-term.png differ
diff --git a/tips/README.md b/tips/README.md
new file mode 100644
index 0000000..7d1ce87
--- /dev/null
+++ b/tips/README.md
@@ -0,0 +1,3 @@
+# OpenAPI Best Practices and Tips
+
+TODO: Would it make sense to move/copy the [best practices and tips blog posts](https://www.speakeasyapi.dev/post/categories/open-api-tips) here?
diff --git a/tutorials/README.md b/tutorials/README.md
new file mode 100644
index 0000000..81b3795
--- /dev/null
+++ b/tutorials/README.md
@@ -0,0 +1,6 @@
+# OpenAPI Tutorials
+
+TODO: Two detailed tutorials to start with:
+
+1. OpenAPI Design-First Tutorial: Design a small API using OpenAPI, and generate SDKs, server stubs, and documentation.
+2. API-first OpenAPI Tutorial: Create an OpenAPI document to describe an existing API.