A CLI for REST APIs
Tags: rest, http2, cli, openapi
Published: 2020-06-03 17:58:27

*Standardizing how power users and scripts interact with your service*

Sorry about the acronym soup in the title! 😅

Today I want to talk about an oft-neglected aspect of building REST or HTTP APIs. There are plenty of articles about API design, API description formats like OpenAPI, and lots of libraries and code generators used to talk to the API from code. What is missing in my opinion is a high-quality command line client that’s generic enough to be used for most HTTP APIs.

But there’s `curl`, you say. Many service docs even include examples specifically for calling the service’s API via `curl` commands. I love `curl` and HTTPie, but these are just generic HTTP clients. There’s not enough specialization for REST or HTTP APIs. HTTPie comes close since it speaks JSON, the lingua franca of web APIs, but falls short in other ways, such as describing complex inputs for API operations.

What fancy-pants features would make me happy, you ask? My list would include at least the following:

- Easy to install & fast startup
- Default to HTTP/2 (with TLS), which is now 5 years old! 😮
- Speaks JSON, YAML, and their binary relatives natively
- Caching of responses when appropriate headers are set
- Built-in common API authentication mechanisms like OAuth 2
- Automatically handle pagination of collections
- An easy way to input complex nested data
- Pretty colorized output with the ability to filter built-in
- An understanding of API specs like OpenAPI with auto-discovery
- Always having access to the latest API features & docs

I think that would be a good start to getting where we should be in 2020. With that in mind, I’d like to introduce my new CLI tool for REST & HTTP APIs called Restish (https://rest.sh/).

![Restish logo](https://dev-to-uploads.s3.amazonaws.com/i/v17eg9cu3b4oxbjq75mc.png)

Restish can do all of the above wish list, and more. Installing it is easy if you have Homebrew:

```sh
$ brew tap danielgtaylor/restish && brew install restish
```

Windows users will need to [download a release](https://github.com/danielgtaylor/restish/releases). At its most basic it can be used very similar to how you might use `curl`:

```sh
$ restish -H Authorization:abc123 api.example.com/items/1
HTTP/2.0 200 OK
Content-Encoding: br
Content-Type: application/json
Date: ...

{
  name: "Item number one"
  cost: 12.34
  created: "2020-01-01T12:00:00Z"
  tags: ["grocery"]
}
```

The real magic happens when you register an API base URI with Restish through the interactive `configure` sub-command:

```sh
$ restish api configure example
? Base URI [? for help]: https://api.example.com
Setting up a `default` profile
? Select option for profile `default` Add header
? Header name Authorization
? Header value (optional) abc123
? Select option Save and exit

$ restish get example/items/1
...

$ restish post example/items name: Another, cost: 2.50, tags[]: household
HTTP/2.0 201 Created
Location: /items/2
```

If the API provides an OpenAPI spec via a known link relation header or some common path like /openapi.json then things get even more interesting because you can directly call described API operations rather than specific URIs:

```sh
$ restish example create-item name: Another, cost: 2.50, tags[]: household
HTTP/2.0 201 Created
Location: /items/3
```

The popular [FastAPI Python library](https://fastapi.tiangolo.com/) provides exactly that, so any services written with it will just work out of the box with Restish. And because Restish loads the OpenAPI spec on the fly, whenever you push updates to your FastAPI service then your CLI users will already have the new features available.

Even better, CLI users can query the API for information on structure, including any updates you push to the API. For example:

```sh
$ restish example create-item --help
Create a new item in the inventory

# Request Schema (application/json)

{
  name*: (string) The item name
  cost*: (number min:0) The cost of the item
  tags: [
    (string maxLen:12) Tag name
  ]
}

# Response 201

A new item has been created. The `Location` header links to the item.

Usage:
  restish example create-item ...

Example:
  restish example create-item name: string, cost: 1.0, tags[]: string
  restish example create-item <input.json
...
```

This is win-win for everyone. Users get a high quality CLI tool with advanced features built-in to interact with your service. Your developers don’t have to waste time building and maintaining a custom CLI or getting users to upgrade to access the newest API features.

You should consider adopting Restish for your APIs and adding the “[Works with Restish](https://img.shields.io/badge/Works%20With-Restish-ff5f87)” badge to your documentation.

![Works with Restish](https://dev-to-uploads.s3.amazonaws.com/i/upuey70l61iq1xrqk6ml.png)

There is a ton more breadth and depth to Restish. This quick introduction is just the first of a multi-part series to go into the various features and use-cases with lots of examples, so stay tuned and thanks for reading!