Skip to main content

2. Create and document an API using OpenAPI

The Provider

Design the API

As we are following a specification or design first approach to API development, we start by creating an OpenAPI description document, that describes how our API should work.

Authoring an OAS document is beyond the scope of this tutorial, but you can find plenty of resources on the internet (such as at swagger.io).

openapi: 3.0.1
info:
title: Product API
description: PactFlow Product API demo
version: 1.0.0
paths:
/products:
post:
summary: Create a product
description: Creates a new product
operationId: createProduct
requestBody:
description: Create a new Product
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Product'
examples:
application/json:
value:
id: "1234"
type: "food"
price: 42
responses:
"200":
description: successful operation
content:
"application/json; charset=utf-8":
schema:
oneOf:
- $ref: '#/components/schemas/Product'
examples:
application/json:
value:
id: "1234"
type: "food"
price: 42
get:
summary: List all products
description: Returns all products
operationId: getAllProducts
responses:
"200":
description: successful operation
content:
"application/json; charset=utf-8":
schema:
type: "array"
items:
$ref: '#/components/schemas/Product'
examples:
application/json:
value:
- id: "1234"
type: "food"
price: 42
# name: "pizza"
# version: "1.0.0"
# see https://github.com/apiaryio/dredd/issues/1430 for why
"400":
description: Invalid ID supplied
content: {}
/product/{id}:
get:
summary: Find product by ID
description: Returns a single product
operationId: getProductByID
parameters:
- name: id
in: path
description: ID of product to get
schema:
type: string
required: true
example: 10
responses:
"200":
description: successful operation
content:
"application/json; charset=utf-8":
schema:
$ref: '#/components/schemas/Product'
examples:
application/json:
value:
id: "1234"
type: "food"
price: 42
# name: "pizza"
# version: "1.0.0"
# see https://github.com/apiaryio/dredd/issues/1430 for why
"400":
description: Invalid ID supplied
content: {}
"404":
description: Product not found
content: {}
components:
schemas:
Product:
type: object
required:
- id
- name
- price
additionalProperties: false
properties:
id:
type: string
type:
type: string
name:
type: string
version:
type: string
price:
type: number

As you can see, we have 3 main endpoints:

  1. POST /products - create a new product
  2. GET /products - gets all products
  3. GET /products/:id - gets a single product

Having designed our API, we can now set about building it.

Implement the Product API

Here is the Product API using the Express JS framework. Once again, writing an API is beyond the scope of this tutorial.

We define our product, the available routes, the datastore (an simple in-memory database) and the server.

src/product/product.js
loading...
src/product/product.routes.js
loading...
src/product/product.repository.js
loading...
src/product/product.controller.js
loading...
server.js
loading...
info

You can pick your provider now

Fork and clone the provider

  1. Fork the example-bi-directional-provider-dredd project in to your own Github account (click the 'Fork' button in the top right).

  2. Clone the repository on to your local machine.

    git clone git@github.com:<YOUR_GITHUB_USERNAME>/example-bi-directional-provider-dredd.git
  3. Install the dependencies.

    npm install

Check

Before moving to the next step, cd into the example-bi-directional-provider-dredd directory and run the provider to see if it starts.

The tutorial environment should have installed 2 projects and their dependencies. Once the terminal process completes you can run:

  1. cd /root/example-bi-directional-provider-dredd
  2. npm i
  3. npm start

Open up a separate terminal and run the following command:

  1. cd /root/example-bi-directional-provider-dredd
  2. curl localhost:3001/products | jq .

You should see the following output:

[
{
"id": "09",
"type": "CREDIT_CARD",
"name": "Gem Visa",
"version": "v1",
"price": 99.99
},
{
"id": "10",
"type": "CREDIT_CARD",
"name": "28 Degrees",
"version": "v1",
"price": 49.49
},
{
"id": "11",
"type": "PERSONAL_LOAN",
"name": "MyFlexiPay",
"version": "v2",
"price": 16.5
}
]

Switch back to your first terminal and terminate (ctrl-c) the process to make sure your provider is no longer running.