Skip to content

A developer ships a small backend change. The API still returns 200 OK. Integration tests pass. Monitoring dashboards stay green.

Two days later, support tickets start pouring in. The mobile app is crashing on a screen that nobody changed. Turns out the API dropped a required field from the response--totalPrice, gone. The response was still valid JSON. Still 200.

Nobody's tests checked whether the API kept its promise.

That's the problem API contract testing solves. And with Arazzo and Respect, you can set it up in two commands.


Why your current tests miss this

You probably already test your API. Unit tests, integration tests, maybe end-to-end flows. Here's why contract drift still gets through:

  • Unit tests verify isolated functions. They don't send HTTP requests to your live API.
  • Integration tests check whether components work together. They don't validate the response body against your OpenAPI schema.
  • E2E tests confirm user flows work. They don't notice when a new field leaks internal data or a required field disappears.
  • Uptime monitoring confirms the API responds. It doesn't care what's in the response.

None of these are designed to enforce your API contract. All of them can pass while your API silently breaks it.

Testing typeWhat it answersCatches contract drift?
Unit testsDoes this function work in isolation?No
Integration testsDo components work together?Sometimes, indirectly
E2E testsDoes the user flow complete?Sometimes, indirectly
Uptime monitoringIs the API responding?No
Contract testingDoes the response match the OpenAPI spec?Yes, by definition

Contract testing is the missing layer. It treats your OpenAPI description as the source of truth and validates every live response against it--status codes, content types, schemas, headers. Not "does it work?" but "does it match the contract?"


What Respect does about it

Respect is an open-source CLI that removes an entire class of tests you currently maintain. It's part of Redocly CLI--the same toolchain you may already use for linting and bundling OpenAPI.

You already wrote these tests. You just didn't realize your spec could replace them.

No assertions to write. No test scripts to keep in sync. No spec duplicated in a test framework.

Your OpenAPI description already defines what the API should return. Respect reads it, sends real HTTP requests to your live API, and validates every response against the spec. The spec is the test.

Two commands. Zero test code.
# Generate test workflows from your OpenAPI spec
npx @redocly/cli generate-arazzo openapi.yaml

# Run contract tests against your live API
npx @redocly/cli respect auto-generated.arazzo.yaml --verbose

That's it. No test framework to configure. No collection files to export. No assertion libraries. Just your spec, your running API, and the truth about whether they agree.

Works with the API you have

Respect doesn't require a perfect OpenAPI description. Start with what you have--even a partially documented spec catches real issues. You can iteratively improve your spec as Respect reveals gaps.


What Arazzo adds: multi-step workflows without glue code

OpenAPI describes individual endpoints. But real API usage is never a single call.

You authenticate, create a resource, read it back, update it, verify the update. Before Arazzo, testing these flows meant writing custom glue code: scripts that chain requests, extract tokens, pass IDs between steps, and hope nothing breaks when the API changes.

The Arazzo Specification--an open standard from the OpenAPI Initiative--replaces all of that with pure data flow. No custom code. Outputs from one step feed directly into the next, declared in YAML:

cafe-order-flow.arazzo.yaml
arazzo: "1.0.1"
info:
  title: Redocly Cafe order flow
  version: 1.0.0
sourceDescriptions:
  - name: cafeApi
    type: openapi
    url: openapi.yaml
workflows:
  - workflowId: createMenuItemAndOrder
    steps:
      - stepId: createMenuItem
        operationId: cafeApi.createMenuItem
        requestBody:
          payload:
            name: "Espresso"
            price: 350
            category: "beverage"
        successCriteria:
          - condition: $statusCode == 201
        outputs:
          menuItemId: $response.body#/id

      - stepId: placeOrder
        operationId: cafeApi.createOrder
        requestBody:
          payload:
            customerName: "Mary Ann"
            orderItems:
              - menuItemId: $steps.createMenuItem.outputs.menuItemId
                quantity: 2
        successCriteria:
          - condition: $statusCode == 201
        outputs:
          orderId: $response.body#/id

      - stepId: verifyOrder
        operationId: cafeApi.getOrderById
        parameters:
          - name: orderId
            in: path
            value: $steps.placeOrder.outputs.orderId
        successCriteria:
          - condition: $statusCode == 200

See $steps.createMenuItem.outputs.menuItemId? The menu item ID from step one flows into step two automatically, then the order ID flows into step three. This replaces the glue scripts, the variable chaining, the brittle test harnesses. One YAML file. In your repo. Versioned with your API.

Arazzo is an open standard

Arazzo is maintained by the OpenAPI Initiative--the same organization behind OpenAPI itself. Your workflow definitions are portable and vendor-neutral. Learn more about Arazzo.


What gets caught

When Respect runs your workflows, it validates every response against the linked OpenAPI description. Here's what that looks like in practice.

Status codes

