I presume we all have written one or multiple API at certain point in time in our career, otherwise you would not have bumped into this article. The article does not describe what REST API is, rather you should have some basic knowledge about REST API before going through the article. Disclaimer: Introduction: Generally when we write REST API, we focus a lot on implementation & very little time on designing the proper request / response schema, API resource models. We jot down just all necessary request & response (in most of the cases HTTP Code 200 series response) parameters in a document, get it reviewed quickly, accordingly we create some resource models & jump into implementation. This strategy works in small to mid-size companies or startup companies. But once you start designing API for larger audience in a enterprise company or consumer internet company, you can’t so easily get away with such minimalist design, a lot of stake holders / teams are involved in the process, a lot of systems might get involved, so a homogeneous & consistent design strategy has to be developed which every stake holder in your organization ( even outside organizations as well ) can relate & contribute to. Open API specification (henceforth called OAS) solves that problem. It’s a standard of describing API comprehensively in machine & human understandable format. The idea is the API should be self sufficient to describe itself with enough granular level details. Major Advantages of having API design standard: It forces you to get a ‘Design First’ attitude. Don’t delve into implementation quickly, spend enough time on designing the API, rectify all possible mistake first. It promotes collaboration. Organisation should have a common standard so that all developers understand the API descriptions & documentation without gaining specialised knowledge for each & every API, API design review becomes better when everyone follows the same standard. A tools ecosystem can be built around this standard which can auto validate the API design, auto generates code & documentation, enhance security for all API. API consumption become easier if both the API creator & consumer (might be different organizations) expresses the API in a common design standard. So you can standardize API design across teams hence cutting down time on developers’ effort to understand each API in a different way. A Brief About OpenAPI Standard: In 2009, a guy called started working on creating a API specification standard what would become Swagger API specification. In August 2012, he published version 1.1 of Swagger spec while working at Reverb Technologies. In March 2014, version 1.2 was published which was more inclined towards . This was the first version to gain widespread adoption across the API industry, and is still in use by some API providers today. Swagger specification 2.0 was published in September 2014 with lot of changes & improvement. In March 2015, acquired interest in Swagger intellectual property & other open source technologies from Reverb Technologies. In December 2015, Swagger specification was donated by SmartBear to a new open-governance organization, set up under Linux foundation: the . These ten companies were the founding member of OpenAPI initiative: 3Scale, Apigee, CapitalOne, Google, IBM, Intuit, Microsoft, PayPal, Restlet and SmartBear. Currently around 30 companies are active member of OpenAPI initiative. In July 2017, the OpenAPI initiative announced the release of OAS v3.0.0, this specification conforms to JSON Schema Draft 5 & it introduced some changes around the schema, introduced new concepts like links, callbacks etc. Tony Tam JSON Schema Draft 4 standard SmartBear Technologies OpenAPI Initiative A Brief About Swagger: Swagger is a tools ecosystem built around OpenAPI specification. Following are some capabilities of different Swagger tools: Swagger provides both online ( called ) & offline ( ) interface where developers can write API specification in YAML format & the editor validates the design in real time, checks compatibility with OAS standard, detects errors on the fly & shows them visually. So it simplifies API development & helps developers to accurately model resources & APIs. Swagger Editor: SwaggerHub downloadable UI can generate API boilerplate code & API models (server stubs) etc from the specification in 20+ languages. This greatly reduces developers’ effort to manually write those code. Swagger Codegen can generate client side code to consume the APIs. This tool can generate client side SDK as well in-case developers want to use SDK at the client app. Swagger Codegen: This tool provides the capability to mock the APIs defined in the specification on the fly. This facility greatly helps to test APIs in a cleaner way without spending extra money & time to create mock servers during the development life cycle. The offline Swagger UI does not provide this capability. Mocking API: SwaggerHub Maintaining API documentation manually is hard as API keeps evolving & for every minor change you don’t need to create a new API version. Swagger has out of the box capability to create & sync documentation from OAS. In case you want to generate documentation for already existing API, you can use to create documentation in run time using annotations or using , you can hit an API end point & generate open API specification from this interface & generate documentation from that specification as well. API Documentation: Swagger Inflector Swagger Inspector Using Swagger Inspector, you can hit end point with proper request & check out the response. API Testing: In many cases, your company might not allow you to use SwaggerHub to maintain API because SwaggerHub is not free (free till a very limited use) & your organization might not trust it. So in order to facilitate the development process, you might need to install Swagger UI in your local machine. Follow the instructions below to create a local Swagger environment where you can non-restrictively create & maintain APIs: We will install Swagger UI & Swagger Editor using docker. So install docker first. docker here, follow the instructions according to your operating system. Download Install Swagger UI, run: docker pull swaggerapi/swagger-ui Run Swagger UI: .This will run the UI on port 8000. Go to browser & type: . You will see Swagger UI running. docker run -p 8000:8080 swaggerapi/swagger-ui [http://localhost](http://localhost/):8000 Install Swagger Editor: docker pull swaggerapi/swagger-editor Run Swagger Editor: . This will run the editor on port 81. docker run -p 81:8080 swaggerapi/swagger-editor Create a project folder in any favourable location. I have created under folder ( I have Ubuntu machine). My project name is: . So the complete directory path of the project is: . You can clone my project & see the code: /home/kousik/gitrepo DummyApiSpec /home/kousik/gitrepo/DummyApiSpec https://github.com/kousiknath/OpenAPISpecExample.git Swagger UI needs a URL to fetch API specification. Since we are hosting Swagger locally, we have to serve the specification file from server. Hence we will install a Simple HTTP file Server in python & use that to serve any file which resides in either or any of its child directories. Go to the folder & create a file called & paste the following code: localhost /home/kousik/gitrepo /home/kousik/gitrepo server.py #!/usr/bin/env pythontry:# Python 3from http.server import HTTPServer, SimpleHTTPRequestHandler, test as test_origimport sysdef test (*args):test_orig(*args, port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000)except ImportError: # Python 2from BaseHTTPServer import HTTPServer, testfrom SimpleHTTPServer import SimpleHTTPRequestHandler class CORSRequestHandler (SimpleHTTPRequestHandler):def end_headers (self):self.send_header('Access-Control-Allow-Origin', '*')SimpleHTTPRequestHandler.end_headers(self) if __name__ == '__main__':test(CORSRequestHandler, HTTPServer) You can go to the folder containing file & run this simple server issuing the following command: server.py python server.py This will by default run the server at port . In order to run the server at any particular port, you can run it like: 8000 python server.py 8100 The above command will run the server at port 8100. This creates a local HTTP file server that can serve any file residing under its parent or any nested sub-directory. The parent directory acts as the base directory of web server, other paths must be relative to this base directory. Since my project & reside under , I can access the API spec from localhost like: . Arrange the directories accordingly & make sure that you are able to access the API spec file from localhost. DummyApiSpec server.py /home/kousik/gitrepo [http://localhost:8100/DummyApiSpec/openapi-3.0/schema/spec.json](http://localhost:8100/DummyApiSpec/openapi-3.0/schema/spec.json) Hands-On with OpenAPI specification: We will create a API specification to better understand different aspects of OAS v2.0 & v3.0. Let’s say you want to create a User service (micro service) which owns all user data. Say this service has a functionality to create a random user which only works in a sandbox / testing environment. You can also get specific user details by querying the service with the corresponding user id. User details contains id, name, date of birth, gender, contact details, user home location, user device preferences etc. We will create the Open API specification for creating & getting the user details using Swagger. Go to the location where you created the project. In my case the project name is & location is: .The directory structure should look like as shown in the below image: DummyApiSpec /home/kousik/gitrepo/DummyApiSpec I am using IntelliJIDEA, any IDE should have the same structure. The folder under contains the specification file defined in accordance with OAS v3.0. The file defined inside is defined according to Swagger-2.0 specification, remember OAS v3.0 is derived from & improved version of Swagger Specification v2.0. The folder contains all reusable API resource models in separate JSON files. For the time being you can just create the folders as shown in picture. You can ignore related folder & files. schema openapi-3.0 spec.json spec.json swagger-2.0 components gradle We will see how to create OAS specification in both v2.0 & v3.0 below & compare them. Creating Random User Generation API with OAS v2.0: OAS v2.0 is the most popular OAS version used today. It has the following schema structure. All the colourful rectangular blocks represents different component at the global / root level in the specification. Following gist is JSON representation of OAS v2.0 of our random user generation API. Let’s decode different components. The first section in the JSON file is which represents which specification version does the file represent. 'swagger' The key maps to a object that contains basic information about the API like API version, title, basic description, developer contact details etc. Put your own details accordingly. info The keys , , together represents the API server URL where the API is supposed to be hosted. So according to the above spec, the API server URL is: . When you use Swagger UI or SwaggerHub to test any API mentioned in the specification file, they internally use this API server URL for testing & all API requests hit this address to get data. schemes host basePath [https://your-domain.com/api/1.0.0](https://your-domain.com/api/1.0.0.) The section represents all security schemes which are supported by our API, it does not apply any of these scheme to any API, it only defines the available schemes. Swagger / OAS v2.0 standard supports the Basic Authorization, API key based authentication through header or query parameter & OAuth 2.0 authentication. It’s up to you which scheme you use for your API, you can use a mix of authentication schemes for different API defined in the same specification file, I have shown here all schemes for example purpose. securityDefinitions mapped object contains many keys like , , , , — these are random names, you can put any name to represent the security schemes, the main thing that matters is the objects represented by those keys: represents Basic Authorization through built in mechanism. supports sending an header that contains ‘Basic’ word followed by a space & base 64 encoded string. Example header: . This mechanism is not secure as base 64 encoded strings can be decoded as well, use to make it more secure. securityDefinitions BasicAuth ApiKey AppId SessionKey OAuth2 BasicAuth HTTP HTTP Authorization username:password Authorization Authorization: Basic 63jYu7uu38uqt356q= HTTPS / / maps to a JSON objects that represent authentication key value pair passed through header keys: ApiKey AppId SessionKey : { : , : , : **"X-API-KEY"**}, : { : , : , : **"X-APP-ID"**}, : { : , : , : **"SESSION-ID"**} "ApiKey" "type" "apiKey" "in" "header" "name" "AppId" "type" "apiKey" "in" "header" "name" "SessionKey" "type" "apiKey" "in" "query" "name" Here, the key has the value , it’s a Swagger / OAS defined type, the key represents where the key has to be passed — either or parameter section, represents the name of the key. type apiKey in header query name represents OAuth2 standard authorization scheme: OAuth2 : { : , : , : , : , : { : , : , : }} "OAuth2" "type" "oauth2" "flow" "accessCode" "authorizationUrl" "https://your-auth-domain.com/oauth/authorize" "tokenUrl" "https://your-auth-domain.com/oauth/token" "scopes" "read" "Grants read access to user resources" "write" "Grants write access to user resources" "admin" "Grants read and write access to administrative information" OAuth2 requires some based on clients will be granted permission to access the corresponding resource. scope The section defines which authentication / authorization scheme is going to be imposed on which API. We have defined global section at the root level that is inherited by all API defined in the spec, we will see how we can override authorization mechanism at individual API level later. is a list of schemes wrapped in JSON objects like: security security security : [{ : [ ]}] "security" "OAuth2" "read" When multiple JSON objects are present inside the list, schemes represented by any of the JSON object will work. Multiple Schemes represented as separate JSON objects maintain relationship. Example: Look at the section of the API: logical OR security GET /users/{user_id} : [{ : [ ]},{ : [], : []},{ : []},{ : []}] "security" "OAuth2" "read" "ApiKey" "ApiId" "BasicAuth" "SessionKey" In the above list, four authentication schemes are applicable for this API for demonstration purpose. All these schemes are in relationship. So proving proper data to any of these schemes will pass the authorization check. For relationship, you can put multiple schemes inside the same JSON object. Like consider the following portion in the above code snippet: logical OR logical AND { : [], : []} "ApiKey" "ApiId" You need to provide both the API key & API Id to pass this combined authorization since both are part of the same JSON object — this is relationship. logical AND In the JSON object, the key name should be exactly equal to any of the scheme name defined in the section i.e; in this example, the key name is which is registered inside , the value is a list of scopes i.e; in the above case, scope is specified. securityDefinition OAuth2 securityDefinitions read More on Swagger / OAS v2.0 authentication . here The keys & maps to list of MIME Types that the APIs can consume in a request body ( not for GET request obviously ) & produce as a response. The top level MIME Types are inherited by all defined APIs although individual API can override these types. consumes produces More on Swagger / OAS v2.0 MIME Types . here section describes all API end points & operations. Let’s explore the API to understand all aspects. paths /user : { : { : , : , : , : , : [ ], : [{ : [ , ]}], : [{ : , : , : , : , : { : }},{ : },{ : }], : { : { }, : { }, : { }, : [ ], : { : , : }}} "/users" "post" "description" "User provides some basic details & this api creates a random user with those details" "summary" "POST api to create a random user" "operationId" "generate_user.post" "deprecated" false "produces" "application/json" "security" "OAuth2" "read" "write" "parameters" "name" "body" "in" "body" "required" true "description" "The user provided basic details will be used to create a random user" "schema" "$ref" "#/definitions/UserBasicDetails" "$ref" "../../components/header_request_id.json" "$ref" "../../components/header_client_id.json" "responses" "201" .... "400" .... "409" .... "tags" "users" "externalDocs" "url" "https://your-domain.com/api/docs/users" "description" "See more on user operations." In OAS terminology, API end point like is called path, all paths are relative to the API server URL as mentioned earlier & associated HTTP verbs are called operations. Since we want to create a random user, our end point is associated with operation ( HTTP verb POST equivalent). /user /user post Swagger 2.0 supports get, post, put, patch, delete, head, and options. Swagger defines a unique operation as a combination of a path and an HTTP method. This means that two GET or two POST methods for the same path are not allowed — even if they have different parameters (parameters have no effect on uniqueness). The keyword is optional, but if provided, it should be unique for each operation. operationId indicates whether the API should be decommissioned soon, it’s useful if the API is already being used by some client, but you have a new version or a alternative API. deprecated We have used to specify a list of MIME Types in global / root level already, we have again specified the same in the operation of API just to show how to override properties inherited from root level. Once overridden, the root level features have no impact on this operation. You can override also in a similar way. produces post /user consumes We have overridden schemes as well inside this operation, since we are creating user here, we have used security scheme with & scope only. Once overridden, the global level schemes will not be imposed on this operation any more. security OAuth2 read write security The section is a list of parameters represented as JSON objects. The key of the parameter object indicates the location where the parameter is expected. Based on location, following are the type of parameters: parameters in This kind of parameter is expected as part of request body, the location is signified by " inside the parameter object. Not applicable for HTTP GET request. Body Parameters: in": "body" If you want to expose parameters in URL like: , here is a query parameter, it’s signified by inside the parameter object. Query Parameter: /api/users?attributes=location,devices attributes "in": "query" If you want to represent API path as a URL like this: , here wrapped inside is a mandatory path parameter. It’s signified by in the parameter object. Path Parameter: /api/user/{user_id} user_id {} "in": "path" More on Swagger v2.0 parameters can be found . here means whether the parameter is mandatory, it’s mandatory when the key’s value is set to . required true is used to describe primitive values, as well as simple arrays and objects serialized into a string. schema lets you refer to content defined in different section like global section in the same specification file or another JSON file in a different directory in the same server or file hosted in another server etc. In our specification, the following code snippet describes that the request body of this particular API operation exists under global section as a JSON object mapped to the key . $ref definitions definitions UserBasicDetails : { : **"#/definitions/UserBasicDetails"**} "schema" "$ref" The value of uses the notation, and the portion starting with uses the notation. This notation lets you specify the target file or a specific part of a file you want to reference. _$ref_ JSON Reference _#_ JSON Pointer In , the resolving starts from the root of the current specification file, then section is found under the root, is found inside this section. So it’s similar to file system directory structure resolution. #/definitions/UserBasicDetails definitions UserBasicDetails definition can also refer to any JSON file lying under any directory, you just need to provide the relative path of that JSON file with respect to the current JSON file. Example: $ref { : **"../../components/header_request_id.json"**} "$ref" The above snippet means, there exists a file called in the directory called which exists in parent of parent of our specification file, refer to the directory structure image to understand properly. header_request_id.json components When is used in a section, all it’s siblings are ignored, this is because replaces itself & all it’s siblings by the value it’s pointing to. So in the following code snippet, the , or any attribute residing in the same level of is ignored. Caution: $ref $ref description title $ref : { : "schema" "$ref" "#/definitions/UserBasicDetails","description": "A reusable user basic details component","title": "xyzab" } More details on . $ref here The section under any API operation defines all the possible response schema for that operation. It’s a JSON object where key names are HTTP status codes like , etc & mapped values define the schema & metadata of that response object. Your API response for that particular HTTP status code will exactly follow the same structure. Let’s see the response structure for HTTP status 201 when the user object gets created: responses 200 400 : { : , : { : { : , : { : , : }}, : { : , : { : , : }}}, : { : }} "201" "description" "" "headers" "X-RateLimit-Limit" "description" "Number of request per time window (hour / 5 min / 15 min)" "schema" "type" "number" "format" "integer" "X-RateLimit-Remaining" "description" "Number of request remaining per time window (hour / 5 min / 15 min)" "schema" "type" "number" "format" "integer" "schema" "$ref" "../../components/user.json" Response structure has general about the response, & actual response . In our API, & headers are defined with their own description & schema, you can put any suitable header key & their type as shown above. description header schema X-RateLimit-Limit X-RateLimit-Remaining Again the actual response body resides in file in the folder & we use to refer to that file relative to the current file (here our file path) path. user.json components $ref spec.json The section inside an API operation contains list of tag names which are used by tools like Swagger UI to logically group operations in the UI. It’s nothing but a grouping of operation in the UI for better clarity. It’s an optional field. tags In the end of the specification file, there is a global sections defined which is array of JSON objects: tags : [{ : , : , : { : }}] "tags" "name" "users" "description" "User related operations exposed by this service" "externalDocs" "url" "https://some-domain.com/users/operations" This section is also an optional field which describes all tags used in the individual API operation level as we saw earlier. We used tag in individual API operations as shown already, here we describe those tags with , & for further information if any. The tag name in these objects should exactly match the individual API level operations’ tags. If any tag name mismatch is there in the global objects, an unnecessary group will be created & shown in the UI. users name description externalDocs tags The section define extra documentation for API operations & tags. This is optional field. externalDocs Representation of reusable Objects / API components: In real life, many of our API which are correlated to the same business problems or domain end up using many common components or resource models. So it does not make sense to write those component again & again for each specification, rather you can place them in a common module or a git repository & reuse them. In our directory structure, the folder holds all reusable components. Reusable components can be defined in the following ways: component Swagger / OAS 2.0 defines a global section where you can define all resource models. Example: in our specification, we defined model just for demonstration. You can define any number of models as per your need. 1. “definitions” section: definitions UserBasicDetails : { : { : , : , : { : { : , : }, : { : , : }}, : [ , ]}} "definitions" "UserBasicDetails" "title" "UserBasicDetails" "type" "object" "properties" "name" "example" "Tony Stark" "type" "string" "gender" "example" "Male" "type" "string" "required" "name" "gender" We referred to this section from the section of api like following: parameters POST /users : [{ : , : , : , : , : { : },......] "parameters" "name" "body" "in" "body" "required" true "description" "The user provided basic details will be used to create a random user" "schema" "$ref" "#/definitions/UserBasicDetails" refers to under the global definitions section. #/definitions/YourModelName YourModelName We have already talked about placing models in any directory like in our case & accessing JSON files residing in those locations through relative path like: 2. Accessing models residing in a different directory: components : { : } "schema" "$ref" "../../components/user.json" This method is particularly useful when you don’t want to put all models in the same specification file rather maintain a modular directory structure. Some Important Data Types: Let’s see the content of the file which represents date of birth of a person: components/dob.json { : [ , ], : , : { : { : 50, : 1, : , : }, : { : , : , : 10, : 60}}} "required" "age" "date" "type" "object" "properties" "date" "maxLength" "minLength" "type" "string" "format" "date-time" "age" "type" "number" "format" "integer" "minimum" "maximum" We have two properties here. The property represents date of birth of the person. Type of this field is , we have specified & attributes of this field, those are optional, but it’s good to have boundary. The field is a hint how to show the data in the UI or treat the data. date string minLength maxLength format The is of type with format. Other available format for type are: , , , . The attributes & are the boundary in which should exist. age number integer number float double int32 int64 minimum maximum age Defining array: Our file looks like below: components/devices.json { : , : { : }, : 0, : 20} "type" "array" "items" "$ref" "./device.json" "minItems" "maxItems" The type of the object is & array objects are placed under field. You can define objects inside or can refer to other existing JSON file using as shown above. & define the limit of total items in an array, these are optional fields, but it’s good to know limits. array items items $ref minItems maxItems More on Swagger (v2.0 & v3.0 both) data types can be found . here Defining enum: Have a look at the API. In the parameters section, we have defined a parameter: GET /users/{user_id} minimal { : , : , : , : , : , : [ , ]} "name" "minimal" "in" "query" "description" "When set to true, returned user object will have only minimum necessary fields, otherwise verbose object will be returned" "required" false "type" "boolean" "enum" true false The parameter identifies whether the object representation in the API response should be minimal with extremely necessary data or complete representation. It’s a boolean field, by default set to false. The boolean values are defined as list, the values defined inside field must match the type defined of the parameter which is in this case. enum enum boolean There is another way to define enum — using vendor extension. Take a look at the file: components/state.json { : 50, : 1, : , : , : [ { : , : }, { : , : }, { : , : }, { : , : } ]} "maxLength" "minLength" "type" "string" "example" "Karnataka" "x-enum" "value" "KA" "description" "Karnataka" "value" "AP" "description" "Andhra Pradesh" "value" "TN" "description" "Tamilnadu" "value" "MH" "description" "Maharasthra" Since we have a limited number of states that are supported in our API, for demonstration purpose, we have made state as enum. is a supported by Swagger. It defines enum values as JSON object with value & description hence making the meaning of enum constants meaningful. The enum’s value is of type here with maximum length of 50. x-enum vendor extension string More on enum can be found . here Now let’s see how Swagger UI shows the API documentation:Go to browser & hit the URL where Swagger UI is running. In my machine, the URL is: Once the page loads, put the URL for swagger specification file in the top bar text box & click on ‘Explore’ button. My spec file URL: [http://localhost:8000](http://localhost:8000.) . http://localhost:8100/DummyApiSpec/swagger-2.0/schema/spec.json image1 In the above figure, appears as http scheme because in our API spec, we defined as . The section lists out all API tagged with . Since we used same tag for both the APIs, they appear in the same section. The section shows all the API models / resources defined under the global section. Since we defined only in the section, that appears here. HTTPS schemes ["https"] users users users Models definitions UserBasicDetails definitions Once you click the green bordered button, it will list out all available authorization schemes that we defined under section. Authorize securityDefinitions Let’s click on the green colour API section, it will expand & look like: POST /users image2 This green section represents the verb / operation at the top of this section — here it’s , then in the next section, & data is rendered. In the section of the page, all , & parameters are shown with a red asterisk (*) meaning that the parameter is required. The supported content type of the request body is shown as a drop-down just below the . HTTP POST description externalDocs Parameters body header query body section Let’s click on the button on the right side. We see the following UI: Try It Out image3 The UI opens up editable text area for & text fields for other applicable parameters like & (not shown here since it’s a POST API). You can insert proper data & click on blue coloured button, the UI will hit the server described in the specification file & show the response. This UI can be used to test API during the development time. Click on red button & go back the the previous UI — image2. body header query Execute Cancel Now in the image 2, click on the Lock symbol (shown at the top right corner of image 2), it will show you the authorization scheme applicable for this API. This applicable scheme comes from the section either defined inside the API operation or from the global / root level definition. We overrode the section inside this API to use . So the authorization UI shows only OAuth related text box. Put proper data if you want to test the API & your make sure your URLs as described in the specification file work. security security OAuth2 OAuth image4 Close the UI & come back to image2. Scroll down to the section which shows all response defined in the specification file with example values as provided in the spec. If no example value is provided for a field, the type of the field like , will become its value. Responses string integer image5 In the above image, the left column corresponds to status code as described in the section of the API spec, the right side drop-down shows the corresponding data type of the response object, it comes from the section of the spec file. Just above the black colour section, you can see is in bold in this image meaning that the black colour response body section only shows sample response, you can click the link next to it, the models associated with the response will be shown. HTTP responses consumes Example Value Model After the section, all with their & are shown. In our API spec, we are returning & headers. You can return anything. body headers description type X-RateLimit-Limit X-RateLimit-Remaining The section errors has the following model & example value: 400 image6 In a similar way, the UI of the looks like: Try It Out GET /users/{user_id} image7 Since this is a API, there is no (request body) parameter in the section, only , & parameters are there. You can see a drop-down containing / values for the boolean field , these values come from the enum defined for the query parameter in the specification file. GET body Parameters path query header true false minimal minimal You have now fair idea about how Swagger documentation looks from UI perspective, once you install Swagger locally or use SwaggerHub, you can play around with the UI & explore more. OAS v3.0 specification of the same API: Basic structure of OAS v3.0 specification: This is how the Open API Specification v3.0 version of our API specification looks like: OAS v3.0 has made some changes in structuring of the file. No , or parameters are used to describe server address or API base URL in OAS v3.0, rather the following is used: schemes basePath host : [{ : }] "servers" "url" "https://your-domain.com/api/1.0.0" So instead of one, you can accommodate multiple servers. OAS v3.0 emphasises on re-usability because multiple API / API operations can share same parameter, request & response body & other metadata. So OAS v3.0 defines a global section & it puts the following re-usable optional sub-sections inside it: components components: Reusable schemas (data models) schemas:... Reusable path, query, header and cookie parameters parameters:... Security scheme definitions (see Authentication) securitySchemes:... Reusable request bodies requestBodies:... Reusable responses, such as 401 Unauthorized or 400 Bad Request responses:... Reusable response headers headers:... Reusable examples examples:... Reusable links links:... Any model residing in this section can be accessed like: : : "$ref" "#/components/requestBodies/YourComponent"or"$ref" "#/components/examples/YourComponent" If you plan to use multiple files describing the models, then you can access as shown already earlier like: : "$ref" "relative/path/to/your/component_file" More on components . here OAS v3.0 uses section inside an API operation to describe , , & parameters. parameter is newly introduced in OAS v3.0. Request body or type parameter is no more supported in this section. For request body, a new section called is introduced inside API operation section, this new section can take text based request body data and form data. parameters path query header cookie Cookie body requestBody More on parameters . here More on request body . here There is no in OAS v3.0, it’s renamed to & has been moved under global section. A new security scheme is introduced as well — cookie based scheme. It’s described as below: securityDefinitions securitySchemes components : { : , : , : **"SESSION_ID"**} "CookieAuth" "type" "apiKey" "in" "cookie" "name" Like all other security schemes, it also can be used in global or API operation level like below: : [{ : []}] "security" "CookieAuth" Here the name inside the objects should exactly match the name of the security scheme described inside the . security securityScheme There has been some changes in how basic auth scheme is defined, has been replaced with . All based security mechanisms like basic or bearer token based auth have been moved to type . This is how http mechanism is described now: type: basic type: basic, scheme: http http http basic : { : , : **"basic"**} "BasicAuth" "type" "http" "scheme" More on authentication . here Let’s see the OAS v3,0 specific changes in API: POST /login The request body section is defined quite differently in OAS v3.0: : { : { : { : [{ : },{ : }]}}} "requestBody" "content" "application/json" "oneOf" "$ref" "#/components/requestBodies/EmailLoginRequest" "$ref" "#/components/requestBodies/MobileLoginRequest" Actual request body structure is defined inside corresponding content type like or or something similar. All these content types are contained inside . So this makes content negotiation very clear to describe, there is no requirement of array any more, you are free to choose content type & their corresponding body & you can describe all of them as above. Open API v3.0 provides support of validating request body schema through a collection of schema, the keywords such as — , , are built for those purpose. These keywords take a list of schema & checks accordingly if the request body schema matches the schema. checks if it given request body schema matches exactly one of the given schema in the list, check if it matches any of the given schema, checks whether it matches all of the schema. So in our example, the request body schema of API should match exactly with only one of the provided schema — or . application/json text/plain content consumes oneOf allOf anyOf oneOf anyOf allOf /login EmailLoginRequest MobileLoginRequest More on , , support . oneOf allOf anyOf here OAS v3.0 introduced callback support. The callback section is defined for API as below: POST /login : { : { : { : { : { : , : { : { : { : , : { : { : , : }}} }}}}}}} "callbacks" "loginEvent" "{$request.body#/callback/url}" "post" "requestBody" "required" true "content" "application/json" "schema" "type" "object" "properties" "message" "type" "string" "example" "Login happened, please process the event." Our API takes a callback URL, when some user logins, we shall call that callback URL with appropriate data & inform about the login event. This example is for demonstration purpose. Here inside the section, we define a random event name called , you can define any name. The event defines which call back URL will be called & with what data. The signifies that our request body has a section called , under that section, key exists. This expression is evaluated in run time & it retrieves the actual callback URL passed in the request body through that key. The section under the callback URL describes how to form the request body to invoke the callback URL. /login callbacks loginEvent {$request.body#/callback/url} callback url post More on callback & run time expression evaluation . here Let’s consider the section for API: responses /login : { : { : { : { : , : { : , : }}}, : , : { : { : { : }, : { : { : , : , : { : , : , : }, : { : , : , : }}, : { : , : , : { : , : , : }, : { : , : , : }}}}}, : { : { : }}},......} "responses" "200" "headers" "Set-Cookie" "description" "Session key is set in cookie named SESSION_ID" "schema" "type" "string" "example" "SESSION_ID=hfuy8747b7gb4dgy466t46; Path=/; HttpOnly" "description" "Successful login" "content" "application/json" "schema" "$ref" "../../components/user.json" "examples" "ex1" "id" "90d640ab-548a-4a72-a89e-b86cdf4f1887" "gender" "Male" "name" "title" "Mr." "first" "Kousik" "last" "Nath" "contact" "email" "you@your-domain.com" "phone" "140000" "cell" "9090909090" "ex2" "id" "4f7386f6-3c89-11e9-b210-d663bd873d93" "gender" "Female" "name" "title" "Mrs." "first" "XYZ" "last" "ABC" "contact" "email" "xyz@abc.com" "phone" "111200" "cell" "9090909090" "links" "GetUserById" "$ref" "#/components/links/GetUserById" In the above code snippet, we are returning header so that for cookie based authentication, this cookie can be used till it’s expired. "Set-Cookie" There is no section in this specification file, rather the content negotiation is made simpler by putting the response schema under particular content type like under mapped to individual response code like in the above snippet. You can use as many as content-types along with their content description. produces application-json content 200 Examples can be added to parameter, object, properties etc to make the API specification clear as examples describe what value a field can take. In OAS v3.0, the is enhanced. You can now use — a JSON object of examples. All keys in this JSON object are distinct & their mapped value describe examples. You can define example schema under the global section and re-use them by referring to them with . example examples components/examples $ref More on examples . here Links are one of the new features of OpenAPI 3.0. Using links, you can describe how various values returned by one operation can be used as input for other operations. This way, links provide a known relationship and traversal mechanism between the operations. The concept of links is somewhat similar to , but OpenAPI links do not require the link information present in the actual responses. hypermedia We have defined section under the global section: links components : { : { : , : , : { : }}} "links" "GetUserById" "description" "Retrieve the user with GET /users/{user_id} API using `id` from the response body" "operationId" "users.get" "parameters" "user_id" "$response.body#/id" We have defined in the also. So once a new user is created through or user logs in through API, we expose the operation to retrieve the created / logged in user through API. We have defined field inside section which maps to the a JSON object that declares which operation we are going to expose as a hypermedia link. The here — points to the API, since both of the APIs are defined in the same specification file, we can use , if APIs are defined in different specification file, we have to use . More details on the link below. The section inside this JSON describes what parameter you need to send while calling the exposed API, in this section, we basically compute any sort of parameter / request body that has to be sent to the exposed API. The retrieves the field from the current API response body in run time. links POST /users POST /users POST /login GET /users/{user_id GetUserById links operationId users.get GET /users/{user_id} operationId operationRef parameters GetUserById $response.body#/id id More on links . here OpenAPI v2.0 is quite a wide spread standard, organizations are moving to OAS v3.0 slowly, but the good part of using such specification is that it scales the API design process, it’s absolutely necessary for big organizations. This post describes API designing both in OAS 2.0 & OAS 3.0, rest is up to you, if you can relate to the benefits of such design, just go for it. References: https://swagger.io/specification/ https://swagger.io/blog/news/whats-new-in-openapi-3-0/ https://github.com/kousiknath/OpenAPISpecExample.git