# ApiRoute

The node is used for the specific endpoint description. Its interface is smilar to the one of a [RequestStep](https://docs.testmace.com/master/node-types/request-step) node. No surprises, in both cases we deal with HTTP requests.

The main features of an ApiRoute node are:

* Describing request HTTP headers, query parameters, body parameters and response HTTP codes, HTTP headers and body parameters;
* Using types for describing every header, query parameter, and body parameter. Supported types: `string`, `number`, `integer`, `boolean`, `array`, and `object`;
* Describing every entity;
* Describing a number of request body parameters (based on content-type);
* Describing a number of possible responses;
* Creating a request out of the description;
* Autocompletion of URLs, HTTP headers, query and body parameters in [RequestStep](https://docs.testmace.com/master/node-types/request-step) nodes.

## Interface Overview

To create an **ApiRoute** node right-click in the [ApiFolder](https://docs.testmace.com/master/node-types/api-description/apifolder) node and choose **Add node** -> **ApiRoute.**

### An ApiRoute node in the project tree

This is how it looks like in the project tree:

![An ApiRoute node in the project tree](https://1914040845-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYfhIaTTw23Sf3L5jfe%2F-Lh-8_-iIrkPlQPxdRGh%2F-Lh0BtMevPi0x9AEv_1R%2F1.png?alt=media\&token=5d8a9b58-fcab-4508-be4b-01e09b6ea59d)

The icon of these nodes is the HTTP method name. An **ApiRoute** node has the following context menu:

![The ApiRoute context menu](https://1914040845-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYfhIaTTw23Sf3L5jfe%2F-Lh-8_-iIrkPlQPxdRGh%2F-Lh0CEFd52BzWxfzlx-f%2F2.png?alt=media\&token=e1bec327-9045-4e8a-975c-359648e846cf)

* **Rename.** Change the node name.
* **Duplicate.** Make a copy of the node. The new node will be named NodeName \[Copy \[number]].
* **Remove node.** Use it to delete the node.
* **Show in explorer.** Open the folder with the node in the file manager.

### The **ApiRoute** Tab Interface

The **ApiRoute** node tab looks like this:

![The ApiRoute tab](https://1914040845-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYfhIaTTw23Sf3L5jfe%2F-Lh-8_-iIrkPlQPxdRGh%2F-Lh0DZRq-N6KeKpQN0Mg%2F3.png?alt=media\&token=2a87fbb8-10f7-4e67-b495-756c654835bc)

#### General Request Parameters

Look a little closer at the top part of the tab:

![The top part of the ApiRoute node tab](https://1914040845-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYfhIaTTw23Sf3L5jfe%2F-Lh-8_-iIrkPlQPxdRGh%2F-Lh0GJ0lG6uWS8DImhSP%2F4.png?alt=media\&token=666d82ea-0637-40bb-b3e1-582ef7b8013e)

In the screenshot you can see the following parts of the interface.

1. HTTP method. The list of available methods is identical to the one of [RequestStep](https://docs.testmace.com/master/node-types/request-step) nodes.
2. URL with the [variables mechanism support](https://docs.testmace.com/master/variables/variables).
3. The [Variables dialog](https://docs.testmace.com/master/variables/user-variables) button.
4. The button to create a request out of the current API description.
5. The request description (text).

#### Request parameters description area

At the bottom left of the screen you can see the request description area. There are 3 tabs - **Headers**, **Query parameters**, and **Body**, that you can use to edit HTTP headers, query parameters, and request body parameters accordingly.

Let's look at the **Headers** tab. You can see that it is a table with the following fields:

* Header name;
* Header value type (as described above);
* Description.

All possible standard operations are supported.

The **Query Parameters** tab is used for editing query parameters, and it is functually identical to the **Headers** tab.

As mentioned before, in an **ApiRoute** node you can describe several bodies for a single request. For example, a single endpoint can take the data both with the `application/json` and `application/xml` `Content-Type`. There are several different content-type tabs on the **Body** tab:

![The Body tab of the request description interface](https://1914040845-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYfhIaTTw23Sf3L5jfe%2F-Lh-8_-iIrkPlQPxdRGh%2F-Lh0NcNadYlwdkCel30V%2F5.png?alt=media\&token=c8398894-1259-49f9-9eb9-5f1311d5f353)

In the screenshot you can see the following parts of the interface:

1. The button that edits the current `content-type` value. If you click on it, you'll see a text box instead, where you can enter your `content-type` value.
2. Delete the request body button.
3. Add the request body button.
4. The current `content-type` of the node.
5. The request body editing area.

The request body editing area changes according to the `content-type` value:  if the `content-type` is`application/x-www-form-urlencoded` or`multipart/form-data`, then the editing area looks like a table (like in the **Headers** tab), otherwise it has the text representation like in the screenshot above. The description format is [OpenAPI](https://swagger.io/specification/#requestBodyObject) in this case.

#### Request parameters description area

There is a response editing panel at the bottom right of the **ApiRoute** tab interface. As mentioned before, TestMace allows you to describe several responses for a single endpoint. Look at the interface:

![The server response editing area](https://1914040845-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYfhIaTTw23Sf3L5jfe%2F-Lh-8_-iIrkPlQPxdRGh%2F-Lh0aybnLxCtZilFBOpr%2F6.png?alt=media\&token=af6ab711-6523-4a2c-b2f2-e70f53c44538)

There is a separate tab for each response. On these tabs you can edit response codes, descriptions, and even response HTTP headers and bodies. The interface is similar to ones in the request area.

### Integration with RequestStep nodes

TestMace provides integration with **ApiRoute** nodes in **RequestStep** nodes. The integration is implemented in autocompletion of URLs, HTTP headers, query parameters, **RequestStep** nodes' request body parameters. Autocompletion works for all **ApiRoute** nodes URLs, but for other parameters the following algorithm is applied:

* Take the **RequestStep** node method and URL;
* Find all **ApiRoute** nodes with this method and URL;
* Run the specified parameter (e. g. an HTTP header) search among the **ApiRoute** nodes.

## File Representation

An **ApiRoute** node is a folder with the node name, containing the index.yml file with the following format:

```javascript
{
  "type": "object",
  "properties": {
    "type": {
      "description": "Type of ApiRoute node",
      "const": "ApiRoute",
      "type": "string"
    },
    "url": {
      "type": "string",
      "default": ""
    },
    "method": {
      "$ref": "#/definitions/RequestMethod"
    },
    "description": {
      "type": "string",
      "default": ""
    },
    "requests": {
      "$ref": "#/definitions/ApiRequests",
      "description": "List of requests"
    },
    "responses": {
      "description": "List of responses",
      "type": "array",
      "items": {
        "$ref": "#/definitions/ResponseParameters"
      },
      "default": []
    },
    "children": {
      "description": "List of children names",
      "type": "array",
      "items": {
        "type": "string"
      },
      "default": []
    },
    "variables": {
      "$ref": "#/definitions/NodeVariables",
      "description": "Node variables dictionary"
    },
    "name": {
      "description": "Node name",
      "type": "string"
    }
  },
  "required": [
    "children",
    "description",
    "method",
    "name",
    "requests",
    "responses",
    "type",
    "url",
    "variables"
  ],
  "definitions": {
    "RequestMethod": {
      "enum": [
        "DELETE",
        "GET",
        "OPTIONS",
        "PATCH",
        "POST",
        "PUT"
      ],
      "type": "string"
    },
    "ApiRequests": {
      "type": "object",
      "properties": {
        "queryParameters": {
          "description": "List of query parameters",
          "type": "array",
          "items": {
            "$ref": "#/definitions/QueryParameter"
          }
        },
        "headers": {
          "description": "List of headers",
          "type": "array",
          "items": {
            "$ref": "#/definitions/QueryParameter"
          }
        },
        "cookies": {
          "description": "List of cookies",
          "type": "array",
          "items": {
            "$ref": "#/definitions/QueryParameter"
          }
        },
        "bodies": {
          "description": "List of bodies",
          "type": "array",
          "items": {
            "$ref": "#/definitions/RequestParameters"
          },
          "default": []
        }
      },
      "required": [
        "bodies",
        "cookies",
        "headers",
        "queryParameters"
      ]
    },
    "QueryParameter": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "type": {
          "enum": [
            "array",
            "boolean",
            "integer",
            "number",
            "object",
            "string"
          ],
          "type": "string"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "name",
        "type"
      ]
    },
    "RequestParameters": {
      "type": "object",
      "properties": {
        "contentType": {
          "type": "string"
        },
        "schema": {
          "anyOf": [
            {
              "$ref": "#/definitions/SchemaRef"
            },
            {
              "$ref": "#/definitions/OneOf"
            },
            {
              "$ref": "#/definitions/AllOf"
            },
            {
              "$ref": "#/definitions/AnyOf"
            },
            {
              "$ref": "#/definitions/ObjectMember"
            },
            {
              "$ref": "#/definitions/ArrayMember"
            },
            {
              "$ref": "#/definitions/ScalarMember"
            }
          ]
        }
      },
      "required": [
        "contentType",
        "schema"
      ]
    },
    "SchemaRef": {
      "type": "object",
      "properties": {
        "$ref": {
          "type": "string"
        }
      },
      "required": [
        "$ref"
      ]
    },
    "OneOf": {
      "type": "object",
      "properties": {
        "oneOf": {
          "type": "array",
          "items": {
            "anyOf": [
              {
                "$ref": "#/definitions/SchemaRef"
              },
              {
                "$ref": "#/definitions/OneOf"
              },
              {
                "$ref": "#/definitions/AllOf"
              },
              {
                "$ref": "#/definitions/AnyOf"
              },
              {
                "$ref": "#/definitions/ObjectMember"
              },
              {
                "$ref": "#/definitions/ArrayMember"
              },
              {
                "$ref": "#/definitions/ScalarMember"
              }
            ]
          }
        }
      },
      "required": [
        "oneOf"
      ]
    },
    "AllOf": {
      "type": "object",
      "properties": {
        "allOf": {
          "type": "array",
          "items": {
            "anyOf": [
              {
                "$ref": "#/definitions/SchemaRef"
              },
              {
                "$ref": "#/definitions/OneOf"
              },
              {
                "$ref": "#/definitions/AllOf"
              },
              {
                "$ref": "#/definitions/AnyOf"
              },
              {
                "$ref": "#/definitions/ObjectMember"
              },
              {
                "$ref": "#/definitions/ArrayMember"
              },
              {
                "$ref": "#/definitions/ScalarMember"
              }
            ]
          }
        }
      },
      "required": [
        "allOf"
      ]
    },
    "AnyOf": {
      "type": "object",
      "properties": {
        "anyOf": {
          "type": "array",
          "items": {
            "anyOf": [
              {
                "$ref": "#/definitions/SchemaRef"
              },
              {
                "$ref": "#/definitions/OneOf"
              },
              {
                "$ref": "#/definitions/AllOf"
              },
              {
                "$ref": "#/definitions/AnyOf"
              },
              {
                "$ref": "#/definitions/ObjectMember"
              },
              {
                "$ref": "#/definitions/ArrayMember"
              },
              {
                "$ref": "#/definitions/ScalarMember"
              }
            ]
          }
        }
      },
      "required": [
        "anyOf"
      ]
    },
    "ObjectMember": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "object"
          ]
        },
        "properties": {
          "$ref": "#/definitions/SchemaMember"
        },
        "required": {
          "type": "boolean"
        },
        "additionalProperties": {
          "$ref": "#/definitions/ScalarMember"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "type"
      ]
    },
    "SchemaMember": {
      "type": "object",
      "additionalProperties": {
        "anyOf": [
          {
            "$ref": "#/definitions/SchemaRef"
          },
          {
            "$ref": "#/definitions/OneOf"
          },
          {
            "$ref": "#/definitions/AllOf"
          },
          {
            "$ref": "#/definitions/AnyOf"
          },
          {
            "$ref": "#/definitions/ObjectMember"
          },
          {
            "$ref": "#/definitions/ArrayMember"
          },
          {
            "$ref": "#/definitions/ScalarMember"
          }
        ]
      }
    },
    "ArrayMember": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "array"
          ]
        },
        "items": {
          "anyOf": [
            {
              "$ref": "#/definitions/SchemaRef"
            },
            {
              "$ref": "#/definitions/OneOf"
            },
            {
              "$ref": "#/definitions/AllOf"
            },
            {
              "$ref": "#/definitions/AnyOf"
            },
            {
              "$ref": "#/definitions/ObjectMember"
            },
            {
              "$ref": "#/definitions/ArrayMember"
            },
            {
              "$ref": "#/definitions/ScalarMember"
            }
          ]
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "items",
        "type"
      ]
    },
    "ScalarMember": {
      "type": "object",
      "properties": {
        "type": {
          "$ref": "#/definitions/ScalarSchemaType"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "type"
      ]
    },
    "ScalarSchemaType": {
      "enum": [
        "boolean",
        "integer",
        "number",
        "string"
      ],
      "type": "string"
    },
    "ResponseParameters": {
      "type": "object",
      "properties": {
        "code": {
          "description": "Http-code (e.g. 200, 404)",
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "headers": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/QueryParameter"
          }
        },
        "content": {
          "$ref": "#/definitions/RequestParameters",
          "description": "Response body"
        }
      },
      "required": [
        "code",
        "content"
      ]
    },
    "NodeVariables": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      }
    }
  },
  "$schema": "http://json-schema.org/draft-07/schema#"
}
```
