Use Respect, powered by Arazzo workflows, for API contract testing.
Learn how to:
- Automate repetitive API workflows.
- Add API contract tests to CI/CD routines.
- Keep API documentation synchronized with actual API behavior.
- Share described workflows across teams.
- Use the open-source Redocly CLI to execute Arazzo workflows, inspect contract test results, and fix mismatches between the OpenAPI description and the actual API response.
Many teams test APIs by writing test code in the same language as the API implementation. This approach can work well for a single service, but it becomes harder to maintain in systems with multiple products, repositories, and programming languages.
Another common challenge is keeping API documentation aligned with actual API behavior. Developers may update an endpoint but forget to update its OpenAPI description, or the documentation may change without the implementation following it. Over time, these small differences make it harder for QA engineers, developers, and technical writers to trust the API contract.
Respect helps address this problem by executing Arazzo workflows against a running API and validating the responses against the connected OpenAPI description. This strategy makes API contract testing more declarative and easier to share across teams.
To follow the examples in this article, you need:
- Basic familiarity with Arazzo.
- An API described with OpenAPI. The examples use a modified version of the Redocly Cafe API description.
The API description used here intentionally contains a discrepancy for demonstration purposes.
Open redocly-cafe-api.yaml in the right panel to follow along. The two important pieces for this walkthrough are the GET /menu operation and the MenuItemList response schema it references.
GET /menu operation
The GET /menu operation returns a paginated list of menu items. The 200 response points to the MenuItemList schema, which is where the intentional discrepancy lives.
MenuItemList (broken)
The schema declares the response as an array, but the real API returns a paginated object with object, page, and items fields. Later in this walkthrough, Respect will compare this contract with the real API response and surface the mismatch.
There are several ways to create an Arazzo description:
- Read the Arazzo specification and write the file from scratch for full control.
- Use the
npx @redocly/cli generate-arazzo openapi.yamlcommand as a starting point. - Use AI assistance to draft the Arazzo description, then lint the output to catch structural or syntax errors.
Whichever approach you choose, validate the Arazzo file with Redocly CLI:
npx @redocly/cli lint redocly-cafe-api.arazzo.yamlThe tool informs you that the description is valid.
Switch to redocly-cafe-api.arazzo.yaml in the right panel and walk through it section by section.
Connect an OpenAPI source
sourceDescriptions defines the connection to one or more OpenAPI files.
The example references the local redocly-cafe-api.yaml and gives it the name redocly-cafe-api. This name is used later to refer to operations from that description.
Define a workflow
A single Arazzo file can declare multiple workflows. Each workflow has a unique workflowId and a summary. This example defines menu-items-workflow, which retrieves the menu items list.
Add steps
Each workflow is composed of one or more steps. A step is the smallest unit of execution: typically a single API call against an operation from the connected source description.
Reference an operation
The step uses operationId to connect to an operation in the OpenAPI description, using the pattern:
$sourceDescriptions.<source-name>.<operationId>In this example, the step resolves to the listMenuItems operation from the redocly-cafe-api source.
The resolved operation
This is the operation the step resolves to in redocly-cafe-api.yaml.
Because the step is connected to an OpenAPI operation, Respect knows the documented status codes, content types, and response schema for the request and can automatically validate them.
Pass parameters
Steps can pass parameters to the operation. Here, the limit query parameter restricts the response to a single menu item, which keeps the example output small and easy to read.
Define success criteria
Steps can include a successCriteria block to define workflow-specific expectations.
This example asserts that the API responds with a 200 status code. Respect also runs additional automatic checks based on the connected OpenAPI description (see the next section).
@redocly/cli is an open-source tool that can execute Arazzo descriptions with the respect command:
npx @redocly/cli respect redocly-cafe-api.arazzo.yamlThe workflow targets the server defined in the OpenAPI description, so you do not need to provide one via the command line.
The full output is useful for debugging, but the most important lines are the checks near the end of the step:
- The success criteria check passes because the API returns status code
200. - The status code and content type checks pass because the response matches the documented response metadata.
- The schema check fails because the response body shape does not match the documented schema.
Respect execution output
Running workflow redocly-cafe-api.arazzo.yaml / menu-items-workflow
✗ GET /menu - step get-products
Request URL: http://localhost:4096/menu?limit=1
Request Headers:
accept: application/json, application/problem+json
Response status code: 200
Response time: 17 ms
Response Headers:
access-control-allow-credentials: true
connection: keep-alive
content-length: 435
content-type: application/json; charset=utf-8
date: Wed, 29 Apr 2026 12:00:44 GMT
etag: W/"1b3-id35eE7Zv3L2+3iA/a3QCfYtLb0"
keep-alive: timeout=5
vary: Origin
x-powered-by: Express
Response Size: 435 bytes
Response Body:
{
"object": "list",
"page": {
"startCursor": "ixCALWlkOnByZF8wMDAwMDAwMDAwc2VlZHRyYW1zMDAwMDAwMAM",
"endCursor": "ixCALWlkOnByZF8wMDAwMDAwMDAwc2VlZHRyYW1zMDAwMDAwMAM",
"hasNextPage": true,
"hasPrevPage": false,
"limit": 1,
"total": 5
},
"items": [
{
"id": "prd_0000000000seedtrams0000000",
"name": "tiramisu",
"price": 13000,
"category": "dessert",
"createdAt": "2026-04-29T10:00:50.610Z",
"updatedAt": "2026-04-29T10:00:50.610Z",
"object": "menuItem",
"calories": 450
}
]
}
✓ success criteria check - $statusCode == 200
✓ status code check - $statusCode in [200, 400, 500]
✓ content-type check
✗ schema check
Summary for redocly-cafe-api.arazzo.yaml
Workflows: 1 failed, 1 total
Steps: 1 failed, 1 total
Checks: 3 passed, 1 failed, 4 total
Time: 58ms In addition to the success criterion declared in the Arazzo file, Respect performed three additional checks automatically:
status code checkcontent-type checkschema check
Because the workflow step is connected to an OpenAPI description, @redocly/cli verifies that the API returns a documented status code, the expected content type, and a response body that matches the documented schema.
Switch back to redocly-cafe-api.yaml in the right panel. The failed schema check reports the following message:
| ^^ 👈🏽 type must be arraySpot the mismatch
The OpenAPI description declares MenuItemList as an array, but the actual API response is a paginated object with object, page, and items properties. This is the intentional discrepancy in the example.
Respect made this drift visible immediately, without anyone having to read both the OpenAPI description and the API output side-by-side.
Updated MenuItemList schema
In redocly-cafe-api.yaml, change MenuItemList from an array to an object with object, page, and items properties so the schema matches the response the API actually returns.
Compare the highlighted block in the right panel with the corrected version below:
MenuItemList:
type: object
properties:
object:
type: string
const: list
description: Entity name.
page:
$ref: '#/components/schemas/Page'
items:
type: array
items:
$ref: '#/components/schemas/MenuItem'
required:
- object
- page
- itemsRe-run the workflow to confirm that all checks now pass:
npx @redocly/cli respect redocly-cafe-api.arazzo.yamlAfter the schema is updated, the response body matches the documented contract.
This example demonstrates the core value of contract testing with Respect: when the API and its OpenAPI description drift apart, the workflow highlights the mismatch immediately.
After you create and verify an Arazzo workflow locally, you can use it in several ways:
Include the workflow in a CI/CD pipeline to keep API documentation synchronized with actual API behavior:
# Spawn your API instance, then run the workflow npx @redocly/cli respect redocly-cafe-api.arazzo.yaml --verboseAutomate routine API workflows for development and QA tasks.
Describe important application flows with Arazzo and share them with team members. Non-technical users can also use visualization tools like Replay to understand the workflows.
Arazzo provides a standard way to describe API workflows declaratively. Respect uses those workflows to run API contract tests against real API behavior.
With this approach, teams can maintain API test coverage, detect documentation drift earlier, and share executable API workflows across engineering, QA, and documentation teams.
arazzo: 1.0.1
info:
title: Redocly Cafe API - Products
version: 1.0.0
description: This is a test suite for the Redocly Cafe API.
sourceDescriptions:
- name: redocly-cafe-api
type: openapi
url: redocly-cafe-api.yaml
workflows:
- workflowId: menu-items-workflow
summary: Menu Items Workflow
steps:
- stepId: get-products
operationId: $sourceDescriptions.redocly-cafe-api.listMenuItems
description: This step retrieves all products.
parameters:
- in: query
name: limit
value: 1
successCriteria:
- condition: $statusCode == 200