Learn Arazzo by example

Boilerplate structure

Every Arazzo specification requires a few key components to get started. These elements form the basic structure that all Arazzo files must follow.

Spec

The arazzo version declaration at the top of the file (e.g. arazzo: 1.0.1)

Info

Similar to OpenAPI, Arazzo uses info to describe the API. It also declares which version of Arazzo is used (even though only version 1.0.x is available at the moment).

Source Descriptions

The sourceDescriptions section is used to describe the sources of the API. It is a list of objects, each containing a name and a url (path to the OpenAPI file). It only supports openapi type at the moment (but is expected to support more types such as asyncapi in the future). We can supply an optional x-serverUrl property to specify a specific server URL of the API.

Workflows

The workflows section is used to define the workflows of the API. It is a list of objects, each containing a name and a description. We'll dive deeper into workflows in the next major section.

This specific workflow is based on the "Lost Invention Mission".

Steps

The steps section is used to define the steps of a specific workflow. Each step contains a name, a description, and a request object. The request object contains the API call to be made. We'll dive deeper into steps in the next section. This specific workflow is based on the "Lost Invention Mission".

Workflow structure

An Arazzo can contain multiple workflows. This example Arazzo contains only a single workflow (with multiple steps).

Workflow: Lost Invention

This workflow is based on the "Lost Invention Mission".

Workflow: Lost Invention - Inputs

The inputs section is used to define the inputs of a specific workflow. It is a json schema object describing each input. This specific API requires a token input. We'll pass the token into the Arazzo workflow runner using an input parameter (or environment variable).

Workflow: Lost Invention - Parameters

The parameters section is used to define the parameters of a specific workflow. It is a list of objects, each containing a name, an in property, and a value property. The value in this case uses the prefixes the "Bearer " to the input parameter token and passes it to the API as part of the Authorization header.

Steps structure

A workflow can contain multiple steps. Each step contains a name, a description, and a reference to an operation in the API (such as an operationId or path).

Steps

The steps section is used to define the steps of a specific workflow. The stepId is required and used to uniquely identify the step. It's a good practice to give each step a meaningful description.

Operation ID

The operationId is the operation ID of the API call to be made. Arazzo has some flexibility in how it references the operation either by operationId or an operationPath. In this case, we're using the operationId to reference the setAnchor operation in the api-reference API. Note that the operationId is prefixed with the sourceDescription.name (in this case, api-reference) which allows Arazzo to disambiguate between operations with the same ID or path in different APIs.

Outputs

The outputs section is used to define the outputs of a specific step. Output is only defined for passing data to another step. It does not describe the full API response.

In this case, we're using the anchor_id output to pass the ID of the anchor to the next step. The value is $response.body#/id which means that the value is the id field in the response body.

The format of outputs is a map object where each key is the output name and the value follows a convention described in the Arazzo specification as a runtime expression.

Runtime expression following an ABNF syntax
Runtime Expression ABNF
expression = ( "$url" / "$method" / "$statusCode" / "$request." source / "$response." source / "$inputs." name / "$outputs." name / "$steps." name / "$workflows." name / "$sourceDescriptions." name / "$components." name / "$components.parameters." parameter-name)
parameter-name = name ; Reuses 'name' rule for parameter names
source = ( header-reference / query-reference / path-reference / body-reference )
header-reference = "header." token
query-reference = "query." name
path-reference = "path." name
body-reference = "body" ["#" json-pointer ]
json-pointer    = *( "/" reference-token )
reference-token = *( unescaped / escaped )
unescaped       = %x00-2E / %x30-7D / %x7F-10FFFF
  ; %x2F ('/') and %x7E ('~') are excluded from 'unescaped'
escaped         = "~" ( "0" / "1" )
; representing '~' and '/', respectively
name = *( CHAR )
token = 1*tchar
tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA

Request Body

The requestBody section is used to define the request body of a specific step. You can supply a payload object to pass data to the API. In this case, we're using the requestBody to pass the timeline_id and proposed_changes to the API. You can "hardcode" the values or use the outputs from previous steps.

Using outputs from previous steps

In this exmaple, we're using the output from the setAnchorToCurrentTime step to pass the anchor_id to the returnToPresent step.

Success criteria

Success criteria can be optionally defined for each step.

Success Criteria

The successCriteria section is used to define the success criteria of a specific step. It is a list of objects, each containing a condition and a context. The condition is a boolean expression that describes the success criteria. The context is the context of the success criteria.

What can we do with Arazzo?

Respect is a powerful tool that can be used to test APIs described with Arazzo.

It checks that the API is working as expected by validating the API responses against the success criteria. Good news is that even if you don't take the time to define success criteria (or your success criteria are not exhaustive), Arazzo still validates the API responses (headers, status code, and body schemas) against the linked OpenAPI source description.

Try it out for yourself by running the workflow in Respect after you download these files into a folder (both the arazzo.yaml and openapi.yaml files), change into that folder and run the following command (no real token is needed for this example because the server is a mock server):

npx @redocly/cli@latest respect warp.arazzo.yaml --input token=your-token-here

Read more about Respect in Testing Arazzo Workflows.

# How to run workflows: npx @redocly/cli respect ./apis/warp.arazzo.yaml --input token=abc
arazzo: 1.0.1
info:
  title: Warp API
  version: 1.0.0
sourceDescriptions:
  - name: api-reference
    type: openapi
    url: warp.openapi.yaml
    x-serverUrl: "https://warp-multi-sidebars.redocly.app/_mock/apis/"
workflows:
  - workflowId: missionLostInvention
    summary: Lost invention
    description: |-
      Travel back to the year 1889 and retrieve the blueprint for Nikola Tesla’s lost invention before it’s destroyed in a mysterious fire.
    inputs:
      type: object
      properties:
        token:
          type: string
          format: password
          description: JWT Bearer token
    parameters:
      - name: Authorization
        in: header
        value: "Bearer {$inputs.token}"
    steps:
      - stepId: setAnchorToCurrentTime
        operationId: api-reference.setAnchor
        description: Set an anchor to the current time.
        outputs:
          anchor_id: $response.body#/id
      - stepId: createTimelineTo1889
        operationId: api-reference.createTimeline
        description: Create a timeline to 1889.
        outputs:
          timeline_id: $response.body#/id
      - stepId: travelTo1889
        operationId: api-reference.timeTravel
        description: Travel to 1889.
        requestBody:
          payload:
            destination: $steps.createTimelineTo1889.outputs.timeline_id
      - stepId: findAndRegisterBlueprint
        operationId: api-reference.registerItem
        description: Find the blueprints. Then, register them using the `registerItem` API call.
        requestBody:
          payload:
            description: Tesla's blueprint
        outputs:
          item_id: $response.body#/id
      - stepId: avoidParadox
        operationId: api-reference.checkParadox
        description: Check for paradoxes.
        requestBody:
          payload:
            timeline_id: $steps.createTimelineTo1889.outputs.timeline_id
            proposed_changes:
              - event: Sneak in to retrieve Tesla's blueprint
                time: "1889-03-10T23:50:00Z"
              - item_id: $steps.findAndRegisterBlueprint.outputs.item_id
        successCriteria:
          - condition: $statusCode == 200
          - condition: $.is_stable == true
            context: $response.body
            type: jsonpath
      - stepId: returnToPresent
        operationId: api-reference.timeTravel
        description: Return to the present.
        requestBody:
          payload:
            destination: $steps.setAnchorToCurrentTime.outputs.anchor_id
            items:
              - $steps.findAndRegisterBlueprint.outputs.item_id