Search results

Step 4: The paths object (OpenAPI tutorial)

The paths object contains the meat of your API information. The paths object has a number of sub-objects: a path items object, an operations object, and more.

My preferred term is “endpoint” rather than “path,” but to be consistent with the terminology of the openAPI spec, I refer to them as “paths” here.

Start by listing the paths

Start by listing the paths (endpoints) and their allowed operations (methods). For the weather endpoint in the OpenWeatherMap API, there is just 1 path with the get operation:

paths:
  /weather:
    get:

Operation Objects

Each path item object contains an operation object. Operations are the GET, POST, PUT, and DELETE methods we explored in the Endpoints section of the API reference tutorial methods. The operation object contains a number of potential properties and objects:

  • tags: A tag to organize the path under when displayed in the Swagger UI. Swagger UI will organize or group endpoints under tag headings.
  • summary: A brief overview of the path. Swagger UI displays the summary next to the path name. Limit the summary to 5-10 words only. The display appears even when this section is collapsed.
  • description: A full description of the path. Include as much detail as you want. There’s a lot of space in the Swagger UI for these details. CommonMark Markdown is allowed.
  • externalDocs (object): Links to documentation for more information about the path.
  • operationId: A unique identifier for the path.
  • parameters (object): Parameters accepted by the path. Does not include request body parameters, which are instead detailed in the requestBody object. The parameters object can also include a reference object that simply contains a pointer to the description in the components object (this is explained in step 5).
  • requestBody (object): The request body parameter details for this path. The requestBody object can also include a reference object that simply contains a pointer to the description in the components object (explained in step 5).
  • responses (object): Responses provided from requests with this path. The responses object can also include a reference object that simply contains a pointer to the description in the components object. Responses use standard status codes.
  • callbacks (object): Callback details to be initiated by the server if desired. Callbacks are operations performed after a function finishes executing. The callbacks object can also include a reference object that simply contains a pointer to the description in the components object.
  • deprecated: Whether the path is deprecated. Omit unless you want to indicate a deprecated field. Boolean.
  • security (object): Security authorization method used with the operation. Only include this object at the path level if you want to overwrite the security object at the root level. The name is defined by the securitySchemes object in the components object. More details about this are provided in the security object.
  • servers (object): A servers object that might differ for this path than the global servers object.

Each of the above hyperlinked properties that say “(object)” contain additional levels. Their values aren’t just simple data types like strings but are rather objects that contain their own properties.

Let’s add a skeleton of the operation object details to our existing code:

paths:
  /weather:
    get:
      tags:
      summary:
      description:
      operationId:
      externalDocs:
      parameters:
      responses:
      deprecated:
      security:
      servers:
      requestBody:
      callbacks:

Now we can remove a few unnecessary fields:

  • There’s no need to include requestBody object here because none of the OpenWeatherMap API paths contain request body parameters.
  • There’s no need to include the servers object because the paths just use the same global servers URL that we defined globally at the root level.
  • There’s no need to include security because all the paths use the same security object, which we defined globally at the root (see step 6).
  • There’s no need to include deprecated because none of the paths are deprecated.
  • There’s no need to include callbacks because our paths don’t use callbacks.

As a result, we can reduce the number of fields to concern ourselves with:

paths:
  /weather:
    get:
      tags:
      summary:
      description:
      operationId:
      externalDocs:
      parameters:
      responses:

You’ll undoubtedly need to consult the OpenAPI spec to see what details are required for each of the values and objects here. I can’t replicate all the detail you need, nor would I want to. I’m just trying to introduce you to the OpenAPI properties at a surface level.

Most of the properties for the operation object either require simple strings or include relatively simple objects. The most detailed object here is the parameters object.

Parameters object

The parameters object contains an array (list designated with dashes) with these properties:

parameters:

  • name: Parameter name.
  • in: Where the parameter appears. Possible values: header, path, query, or cookie. (Request body parameters are not described here.)
  • description: Description of the parameter.
  • required: Whether the parameter is required.
  • deprecated: Whether the parameter is deprecated.
  • allowEmptyValue: Whether the parameter allows an empty value to be submitted.
  • style: How the parameter’s data is serialized (converted to bytes during data transfer).
  • explode: Advanced parameter related to arrays.
  • allowReserved: Whether reserved characters are allowed.
  • schema (object): The schema or model for the parameter. The schema defines the input or output data structure. Note that the schema can also contain an example object.
  • example: An example of the media type. If your examples object contains examples, those examples appear in Swagger UI rather than the content in the example object.
  • examples (object): An example of the media type, including the schema.

