Forum Discussion

kip's avatar
kip
New Contributor
6 years ago

Reducing redundant endpoint definitions

Hey forum,

 

I have a design question concerning the best practise for the following scenario.

 

I have a bunch of endpoints defined in my OpenAPI specification, but actually double what really ought to be fully defined. These operations apply to specific entities (let's say songs for the sake of example). Each song has a unique database assigned numeric song_id, but also has a freeform unique text "reference" that the client assigns when adding the song to the database. When a request is made to an endpoint that uses a song_reference, the server translates the reference into a song_id and then performs the request. The song_reference endpoints are effectively just wrappers for the song_id endpoints.

 

I don't want to have to define two sets of operations for what's effectively the same endpoints under the hood.

 

I have reproduced a minimal below:

 

openapi: "3.0.1"

info:
  title: "Some API"
  version: "0.1"

paths:

  /songs/download/by_id/{song_id}:

    get:

      summary: "Download a song by ID."
      operationId: getSongDownloadById
      parameters:

        - name: song_id
          in: path
          explode: false
          required: true
          description: "ID of song to download."
          schema:
            $ref: "#/components/schemas/song_id"
          example: 1434

      responses:

        200:
          description: "Operation successful"
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
                example: "...file's raw binary data..."

        304:
          description: "Not modified"

        404:
          description: "Not found response."

# Redundant endpoint definition below which is exactly the same except expects song_reference. /songs/download/by_reference/{song_reference}: get: summary: "Download a song by reference." operationId: getSongDownloadByReference parameters: - name: song_reference in: path explode: false required: true description: "Reference of song to download." schema: $ref: "#/components/schemas/song_reference" example: "some_reference" responses: 200: description: "Operation successful" content: application/octet-stream: schema: type: string format: binary example: "...file's raw binary data..." 304: description: "Not modified" 404: description: "Not found response" components: schemas: song_id: type: "integer" description: "Database assigned unique song ID." song_reference: type: "string" description: "Similar to song ID, but assigned by client when song added to database. Unique."

My goal is of course to reduce redundancy in the specification. Suggestions?

  • Hi there! Great question. Based on what you're describing, the operations are not really the same, because the input is different. However, it's clear the output is the same. What you can do, is define the responses as shared components and reference them, so you don't have to duplicate the definition. At the moment, that means you'll have to do that for each reference, as there's no support for grouped references, but hopefully will change in the future.

  • Hi there! Great question. Based on what you're describing, the operations are not really the same, because the input is different. However, it's clear the output is the same. What you can do, is define the responses as shared components and reference them, so you don't have to duplicate the definition. At the moment, that means you'll have to do that for each reference, as there's no support for grouped references, but hopefully will change in the future.

    • kip's avatar
      kip
      New Contributor

      Thank you. I will give it a try.