Apigee Developer Portal - Custom - SmartDocs Template - Request Body Parameters - SDCT002

Hello Everyone,

Ability to customize smartdocs & displaying information from OpenAPI Spec, It's a pain from long time.

Many times i came across the conversations related to displaying API information submitted in Open API spec. Today, We take the Open API Spec & We give limited handlebar variables in the template. Original spec is lost once submitted. It created many limitations when it comes to customization.

Handle bar variables which are available in the smartdocs template are limited & they come from Edge API which is totally hidden to developer working on SmartDocs in developer portal.

Recently, when i was working with a customer of Apigee, They highlighted how Apigee Smartdocs is a differentiator from Swagger UI with capabilities like Categorization, Role Based Access & Search functionality. At the same time, Many struggled with customization of smartdocs & displaying information from OpenAPI Spec.

I have decided to solve the mystery of SmartDocs customization one issue at a time by building custom templates. I hope one day these templates make into product.

In this template, You will see how to display request body parameters in SmartDocs Method page.

For example, Let's take the famous petstore Open API Spec example with description added to addPet API.

{
  "swagger": "2.0",
  "info": {
    "description": "This is a sample server Petstore server.  You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, you can use the api key `special-key` to test the authorization filters.",
    "version": "1.0.0",
    "title": "Swagger Petstore",
    "termsOfService": "http://swagger.io/terms/",
    "contact": {
      "email": "apiteam@swagger.io"
    },
    "license": {
      "name": "Apache 2.0",
      "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
    }
  },
  "host": "petstore.swagger.io",
  "basePath": "/v2",
  "tags": [
    {
      "name": "pet",
      "description": "Everything about your Pets",
      "externalDocs": {
        "description": "Find out more",
        "url": "http://swagger.io"
      }
    },
    {
      "name": "store",
      "description": "Access to Petstore orders"
    },
    {
      "name": "user",
      "description": "Operations about user",
      "externalDocs": {
        "description": "Find out more about our store",
        "url": "http://swagger.io"
      }
    }
  ],
  "schemes": [
    "http"
  ],
  "paths": {
    "/pet": {
      "post": {
        "tags": [
          "pet"
        ],
        "summary": "Add a new pet to the store",
        "description": "",
        "operationId": "addPet",
        "consumes": [
          "application/json",
          "application/xml"
        ],
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "body",
            "description": "Pet object that needs to be added to the store",
            "required": true,
            "schema": {
              "$ref": "#/definitions/Pet"
            }
          }
        ],
        "responses": {
          "405": {
            "description": "Invalid input"
          }
        },
        "security": [
          {
            "petstore_auth": [
              "write:pets",
              "read:pets"
            ]
          }
        ]
      },
      "put": {
        "tags": [
          "pet"
        ],
        "summary": "Update an existing pet",
        "description": "",
        "operationId": "updatePet",
        "consumes": [
          "application/json",
          "application/xml"
        ],
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "body",
            "description": "Pet object that needs to be added to the store",
            "required": true,
            "schema": {
              "$ref": "#/definitions/Pet"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Pet not found"
          },
          "405": {
            "description": "Validation exception"
          }
        },
        "security": [
          {
            "petstore_auth": [
              "write:pets",
              "read:pets"
            ]
          }
        ]
      }
    },
    "/pet/findByStatus": {
      "get": {
        "tags": [
          "pet"
        ],
        "summary": "Finds Pets by status",
        "description": "Multiple status values can be provided with comma separated strings",
        "operationId": "findPetsByStatus",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Status values that need to be considered for filter",
            "required": true,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "available",
                "pending",
                "sold"
              ],
              "default": "available"
            },
            "collectionFormat": "multi"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/Pet"
              }
            }
          },
          "400": {
            "description": "Invalid status value"
          }
        },
        "security": [
          {
            "petstore_auth": [
              "write:pets",
              "read:pets"
            ]
          }
        ]
      }
    },
    "/pet/findByTags": {
      "get": {
        "tags": [
          "pet"
        ],
        "summary": "Finds Pets by tags",
        "description": "Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.",
        "operationId": "findPetsByTags",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "name": "tags",
            "in": "query",
            "description": "Tags to filter by",
            "required": true,
            "type": "array",
            "items": {
              "type": "string"
            },
            "collectionFormat": "multi"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/Pet"
              }
            }
          },
          "400": {
            "description": "Invalid tag value"
          }
        },
        "security": [
          {
            "petstore_auth": [
              "write:pets",
              "read:pets"
            ]
          }
        ],
        "deprecated": true
      }
    },
    "/pet/{petId}": {
      "get": {
        "tags": [
          "pet"
        ],
        "summary": "Find pet by ID",
        "description": "Returns a single pet",
        "operationId": "getPetById",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "name": "petId",
            "in": "path",
            "description": "ID of pet to return",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "schema": {
              "$ref": "#/definitions/Pet"
            }
          },
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Pet not found"
          }
        },
        "security": [
          {
            "api_key": [
              
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "pet"
        ],
        "summary": "Updates a pet in the store with form data",
        "description": "",
        "operationId": "updatePetWithForm",
        "consumes": [
          "application/x-www-form-urlencoded"
        ],
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "name": "petId",
            "in": "path",
            "description": "ID of pet that needs to be updated",
            "required": true,
            "type": "integer",
            "format": "int64"
          },
          {
            "name": "name",
            "in": "formData",
            "description": "Updated name of the pet",
            "required": false,
            "type": "string"
          },
          {
            "name": "status",
            "in": "formData",
            "description": "Updated status of the pet",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "405": {
            "description": "Invalid input"
          }
        },
        "security": [
          {
            "petstore_auth": [
              "write:pets",
              "read:pets"
            ]
          }
        ]
      },
      "delete": {
        "tags": [
          "pet"
        ],
        "summary": "Deletes a pet",
        "description": "",
        "operationId": "deletePet",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "name": "api_key",
            "in": "header",
            "required": false,
            "type": "string"
          },
          {
            "name": "petId",
            "in": "path",
            "description": "Pet id to delete",
            "required": true,
            "type": "integer",
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Pet not found"
          }
        },
        "security": [
          {
            "petstore_auth": [
              "write:pets",
              "read:pets"
            ]
          }
        ]
      }
    },
    "/pet/{petId}/uploadImage": {
      "post": {
        "tags": [
          "pet"
        ],
        "summary": "uploads an image",
        "description": "",
        "operationId": "uploadFile",
        "consumes": [
          "multipart/form-data"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "petId",
            "in": "path",
            "description": "ID of pet to update",
            "required": true,
            "type": "integer",
            "format": "int64"
          },
          {
            "name": "additionalMetadata",
            "in": "formData",
            "description": "Additional data to pass to server",
            "required": false,
            "type": "string"
          },
          {
            "name": "file",
            "in": "formData",
            "description": "file to upload",
            "required": false,
            "type": "file"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "schema": {
              "$ref": "#/definitions/ApiResponse"
            }
          }
        },
        "security": [
          {
            "petstore_auth": [
              "write:pets",
              "read:pets"
            ]
          }
        ]
      }
    },
    "/store/inventory": {
      "get": {
        "tags": [
          "store"
        ],
        "summary": "Returns pet inventories by status",
        "description": "Returns a map of status codes to quantities",
        "operationId": "getInventory",
        "produces": [
          "application/json"
        ],
        "parameters": [
          
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "integer",
                "format": "int32"
              }
            }
          }
        },
        "security": [
          {
            "api_key": [
              
            ]
          }
        ]
      }
    },
    "/store/order": {
      "post": {
        "tags": [
          "store"
        ],
        "summary": "Place an order for a pet",
        "description": "",
        "operationId": "placeOrder",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "body",
            "description": "order placed for purchasing the pet",
            "required": true,
            "schema": {
              "$ref": "#/definitions/Order"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "schema": {
              "$ref": "#/definitions/Order"
            }
          },
          "400": {
            "description": "Invalid Order"
          }
        }
      }
    },
    "/store/order/{orderId}": {
      "get": {
        "tags": [
          "store"
        ],
        "summary": "Find purchase order by ID",
        "description": "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions",
        "operationId": "getOrderById",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "description": "ID of pet that needs to be fetched",
            "required": true,
            "type": "integer",
            "maximum": 10.0,
            "minimum": 1.0,
            "format": "int64"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "schema": {
              "$ref": "#/definitions/Order"
            }
          },
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      },
      "delete": {
        "tags": [
          "store"
        ],
        "summary": "Delete purchase order by ID",
        "description": "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors",
        "operationId": "deleteOrder",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "description": "ID of the order that needs to be deleted",
            "required": true,
            "type": "integer",
            "minimum": 1.0,
            "format": "int64"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid ID supplied"
          },
          "404": {
            "description": "Order not found"
          }
        }
      }
    },
    "/user": {
      "post": {
        "tags": [
          "user"
        ],
        "summary": "Create user",
        "description": "This can only be done by the logged in user.",
        "operationId": "createUser",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "body",
            "description": "Created user object",
            "required": true,
            "schema": {
              "$ref": "#/definitions/User"
            }
          }
        ],
        "responses": {
          "default": {
            "description": "successful operation"
          }
        }
      }
    },
    "/user/createWithArray": {
      "post": {
        "tags": [
          "user"
        ],
        "summary": "Creates list of users with given input array",
        "description": "",
        "operationId": "createUsersWithArrayInput",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "body",
            "description": "List of user object",
            "required": true,
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/User"
              }
            }
          }
        ],
        "responses": {
          "default": {
            "description": "successful operation"
          }
        }
      }
    },
    "/user/createWithList": {
      "post": {
        "tags": [
          "user"
        ],
        "summary": "Creates list of users with given input array",
        "description": "",
        "operationId": "createUsersWithListInput",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "body",
            "description": "List of user object",
            "required": true,
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/User"
              }
            }
          }
        ],
        "responses": {
          "default": {
            "description": "successful operation"
          }
        }
      }
    },
    "/user/login": {
      "get": {
        "tags": [
          "user"
        ],
        "summary": "Logs user into the system",
        "description": "",
        "operationId": "loginUser",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "description": "The user name for login",
            "required": true,
            "type": "string"
          },
          {
            "name": "password",
            "in": "query",
            "description": "The password for login in clear text",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "schema": {
              "type": "string"
            },
            "headers": {
              "X-Rate-Limit": {
                "type": "integer",
                "format": "int32",
                "description": "calls per hour allowed by the user"
              },
              "X-Expires-After": {
                "type": "string",
                "format": "date-time",
                "description": "date in UTC when token expires"
              }
            }
          },
          "400": {
            "description": "Invalid username/password supplied"
          }
        }
      }
    },
    "/user/logout": {
      "get": {
        "tags": [
          "user"
        ],
        "summary": "Logs out current logged in user session",
        "description": "",
        "operationId": "logoutUser",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          
        ],
        "responses": {
          "default": {
            "description": "successful operation"
          }
        }
      }
    },
    "/user/{username}": {
      "get": {
        "tags": [
          "user"
        ],
        "summary": "Get user by user name",
        "description": "",
        "operationId": "getUserByName",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "name": "username",
            "in": "path",
            "description": "The name that needs to be fetched. Use user1 for testing. ",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "successful operation",
            "schema": {
              "$ref": "#/definitions/User"
            }
          },
          "400": {
            "description": "Invalid username supplied"
          },
          "404": {
            "description": "User not found"
          }
        }
      },
      "put": {
        "tags": [
          "user"
        ],
        "summary": "Updated user",
        "description": "This can only be done by the logged in user.",
        "operationId": "updateUser",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "name": "username",
            "in": "path",
            "description": "name that need to be updated",
            "required": true,
            "type": "string"
          },
          {
            "in": "body",
            "name": "body",
            "description": "Updated user object",
            "required": true,
            "schema": {
              "$ref": "#/definitions/User"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid user supplied"
          },
          "404": {
            "description": "User not found"
          }
        }
      },
      "delete": {
        "tags": [
          "user"
        ],
        "summary": "Delete user",
        "description": "This can only be done by the logged in user.",
        "operationId": "deleteUser",
        "produces": [
          "application/xml",
          "application/json"
        ],
        "parameters": [
          {
            "name": "username",
            "in": "path",
            "description": "The name that needs to be deleted",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid username supplied"
          },
          "404": {
            "description": "User not found"
          }
        }
      }
    }
  },
  "securityDefinitions": {
    "petstore_auth": {
      "type": "oauth2",
      "authorizationUrl": "http://petstore.swagger.io/oauth/dialog",
      "flow": "implicit",
      "scopes": {
        "write:pets": "modify pets in your account",
        "read:pets": "read your pets"
      }
    },
    "api_key": {
      "type": "apiKey",
      "name": "api_key",
      "in": "header"
    }
  },
  "definitions": {
    "Order": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "petId": {
          "type": "integer",
          "format": "int64"
        },
        "quantity": {
          "type": "integer",
          "format": "int32"
        },
        "shipDate": {
          "type": "string",
          "format": "date-time"
        },
        "status": {
          "type": "string",
          "description": "Order Status",
          "enum": [
            "placed",
            "approved",
            "delivered"
          ]
        },
        "complete": {
          "type": "boolean",
          "default": false
        }
      },
      "xml": {
        "name": "Order"
      }
    },
    "Category": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64",
          "description": "Pet Category Id: Example : C001"
        },
        "name": {
          "type": "string",
          "description": "Pet Category Name: Example : Greden"
        }
      },
      "xml": {
        "name": "Category"
      }
    },
    "User": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64"
        },
        "username": {
          "type": "string"
        },
        "firstName": {
          "type": "string"
        },
        "lastName": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "password": {
          "type": "string"
        },
        "phone": {
          "type": "string"
        },
        "userStatus": {
          "type": "integer",
          "format": "int32",
          "description": "User Status"
        }
      },
      "xml": {
        "name": "User"
      }
    },
    "Tag": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64",
          "description": "Pet Tag Id: Example : PT001"
        },
        "name": {
          "type": "string",
          "description": "Pet Tag Name: Example : Black"
        }
      },
      "xml": {
        "name": "Tag"
      }
    },
    "Pet": {
      "type": "object",
      "required": [
        "name",
        "photoUrls"
      ],
      "properties": {
        "id": {
          "type": "integer",
          "format": "int64",
          "description": "Pet unique id : Example : 123456789"
        },
        "category": {
          "$ref": "#/definitions/Category"
        },
        "name": {
          "type": "string",
          "example": "doggie",
          "description": "Pet name: Example : doggie"
        },
        "photoUrls": {
          "type": "array",
          "description": "Pet Photo URLs - Array of links",
          "xml": {
            "name": "photoUrl",
            "wrapped": true
          },
          "items": {
            "type": "string"
          }
        },
        "tags": {
          "type": "array",
          "description": "Pet Categories - Array of tags",
          "xml": {
            "name": "tag",
            "wrapped": true
          },
          "items": {
            "$ref": "#/definitions/Tag"
          }
        },
        "status": {
          "type": "string",
          "description": "pet status in the store",
          "enum": [
            "available",
            "pending",
            "sold"
          ]
        }
      },
      "xml": {
        "name": "Pet"
      }
    },
    "ApiResponse": {
      "type": "object",
      "properties": {
        "code": {
          "type": "integer",
          "format": "int32"
        },
        "type": {
          "type": "string"
        },
        "message": {
          "type": "string"
        }
      }
    }
  },
  "externalDocs": {
    "description": "Find out more about Swagger",
    "url": "http://swagger.io"
  }
}