Here’s the operation object defined for the OpenWeatherMap API:

paths:
  /weather:
    get:
      tags:
      - Current Weather Data
      summary: "Call current weather data for one location"
      description: "Access current weather data for any location on Earth including over 200,000 cities! Current weather is frequently updated based on global models and data from more than 40,000 weather stations."
      operationId: CurrentWeatherData
      parameters:
      - name: q
        in: query
        description: "**City name**. *Example: London*. You can call by city name, or by city name and country code. The API responds with a list of results that match a searching word. For the query value, type the city name and optionally the country code divided by comma; use ISO 3166 country codes."
        schema:
          type: string

      - name: id
        in: query
        description: "**City ID**. *Example: `2172797`*. You can call by city ID. API responds with exact result. The List of city IDs can be downloaded [here](http://bulk.openweathermap.org/sample/). You can include multiple cities in parameter — just separate them by commas. The limit of locations is 20. *Note: A single ID counts as a one API call. So, if you have city IDs. it's treated as 3 API calls.*"
        schema:
          type: string

      - name: lat
        in: query
        description: "**Latitude**. *Example: 35*. The latitude cordinate of the location of your interest. Must use with `lon`."
        schema:
          type: string

      - name: lon
        in: query
        description: "**Longitude**. *Example: 139*. Longitude cordinate of the location of your interest. Must use with `lat`."
        schema:
          type: string

      - name: zip
        in: query
        description: "**Zip code**. Search by zip code. *Example: 95050,us*. Please note if country is not specified then the search works for USA as a default."
        schema:
          type: string
          default: "94040,us"
        example:
          "94040,us"

      - name: units
        in: query
        description: '**Units**. *Example: imperial*. Possible values: `metric`, `imperial`. When you do not use units parameter, format is `standard` by default.'
        schema:
          type: string
          enum: [standard, metric, imperial]
          default: "standard"
        example: "imperial"

      - name: lang
        in: query
        description: '**Language**. *Example: en*. You can use lang parameter to get the output in your language. We support the following languages that you can use with the corresponded lang values: Arabic - `ar`, Bulgarian - `bg`, Catalan - `ca`, Czech - `cz`, German - `de`, Greek - `el`, English - `en`, Persian (Farsi) - `fa`, Finnish - `fi`, French - `fr`, Galician - `gl`, Croatian - `hr`, Hungarian - `hu`, Italian - `it`, Japanese - `ja`, Korean - `kr`, Latvian - `la`, Lithuanian - `lt`, Macedonian - `mk`, Dutch - `nl`, Polish - `pl`, Portuguese - `pt`, Romanian - `ro`, Russian - `ru`, Swedish - `se`, Slovak - `sk`, Slovenian - `sl`, Spanish - `es`, Turkish - `tr`, Ukrainian - `ua`, Vietnamese - `vi`, Chinese Simplified - `zh_cn`, Chinese Traditional - `zh_tw`.'
        schema:
          type: string
          enum: [ar, bg, ca, cz, de, el, en, fa, fi, fr, gl, hr, hu, it, ja, kr, la, lt, mk, nl, pl, pt, ro, ru, se, sk, sl, es, tr, ua, vi, zh_cn, zh_tw]
          default: "en"
        example: "en"
      - name: mode
        in: query
        description: "**Mode**. *Example: html*. Determines format of response. Possible values are `xml` and `html`. If mode parameter is empty the format is `json` by default."
        schema:
          type: string
          enum: [json, xml, html]
          default: "json"
        example: "json"

Parameter dependencies

The OpenAPI specification doesn’t allow you to declare dependencies with parameters, or mutually exclusive parameters. According to the Swagger OpenAPI documentation,

OpenAPI 3.0 does not support parameter dependencies and mutually exclusive parameters. There is an open feature request at https://github.com/OAI/OpenAPI-Specification/issues/256. What you can do is document the restrictions in the parameter description and define the logic in the 400 Bad Request response. (Parameter Dependencies)

In the case of the weather endpoint with the OpenWeatherMap, most of the parameters are mutually exclusive. You can’t search by City ID and by zip code. Although the parameters are optional, you have to use at least one parameter. Also, if you use the latitude parameter, you must also use the longitude parameter, as they’re a pair. The OpenAPI spec can’t programmatically reflect that structured logic, so you just have to explain it in the description property or in other more conceptual documentation.

Single-sourcing definitions across objects

Instead of defining all your parameters and schemas in the paths object, if you re-use the same parameters or schemas across multiple endpoints, you can store these definitions in components and then reference them using $ref pointers ($ref stands for reference object). I explain more about using $ref in step 5.

In this example, I’m just documenting one endpoint in the OpenWeatherMap API. But suppose some parameters such as lat and lon are re-used across many endpoints. In that case, you would want to store each of these parameters in components so that you can re-use them. Copying and pasting information multiple times is inefficient and can lead to inconsistency. The OpenAPI spec allows you to single source the parameter information from a common definition.

The code below shows how you reference a common definition stored in components. See how parameters simply contains a $ref: '#/components/parameters/q, which is defined in components. For brevity, I included just 2 parameters in this example.

paths:
  /weather:
    get:
      tags:
      - Current Weather Data
      summary: "Call current weather data for one location"
      description: "Access current weather data for any location on Earth including over 200,000 cities! Current weather is frequently updated based on global models and data from more than 40,000 weather stations."
      operationId: CurrentWeatherData
      parameters:
        - $ref: '#/components/parameters/q'
        - $ref: '#/components/parameters/id'
        ...

components:
  parameters:
    q:
      in: query
      description: "**City name**. *Example: London*. You can call by city name, or by city name and country code. The API responds with a list of results that match a searching word. For the query value, type the city name and optionally the country code divided by comma; use ISO 3166 country codes."
      schema:
        type: string

    id:
      in: query
      description: "**City ID**. *Example: `2172797`*. You can call by city ID. API responds with exact result. The List of city IDs can be downloaded [here](http://bulk.openweathermap.org/sample/). You can include multiple cities in parameter — just separate them by commas. The limit of locations is 20. *Note: A single ID counts as a one API call. So, if you have city IDs. it's treated as 3 API calls.*"
      schema:
        type: string
      ...

See Re-using response objects for more details. Also see Describing Parameters in Swagger’s OpenAPI documentation.

Responses

One property of the operation object that we haven’t yet defined is the responses object. responses is at the same level as parameters. For the responses property, we typically just reference a full definition in the components object, so I’ll cover the responses object in the next section — Step 5: The components object.

For now, just add a $ref pointer to it:

paths:
  /weather:
    get:
      tags:
      summary: Get current weather data
      description: Access current weather data for any location on Earth including over 200,000 cities! Current weather is frequently updated based on global models and data from more than 40,000 weather stations.
      operationId: WeatherGet
      parameters:

      - name: q
        in: query
        description: "**City name**. *Example: London*. You can call by city name, or by city name and country code. The API responds with a list of results that match a searching word. For the query value, type the city name and optionally the country code divided by comma; use ISO 3166 country codes."
        schema:
          type: string

      - name: id
        in: query
        description: "**City ID**. *Example: `2172797`*. You can call by city ID. API responds with exact result. The List of city IDs can be downloaded here http://bulk.openweathermap.org/sample/. You can include multiple cities in parameter -- just separate them by commas. The limit of locations is 20. NOTE: A single ID counts as a one API call. So, if you have city IDs. it's treated as 3 API calls."
        schema:
          type: string

        ...

      responses:
        200:
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/200'
        404:
          description: Not found response
          content:
            text/plain:
              schema:
                title: Weather not found
                type: string
                example: Not found

We’ll define the details for $ref: '#/components/schemas/200' in the next topic.

Appearance of paths in Swagger UI

Swagger UI displays the paths object like this:

When you click Try it out, the example value populates the parameters field.

Each path is collapsed by default, but you can set whether the initial display is collapsed or open using the docExpansion parameter in Swagger UI.

This docExpansion parameter is for Swagger UI and isn’t part of the OpenAPI spec. Swagger UI has more than 20 different parameters that control its display. If you don’t want the Models section to appear, add the parameter defaultModelsExpandDepth: -1, in your Swagger UI file.

69% Complete

69/101 pages complete. Only 32 more pages to go...

Donate?

Would you like to help encourage more content development and updates? If so, click the Donate button below to donate $10 through Paypal.

Get new posts delivered straight to your inbox.

Subscriber count: 4,285