Image for post
Image for post

Creating a Simple OpenAPI Spec

Having API descriptions in your workflow is a game-changer, but how do you get from nothing to a functioning spec in the first place? I recently made a very simple spec for a very simple API, and thought it might make a good example for anyone looking to create a spec for the first time. OpenAPI specs are very verbose so this very tiny API makes quite a manageable example!

About the API

I’ve been using a very trivial API example project in a few of my recent talks on API-adjacent topics, with just a couple of endpoints. There’s a blog post about the Planets API but in short you can get a list of either one planet or many, with requests like:

GET http://localhost:5000/planets
GET http://localhost:5000/planets/3

Create File, Configure Tools

I’ll be using YAML, you can use JSON instead if you prefer. My file is called openapi.yaml which is a reasonably common file name but you can name your file what you like.

watch -n 3 spectral lint openapi.yaml
openapi: 3.0.3
info:
title: Planets and Webhooks Demo API
version: 0.0.1
description: Simple flask-backed API showing some example API endpoints and with webhook debugging features.
contact:
name: Lorna Mitchell
url: https://github.com/lornajane/flask-planets-and-webhooks
email: github@lornajane.net
servers:
- url: http://localhost:5000
description: Sample project running locally
externalDocs:
description: GitHub project for the code and information about this API
url: https://github.com/lornajane/flask-planets-and-webhooks

Add API Endpoints

This API has two endpoints, so it’s a nice, small problem space to try to describe! The /planets route returns JSON, an array of objects where each object describes a planet. The /planets/{id} route returns just one object, but it is identical to the object returned by the collection. OpenAPI supports a special $ref field for reusing definitions across different parts of the spec. You can use it to structure your spec in a more readable way - but its superpower is in making sure that things that are the same are only defined once, making it easier to keep everything consistent and maintainable.

paths:
/planets/{planetId}:
get:
operationId: onePlanet
summary: Fetch one planet by position
description: Get the data relating to one planet
parameters:
- name: planetId
in: path
required: true
schema:
type: number
example: 4
responses:
'200':
description: Planets in a list
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: Name of planet
example: "Saturn"
position:
type: number
description: Order in place from the sun
example: 6
moons:
type: number
description: Number of moons, according to NASA
example: 62
paths:
/planets/{planetId}:
get:
operationId: onePlanet
summary: Fetch one planet by position
description: Get the data relating to one planet
parameters:
- name: planetId
in: path
required: true
schema:
type: number
example: 4

responses:
'200':
description: Planets in a list
content:
application/json:
schema:
$ref: "#/components/schemas/planet"

components:
schemas:
planet:
type: object
properties:
name:
type: string
description: Name of planet
example: "Saturn"
position:
type: number
description: Order in place from the sun
example: 6
moons:
type: number
description: Number of moons, according to NASA
example: 62
paths:
/planets:
get:
operationId: allPlanets
summary: List all planets
description: Returns a list of all the planets that are stored in the system.
responses:
'200':
description: Planets in a list
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/planet"

Documentation as Output

There are so many things you can do with an OpenAPI spec but a very human-centric one is to generate documentation. There are a few options for this, again Stoplight Studio has it built in, but I mostly use open source tool ReDoc — their 2.0 release isn’t official yet but it is great! Importantly, the project was very receptive to, and quick to fix, the accessibility issues I logged.

screenshot of redoc rendering openapi.yaml
screenshot of redoc rendering openapi.yaml

Final Touches

If you’re playing along at home, you’ll notice that spectral is still having Opinions! That’s because we haven’t added tags yet. Tags aren’t that useful on an OpenAPI spec this size, but for larger APIs they are an excellent innovation. The previous yaml example showing the collection endpoint has a tag, and to finish, all I need to show you is the tags: element in the spec:

tags:
- name: planets
description: API containing solar system data

Polyglot programmer, technology addict, open source fanatic and incurable blogger (see http://lornajane.net)

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store