# release-oss-arazzo-parser
Source: https://speakeasy.com/blog/release-oss-arazzo-parser


import { CodeWithTabs } from "@/mdx/components";

We've been hard at work on building an automated end-to-end testing framework for REST APIs. That's meant building a lot of internal tooling to work with the [Arazzo specification](https://github.com/OAI/Arazzo-Specification).

Today, we're excited to announce the release of our Arazzo parser, a powerful tool for working with the Arazzo specification. We hope that this will be help the community build more tooling that leverages the Arazzo specification.

[Check it out on GitHub →](https://github.com/speakeasy-api/openapi/tree/main/arazzo)

## What is Arazzo?

The Arazzo specification is a language-agnostic way to describe chains of API calls. While OpenAPI documents define the individual API endpoints and methods available, Arazzo allows you to define sequences of calls that relate to those OpenAPI documents. This means you can create complex workflows like "authenticate → create user → get user → delete user" and ensure the output of one call feeds correctly into the inputs of another.

What makes Arazzo particularly powerful is its ability to reference multiple OpenAPI documents from different providers, enabling you to build and test intricate integrations across various services.

## Why'd we build a parser?

Developers testing API workflows often resort to writing custom testing applications or using end-to-end testing frameworks that don't integrate well with their API tooling. This leads to duplicate schema definitions and a disconnect between testing and the rest of the API development lifecycle.

We see Arazzo bridging this gap by providing a native way to define workflows that leverage your existing OpenAPI specifications. This means you're not just testing individual API endpoints – you're validating entire workflows while ensuring your SDKs and integrations work as expected.

## Basic Example

Here's a simple example of an Arazzo workflow for a hypothetical bar API:

```yaml
workflows:
  createDrink:
    workflowId: create-drink
    summary: Creates a new drink in the system
    inputs:
      drinkName: string
      drinkType: string
      price: number
    steps:
      - operationId: authenticate
        inputs:
          username: ${inputs.username}
          password: ${inputs.password}
      - operationId: createDrink
        inputs:
          name: ${inputs.drinkName}
          type: ${inputs.drinkType}
          price: ${inputs.price}
```

## What's in the parser

The parser includes comprehensive features for:

- **Reading** Arazzo documents
- **Validating** documents
- **Walking** through a document
- **Creating** new documents
- **Mutating** existing documents

Here's how you can get started:

<CodeWithTabs
  tabs={[
    {
      label: "read.go",
      language: "go",
      code: `package main

import (
    "bytes"
    "context"
    "fmt"
    "os"

    "github.com/speakeasy-api/openapi/arazzo"

)

func main() {
ctx := context.Background()

    r, err := os.Open("testdata/speakeasybar.arazzo.yaml")
    if err != nil {
        panic(err)
    }
    defer r.Close()

    // Unmarshal the Arazzo document which will also validate it
    // against the Arazzo Specification
    a, validationErrs, err := arazzo.Unmarshal(ctx, r)
    if err != nil {
        panic(err)
    }

    // Validation errors are returned separately from any errors that block
    // the document from being unmarshalled
    // allowing an invalid document to be mutated and fixed before being
    // marshalled again
    for _, err := range validationErrs {
        fmt.Println(err.Error())
    }

    // Mutate the document by just modifying the returned Arazzo object
    a.Info.Title = "Speakeasy Bar Workflows"

    buf := bytes.NewBuffer([]byte{})

    // Marshal the document to a writer
    if err := arazzo.Marshal(ctx, a, buf); err != nil {
        panic(err)
    }

    fmt.Println(buf.String())

}`,
    },
    {
      label: "validate.go",
      language: "go",
      code: `package main

import (
    "context"
    "fmt"
    "os"

    "github.com/speakeasy-api/openapi/arazzo"

)

func main() {
ctx := context.Background()

    f, err := os.Open("arazzo.yaml")
    if err != nil {
        panic(err)
    }

    _, validationErrs, err := arazzo.Unmarshal(ctx, f)
    if err != nil {
        panic(err)
    }

    for _, err := range validationErrs {
        fmt.Printf("%s\\n", err.Error())
    }

}`,
    },
    {
      label: "walk.go",
      language: "go",
      code: `package main

import (
    "context"
    "fmt"
    "os"

    "github.com/speakeasy-api/openapi/arazzo"

)

func main() {
ctx := context.Background()

    f, err := os.Open("arazzo.yaml")
    if err != nil {
        panic(err)
    }

    a, _, err := arazzo.Unmarshal(ctx, f)
    if err != nil {
        panic(err)
    }

    err = arazzo.Walk(ctx, a, func
    (ctx context.Context, node, parent arazzo.MatchFunc, a *arazzo.Arazzo)
    error {
        return node(arazzo.Matcher{
            Workflow: func(workflow *arazzo.Workflow) error {
                fmt.Printf("Workflow: %s\\n", workflow.WorkflowID)
                return nil
            },
        })
    })
    if err != nil {
        panic(err)
    }

}`,
    },
    {
      label: "create.go",
      language: "go",
      code: `package main

import (
    "context"
    "fmt"

    "github.com/speakeasy-api/openapi/arazzo"
    "github.com/speakeasy-api/openapi/pointer"

)

func main() {
ctx := context.Background()

    arazzo := &arazzo.Arazzo{
        Arazzo: arazzo.Version,
        Info: arazzo.Info{
            Title:   "My Workflow",
            Summary: pointer.From("A summary"),
            Version: "1.0.0",
        },
        // ...
    }

    buf := bytes.NewBuffer([]byte{})

    err := arazzo.Marshal(ctx, buf)
    if err != nil {
        panic(err)
    }

    fmt.Printf("%s", buf.String())

}`,
    },
    {
      label: "mutate.go",
      language: "go",
      code: `package main

import (
    "context"
    "fmt"

    "github.com/speakeasy-api/openapi/arazzo"

)

func main() {
ctx := context.Background()

    f, err := os.Open("arazzo.yaml")
    if err != nil {
        panic(err)
    }

    arazzo, _, err := arazzo.Unmarshal(ctx, f)
    if err != nil {
        panic(err)
    }

    arazzo.Info.Title = "My updated workflow title"

    buf := bytes.NewBuffer([]byte{})

    if err := arazzo.Marshal(ctx, buf); err != nil {
        panic(err)
    }

    fmt.Printf("%s", buf.String())

}`,
}
]}
/>

## What's Next?

While the Arazzo specification is broad and deep, we're starting with focused support for testing workflows against single APIs. Our roadmap includes:

- Visual workflow builders to make creating Arazzo documents more intuitive
- Enhanced testing capabilities across multiple APIs
- Integration with our existing SDK generation tools
- Expanded tooling in our CLI for Arazzo validation and workflow management

## Try It Out

The Arazzo parser is available now on GitHub. Get started by checking out our [documentation](https://www.speakeasy.com/openapi/arazzo) and let us know what you build with it!

We're excited to see how the community uses Arazzo to improve their API testing and integration workflows. This is just the beginning of our journey to make API development more streamlined and reliable.