Documenting API Workflows with Arazzo
Having the same source of truth for both machine- and human-readable API workflow documentation is possible.
An API is as useful as the use cases it can fulfill. And use cases usually involve more than one single API operation. The best way to describe them—until now—is to use code or write them down as a recipe. While code makes use cases machine-readable, documentation makes them easy to understand. Now you can have the best of both worlds by using the Arazzo specification.
This article is brought to you with the help of our supporter, Scalar.
Scalar is a suite of powerful & customizable developer tools to help you at all stages of API development. Create beautiful API Documentation in a notion-like editing experience.
Most people are familiar with services that automate the connection with one or several APIs in an orchestrated way. So-called "no-code" services offer an easy way to set up several operations involving multiple APIs. I wrote about how this category of integration products has evolved since the 2010s. "One approach that gained the most popularity over the years is to provide a visual User Interface. Users can see how different parts of an integration connect to each other and can quickly change the connections visually."
Seeing how different parts of an integration interact is crucial to understanding how data flows. Knowing how data flows is important. You get to understand not just what APIs—and operations—contribute to a workflow, but also the business logic applied to each call. That's why most solutions have put effort into visually describing the shape of integrations. While the visual UI is what you see, behind the scenes each solution uses its own definition paradigm.
The case for Arazzo is easy to understand, in my opinion. It aims to solve a growing challenge where there's no clear standardized solution. According to the specification, Arazzo "defines a standard, programming language-agnostic mechanism to express sequences of calls and articulate the dependencies between them to achieve a particular outcome." In other words, it defines a format for describing the actors, actions, and data that constitute a workflow.
Frank Kilcommins, who's spearheading the project, recently presented Arazzo at the apidays Helsinky conference. Following the presentation Erik Wilde published a video interview summarizing the public launch of Arazzo. According to Kilcommins, the specification allows you to document use-case-oriented workflows.
You can think of a workflow as "a series of API calls which when woven together accomplish some business objective." One of the goals of Arazzo is to offer a deterministic source of truth for interactions involving multiple operations spanning across several APIs. Right now Arazzo's focus is on attracting vendors to build tools around the specification.
So, what can you do with Arazzo? There are no tools that support it yet. Probably, the best thing you can do with it is document workflows. Let's take a look at how that would work. Imagine you have customers who pay for your product or service. Suppose you want to create a workflow to notify the first customer who has at least one outstanding invoice. This workflow involves making calls to two different APIs. Let's say you're using Stripe to manage billing and Resend to send email messages.
The first thing to do is to locate the OpenAPI definitions of the two services you'll use:
Stripe:
https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.yaml
(be aware this is a rather large file)Resend:
https://raw.githubusercontent.com/resend/resend-openapi/main/resend.yaml
Now, let's craft our first Arazzo definition. We start by identifying what the workflow is about and where the OpenAPI definitions of the involved APIs are located.
arazzo: 1.0.0
info:
title: Notify customers with outstanding invoices
summary: Send an email notification to the first customer with at least one outstanding invoice
description: |
This workflow uses Stripe and Resend to discover who the first customer with outstanding invoices is and then send them an email reminder.
version: 0.1.0
sourceDescriptions:
- name: stripeDescription
url: https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.yaml
type: openapi
- name: resendDescription
url: https://raw.githubusercontent.com/resend/resend-openapi/main/resend.yaml
type: openapi
Now we define what the workflow does, step by step. We only have one workflow to define but the Arazzo specification lets you document more than one using a single document. Our workflow has two inputs, the API keys of both Stripe and Resend.
workflows:
- workflowId: notifyOutstandingCustomers
inputs:
type: object
properties:
stripeApiKey:
type: string
resendApiKey:
type: string
It then defines two steps. The first one connects to Stripe's getInvoices
operation to list the first invoice with a status of open
. Its output is the invoice data. In the second step, we connect to Resend's API and make a POST
request to the /emails
path. The step uses the customer's email address which comes from the invoice obtained in the first step.
steps:
- stepId: getFirstOutstandingInvoice
operationId: GetInvoices
parameters:
- name: Authorization
in: header
value: "Bearer {$inputs.stripeApiKey}"
- name: status
in: query
value: open
- name: limit
in: query
value: 1
successCriteria:
- condition: $statusCode == 200
outputs:
invoice: $response.body.data[0]
- stepId: sendNotification
operationPath: '{$sourceDescriptions.resendDescription.url}#/paths/emails/post'
parameters:
- name: Authorization
in: header
value: "Bearer {$inputs.resendApiKey}"
requestBody:
contentType: application/json
payload:
from: email@example.com
to: $steps.getFirstOutstandingInvoice.invoice.customer_email
subject: Payment reminder
text: Payment reminder example message.
successCriteria:
- condition: $statusCode == 200
I found some things aren't yet fully defined in the specification. For example, originally I wanted to create a workflow to loop through all customers and send an email to each one. However, that's not yet possible to document at this stage, so I changed my approach to grab the first customer. Another area where I had difficulty was in the extraction of data from step outputs. In this case, I wanted to extract the email address from the invoice coming from the previous step. I ended up using a dot notation to specify what I wanted to extract. However, I'm not sure if that's the best approach here.
Overall I think Arazzo is a major step forward in providing a standardized approach to documenting API workflows. I hope vendors jump on board quickly and start building the much-needed tooling. I'd love to see visualization tools that could act as a workflow UI using Arazzo behind the scenes.