# Introduction

![](https://366577423-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvM_hZte9ukPjdd%2F-LA-UabHlif69kQ2nJOL%2F-LA-Urn33Tn6OkP5nQwg%2FrelaxLogo150.png?generation=1523648004839169\&alt=media)

## ColdBox Relax v3.0

> RELAX = RESTFul Tools For Lazy Experts!

What is Relax? ColdBox Relax is a set of RESTFul tools for lazy experts. We pride ourselves in helping you (the developer) work smarter, saving yourself time to write great applications!

Relax is a tool to help you document and describe your API services to both end-users, as well as providing an interface for testing endpoint responses.

Providing you with the necessary tools to "automagically" model, document and test your RESTFul services, think of ColdBox Relax as a key tool in your RESTFul web services toolkit.

### License

Apache License, Version 2.0.

### Versioning

ColdBox Relax is maintained under the [Semantic Versioning](http://semver.org) guidelines as much as possible.Releases will be numbered with the following format:

```
<major>.<minor>.<patch>
```

And constructed with the following guidelines:

* Breaking backward compatibility bumps the major (and resets the minor and patch)
* New additions without breaking backward compatibility bumps the minor (and resets the patch)
* Bug fixes and misc changes bumps the patch

### Important Links

* Source Code: <https://github.com/coldbox-modules/coldbox-relax>
* Issues: <https://ortussolutions.atlassian.net/projects/RELAX/issues>
* Documentation: <http://coldbox-relax.ortusbooks.com>

## Discussion & Help

The Box products help and discussion group can be found here:&#x20;

<https://community.ortussolutions.com/c/box-modules/relax/32>

### Professional Open Source

![Ortus Solutions, Corp](https://366577423-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvM_hZte9ukPjdd%2F-LA-UabHlif69kQ2nJOL%2F-LA-UrndOKWl6HPararJ%2Fortussolutions_button.png?generation=1523648004865762\&alt=media)

ColdBox Relax is a professional open source software backed by [Ortus Solutions, Corp](http://www.ortussolutions.com/services) offering services like:

* Custom Development
* Professional Support & Mentoring
* Training
* Server Tuning
* Security Hardening
* Code Reviews
* [Much More](http://www.ortussolutions.com/services)

#### HONOR GOES TO GOD ABOVE ALL

Because of His grace, this project exists. If you don't like this, then don't read it, it's not for you.

> "Therefore being justified by **faith**, we have peace with God through our Lord Jesus Christ:\
> By whom also we have access by **faith** into this **grace** wherein we stand, and rejoice in hope of the glory of God." Romans 5:5


# Overview

So what can you do with Relax?

* Define your ReSTful services via the OpenAPI/Swagger JSON syntax
* Export your documentation to:&#x20;
* * HTML
  * PDF
  * Trac Wiki Markup
  * Mediawiki Wiki Markup (CodexWiki)
* Use the "Relaxer" API Test tool to test your RESTful web service enpoints
* Use the "Relaxer" API Test tool to test against ANY RESTful service
* Keep a history of your latest Relaxed test requests so you can rebuild your request and test again
* Programmatic DSL for configuration of your RESTful services (Deprecated as of v2.3)

## SYSTEM REQUIREMENTS

* Lucee 4.5+
* ColdFusion 10+

## INSTRUCTIONS

Use the box-cli to install

`box install relax`

Or, to install the bleeding-edge version

`box install relax@be`


# Changelog

## 3.0.0

* Standardizes OpenAPI specification
* Relax DSL marked as deprecated ( EOL @ 4.0.0 )
* ACF Compatibility updates
* PDF/HTML Export strategy updates
* UI Bug fixes and enhancements
* Relaxer Test Tool UI and history replay improvements
* ACF Compatibility updates
* Performance enhancements for OpenAPI doc parsing
* Improvements to `$ref` parsing and recursion
* Relaxer service not sending form data correctly
* Refactoring of Relaxer to support typed API on calls to HTTP
* Relaxer not sending http proxy ports
* Relaxer not sending right name for params
* PDF Export Capabilities

## 2.3.1

* Migrates core OpenAPI parsing to swagger-sdk module
* Implements one-click route population and testing in API test tool
* Misc bug fixes and additional support for recursion

## 2.3.0

* \[RELAX-25] - SSL support for assets
* Converts development workflow to user Grunt/SASS/RJS Optimizer
* \[RELAX-5] - Implements OpenAPI Specification as Relax default
* Implements backward compatiblity for RelaxDSL
* \[RELAX-3] - Relaxer is now async
* \[RELAX-11] - Relaxer functionality is now rendered in-page
* \[RELAX-7] - Udates DSL Documentation to use dynamic JS Templating
* Documentation loading is now async
* Adds OpenAPI specification documentation
* Exports for Trac and WikiMedia are now async
* Import issues resolved and converted to async
* Converts code highlighter from SyntaxHighlighter to Prism.js

## 2.2.0

* \[RELAX-22] - Updated build scripts for using DocBox
* \[RELAX-23] - Travis CI integration for tests
* \[RELAX-24] - Update of all dependencies of the shell tester
* \[RELAX-21] - Update StringBuffer to StringBuilders
* \[RELAX-4] - Remove dependency on sessions
* \[RELAX-12] - Sample API is excluded
* \[RELAX-20] - The Resource URL changes for every code change, updated internal hash to pattern hash
* \[RELAX-1] - Implement display and DSLDoc modeling modifications to the Relax module
* \[RELAX-17] - Make test shell full URL rewritable
* \[RELAX-18] - Ability to view resource details from doc viewer

## 2.1.0

* Updates on box.json and locations
* Updated readme
* Updated full skin assets
* Included sample resources in build
* Navigation fixes
* Module Standalone route generation

## 2.0.1

* Fixed resource headers, as they are not showing

## 2.0.0

* <https://ortussolutions.atlassian.net/browse/RELAX/fixforversion/13801>


# Installation

Use [CommandBox](https://www.gitbook.com/book/ortus/commandbox-documentation/details) to install

`box install relax`

Or, to install the bleeding-edge version

`box install relax@be`

## System Requirements

* Lucee 4.5+
* Railo 4+
* ColdFusion 9+

## Settings

You will need to update the your `ColdBox.cfc` with a `relax` structure with your preferred settings for Relax.

```javascript
// Relax Configuration Settings
relax = {
    // The location of the relaxed APIs, defaults to models.resources
    APILocation = "models.resources",
    // Default API to load, name of the directory inside of resources
    defaultAPI = "forgebox",
    // Whether to cache the API Service as a singleton - In development/authoring, you'll want this set to false
    cache = false
};
```

## Modeling

You can look at the samples inside of the `relax` module under the `models/resources` directory.

You may also open up the Relax ui and click the "Export" button on the sidebar to export an example JSON schema which may be customized and then imported back in to Relax.

For reference, the the contents of that export, at the present, would be:

```javascript
{
    "swagger": "2.0",
    "info": {
        "contact": {},
        "termsOfService": "",
        "version": "",
        "license": {},
        "title": "My RESTFul Service",
        "description": "A very cool RESTFul Service"
    },
    "host": "www.myapi.com",
    "basePath": "/",
    "schemes": "http",
    "consumes": [
        "application/json",
        "multipart/form-data",
        "application/x-www-form-urlencoded"
    ],
    "produces": [
        "application/xml",
        "application/json",
        "application/jsont",
        "application/wddx",
        "text/html"
    ],
    "paths": {
        "/api/users": {
            "put": {
                "x-coldbox-handler": "rest.user",
                "parameters": {
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/xml",
                    "application/json",
                    "application/jsont",
                    "application/wddx",
                    "text/html"
                ],
                "x-resourceId": "423bb48aee1fdd4188d0437fd34b3a37",
                "responses": {
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "rest.user.list",
                "description": "Returns all users"
            },
            "x-resourceId": "5dd78a14d6e453994bd4d5c563f90e04",
            "get": {
                "x-coldbox-handler": "rest.user",
                "parameters": {
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/xml",
                    "application/json",
                    "application/jsont",
                    "application/wddx",
                    "text/html"
                ],
                "x-resourceId": "20bab3eff0b870b1f3138093f84ffc8e",
                "responses": {
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "rest.user.list",
                "description": "Returns all users"
            },
            "post": {
                "x-coldbox-handler": "rest.user",
                "parameters": {
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/xml",
                    "application/json",
                    "application/jsont",
                    "application/wddx",
                    "text/html"
                ],
                "x-resourceId": "5cb14ce2dfbed7be9370e932362111ba",
                "responses": {
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "rest.user.list",
                "description": "Returns all users"
            }
        },
        "/api/myResource": {
            "x-resourceId": "c4c000ce2d6075b2f442c39c5834bbb2",
            "get": {
                "x-coldbox-handler": "rest.myUser",
                "parameters": {
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/xml",
                    "application/json",
                    "application/jsont",
                    "application/wddx",
                    "text/html"
                ],
                "x-resourceId": "b9644301f7e1e557b3f63f1df8f9da50",
                "responses": {
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "rest.myUser",
                "description": "Returns of my available resources"
            },
            "post": {
                "x-coldbox-handler": "rest.myUser",
                "parameters": {
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/xml",
                    "application/json",
                    "application/jsont",
                    "application/wddx",
                    "text/html"
                ],
                "x-resourceId": "752d1e616a6d0dfa1524d4fd827ebf19",
                "responses": {
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "rest.myUser",
                "description": "Returns of my available resources"
            }
        },
        "/api/user/{username}": {
            "put": {
                "x-coldbox-handler": "rest.user",
                "parameters": {
                    "username": {
                        "required": true,
                        "in": "path",
                        "type": "string",
                        "x-defaultValue": "",
                        "description": "The resource username to interact with"
                    },
                    "firstName": {
                        "required": true,
                        "in": "formData",
                        "type": "string",
                        "description": "The user firstname. Only used on PUT and POST operations"
                    },
                    "lastName": {
                        "required": true,
                        "in": "formData",
                        "type": "string",
                        "description": "The user lastname. Only used on PUT and POST operations"
                    },
                    "email": {
                        "required": false,
                        "in": "formData",
                        "type": "string",
                        "description": "The user email. Only used on PUT and POST operations"
                    },
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/xml",
                    "application/json",
                    "application/jsont",
                    "application/wddx",
                    "text/html"
                ],
                "x-resourceId": "20a39f01ddab3c47ae9b61a87bb3eaef",
                "responses": {
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "rest.user.{'get':'view','post':'create','put':'update','delete','remove'}",
                "description": "The representation for system users.  You can also interact with creation, updating and deletion via this resource"
            },
            "x-resourceId": "2163611f9de439f64b77aededadcd326",
            "get": {
                "x-coldbox-handler": "rest.user",
                "parameters": {
                    "username": {
                        "required": true,
                        "in": "path",
                        "type": "string",
                        "x-defaultValue": "",
                        "description": "The resource username to interact with"
                    },
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/xml",
                    "application/json",
                    "application/jsont",
                    "application/wddx",
                    "text/html"
                ],
                "x-resourceId": "41a531c92e771514f7f3ae973a50ade7",
                "responses": {
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "rest.user.{'get':'view','post':'create','put':'update','delete','remove'}",
                "description": "The representation for system users.  You can also interact with creation, updating and deletion via this resource"
            },
            "delete": {
                "x-coldbox-handler": "rest.user",
                "parameters": {
                    "username": {
                        "required": true,
                        "in": "path",
                        "type": "string",
                        "x-defaultValue": "",
                        "description": "The resource username to interact with"
                    },
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/xml",
                    "application/json",
                    "application/jsont",
                    "application/wddx",
                    "text/html"
                ],
                "x-resourceId": "b72f4b14a1c422c589e14b5400f1829b",
                "responses": {
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "rest.user.{'get':'view','post':'create','put':'update','delete','remove'}",
                "description": "The representation for system users.  You can also interact with creation, updating and deletion via this resource"
            },
            "post": {
                "x-coldbox-handler": "rest.user",
                "parameters": {
                    "username": {
                        "required": true,
                        "in": "path",
                        "type": "string",
                        "x-defaultValue": "",
                        "description": "The resource username to interact with"
                    },
                    "firstName": {
                        "required": true,
                        "in": "formData",
                        "type": "string",
                        "description": "The user firstname. Only used on PUT and POST operations"
                    },
                    "lastName": {
                        "required": true,
                        "in": "formData",
                        "type": "string",
                        "description": "The user lastname. Only used on PUT and POST operations"
                    },
                    "email": {
                        "required": false,
                        "in": "formData",
                        "type": "string",
                        "description": "The user email. Only used on PUT and POST operations"
                    },
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/xml",
                    "application/json",
                    "application/jsont",
                    "application/wddx",
                    "text/html"
                ],
                "x-resourceId": "89a4cede37f15fbd5ff1bbbaec48eb3e",
                "responses": {
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "rest.user.{'get':'view','post':'create','put':'update','delete','remove'}",
                "description": "The representation for system users.  You can also interact with creation, updating and deletion via this resource"
            }
        },
        "/api/tables/{action}": {
            "x-resourceId": "170810066fc87804d4a6a08dba26fc95",
            "get": {
                "x-coldbox-handler": "rest.table",
                "parameters": {
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/xml",
                    "application/json",
                    "application/jsont",
                    "application/wddx",
                    "text/html"
                ],
                "x-resourceId": "96148eae1c77b5237b9344ddee6dc7c0",
                "responses": {
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "rest.table",
                "description": "Returns table actions"
            }
        },
        "/api/user": {
            "x-resourceId": "d2425574595d4e326a17a88cef917034",
            "get": {
                "x-coldbox-handler": "rest.user",
                "parameters": {
                    "userID": {
                        "required": false,
                        "in": "query",
                        "type": "string",
                        "description": "The userID of the User record."
                    },
                    "username": {
                        "required": false,
                        "in": "query",
                        "type": "string",
                        "description": "The username of the User record."
                    },
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/xml",
                    "application/json",
                    "application/jsont",
                    "application/wddx",
                    "text/html"
                ],
                "x-request-samples": {
                    "examples": {
                        "application/json": {
                            "status": "success",
                            "message": "",
                            "data": {
                                "userid": 1001,
                                "username": "admin",
                                "useremail": "admin@server.com",
                                "userfirstname": "Administrator",
                                "userlastname": "",
                                "userrole": "admin",
                                "clientid": 1001,
                                "clientname": "System"
                            }
                        },
                        "default": {
                            "status": "failure",
                            "message": "Error message",
                            "data": ""
                        }
                    },
                    "sample": {
                        "type": "object"
                    },
                    "x-resourceId": "a23757049c02dff3d4efac828e41edc7",
                    "description": "The basic user information will be returned in a flat object."
                },
                "x-resourceId": "f2345b19ba7c3b061c490ba2e42c7330",
                "responses": {
                    "200": {
                        "examples": {
                            "application/json": {
                                "description": "Response for /users/user resource.",
                                "type": "object",
                                "properties": {
                                    "status": {
                                        "type": "string"
                                    },
                                    "message": {
                                        "type": "string"
                                    },
                                    "data": {
                                        "type": "object",
                                        "properties": {
                                            "userid": {
                                                "type": "integer"
                                            },
                                            "username": {
                                                "type": "string"
                                            },
                                            "useremail": {
                                                "type": "string"
                                            },
                                            "userfirstname": {
                                                "type": "string"
                                            },
                                            "userlastname": {
                                                "type": "string"
                                            },
                                            "userrole": {
                                                "type": "string"
                                            },
                                            "clientid": {
                                                "type": "integer"
                                            },
                                            "clientname": {
                                                "type": "string"
                                            }
                                        }
                                    }
                                }
                            },
                            "application/xml": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\">\n\n\t<xs:element name=\"struct\">\n\t\t<xs:complexType>\n\t\t\t<xs:all>\n\t\t\t\t<xs:element name=\"message\" type=\"xs:string\"></xs:element>\n\t\t\t\t<xs:element name=\"status\" type=\"xs:string\"></xs:element>\n\t\t\t\t<xs:element name=\"data\">\n\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t<xs:element name=\"struct\">\n\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t<xs:all>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userid\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"username\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"useremail\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userlastname\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userfirstname\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userrole\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userstatus\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"clientid\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"clientname\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t</xs:all>\n\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t</xs:complexType>\n\t\t\t\t</xs:element>\n\t\t\t</xs:all>\n\t\t</xs:complexType>\n\t</xs:element>\n\n</xs:schema>\n"
                        },
                        "schema": {
                            "type": "object"
                        },
                        "description": "The following will be returned when the format requested is JSON."
                    },
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "rest.user",
                "description": "User resource."
            },
            "post": {
                "x-coldbox-handler": "rest.user",
                "parameters": {
                    "userID": {
                        "required": false,
                        "in": "formData",
                        "type": "string",
                        "description": "The userID of the User record."
                    },
                    "username": {
                        "required": false,
                        "in": "formData",
                        "type": "string",
                        "description": "The username of the User record."
                    },
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/xml",
                    "application/json",
                    "application/jsont",
                    "application/wddx",
                    "text/html"
                ],
                "x-request-samples": {
                    "examples": {
                        "application/json": {
                            "status": "success",
                            "message": "",
                            "data": {
                                "userid": 1001,
                                "username": "admin",
                                "useremail": "admin@server.com",
                                "userfirstname": "Administrator",
                                "userlastname": "",
                                "userrole": "admin",
                                "clientid": 1001,
                                "clientname": "System"
                            }
                        },
                        "default": {
                            "status": "failure",
                            "message": "Error message",
                            "data": ""
                        }
                    },
                    "sample": {
                        "type": "object"
                    },
                    "x-resourceId": "a23757049c02dff3d4efac828e41edc7",
                    "description": "The basic user information will be returned in a flat object."
                },
                "x-resourceId": "e1b3f5bec92ad2667234472c246f780c",
                "responses": {
                    "201": {
                        "examples": {
                            "application/json": {
                                "description": "Response for /users/user resource.",
                                "type": "object",
                                "properties": {
                                    "status": {
                                        "type": "string"
                                    },
                                    "message": {
                                        "type": "string"
                                    },
                                    "data": {
                                        "type": "object",
                                        "properties": {
                                            "userid": {
                                                "type": "integer"
                                            },
                                            "username": {
                                                "type": "string"
                                            },
                                            "useremail": {
                                                "type": "string"
                                            },
                                            "userfirstname": {
                                                "type": "string"
                                            },
                                            "userlastname": {
                                                "type": "string"
                                            },
                                            "userrole": {
                                                "type": "string"
                                            },
                                            "clientid": {
                                                "type": "integer"
                                            },
                                            "clientname": {
                                                "type": "string"
                                            }
                                        }
                                    }
                                }
                            },
                            "application/xml": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\">\n\n\t<xs:element name=\"struct\">\n\t\t<xs:complexType>\n\t\t\t<xs:all>\n\t\t\t\t<xs:element name=\"message\" type=\"xs:string\"></xs:element>\n\t\t\t\t<xs:element name=\"status\" type=\"xs:string\"></xs:element>\n\t\t\t\t<xs:element name=\"data\">\n\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t<xs:element name=\"struct\">\n\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t<xs:all>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userid\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"username\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"useremail\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userlastname\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userfirstname\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userrole\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userstatus\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"clientid\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"clientname\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t</xs:all>\n\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t</xs:complexType>\n\t\t\t\t</xs:element>\n\t\t\t</xs:all>\n\t\t</xs:complexType>\n\t</xs:element>\n\n</xs:schema>\n"
                        },
                        "schema": {
                            "type": "object"
                        },
                        "description": "The following will be returned when the format requested is JSON."
                    },
                    "default": {
                        "examples": {
                            "application/xml": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\">\n\n\t<xs:element name=\"struct\">\n\t\t<xs:complexType>\n\t\t\t<xs:all>\n\t\t\t\t<xs:element name=\"message\" type=\"xs:string\"></xs:element>\n\t\t\t\t<xs:element name=\"status\" type=\"xs:string\"></xs:element>\n\t\t\t\t<xs:element name=\"data\">\n\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t<xs:sequence>\n\t\t\t\t\t\t\t<xs:element name=\"struct\">\n\t\t\t\t\t\t\t\t<xs:complexType>\n\t\t\t\t\t\t\t\t\t<xs:all>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userid\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"username\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"useremail\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userlastname\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userfirstname\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userrole\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"userstatus\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"clientid\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t\t<xs:element name=\"clientname\" type=\"xs:string\"></xs:element>\n\t\t\t\t\t\t\t\t\t</xs:all>\n\t\t\t\t\t\t\t\t</xs:complexType>\n\t\t\t\t\t\t\t</xs:element>\n\t\t\t\t\t\t</xs:sequence>\n\t\t\t\t\t</xs:complexType>\n\t\t\t\t</xs:element>\n\t\t\t</xs:all>\n\t\t</xs:complexType>\n\t</xs:element>\n\n</xs:schema>\n"
                        },
                        "schema": {
                            "type": "object"
                        },
                        "description": "The following will be returned when the format requested is XML."
                    },
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "rest.user",
                "description": "User resource."
            }
        }
    },
    "securityDefinitions": {
        "apikey": {
            "in": "header",
            "name": "apikey",
            "type": "basic",
            "description": "The apikey needed for request authentication."
        }
    },
    "x-extensionDetection": true,
    "x-throwOnInvalidExtension": false,
    "x-entryPoint": {
        "DEV": "http://dev.myapi.com",
        "PRODUCTION": "http://www.myapi.com"
    }
}
```


# Getting Started

Relax comes with three example API's which are configured by default:

* Swagger Petstore - The swagger Petstore API example, which is described using the OpenAPI/Swagger specification
* Forgebox API - Version 2 of the Forgebox API, which is described through the, now-deprecated, RelaxDSL specification.&#x20;
* MyAPI - Another example, using the RelaxDSL specification. &#x20;

Both `Forgebox` and `MyAPI` may be exported from within the interface in to a normalized Swagger JSON schema, while the `Petstore` example provides and complete example of using a nested file structure to contain different parts of your API documentation.

## Configuration

For custom configuration of your API documentation, you simply add a `relax` configuration to your `Coldbox.cfc` configuration file:

Below is the default configuration structure:

```javascript
// Relax Configuration Settings
relax = {
    // The location of the relaxed APIs, defaults to models.resources
    APILocation = "models.resources",
    // Default API to load, name of the directory inside of resources
    defaultAPI = "forgebox",
    // Whether to cache the API Service as a singleton - In development/authoring, you'll want this set to false
    cache = false
};
```

Note that the `APILocation` key denotes the path to your API resources. You will need to have at lease one API described, in one of the supported specifications, in order to load a default API. You may import new API documentation from the interface, and create additional API's as you continue to develop new services and endpoints.

## Considerations

As you develop your API endpoints, you'll find that the size of your API documentation quickly grows with sample requests, responses, and general documentation on parameters and security constraints. For this reason, it is recommended that you take an "Active Entity" approach to separation of your API documentation. For example, group together a collections of endpoints and paths which related to specific segments of your API. Expanding the "Petstore" example, you might have API's for:

* `/pets`
* `/stores`
* `/products`
* `/orders`

By segmenting your documentation in to functional groups, you make updates and addition of endpoints easier, in the long run.


# Relax Documentation Formats

As of Relax v2.3 and above, the [OpenAPI v2.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md) is the default format for documentation in Relax. The previous RelaxDSL has been deprecated and is schedule to sunset at Relax v4.0. It is, however, still available for use through that time, to support previous documentation.

## ColdBox Relax Available Formats:

* [**OpenAPI/Swagger**](/relax-documentation-formats/openapi-aka-swagger)
* [**Relax Programmatic DSL (Deprecated)**](/relax-documentation-formats/index)


# OpenAPI (AKA Swagger)

As of Relax v2.3 and above, the [OpenAPI v2.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md) is the default format for documentation in Relax. The previous RelaxDSL has been deprecated and is schedule to sunset at Relax v4.0.

The OpenAPI specification offers a convenient and portable way to describe your API, its requirements, parameters, and data conventions. You may also choose to use this to describe your API in the form of [HTTP OPTIONS responses](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) to fulfill [CORS requirements](https://www.w3.org/TR/cors/) or to allow rich [hypermedia](https://en.wikipedia.org/wiki/HATEOAS) documentation for your consumers.

By convention, Relax looks for supported formats in the following order (note that the top-level file shares the name of the parent directory):

1. `myResourceDirectory/myapi/myapi.json`  - JSON OpenAPI schema
2. `myResourceDirectory/myapi/myapi.yaml` - YAML OpenAPI schema
3. `myResourceDirectory/myapi/Relax.cfc` - Relax programmatic DSL (deprecated)

Example ( a segment of the [Forgebox API](https://www.forgebox.io/) ):

```
{
    "swagger": "2.0",
    "info": {
        "contact": {
          "name": "Ortus Solutions",
          "email": "support@ortussolutions.com",
          "url": "http://forgebox.io"
        },
        "termsOfService": "https://www.forgebox.io/policies/terms",
        "version": "2.0",
        "license": {
          "name": "Trademark/Copyright",
          "url": "https://www.forgebox.io/policies/terms"
        },
        "title": "ForgeBox IO",
        "description": "This is the API which powers ForgeBox"
    },
    "host": "forgebox.io",
    "basePath": "/api/v1",,
    "x-entryPoint": {
        "development": "http://localhost:9095",
        "production": "https://forgebox.io",
        "staging": "http://forgebox.stg.ortussolutions.com"
    },
    "schemes": "https",
    "consumes": [
        "application/json",
        "multipart/form-data",
        "application/x-www-form-urlencoded"
    ],
    "produces": [
        "application/json"
    ],
    "paths": {
        "/echo": {
            "x-resourceId": "c2de46855ecc5e676a20e368f4e70297",
            "get": {
                "x-coldbox-handler": "Main",
                "parameters": {
                    "x-resourceId": "166e64f6c3677d0c513901242a3e702d"
                },
                "produces": [
                    "application/json"
                ],
                "x-resourceId": "aeaa242ea76932bd878ddfb1c1f2d881",
                "responses": {
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "operationId": "Main.echo",
                "description": "Simple API echo command"
            }
        }
    },
    "securityDefinitions": {
        "x-app-token": {
            "in": "header",
            "name": "x-app-token",
            "type": "basic",
            "description": "The secret application token"
        }
    },
    "x-extensionDetection": true,
    "x-throwOnInvalidExtension": false
}
```

Note the use of the `x-` attributes, which allow for extensions of the Swagger specification, In addition, more complex API's can use the `$ref` syntax to denote locations and keys of relative JSON files:

```
"paths": {
        "/echo": {"$ref": "paths.json#echo"}
},
```

This notates that the definition for the path `/echo` is found in `paths.json` under the `echo` key. Using the `$ref` notation allows you to store schema examples and other code samples separate from the main JSON or YAML description of your site.

## YAML Support

Per the Swagger formats description:

> The files describing the RESTful API in accordance with the Swagger specification are represented as JSON objects and conform to the JSON standards. YAML, being a superset of JSON, can be used as well to represent a Swagger specification file.

Relax includes support for YAML-format API descriptions, as well.

For full descriptions and examples of the schema specification [read the official OpenAPI v2 specification](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md).


# Relax Programmatic DSL (Deprecated)

## Relax Programmatic DSL

Deprecated as of Relax 2.3, but still available, the Relax DSL configuration object which is mixed into a simple Relax CFC Definition Object so you can use all the methods in this CFC to define RESTful web services. All functions can be concatenated to create a programmatic DSL. This DSL is exportable to OpenAPI formats.

#### Example Using the Forgebox API:

```
this.relax = {
    // Service Title
    title = "ForgeBox IO",
    // Service Description
    description = "This API powers ForgeBox",
    // Service entry point, can be a single string or name value pairs to denote tiers
    //entryPoint = "http://www.myapi.com",
    entryPoint = {
        "production"     : "https://forgebox.io/api/v1",
        "staging"     : "http://forgebox.stg.ortussolutions.com/api/v1",
        "development"     : "http://localhost:9095/api/v1"
    },
    // Does it have extension detection via ColdBox
    extensionDetection = true,
    // Valid format extensions
    validExtensions = "json",
    // Does it throw exceptions when invalid extensions are detected
    throwOnInvalidExtension = false        
};

/************************************** GLOBAL PARAMS +  HEADERS *********************************************/

// Global API Headers
globalHeader( name="x-app-token", description="The secret application token", required=true, type="string" );

/************************************** RESOURCES *********************************************/

// ECHO
resource( pattern="/echo", handler="Main", action="echo" )
    .description( "Simple API echo command" )
    .defaultFormat( "json" )
    .methods( "GET" );
```

## Configuration

The relaxed service information. From here you will define the RESTful service endpoints, extension detection, valid formats, and more.

### Arguments

| Argument                      | Type | Required | Default                     | Description                                 |
| ----------------------------- | ---- | -------- | --------------------------- | ------------------------------------------- |
| title                         | any  | Yes      | ---                         | The title of the RESTful service            |
| description                   | any  | Yes      | ---                         | The description of the RESTful service      |
| entryPoint                    | any  | Yes      | ---                         | A simple URL or a structure of entry points |
| extensionDetection            | any  | No       | true                        | Will this API do extension detection        |
| validExtensions               | any  | No       | json,jsont,xml,html,htm,rss | The valid extensions to detect              |
| The valid extensions to detec | any  | No       | false                       | Throw on invalid extensions or not          |

## Global Headers

Add a global header to the relax definition

### Arguments

| Argument    | Type | Required | Default | Description                      |
| ----------- | ---- | -------- | ------- | -------------------------------- |
| name        | any  | Yes      | ---     | The name of the header           |
| description | any  | No       |         | The description of the header    |
| required    | any  | No       | false   | Is the header required or not    |
| default     | any  | No       |         | The default value of this header |
| type        | any  | No       | string  | The type of the incoming header  |

## Global Params

Add a global parameter to the relax definition

### Arguments

| Argument    | Type | Required | Default | Description                         |
| ----------- | ---- | -------- | ------- | ----------------------------------- |
| name        | any  | Yes      | ---     | The name of the parameter           |
| description | any  | No       |         | The description of the parameter    |
| required    | any  | No       | false   | Is the parameter required or not    |
| default     | any  | No       |         | The default value of this parameter |
| type        | any  | No       | string  | The type of the incoming parameter  |


# Resources

Add a new resource to the API definition, you can then concatenate more methods to the same resource: *methods(),description(),header(),parameter(),placeholder(),schema(),sample()*

## Arguments

| Argument | Type | Required | Default | Description                                  |
| -------- | ---- | -------- | ------- | -------------------------------------------- |
| pattern  | any  | Yes      | ---     | The SES pattern to register for the resource |
| handler  | any  | No       | ---     | The description of the parameter             |
| action   | any  | No       | ---     | Is the parameter required or not             |

## Default Format

Define a default return format for a resource

### Arguments

| Argument | Type | Required | Default | Description                         |
| -------- | ---- | -------- | ------- | ----------------------------------- |
| format   | any  | Yes      | ---     | The format that will be the default |

## Description

Add a description to a resource

### Arguments

| Argument    | Type | Required | Default | Description     |
| ----------- | ---- | -------- | ------- | --------------- |
| description | any  | Yes      | ---     | The description |

## Methods

Add methods to a resource

### Arguments

| Argument | Type | Required | Default | Description               |
| -------- | ---- | -------- | ------- | ------------------------- |
| methods  | any  | Yes      | ---     | The methods list to allow |

## Default Method

Define a default HTTP method for a resource

## Arguments

| Argument | Type | Required | Default | Description                              |
| -------- | ---- | -------- | ------- | ---------------------------------------- |
| method   | any  | Yes      | ---     | The HTTP method that will be the default |


# Parameters

## Param

Add a param to a resource

#### Arguments

| Argument    | Type | Required | Default | Description                    |
| ----------- | ---- | -------- | ------- | ------------------------------ |
| name        | any  | Yes      | ---     | The name of the param          |
| description | any  | No       |         | The description of the param   |
| required    | any  | No       | false   | Is the param required          |
| default     | any  | No       |         | The default value of the param |
| type        | any  | No       | string  | The type of the param          |

## Set All Params

Set all the required parameters of a resource

### Arguments

| Argument | Type  | Required | Default | Description                      |
| -------- | ----- | -------- | ------- | -------------------------------- |
| params   | array | Yes      | ---     | Set the parameters of a resource |


# Placeholders

## Placeholders

Add a placeholder to a resource

### Arguments

| Argument    | Type | Required | Default | Description                          |
| ----------- | ---- | -------- | ------- | ------------------------------------ |
| name        | any  | Yes      | ---     | The name of the placeholder          |
| description | any  | No       |         | The description of the placeholder   |
| required    | any  | No       | false   | Is the placeholder required          |
| default     | any  | No       |         | The default value of the placeholder |
| type        | any  | No       | string  | The type of the placeholder          |

## Set All Placeholders

Set all the required placeholders of a resource

### Arguments

| Argument     | Type  | Required | Default | Description                        |
| ------------ | ----- | -------- | ------- | ---------------------------------- |
| placeholders | array | Yes      | ---     | Set the placeholders of a resource |


# Headers

## Headers

Add a header to a resource

### Arguments

| Argument    | Type | Required | Default | Description                     |
| ----------- | ---- | -------- | ------- | ------------------------------- |
| name        | any  | Yes      | ---     | The name of the header          |
| description | any  | No       |         | The description of the header   |
| required    | any  | No       | false   | Is the header required          |
| default     | any  | No       |         | The default value of the header |
| type        | any  | No       | string  | The type of the header          |

## Set All Headers

Set all the required headers of a resource

### Arguments

| Argument | Type | Required | Default | Description                   |
| -------- | ---- | -------- | ------- | ----------------------------- |
| headers  | any  | Yes      | ---     | Set the headers of a resource |


# Schemas & Samples

## Schemas

Append a schema to a resource

### Arguments

| Argument    | Type | Required | Default | Description                     |
| ----------- | ---- | -------- | ------- | ------------------------------- |
| format      | any  | Yes      | ---     | The format of the schema        |
| description | any  | No       |         | The description of the schema   |
| body        | any  | No       |         | The body contents of the schema |

## Samples

Append a sample to a resource

### Arguments

| Argument    | Type | Required | Default | Description                     |
| ----------- | ---- | -------- | ------- | ------------------------------- |
| format      | any  | Yes      | ---     | The format of the sample        |
| description | any  | No       |         | The description of the sample   |
| body        | any  | No       |         | The body contents of the sample |


# Import and Export Formats

Relax allows you to import an OpenAPI/Swagger JSON specification in to your defined `apiResources` directory, export normalized schema (JSON) for other services and also four export formats:

* HTML
* PDF
* WikiText
* TRAC Format

Markdown export is planned for an upcoming minor release.

![](https://366577423-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LA-UVvM_hZte9ukPjdd%2F-LA-UabHlif69kQ2nJOL%2F-LA-UpwsLrk8Ol1lFyB3%2Frelax-import-export.jpg?generation=1523647997359989\&alt=media)


# cbSwagger Companion Module

The `cbSwagger` module for ColdBox allows you to quickly scaffold your documentation by performing an auto-discovery of your routes and the associated component metadata. To operate, the module requires that SES routing be enabled in your application. For more information [read the official documentation](https://coldbox.ortusbooks.com/the-basics/routing/requirements/rewrite-rules).

## Installation ( via Commandbox )

`box install cbswagger`

> Note: Omit the `box` from your command, if you are already in the Commandbox interactive shell

## Configure cbSwagger to auto-detect your API Routes

By default, cbSwagger looks for routes beginning with `api`. By adding a `cbSwagger` configuration key to your Coldbox configuration, you can add additional metadata to the OpenAPI JSON produced by the module entry point. A full configuration example is provided below:

```
cbswagger = {
    // The route prefix to search.  Routes beginning with this prefix will be determined to be api routes
    "routes":["api"],
    //A base path prefix for your API - leave blank if all routes are configured to the root of the site
    "basePath":"",
    //The API host
    "host":"",
    // Information about your API
    "info":{
        //The contact information
        "contact":{
            "name":"",
            "email":""
        },
        //A title for your API
        "title":"",
        //A descritpion of your API
        "description":"",
        //A url to the License of your API
        "license":{
            "name":"",
            "url":""
        },
        //A terms of service URL for your API
        "termsOfService":"",
        //The version of your API
        "version":""
    },
    //An array of all of the request body formats your your API is configured to consume 
    "consumes": ["application/json","multipart/form-data","application/x-www-form-urlencoded"],
    //An array of all of the response body formats your API delivers
    "produces": ["application/json"]
};
```

## Handler Introspection & Documentation attributes

cbSwagger will automatically introspect your API handlers provided by your routing configuration. You may provide additional function attributes, which will be picked up and included in your documentation. Some notes on function attributes:

* Attributes which are not part of the swagger path specification should be prefixed with an `x-`, [x-attributes](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.md#specificationExtensions) are an official part of the OpenAPI Specification and may be used to provide additional information for your developers and consumers
* You may also provide paths to JSON files which describe complex objects which may not be expressed within the attributes themselves. This is ideal to provide an endpoint for [parameters](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#parameterObject) and [responses](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#responseObject) If the atttribute ends with `.json`, this will be included in the generated OpenAPI document as a [$ref include](https://github.com/OAI/OpenAPI-Specification/blob/OpenAPI.next/versions/3.0.0.md#pathItemObject).

Example:

```javascript
//(POST) /api/v1/users
function add(event,rc,prc)
    description="Adds a new user"
    parameters="/includes/resources/users.add.parameters.json"
    responses="/includes/resources/users.add.responses.json"
    x-SomeAdditionalInfo="Here is some additional information on this path"
{

    ...[ Your code here ]...

}
```


# Swagger SDK

The [ColdBox SwaggerSDK](https://github.com/coldbox-modules/swagger-sdk) is a dependency of the Relax module and is available to allow you to provided consumers of your API with information on paths, methods, expectations and available parameters.

Hypermedia design patterns, usually provided within the content of `OPTIONS` requests to your endpoint, allow you to provide autodiscovery and consumption assistance on-the-fly.

For convenience, built-in methods are available within Relax to simplify the loading and parsing of your existing API documentation.

An example, leveraging an `OPTIONS` request for an endpoint (and using the conventions of the [Coldbox REST API skeleton](https://github.com/coldbox-templates/rest)), might look like:

Routing config:

```
//Pet Routes - collections and additions
addRoute(
    pattern = "api/pets",
    handler = "Pets",
    action  = {
        "GET"    : "index",
        "POST"   : "create",
        "PUT"    : "onInvalidHTTPMethod",
        "PATCH"  : "onInvalidHTTPMethod",
        "DELETE" : "delete",
        "OPTIONS": "options"
    }
);

//Pet Routes - entity methods
addRoute(
    pattern = "api/pets/:id",
    handler = "Pets",
    action  = {
        "GET"    : "get",
        "POST"   : "onInvalidHTTPMethod",
        "PUT"    : "update",
        "PATCH"  : "update",
        "DELETE" : "delete",
        "OPTIONS": "options"
    }
);
```

Now we add an `options` method to our "Pets" handler to serve the documentation

```
public function options( event, rc, prc ){

    petOptions = getInstance( "APIService@relax" ).loadAPI( 'petstore' );

    if( structKeyExists( rc, "id" )){

        prc.response.setData( petOptions.paths[ "/pets/{id}" ] );

    } else {

        prc.response.setData( petOptions.paths[ "/pets" ] );

    }

    prc.response.setStatusCode( STATUS.SUCCESS );

}
```

This will serve information on the requested path of the `petstore` API as a JSON response to an `OPTIONS` request (using the collection example):

```
"/pets": {
            "get": {
                "description": "Returns all pets from the system that the user has access to\nNam sed condimentum est. Maecenas tempor sagittis sapien, nec rhoncus sem sagittis sit amet. Aenean at gravida augue, ac iaculis sem. Curabitur odio lorem, ornare eget elementum nec, cursus id lectus. Duis mi turpis, pulvinar ac eros ac, tincidunt varius justo. In hac habitasse platea dictumst. Integer at adipiscing ante, a sagittis ligula. Aenean pharetra tempor ante molestie imperdiet. Vivamus id aliquam diam. Cras quis velit non tortor eleifend sagittis. Praesent at enim pharetra urna volutpat venenatis eget eget mauris. In eleifend fermentum facilisis. Praesent enim enim, gravida ac sodales sed, placerat id erat. Suspendisse lacus dolor, consectetur non augue vel, vehicula interdum libero. Morbi euismod sagittis libero sed lacinia.\n\nSed tempus felis lobortis leo pulvinar rutrum. Nam mattis velit nisl, eu condimentum ligula luctus nec. Phasellus semper velit eget aliquet faucibus. In a mattis elit. Phasellus vel urna viverra, condimentum lorem id, rhoncus nibh. Ut pellentesque posuere elementum. Sed a varius odio. Morbi rhoncus ligula libero, vel eleifend nunc tristique vitae. Fusce et sem dui. Aenean nec scelerisque tortor. Fusce malesuada accumsan magna vel tempus. Quisque mollis felis eu dolor tristique, sit amet auctor felis gravida. Sed libero lorem, molestie sed nisl in, accumsan tempor nisi. Fusce sollicitudin massa ut lacinia mattis. Sed vel eleifend lorem. Pellentesque vitae felis pretium, pulvinar elit eu, euismod sapien.\n",
                "operationId": "findPets",
                "parameters": [
                    {
                        "name": "tags",
                        "in": "query",
                        "description": "tags to filter by",
                        "required": false,
                        "type": "array",
                        "collectionFormat": "csv",
                        "items": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "description": "maximum number of results to return",
                        "required": false,
                        "type": "integer",
                        "format": "int32"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "pet response",
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "allOf": [
                                    {
                                        "type": "object",
                                        "required": [
                                            "name"
                                        ],
                                        "properties": {
                                            "name": {
                                                "type": "string"
                                            },
                                            "tag": {
                                                "type": "string"
                                            }
                                        }
                                    },
                                    {
                                        "required": [
                                            "id"
                                        ],
                                        "properties": {
                                            "id": {
                                                "type": "integer",
                                                "format": "int64"
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    },
                    "default": {
                        "description": "unexpected error",
                        "schema": {
                            "type": "object",
                            "required": [
                                "code",
                                "message"
                            ],
                            "properties": {
                                "code": {
                                    "type": "integer",
                                    "format": "int32"
                                },
                                "message": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "x-resourceId": "2243b9a60c66378b60108a67ba948b1c"
            },
            "post": {
                "description": "Creates a new pet in the store.  Duplicates are allowed",
                "operationId": "addPet",
                "parameters": [
                    {
                        "name": "pet",
                        "in": "body",
                        "description": "Pet to add to the store",
                        "required": true,
                        "schema": {
                            "type": "object",
                            "required": [
                                "name"
                            ],
                            "properties": {
                                "name": {
                                    "type": "string"
                                },
                                "tag": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "pet response",
                        "schema": {
                            "type": "object",
                            "allOf": [
                                {
                                    "type": "object",
                                    "required": [
                                        "name"
                                    ],
                                    "properties": {
                                        "name": {
                                            "type": "string"
                                        },
                                        "tag": {
                                            "type": "string"
                                        }
                                    }
                                },
                                {
                                    "required": [
                                        "id"
                                    ],
                                    "properties": {
                                        "id": {
                                            "type": "integer",
                                            "format": "int64"
                                        }
                                    }
                                }
                            ]
                        }
                    },
                    "default": {
                        "description": "unexpected error",
                        "schema": {
                            "type": "object",
                            "required": [
                                "code",
                                "message"
                            ],
                            "properties": {
                                "code": {
                                    "type": "integer",
                                    "format": "int32"
                                },
                                "message": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "x-resourceId": "a9f0a3a63fe6b5bd954760c6ac09e85c"
                },
                "x-resourceId": "9b58c599cb38cb1caf7474178e5455df"
            },
            "x-resourceId": "ce256990f68429fe5bbf34dd4676b0be"
}
```

Hypermedia design patterns in your API responses, allow for self-discovery and ease development for API consumption.