When you generate SmartDocs using above spec, Add Pet API Smartdocs page looks like below.

5818-new-apigee-site-addpet.png

How about having a table that lists the information above request parameters with information like description, name, type & default value, required or not ? Just like the one done here or here ? Yes, They are actually Smartdocs but unfortunately hardcoded into html but not generated dynamically from OpenAPI / Swagger Spec.

I am able to solve the issue by modifying the smartdocs template file & implementing a custom template .

Step 1 : Copy Contents of below template file contents.

<!-- Apigee Dev Portal Method Template v6.3 -->
{{!--
Apigee Dev Portal Method Template


Available variables:
- apiId: The UUID of the model.
- apiName: The unique name of the model, for example 'petstore-example'.
- apiRevisionId: The revision of the model.
- baseUrl: The base URL of the model, for example 'http://api.apigee.com/v1'
- body: An object of attributes relating to the method body:
- contentType: The allowed Content-Type values of the body.
- parameters: An array of body parameters, will be populated with values
from OpenAPI (Swagger) 2.0 "in": "formData" parameters.
Helper variables:
- none
--}}
<div class="row smartdocs-wrapper">
    <style>


        .panel-group .panel {
            margin-top: 10px;
        }


        #method_content .operation_container .authentication {
            min-width: inherit;
        }


        body section.page-header {display:none}
        .CodeMirror {min-height:150px}
        .CodeMirror-scroll {padding:0}
        /* Responsiveness */
        @media(max-width:767px) {}
        @media(min-width:768px) {}
        @media(min-width:992px) {}
        @media(min-width:1200px) {}
        @media(min-width:1400px) {}


        .node-type-smart-method .page-content {
            padding: 5px 0 10px;
        }


        .node-type-smart-method div#breadcrumb-navbar {
            margin-top: 10px;
        }


        .node-type-smart-method #method_content h3 {
            padding-top: 5px;
        }


        .node-type-smart-method #method_content .resource_description {
            padding-top: 20px;
            padding-bottom: 20px;
        }


        .panel-heading {
            cursor: pointer;
        }




        .node-type-smart-method #method_content button#send_request {
            border-radius: 0;
            font-family: 'inconsolatamedium',sans-serif !important;
            font-size: 16px !important;
            letter-spacing: 1px;
            text-transform: uppercase;
            background: #2180b5 !important;
            padding: 20px !important;
            width: 212px !important;
            color: #FFF !important;
            line-height: 14px !important;
            border: 1px solid #003f62;
            margin-right: 5px;
        }


        .node-type-smart-method #method_content a.link_reset_default {
            border-radius: 0;
            font-family: 'inconsolatamedium',sans-serif !important;
            font-size: 16px !important;
            letter-spacing: 1px;
            text-transform: uppercase;
            background: #ffffff !important;
            padding: 20px !important;
            width: 212px !important;
            margin: 0 !important;
            color: #000 !important;
            line-height: 14px !important;
            border: 1px solid #003f62;
            text-align: center;


        }


    </style>
    <!-- Main content -->
    <div class="col-sm-7" id="method_content">
        <div class="col-sm-12">
            <!-- Error container -->
            <div data-role="error_container"></div>


            <!-- Inline edit Organization admin credential section -->
            <div class="admin_auth_section hide">
                <a class="set_admin_credentials hide" href="javascript:void(0)" title="set admin credentials.">Set Admin Credentials...</a>
                <a class="auth_admin_email" title="reset admin credentials." href="javascript:void(0)"></a>
                <i title="Clear admin credentials." class="icon-remove"></i>
            </div>
            <div>
                <!-- Resource summary - name, description and resource URL section -->
                <div class="resource_details">
                    <span id="method_name" data-role="method-name" class="hide">{{name}}</span>
                    <div class="title_container">
                        <div class="verb_container">
                            <p class="verb {{verb}}" data-role="verb">{{verb}}</p>
                        </div>
                        <h2 data-role="method-title" data-allow-edit="true">{{#if displayName}}{{displayName}}{{else}}{{name}}{{/if}}</h2>
                    </div>
                    <div class="description_and_url_container">
                        <div class="description_container">
                            <div class="resource_description markdown" data-allow-edit="true" data-role="method-description">{{{description}}}</div>
                        </div>
                    </div>
                </div><!--/.resource_details -->
            </div>
            <div class="row">
                <div class="col-sm-12">
                    <div class="panel-group" id="accordion">
                        <div class="panel panel-default">
                            <div class="panel-heading">
                                <h4 class="panel-title" style="display: inline;">Resource URL</h4>
                                <i id="headerParametersCollapse-arrow" class="glyphicon glyphicon-chevron-right" style="float:right;"></i>
                            </div>
                            <div id="resourceURLTable" class="panel-collapse collapse in">
                                <div class="panel-body">
                                    <div>
                                        <!-- Resource summary - name, description and resource URL section -->
                                        <div class="url_container">
                                            <p data-role="method_url_container">
                                                {{#if baseUrl}}
                                                <span data-role="host">{{baseUrl}}</span>{{/if}}{{#if path}}
                                                <span data-role="path">{{path}}</span>{{/if}}
                                            </p>
                                        </div>
                                        <!--/.resource_details -->
                                    </div>
                                </div>
                            </div>
                        </div>
                        {{#if-query-param this.parameters}}
                        <div class="panel panel-default">
                            <div class="panel-heading">
                                <h4 class="panel-title" style="display: inline;">Query Parameters</h4>
                                <i id="headerParametersCollapse-arrow" class="glyphicon glyphicon-chevron-right" style="float:right;"></i>
                            </div>
                            <div id="queryTable" class="panel-collapse collapse in">
                                <div class="panel-body">
                                    <div class="table-responsive">
                                        <table class="table table-striped">
                                            <thead>
                                            <tr>
                                                <th class="col-sm-2">Name</th>
                                                <th class="col-sm-3">Values</th>
                                                <th class="col-sm-7">Description</th>
                                            </tr>
                                            </thead>
                                            <tbody>
                                            {{#query-list this.parameters}}
                                            <tr data-role="query-param-list" data-scope="{{scope}}">
                                                <td>
                                                    <span data-role="name">{{name}}</span>
                                                    {{#required}}
                                                    <br/><span class="required" data-role="required">(required)</span>
                                                    {{/required}}
                                                </td>
                                                <td>
                                                    {{#if options}}
                                                    <select name="{{name}}" data-role="multiple-value" data-default-value="{{defaultValue}}" class="form-control{{#if defaultValue}} has-default-value{{/if}}">
                                                        {{#if required}}{{else}}<option value="">(no value)</option>{{/if}}
                                                        {{#options}}
                                                        <option value="{{.}}">{{.}}</option>
                                                        {{/options}}
                                                    </select>
                                                    {{else}}
                                                    {{#if required}}
                                                    <input name="{{name}}" type="text" class="form-control" data-role="value" value="{{defaultValue}}"/>
                                                    {{else}}
                                                    <input name="{{name}}" type="text" class="form-control" data-role="value" placeholder="{{defaultValue}}" value=""/>
                                                    {{/if}}
                                                    {{/if}}
                                                </td>
                                                <td>
                                                    <p data-role="description" data-allow-edit="true" class="markdown">{{{description}}}</p>
                                                </td>
                                            </tr>
                                            {{/query-list}}
                                            </tbody>
                                        </table>
                                    </div>
                                </div>
                            </div>
                        </div>
                        {{/if-query-param}}
                        {{#if-header-param this.parameters}}
                        <div class="panel panel-default">
                            <div class="panel-heading">
                                <h4 class="panel-title" style="display: inline;">Header Parameters</h4>
                                <i id="headerParametersCollapse-arrow" class="glyphicon glyphicon-chevron-right" style="float:right;"></i>
                            </div>
                            <div id="headerTable" class="panel-collapse collapse in">
                                <div class="panel-body">
                                    <div class="table-responsive">
                                        <table class="table table-striped">
                                            <thead>
                                            <tr>
                                                <th class="col-sm-2">Name</th>
                                                <th class="col-sm-3">Values</th>
                                                <th class="col-sm-7">Description</th>
                                            </tr>
                                            </thead>
                                            <tbody>
                                            {{#header-list this.parameters}}
                                            <tr data-role="header-param-list" data-scope="{{scope}}">
                                                <td style="vertical-align:middle">
                                                    <span data-role="name">{{name}}</span>
                                                    {{#required}}
                                                    <br/>
                                                    <span class="required" data-role="required">(required)</span>
                                                    {{/required}}
                                                </td>
                                                <td>
                                                    {{#if options}}
                                                    <select name="{{name}}" data-role="multiple-value" data-default-value="{{defaultValue}}" class="form-control{{#if defaultValue}} has-default-value{{/if}}">
                                                        {{#if required}}{{else}}<option value="">(no value)</option>{{/if}}
                                                        {{#options}}
                                                        <option value="{{.}}">{{.}}</option>
                                                        {{/options}}
                                                    </select>
                                                    {{else}}
                                                    {{#if required}}
                                                    <input type="text" class="form-control" data-role="value" value="{{defaultValue}}"/>
                                                    {{else}}
                                                    <input type="text" class="form-control" data-role="value" placeholder="{{defaultValue}}" value=""/>
                                                    {{/if}}
                                                    {{/if}}
                                                </td>
                                                <td style="vertical-align:middle">
                                                    <p data-role="description" data-allow-edit="true" class="markdown">
                                                        {{{ this.description }}}
                                                    </p>
                                                </td>
                                            </tr>
                                            {{/header-list}}
                                            </tbody>
                                        </table>
                                    </div>
                                </div>
                            </div>
                        </div>
                        {{/if-header-param}}
                        <div class="body-parameters-wrapper">
                            {{#if body.parameters}}
                            <div class="panel panel-default">
                                <div class="panel-heading">
                                    <h4 class="panel-title" style="display: inline;">Body Parameters</h4>
                                    <i id="headerParametersCollapse-arrow" class="glyphicon glyphicon-chevron-right" style="float:right;"></i>
                                </div>
                                <div id="bodyTable" class="panel-collapse collapse in">
                                    <div class="panel-body">
                                        <!-- body parameters -->


                                        <form enctype="multipart/form-data" method="post" name="formParams" id="formParams">
                                            <div class="table-responsive">
                                                <table class="table table-striped">
                                                    <thead>
                                                    <tr>
                                                        <th class="col-sm-2">Name</th>
                                                        <th class="col-sm-3">Values</th>
                                                        <th class="col-sm-7">Description</th>
                                                    </tr>
                                                    </thead>
                                                    <tbody>
                                                    {{#each body.parameters}}


                                                    <tr data-role="body-param-list" data-scope="{{scope}}" data-dataType="{{dataType}}">
                                                        <td style="vertical-align:middle">
                                                            <span data-role="name">{{this.name}}</span>
                                                            {{#required}}
                                                            <br/>
                                                            <span class="required" data-role="required">(required)</span>
                                                            {{/required}}
                                                        </td>
                                                        <td>
                                                            {{#if options}}
                                                            <select name="{{this.name}}" data-role="multiple-value" data-default-value="{{defaultValue}}" class="form-control{{#if defaultValue}} has-default-value{{/if}}">
                                                                {{#if required}}{{else}}<option value="">(no value)</option>{{/if}}
                                                                {{#options}}
                                                                <option value="{{.}}">{{.}}</option>
                                                                {{/options}}
                                                            </select>
                                                            {{else}}
                                                            {{#if required}}
                                                            <input name="{{this.name}}" type="text" class="form-control" data-role="value" value="{{defaultValue}}"/>
                                                            {{else}}
                                                            <input name="{{this.name}}" type="text" class="form-control" data-role="value" placeholder="{{defaultValue}}" value=""/>
                                                            {{/if}}
                                                            {{/if}}
                                                        </td>
                                                        <td style="vertical-align:middle">
                                                            <p data-role="description" data-allow-edit="true" class="markdown">
                                                                {{{ this.description }}}
                                                            </p>
                                                        </td>
                                                    </tr>


                                                    {{/each}}
                                                    </tbody>
                                                </table>
                                            </div>
                                        </form>
                                    </div>
                                </div>
                            </div>
                            {{/if}}
                        </div>
                        {{#body}}
                        {{#if attachments}}
                        <div class="panel panel-default">
                            <div class="panel-heading">
                                <h4 class="panel-title" style="display: inline;">Attachments</h4>
                                <i id="headerParametersCollapse-arrow" class="glyphicon glyphicon-chevron-right" style="float:right;"></i>
                            </div>
                            <div id="attachmentsTable" class="panel-collapse collapse in">
                                <div class="panel-body">
                                    <form enctype="multipart/form-data" method="post" name="formAttachment" id="formAttachment">
                                        <h3>Attachments</h3>
                                        <hr>
                                        <div class="table-responsive">
                                            <table class="table table-striped">
                                                <thead>
                                                <tr>
                                                    <th class="col-sm-2">Name</th>
                                                    <th class="col-sm-3">Value</th>
                                                    <th class="col-sm-7">Description</th>
                                                </tr>
                                                </thead>
                                                <tbody>
                                                {{#each attachments}}
                                                <tr class="method_details" data-role="attachments-list" data-scope="{{#if resourceParam}}resource{{else}}method{{/if}}">
                                                    <td>
                                                        <span data-role="name">{{name}}</span>
                                                        {{#required}}
                                                        <br/><span class="required" data-role="required">(required)</span>
                                                        {{/required}}
                                                    </td>
                                                    <td>
                                                        {{#if required}}
                                                        <input name="{{name}}" class="form-control" type="file" data-role="value" required/>
                                                        {{else}}
                                                        <input name="{{name}}" class="form-control" type="file" data-role="value" />
                                                        {{/if}}
                                                    </td>
                                                    <td>
                                                        <p data-role="description" data-allow-edit="true" class="markdown">
                                                            {{{description}}}
                                                        </p>
                                                    </td>
                                                </tr>
                                                {{/each}}
                                                </tbody>
                                            </table>
                                        </div>
                                    </form>
                                </div>
                            </div>
                        </div>
                        {{/if}}
                        {{/body}}
                        <!-- Try it out !! -->
                        <div class="panel panel-default">
                            <div class="panel-heading">
                                <h4 class="panel-title" style="display: inline;">Try it out !!</h4>
                                <i id="headerParametersCollapse-arrow" class="glyphicon glyphicon-chevron-right" style="float:right;"></i>
                            </div>
                            <div id="tryitout-table" class="panel-collapse collapse in">
                                <div class="panel-body">
                                    {{#body}}
                                    <!-- Request payload section -->
                                    <div class="request_payload">
                                        <ul class="nav nav-pills" data-role="request-payload-link">
                                            <li class="active">
                                                <a href="javascript:void(0)" data-role="example-link">Value</a>
                                            </li>
                                            {{#if doc}}
                                            <li>
                                                <a href="javascript:void(0)" data-role="docs-link">Description</a>
                                            </li>
                                            {{/if}}
                                            <li>
                                                <a href="javascript:void(0)" data-role="schema-link">Schema</a>
                                            </li>
                                        </ul>
                                        {{#if doc}}
                                        <div data-role="request-payload-docs" class="docs">
                                            {{{doc}}}
                                        </div>
                                        {{/if}}
                                        <div data-role="request-payload-example">
                                            <textarea class="payload_text" data-format="{{contentType}}"></textarea>
                                        </div>
                                        <div data-role="request-payload-schema" style="display:none">
                                            <textarea class="payload_text_schema" data-format="{{contentType}}" style="width:100%;height:300px;"></textarea>
                                        </div>
                                    </div>
                                    {{/body}}


                                    {{#if-template-param this.parameters}}
                                    <div class="hide" data-role="template-params">
                                        {{#template-list this.parameters}}
                                        <p data-scope="{{scope}}">
                                            <span data-role="name">{{name}}</span>
                                            <span data-role="description" class="markdown">{{{description}}}</span>
                                            <span data-role="defaultValue">{{defaultValue}}</span>
                                            <span data-role="required">{{required}}</span>
                                        </p>
                                        {{/template-list}}
                                    </div>
                                    {{/if-template-param}}
                                    <div class="operation_container">
                                        <!-- Basic authentication, custom token and OAuth 2 authentication container -->
                                        <div class="authentication" data-role="authentication_container">
                                            <div class="well basicauth" data-role="basic_auth_container">
                                                <p class="title">HTTP Basic</p>
                                                <div class="details">
                                                    <a data-toggle="modal" role="button" href="#basicauth_modal" title="Set credentials." class="link_open_basicauth">Set...</a>
                                                    <i title="Clear admin credentials." class="icon-remove"></i>
                                                </div>
                                            </div>
                                            <div class="well oauth2" data-role="oauth2_container">
                                                <p class="title">OAuth 2.0</p>
                                                <div class="details">
                                                    <a data-toggle="modal" role="button" href="#oauth2_modal" title="Set credentials." class="link_open_oauth2">Set...</a>
                                                    <i title="Clear admin credentials." class="icon-remove"></i>
                                                </div>
                                            </div>
                                            <div class="well customtoken" data-role="custom_token_container">
                                                <p class="title">API Key</p>
                                                <div class="details">
                                                    <a data-toggle="modal" role="button" href="#customtoken_modal" title="Set credentials." class="link_open_customtoken">Set...</a>
                                                    <i title="Clear admin credentials." class="icon-remove"></i>
                                                </div>
                                            </div>
                                        </div>
                                        <button id="send_request">SEND
                                        </button>
                                        <a href="javascript:void(0)" class="link_reset_default" title="Reset to default request parameters and body content.">RESET</a>
                                    </div>
                                    <!-- Request and response tab section -->
                                    <div class="request_response_tabs" >
                                        <a href="javascript:void(0)" id="link_request_tab" data-role="request-link">Request</a>
                                        <a href="javascript:void(0)" id="link_response_tab" data-role="response-link" class="selected">Response</a>
                                        <a href="javascript:void(0)" id="link_curl_tab" data-role="curl-link">cURL</a>
                                    </div>
                                    <!-- Request and response container -->
                                    <div id="request_response_container">
                                        <div class="response" data-role="response-container">
                                            <p>Make a request and see the response.</p>
                                        </div>
                                        <div class="request" data-role="request-container">
                                            <p>Make a request and see the response.</p>
                                        </div>
                                        <div class="curl" data-role="curl-container">
                                            <p>Make a request and see the response.</p>
                                        </div>
                                    </div>
                                    {{#response}}
                                    {{#if doc}}
                                    <!-- Response payload doc section -->
                                    <div class="response_payload">
                                        <h3>Response Payload Elements</h3>
                                        <div data-role="response-payload-docs">
                                            {{{response.doc}}}
                                        </div>
                                    </div>
                                    <div data-role="response-content-type" class="hide">{{contentType}}</div>
                                    <textarea data-role="response-payload" class="hide">{{sample}}</textarea>
                                    {{/if}}
                                    {{/response}}
                                </div>
                            </div>
                        </div>
                        <!-- Try it out !! -->


                        <div class="panel panel-default">
                            <div class="panel-heading">
                                <h4 class="panel-title" style="display: inline;">Request Attributes</h4>
                                <i id="headerParametersCollapse-arrow" class="glyphicon glyphicon-chevron-right" style="float:right;"></i>
                            </div>
                            <div class="panel-body">
                                <table class="table table-striped">
                                    <thead>
                                    <tr>
                                        <th>Parameter Name</th>
                                        <th>Parameter Type</th>
                                        <th>Parameter Description</th>
                                    </tr>
                                    </thead>
                                    <tbody id="request-attributes-table">
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>


        </div><!--/.col-sm-12 -->
    </div><!-- #method_content -->
    <div class="col-sm-5">
        <div class="well well-sm">
            <div class="table-responsive">
                <table class="table table-condensed table-resource-summary">
                    <div class="resource_summary">
                        <thead>
                        <tr>
                            <td colspan="2">
                                <h4>Resource Summary</h4>
                            </td>
                        </tr>
                        </thead>
                        <tbody>
                        <tr class="authType">
                            <td>
                                <p class="title">Security</p>
                            </td>
                            <td>
                                <p class="data auth_type" data-role="auth-type"></p>
                            </td>
                        </tr>
                        {{!-- Only output Content Type if it exists, but make
                        sure to check both body.contentType and parameters.
                        --}}
                        {{#if body.contentType}}
                        <tr>
                            <td>
                                <p class="title">Content Type</p>
                            </td>
                            <td>
                                <p class="data content-type-source-body" data-role="content-type">
                                    {{body.contentType}}
                                </p>
                            </td>
                        </tr>
                        {{/if}}
                        {{!-- Only output Category if it exists --}}
                        {{#if tags}}
                        <tr>
                            <td>
                                <p class="title">Category</p>
                            </td>
                            <td>
                                <p class="data" data-role="category">
                                    {{#each tags}}{{.}}{{#unless @last}}, {{/unless}}{{/each}}
                                </p>
                            </td>
                        </tr>
                        {{/if}}
                        </tbody>
                    </div><!--/.resource_summary -->
                </table>
            </div>
            <!-- Resource summary - right side info section -->
        </div>
        {{#response}}
        {{#if errors}}
        <div class="well well-sm">
            <table class="table table-condensed table-error-codes">
                <div class="error_codes">
                    <thead>
                    <tr>
                        <td colspan="2">
                            <h4>Resource Error Codes</h4>
                        </td>
                    </tr>
                    </thead>
                    <tbody>
                    <tr class="headingsErrorCodes">
                        <td>
                            <p class="httpCode-title">HTTP Code</p>
                        </td>
                        <td>
                            <p class="errorCode-title">Error Code</p>
                        </td>
                        <td>
                            <p class="errorDesc-title">Description</p>
                        </td>
                    </tr>
                    {{#each errors}}
                    <tr class="listErrorCodes" data-role="response_errors_list">
                        <td>
                            <p class="httpCode-title">{{httpStatusCode}}</p>
                        </td>
                        <td>
                            <p class="errorCode-title">{{code}}</p>
                        </td>
                        <td>
                            <p class="errorDesc-title">{{{description}}}</p>
                        </td>
                    </tr>
                    {{/each}}


                    </tbody>
                </div><!--/.resource_summary -->
            </table>
        </div>
        {{/if}}
        {{/response}}
    </div>
    <div id="working_alert">
        <p>Working...</p>
    </div>
    <!-- Basic authentication modal -->
    <div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true" id="modal_container" data-role="basic_auth_modal">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close button_close_modal" data-dismiss="modal" aria-hidden="true">×</button>
                    <h3 class="modal-title">Set Authentication</h3>
                </div>
                <div class="modal-body">
                    <form class="form-horizontal">
                        <div class="error_container"></div>
                        <div class="form-group">
                            <label class="control-label" for="inputEmail">Email</label>
                            <input  class="form-control" type="text" id="inputEmail" placeholder="Email"/>
                        </div>
                        <div class="form-group">
                            <label class="control-label" for="inputPassword">Password</label>
                            <input class="form-control" type="password" id="inputPassword" placeholder="Password"/>
                        </div>
                    </form>
                </div>
                <div class="modal-footer">
                    <p>Your credentials are saved for the session only.</p>
                    <a class="btn btn-primary button_save_modal" href="javascript:void(0)">Save</a>
                    <a class="button_close_modal" href="javascript:void(0)">Cancel</a>
                </div>
            </div>
            <!-- /.modal-content -->
        </div>
        <!-- /.modal-dialog -->
    </div>
    <!-- /.modal -->
    <!-- OAuth 2 authentication modal -->
    <div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true" id="modal_container" data-role="oauth2_modal">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close button_close_modal" data-dismiss="modal" aria-hidden="true">×</button>
                    <h3 class="modal-title">Request {{apiName}} permissions</h3>
                </div>
                <div class="modal-body">
                    <div class="content">
                        <p>Making {{apiName}} API requests requires you to grant access to this app.</p>
                        <p>You will be directed to {{apiName}} to approve the use of your credentials and then returned to this page.</p>
                        <p>You can revoke these permissions at any time.</p>
                    </div>
                </div>
                <div class="modal-footer">
                    <p>Your credentials are saved for the session only.</p>
                    <a class="btn btn-primary button_save_modal" href="javascript:void(0)">OK</a>
                    <a class="button_close_modal" href="javascript:void(0)">Cancel</a>
                </div>
            </div>
            <!-- /.modal-content -->
        </div>
        <!-- /.modal-dialog -->
    </div>
    <!-- /.modal -->
    <!-- Custom token authentication modal -->
    <div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true" id="modal_container" data-role="custom_token_modal">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close button_close_modal" data-dismiss="modal" aria-hidden="true">×</button>
                    <h3 class="modal-title">Custom Token</h3>
                </div>
                <div class="modal-body">
                    <div class="content">
                        <form class="form-horizontal">
                            <div data-role="custom_token_rows">
                                <div data-role="custom_token_row">
                                    <div class="form-group">
                                        <label class="control-label">Name:</label>
                                        <input type="text" class="form-control" placeholder="Name" data-role="name">
                                    </div>
                                    <div class="form-group">
                                        <label class="control-label">Value:</label>
                                        <input type="text" class="form-control" placeholder="Value" data-role="value">
                                    </div>
                                </div>
                            </div>
                            <div class="form-group">
                                <label class="control-label">Header:</label>
                                <input type="radio" name="custom_token_type" data-role="header">
                            </div><!-- /input-group -->
                            <div class="form-group">
                                <label class="control-label">Query:</label>
                                <input type="radio" data-role="query" name="custom_token_type">
                            </div><!-- /input-group -->
                        </form>
                    </div>
                </div>
                <div class="modal-footer">
                    <a class="btn btn-primary button_save_modal" href="javascript:void(0)">Ok</a>
                    <a class="button_close_modal" href="javascript:void(0)">Cancel</a>
                </div>
            </div>
            <!-- /.modal-content -->
        </div>
        <!-- /.modal-dialog -->
    </div>
    <!-- /.modal -->
    <!-- Org admin authentication modal -->
    <div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true" id="modal_container" data-role="edit_auth_modal">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close button_close_modal" data-dismiss="modal" aria-hidden="true">×</button>
                    <h3 class="modal-title">Set Organization Admin Credentials</h3>
                </div>
                <div class="modal-body">
                    <form class="form-horizontal">
                        <div class="error_container"></div>
                        <div class="form-group">
                            <label class="control-label" for="inputEmail">Email</label>
                            <input  class="form-control" type="text" id="inputEmail" placeholder="Email"/>
                        </div>
                        <div class="form-group">
                            <label class="control-label" for="inputPassword">Password</label>
                            <input class="form-control" type="password" id="inputPassword" placeholder="Password"/>
                        </div>
                    </form>
                </div>
                <div class="modal-footer">
                    <p>Your credentials are saved for the session only.</p>
                    <a class="btn btn-primary button_save_modal" href="javascript:void(0)">Save</a>
                    <a class="button_close_modal" href="javascript:void(0)">Cancel</a>
                </div>
            </div>
            <!-- /.modal-content -->
        </div>
        <!-- /.modal-dialog -->
    </div>
    <!-- /.modal -->
    <!-- Confirm the changes modal -->
    <div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true" id="modal_container" data-role="confirm_modal">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close button_close_modal" data-dismiss="modal" aria-hidden="true">×</button>
                    <h3 class="modal-title">Warning</h3>
                </div>
                <div class="modal-body">
                    <div class="content">
                        <p>Your changes have not been saved.</p>
                    </div>
                </div>
                <div class="modal-footer">
                    <a class="btn btn-primary button_save_modal" href="javascript:void(0)">Save</a>
                    <a class="button_close_modal" href="javascript:void(0)">Discard</a>
                </div>
            </div>
            <!-- /.modal-content -->
        </div>
        <!-- /.modal-dialog -->
    </div>
    <!-- /.modal -->
    <div id="apigee-apimodel-bodysample" style="display:none">{{body.sample}}</div>
    <div id="apigee-apimodel-bodydoc" style="display:none">{{body.doc}}</div>
    <script type="text/javascript">
        var Apigee = Apigee || {};
        Apigee.APIModel = Apigee.APIModel || {};
        Apigee.APIModel.apiName = "{{apiName}}";
        Apigee.APIModel.revisionNumber = "{{revisionNumber}}";
        Apigee.APIModel.organizationName = "{{organizationName}}";
        Apigee.APIModel.resourceId = "{{resourceId}}";
        Apigee.APIModel.methodId = "{{id}}";
        Apigee.APIModel.methodType = "details";
        Apigee.APIModel.apiKey = "";
        Apigee.APIModel.location = "";
        Apigee.APIModel.templateAuthName = "";
        Apigee.APIModel.verb="{{verb}}".toLowerCase();
        // Init hasRawBody to false.
        Apigee.APIModel.hasRawBody = false;


        {{#if body}}
        Apigee.APIModel.bodyParameters={{#if body.parameters}}{{{body.parameters}}}{{else}}false{{/if}};
        // The following two divs contain HTML-encoded text, to allow us to handle
        // text which includes quotes.
        Apigee.APIModel.bodySample = jQuery('div#apigee-apimodel-bodysample').text();
        if (Apigee.APIModel.bodySample.length == 0) {
            Apigee.APIModel.bodySample = false;
        }
        Apigee.APIModel.bodyDoc = jQuery('div#apigee-apimodel-bodydoc').text();
        if (Apigee.APIModel.bodyDoc.length == 0) {
            Apigee.APIModel.bodyDoc = false;
        }
        {{else}}
        Apigee.APIModel.bodyParameters=false;
        Apigee.APIModel.bodySample=false;
        Apigee.APIModel.bodyDoc=false;
        {{/if}}
        {{#if security}}
        Apigee.APIModel.security = {{{security}}};
        for (var k in Apigee.APIModel.security) {
            if (typeof Apigee.APIModel.security[k] == 'string') {
                Apigee.APIModel.security[k] = JSON.parse(Apigee.APIModel.security[k]);
            }
        }
        {{else}}
        Apigee.APIModel.security = false;
        {{/if}}
        Apigee.APIModel.originalExpandedSchema={{#if apiSchema.expandedSchema}}{{{apiSchema.expandedSchema}}}{{else}}false{{/if}};
        Apigee.APIModel.expandedSchema={{#if apiSchema.expandedSchema}}{{{apiSchema.expandedSchema}}}{{else}}false{{/if}};


        if(Apigee.APIModel.bodyParameters) {
            for(var i in Apigee.APIModel.bodyParameters) {
                // If a parameter is type of object, set hasRawBody to true so we can remove body parameters section.
                if(Apigee.APIModel.bodyParameters[i].dataType && Apigee.APIModel.bodyParameters[i].dataType == "object") {
                    Apigee.APIModel.hasRawBody = true;
                }
                if(Apigee.APIModel.bodyParameters[i].schema) {
                    var resourceSchema = JSON.parse(Apigee.APIModel.bodyParameters[i].schema);


                    if (resourceSchema.$ref) {
                        // There is a reference to the schema in the object.
                        Apigee.APIModel.resourceName = resourceSchema.$ref;
                        Apigee.APIModel.resourceName = Apigee.APIModel.resourceName.split("/");
                        Apigee.APIModel.resourceName = Apigee.APIModel.resourceName[Apigee.APIModel.resourceName.length - 1];
                        break;
                    } else if(resourceSchema.items.$ref) {
                        // There is an array w/a reference.
                        Apigee.APIModel.resourceName = resourceSchema.items.$ref;
                        Apigee.APIModel.resourceName = Apigee.APIModel.resourceName.split("/");
                        Apigee.APIModel.resourceName = Apigee.APIModel.resourceName[Apigee.APIModel.resourceName.length - 1];
                    }
                }
            }
        }


        // -------------------------------------------------------------------------
        // SECURITY
        // -------------------------------------------------------------------------
        var security = [];
        if(Apigee.APIModel.security) {
            for (i=0;i<Apigee.APIModel.security.length;i++){
                security.push(Apigee.APIModel.security[i]);
            }
        }


        // If security is set in the model, display the values in the resource
        // summary table, and pull out the default security values if set.
        var newAuth = [];
        var authTypeEl = jQuery("[data-role='auth-type']");
        authTypeEl.text(newAuth);
        for (var i in security){
            for (var keys in security[i]) {
                if (typeof security[i] == 'string') {
                    security[i] = JSON.parse(security[i]);
                }
                if (security[i][keys].type) {
                    switch (security[i][keys].type) {
                        case 'OAUTH2':
                            newAuth.push('OAuth 2.0');
                            secName = keys;
                            break;
                        case 'BASIC':
                            newAuth.push('HTTP Basic');
                            break;
                        case 'APIKEY':
                            newAuth.push('API Key');
                            if (security[i][keys].templateauths) {
                                for (var key in security[i][keys].templateauths) {
                                    Apigee.APIModel.apiKey = security[i][keys].templateauths[key];
                                    Apigee.APIModel.location = security[i][keys].location.toLowerCase();
                                    Apigee.APIModel.templateAuthName = key.toLowerCase();
                                }
                            }
                            break
                    }
                }
                // If the security object does not have any template auths, it will
                // have an attribute named "error" that will have the value
                // "No templateAuth found for KEYNAME", where KEYNAME is the
                // name of the security object.
                else if (typeof security[i][keys] === "object" && security[i][keys].hasOwnProperty("error")) {
                    newAuth.push("API Key");
                }
            }
        }
        if (newAuth.length == 0) {
            newAuth.push('None');
        }
        authTypeEl.text(newAuth.join(', '));


        // -------------------------------------------------------------------------
        // PAYLOAD
        // -------------------------------------------------------------------------
        var payload = jQuery(".request_payload");
        var payloadTextSchemaEl = jQuery("textarea.payload_text_schema");
        var originalSchemaObj = null;
        if (Apigee.APIModel.expandedSchema) {
            originalSchemaObj = Apigee.APIModel.expandedSchema;
            expandSchema(originalSchemaObj);
        }


        // Extract Request Parameters
        var requestParamsSchema = Apigee.APIModel.expandedSchema[Apigee.APIModel.resourceName];
        function extractParametersInfo(obj, reqResParams)
        {
            var k;
            if (obj.hasOwnProperty('properties')) {
                for (k in obj['properties']) {
                    obj['properties'][k].name = k;
                    reqResParams.push(obj['properties'][k]);
                    if (obj['properties'][k].hasOwnProperty('properties')){
                        extractParametersInfo( obj['properties'][k], reqResParams);
                    }
if (obj['properties'][k].hasOwnProperty('items')) {
					extractParametersInfo( obj['properties'][k]['items'], reqResParams);
						}
					                }
            }
        };
        var reqResParams = [];
        extractParametersInfo(requestParamsSchema, reqResParams);
        console.log(reqResParams);


        for (k in reqResParams) {
if (reqResParams[k]['description'] == undefined) {
			reqResParams[k]['description'] = "⏎";
				}
			            jQuery("#request-attributes-table").append("<tr><td>" + reqResParams[k]['name'] + " </td><td>" + reqResParams[k]['type'] + "</td><td>" + reqResParams[k]['description'] + "</td></tr>");
        }






        if (Apigee.APIModel.verb != "post" && Apigee.APIModel.verb != "put" && Apigee.APIModel.verb != "patch") {
            // Remove request payload for verbs that carry no payload.
            payload.remove();
        }
        else {
            // If a sample exists, use it to populate the body payload text area,
            // else create an example from the api schema to populate the body
            // payload.
            if (Apigee.APIModel.bodySample) {
                // Class payload_text is the request body to send.
console.log(Apigee.APIModel.bodySample);
				                jQuery("textarea.payload_text").val(Apigee.APIModel.bodySample);
            }


            if (Apigee.APIModel.expandedSchema && Apigee.APIModel.resourceName != null) {
                // Put the schema into the Schema tab in the response body.
                var schemaString = JSON.stringify(originalSchemaObj[Apigee.APIModel.resourceName].properties, null, 4);
                payloadTextSchemaEl.val(schemaString);
            }


        }


        // If any select box has a default value, make sure it is set.
        jQuery('select.has-default-value').each(function(index) {
            var defaultValue = jQuery(this).attr('data-default-value');
            jQuery('option', this).each(function (idx) {
                if (jQuery(this).attr('value') == defaultValue) {
                    jQuery(this).attr('selected', 'selected');
                }
            });
        });


        if (Apigee.APIModel.hasRawBody) {
            // Remove the body parameters section if the raw body should be
            // displayed.
            jQuery(".body-parameters-wrapper").remove();
        } else {
            // If the API Model does not have a payload, then remove the payload
            // section.
            payload.remove();
        }
        // For any content-type listing, convert comma-delimited list into a
        // columnar list.
        var contentTypeElements = document.getElementsByClassName('content-type-source-body');
        for (var k = 0; k < contentTypeElements.length; k++) {
            if(contentTypeElements[k] != null && 'innerHTML' in contentTypeElements[k]) {
                contentTypeElements[k].innerHTML = contentTypeElements[k].innerHTML.replace(/,/g, '<br>');
            }
        }


        function expandSchema (obj, originalObj) {
            for (var key in obj) {
                if (typeof obj[key] === "object") {
                    expandSchema(obj[key], (originalObj || obj));
                }
                else {
                    if (key === "$ref") {
                        if (typeof obj[key] === "string" && obj[key].indexOf("#/definitions") != -1) {
                            var objRef = obj[key].slice(14);
                            for (var oKey in originalObj[objRef]) {
                                if(oKey != 'required'){
                                    obj[oKey] = originalObj[objRef][oKey];
                                }
                            }
                            delete obj[key];
                            delete obj["description"];
                        }
                    }
                }
            }
        }


        if (typeof marked != 'undefined') {
            var descriptions = document.getElementsByClassName('markdown');
            for (var i = 0; i < descriptions.length; i++) {
                descriptions[i].innerHTML = marked(descriptions[i].innerHTML);
            }
        }


        (function ($) {
            Drupal.behaviors.exampleModule = {
                attach: function (context, settings) {
                    // Code to be run on page load, and
                    // on ajax load added here
                    $('.panel-heading').bind('click', function() {
                        $(this).parent().find(".panel-collapse").toggle();
                        if ($(this).find("i").hasClass('glyphicon-chevron-right')) {
                            $(this).find("i").removeClass("glyphicon-chevron-right");
                            $(this).find("i").addClass("glyphicon-chevron-down");
                        } else {
                            $(this).find("i").removeClass("glyphicon-chevron-down");
                            $(this).find("i").addClass("glyphicon-chevron-right");
                        }
                    });
                }
            };
        }(jQuery));
    </script>
</div>

Step 2 : Navigate to SmartDocs settings page in your developer portal as Admin , Content -> SmartDocs -> {YOURSMARTDOCS} -> Settings

Step 3 : Replace Method Template content with above file contents you copied, Save Template

Step 4 : Clear Drupal Caches.

You should see updated smartdocs method page with list of request params info like below,

5819-smartdocs-templ2.png

Hope it helps someone looking for same. Please keep us posted with your feedback / queries if any using comments below.

Comments
jaywanttopno
New Member
@Anil Sagar

i do agree with you, regarding request parameter attributes detail. Swagger UI display lot of information, but only few things getting rendered in a node.

for one of our client we are displaying Data Type for Query parameter with Sample response schema. and i feel lot of the things can be achievable.

anilsr
Staff

@jaywant ,

Glad above article is helpful for you. Yes, Totally agree with you. Like said, I am working on solving smartdocs issues one issue at a time. You will see more articles related to same here.

Please try above solution & keep us posted with feedback when you use same. Thank you in advance.

Not applicable

@Anil Sagar I tried with your updated template, But still Request body Parameters default values are empty,. ? But it is getting displayed in swagger. Kindly help me

gluskin-samuel
New Member

Is this template in Github? Seems like progress would be fastest and that we could learn from each other as well by comparing forks.

anilsr
Staff

@Shai Gluskin , It's not in github. Please feel free to create one & update here. I can update the article with reference to same.

gluskin-samuel
New Member
jirawatboonkumn
New Member

Hi @Anil Sagar @ Google

Can we add more field of Smartdocs and also on the edit menu?

Version history
Last update:
‎10-28-2017 10:54 AM
Updated by: