Using $ref in Open API specifications

By John Keyes

May 31, 2024 at 16:32

openapi openapi redoc

What is $ref?

$ref is a keyword that allows a definition to be located in a single place, and be used in multiple locations in the API specification.

The most common use of this is for local references, for example when referencing a response object in a path:

responses:
  '200':
    description: An account
      content:
        application/json:
          schema:
          $ref: '#/components/schemas/Account'

The Account object is then defined in the components section:

components:
  schemas:
    Account:
      type: object
    properties:
      id:
        type: string
        description: Unique identifier for the account.
      name:
        type: string
        description: Name of the account holder.

But, $ref can also be used to reference definitions in other files, or even via URLs.

Using $ref for local files

In the following spec, the definition for the /account path is located in the ./paths/account.yaml file.

openapi: 3.0.0
info:
  description: |
    Example API Specification.    

  version: "1.0"
  title: "Example API"
  license:
    name: Proprietary
    url: https://tp.ie
  contact:
    name: Tapadoo Ltd.
    url: https://tapadoo.com

servers:
  - url: "https://dev.tp.ie"
    description: "Development Server"
  - url: "https://prod.tp.ie"
    description: "Production Server"

paths:
  /account:
    $ref: "./paths/account.yaml"

The ./paths/account.yaml file contains the defintion for the get path and the associated responses:

get:
  summary: Get Account
  description: Get the authenticated user's account details.
  operationId: get_account
  security: []

  responses:
    200:
      description: Successful operation.
      content:
        application/json:
          schema:
            type: object
    401:
      description: Unauthorized request.
      content:
        application/json:
          schema:
            type: object

This is an example of a full file $ref, but what if you wanted to refer to a specific definition.

Refering to a specific defintion in a local file

The ./common_responses.yaml file has a common response for 400 responses:

ValidationError:
  description: Validation error.
  content:
    application/json:
      schema:
        type: object
        properties:
          message:
            type: string
            description: Description of the error.
          field:
            type: string
            description: The field that has failed validation.

We can reference this in the post account path in the ./paths/account.yaml using the hash slash syntax:

post:
  tags:
  summary: Create User
  description: Create an account.
  operationId: create_account
  security: []
  requestBody:
    content:
      application/json:
        schema:
          type: object

  responses:
    200:
      description: Successful operation.
      content:
        application/json:
          schema:
            object
    400:
      $ref: "../common_responses.yaml#/ValidationError"

We can see this reference is resolved in the redoc HTML:

And using a URL?

We can also use URL references, though this is not common in our work, for example let’s use the BuyMuseumTicketsResponse as the response from the GET /account operation:

paths:
  get:
    summary: Get Account
    description: Get the authenticated user's account details.
    operationId: get_account
    security: []

    responses:
      200:
        description: Successful operation.
        content:
          application/json:
            schema:
              $ref: "https://redocly.github.io/redoc/museum.yaml#/components/schemas/BuyMuseumTicketsResponse"
    401:
      description: Unauthorized request.
      content:
        application/json:
          schema:
            type: object

The redoc HTML now displays this schema:

Summary

These few examples show how it’s possible to break a large API specification into smaller logical pieces. Note, one downside of this approach is some editing tools may not be able to resolve the references, making in editor navigation (e.g. Ctrl-click) less developer friendly.

References (no pun intended)

Last updated: May 31, 2024 at 16:32