Your spec says 201 Created, but the API returns 200 OK after a refactor. Functionally fine. Contractually broken. Every consumer expecting 201 now has a bug. Respect catches it.

Content types

The spec declares application/json, but a new middleware starts returning text/html on error paths. Client JSON parsers choke silently. Respect catches it.

Response schemas

A developer removes a required field. Or worse: an internal field like internal_user_id leaks into the public response. Schema validation catches both--missing fields and dangerous extras. Respect catches it.

Headers

CORS headers disappear after a proxy update. Cache-Control goes missing. A security header gets silently dropped. Respect catches it.

Here's a concrete example. Say your OpenAPI spec defines this response schema for GET /orders/{orderId}:

Expected: Order schema from openapi.yaml
properties:
  id:
    type: string
    pattern: ^ord_[0-9abcdefghjkmnpqrstvwxyz]{26}$
  customerName:
    type: string
  status:
    type: string
    enum: [placed, preparing, completed, canceled]
  totalPrice:
    type: integer
    minimum: 0
  orderItems:
    type: array
    minItems: 1
    items:
      type: object
      properties:
        menuItemId:
          type: string
        quantity:
          type: integer
          minimum: 1
      required: [menuItemId, quantity]
      additionalProperties: false
required: [id, customerName, status, totalPrice, orderItems]
additionalProperties: false

But after a deploy, GET /orders/{orderId} returns:

Actual response -- spot the problems
{
  "id": "ord_01h1s5z6vf2mm1mz3hevnn9va7",
  "customerName": "Mary Ann",
  "status": "fulfilled",
  "totalPrice": 200,
  "orderItems": [
    { "menuItemId": "itm_01h1s5z6vf2mm1mz3hevnn9va7", "quantity": 2 }
  ],
  "internalCostCents": 45
}

Two contract violations:

  1. status is "fulfilled" -- not in the enum. Every client with a switch on placed | preparing | completed | canceled just hit the default case.
  2. internalCostCents leaked into the public API. That's internal pricing data exposed to consumers.

Respect flags both automatically. No test code needed--the OpenAPI spec already defines what's allowed.

This is exactly the kind of bug that passes every other test.


Running it in practice

Two commands, from nothing to validated contracts:

Generate and run
npx @redocly/cli generate-arazzo openapi.yaml
npx @redocly/cli respect auto-generated.arazzo.yaml --verbose

The open-standards advantage

Respect builds on two open standards. This avoids tool lock-in entirely.

  • OpenAPI defines your API contract. The same file you use for docs, code generation, and governance now also powers your tests.
  • Arazzo defines your test workflows. An open spec from the OpenAPI Initiative, not a proprietary format tied to a single tool.

Your test definitions are plain YAML files that live in your repo, version with your code, and work with any Arazzo-compatible tool. When your OpenAPI description changes, contract tests validate against the updated spec automatically. No separate test layer to keep in sync.

One spec. One workflow layer. No duplication.


From CLI to continuous monitoring

Respect CLI is free and open source--run it locally, in CI, anywhere. When you need always-on validation, Respect Monitoring extends the same foundation into a hosted service.

CapabilityRespect CLI (free)Respect Monitoring (hosted)
Contract testingYesYes
CI/CD integrationYesYes
Scheduled checksManual / cronBuilt-in (minute / hour / day)
Alerts (Slack, email)NoYes
Dashboards and trend trackingNoYes
Multi-environmentManual configBuilt-in (staging, production)
PricingFree, forever1,000 requests/month free, then usage-based

Start with the CLI during development. Graduate to Monitoring when you need continuous assurance in production.


FAQ

Do I need to write test code?

No. redocly generate-arazzo openapi.yaml creates test workflows from your spec automatically. Customize them for specific scenarios if you want, but the defaults cover your endpoints out of the box.

What if my OpenAPI spec is incomplete?

Start with what you have. An incomplete spec still catches real drift on the endpoints it covers. You can expand coverage incrementally as Respect reveals gaps.

Does this work in CI/CD?

Yes. Respect returns standard exit codes--non-zero means contract violations. GitHub Actions, GitLab CI, Jenkins, CircleCI, plain shell scripts--anything that can run a CLI. Broken contracts don't merge.


Run it once and see what breaks

Your OpenAPI description already defines the contract. You just haven't been enforcing it.

You will find something.

npx @redocly/cli respect your-api.arazzo.yaml --verbose

Your API has been making promises. Time to find out if it's keeping them.

Latest from our blog

Arazzo 1.1 Release

Arazzo 1.1 adds AsyncAPI support, workflow composition, selectors, identity-based references, and clearer runtime behavior.

What you really need to build an API san...

Integration is the most dangerous phase of the API lifecycle. Learn the infrastructure requirements for building a true API sandbox that validates stateful business logic, not just HTTP contracts.

Why API catalogs are critical for agenti...

The primary bottleneck for AI agents in software development is no longer model reasoning capability—it's the ability to validly discover and safely invoke the right tools.