{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-learn/arazzo/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["code-walkthrough","admonition","step"]},"redocly_category":"Learn","type":"markdown"},"seo":{"title":"Test API contracts using Redocly Respect","description":"OpenAPI-generated documentation tool with 24k+ stars on Github - make APIs your company's superpower.","siteUrl":"https://redocly.com","image":"/assets/redocly-card.f670aae34a39545a5ea633a540cb3a4a333a1f23bb2ed3c4a1b17a5fbcf0ac85.db81178d.png","lang":"en-US","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"CodeWalkthrough","attributes":{"__idx":1,"filters":{},"filesets":[{"files":[{"path":"learn/arazzo/_filesets/practical-example-series/contract-testing/redocly-cafe-api.arazzo.yaml","content":["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.",{"start":5,"condition":{"steps":["arazzo-source-descriptions"]},"children":["sourceDescriptions:","  - name: redocly-cafe-api","    type: openapi","    url: redocly-cafe-api.yaml"]},"",{"start":12,"condition":{"steps":["arazzo-workflows"]},"children":["workflows:","  - workflowId: menu-items-workflow","    summary: Menu Items Workflow",{"start":16,"condition":{"steps":["arazzo-steps"]},"children":["    steps:","      - stepId: get-products",{"start":19,"condition":{"steps":["arazzo-operation-id","arazzo-step-operation"]},"children":["        operationId: $sourceDescriptions.redocly-cafe-api.listMenuItems"]},"        description: This step retrieves all products.",{"start":23,"condition":{"steps":["arazzo-parameters"]},"children":["        parameters:","          - in: query","            name: limit","            value: 1"]},{"start":29,"condition":{"steps":["arazzo-success-criteria"]},"children":["        successCriteria:","          - condition: $statusCode == 200"]}]}]},""],"metadata":{"steps":["arazzo-source-descriptions","arazzo-workflows","arazzo-steps","arazzo-operation-id","arazzo-step-operation","arazzo-parameters","arazzo-success-criteria"]},"basename":"redocly-cafe-api.arazzo.yaml","language":"yaml"},{"path":"learn/arazzo/_filesets/practical-example-series/contract-testing/redocly-cafe-api.yaml","content":["openapi: 3.1.0","info:","  title: Redocly Cafe","  version: 1.0.0","  contact:","    email: team@redocly.com","    url: https://redocly.com/contact-us/","  license:","    name: MIT","    url: https://opensource.org/licenses/MIT","  termsOfService: https://redocly.com/subscription-agreement","servers:","  - url: https://cafe.cloud.redocly.com","    description: Live server.","tags:","  - name: Products","    description: Operations related to products.","paths:",{"start":18,"condition":{"steps":["openapi-list-menu-items","arazzo-step-operation"]},"children":["  /menu:","    get:","      tags:","        - Products","      summary: List all menu items","      operationId: listMenuItems","      security: []","      parameters:","        - $ref: '#/components/parameters/Limit'","      responses:","        '200':","          description: Successful operation.","          content:","            application/json:","              schema:","                $ref: '#/components/schemas/MenuItemList'","        '400':","          description: Bad request - invalid input parameters.","        '500':","          description: Internal server error."]},"components:","  parameters:","    Limit:","      name: limit","      in: query","      required: false","      schema:","        type: integer","        minimum: 1","        maximum: 100","        default: 10","      example: 10","  schemas:","    Page:","      type: object","      properties:","        endCursor:","          type:","            - string","            - 'null'","        startCursor:","          type:","            - string","            - 'null'","        hasNextPage:","          type: boolean","        hasPrevPage:","          type: boolean","        limit:","          type: integer","          minimum: 1","          maximum: 100","          default: 10","        total:","          type: integer","          minimum: 0","      required:","        - endCursor","        - startCursor","        - hasNextPage","        - hasPrevPage","        - limit","        - total","    MenuBaseItem:","      type: object","      properties:","        createdAt:","          type: string","          format: date-time","          readOnly: true","        updatedAt:","          type: string","          format: date-time","          readOnly: true","        id:","          type: string","          readOnly: true","          pattern: ^prd_[0-9abcdefghjkmnpqrstvwxyz]{26}$","        object:","          type: string","          const: menuItem","          readOnly: true","        name:","          type: string","          minLength: 1","          maxLength: 50","        price:","          type: integer","          minimum: 0","        photo:","          writeOnly: true","          type:","            - string","            - 'null'","          format: binary","        photoUrl:","          readOnly: true","          type: string","          format: uri","        photoTextDescription:","          type:","            - string","            - 'null'","      required:","        - id","        - name","        - price","        - createdAt","        - updatedAt","        - object","    Beverage:","      allOf:","        - type: object","          properties:","            category:","              type: string","              const: beverage","            volume:","              type: number","              exclusiveMinimum: 0","            containsCaffeine:","              type: boolean","        - $ref: '#/components/schemas/MenuBaseItem'","    Dessert:","      allOf:","        - type: object","          properties:","            category:","              type: string","              const: dessert","            calories:","              type: number","              exclusiveMinimum: 0","        - $ref: '#/components/schemas/MenuBaseItem'","    MenuItem:","      discriminator:","        propertyName: category","        mapping:","          beverage: '#/components/schemas/Beverage'","          dessert: '#/components/schemas/Dessert'","      oneOf:","        - $ref: '#/components/schemas/Beverage'","        - $ref: '#/components/schemas/Dessert'","      required:","        - category",{"start":165,"condition":{"steps":["openapi-broken-schema","schema-failure","schema-fix"]},"children":["    MenuItemList:","      type: array","      items:","        type: object","        properties:","          object:","            type: string","            const: list","          page:","            $ref: '#/components/schemas/Page'","          items:","            type: array","            items:","              $ref: '#/components/schemas/MenuItem'","        required:","          - object","          - page","          - items"]},"    Error:","      type: object","      properties:","        type:","          type: string","          format: uri-reference","          default: about:blank","        title:","          type: string","        status:","          type: integer","          format: int32","          minimum: 100","          exclusiveMaximum: 600","        instance:","          type: string","          format: uri-reference","        details:","          type: object","          additionalProperties: true","      required:","        - type","        - title","        - status",""],"metadata":{"steps":["openapi-list-menu-items","arazzo-step-operation","openapi-broken-schema","schema-failure","schema-fix"]},"basename":"redocly-cafe-api.yaml","language":"yaml"}],"downloadAssociatedFiles":[]}],"steps":[{"id":"openapi-list-menu-items","heading":"GET /menu operation"},{"id":"openapi-broken-schema","heading":"MenuItemList (broken)"},{"id":"arazzo-source-descriptions","heading":"Connect an OpenAPI source"},{"id":"arazzo-workflows","heading":"Define a workflow"},{"id":"arazzo-steps","heading":"Add steps"},{"id":"arazzo-operation-id","heading":"Reference an operation"},{"id":"arazzo-step-operation","heading":"The resolved operation"},{"id":"arazzo-parameters","heading":"Pass parameters"},{"id":"arazzo-success-criteria","heading":"Define success criteria"},{"id":"schema-failure","heading":"Spot the mismatch"},{"id":"schema-fix","heading":"Updated MenuItemList schema"}],"inputs":{},"toggles":{}},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"test-api-contracts-using-redocly-respect","__idx":0},"children":["Test API contracts using Redocly Respect"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use Respect, powered by Arazzo workflows, for API contract testing."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Learn how to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Automate repetitive API workflows."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Add API contract tests to CI/CD routines."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Keep API documentation synchronized with actual API behavior."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Share described workflows across teams."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use the open-source ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.npmjs.com/package/@redocly/cli"},"children":["Redocly CLI"]}," to execute Arazzo workflows, inspect contract test results, and fix mismatches between the OpenAPI description and the actual API response."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"the-problem","__idx":1},"children":["The problem"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"prerequisites","__idx":2},"children":["Prerequisites"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To follow the examples in this article, you need:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Basic familiarity with ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/learn/arazzo/what-is-arazzo"},"children":["Arazzo"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["An API described with OpenAPI."," ","The examples use a modified version of the Redocly Cafe API description."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Tutorial content"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The API description used here intentionally contains a discrepancy for demonstration purposes."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"explore-the-openapi-description","__idx":3},"children":["Explore the OpenAPI description"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Open ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly-cafe-api.yaml"]}," in the right panel to follow along."," ","The two important pieces for this walkthrough are the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /menu"]}," operation and the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MenuItemList"]}," response schema it references."]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"openapi-list-menu-items","heading":"GET /menu operation"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /menu"]}," operation returns a paginated list of menu items."," ","The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["200"]}," response points to the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MenuItemList"]}," schema, which is where the intentional discrepancy lives."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"openapi-broken-schema","heading":"MenuItemList (broken)"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The schema declares the response as an ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["array"]},", but the real API returns a ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["paginated object"]}," with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["object"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["page"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["items"]}," fields."," ","Later in this walkthrough, Respect will compare this contract with the real API response and surface the mismatch."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"create-an-arazzo-description","__idx":4},"children":["Create an Arazzo description"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["There are several ways to create an Arazzo description:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Read the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://spec.openapis.org/arazzo/latest.html"},"children":["Arazzo specification"]}," and write the file from scratch for full control."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["npx @redocly/cli generate-arazzo openapi.yaml"]}," command as a starting point."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use AI assistance to draft the Arazzo description, then lint the output to catch structural or syntax errors."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Whichever approach you choose, validate the Arazzo file with Redocly CLI:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"npx @redocly/cli lint redocly-cafe-api.arazzo.yaml\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The tool informs you that the description is valid."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Switch to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly-cafe-api.arazzo.yaml"]}," in the right panel and walk through it section by section."]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"arazzo-source-descriptions","heading":"Connect an OpenAPI source"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sourceDescriptions"]}," defines the connection to one or more OpenAPI files."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The example references the local ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly-cafe-api.yaml"]}," and gives it the name ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly-cafe-api"]},"."," ","This name is used later to refer to operations from that description."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"arazzo-workflows","heading":"Define a workflow"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A single Arazzo file can declare multiple ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["workflows"]},"."," ","Each workflow has a unique ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["workflowId"]}," and a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["summary"]},"."," ","This example defines ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["menu-items-workflow"]},", which retrieves the menu items list."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"arazzo-steps","heading":"Add steps"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Each workflow is composed of one or more ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["steps"]},"."," ","A step is the smallest unit of execution: typically a single API call against an operation from the connected source description."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"arazzo-operation-id","heading":"Reference an operation"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The step uses ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["operationId"]}," to connect to an operation in the OpenAPI description, using the pattern:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","header":{"controls":{"copy":{}}},"source":"$sourceDescriptions.<source-name>.<operationId>\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In this example, the step resolves to the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["listMenuItems"]}," operation from the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly-cafe-api"]}," source."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"arazzo-step-operation","heading":"The resolved operation"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This is the operation the step resolves to in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly-cafe-api.yaml"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"arazzo-parameters","heading":"Pass parameters"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Steps can pass parameters to the operation."," ","Here, the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["limit"]}," query parameter restricts the response to a single menu item, which keeps the example output small and easy to read."]}]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"arazzo-success-criteria","heading":"Define success criteria"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Steps can include a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["successCriteria"]}," block to define workflow-specific expectations."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This example asserts that the API responds with a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["200"]}," status code."," ","Respect also runs additional automatic checks based on the connected OpenAPI description (see the next section)."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"execute-the-workflow-with-redocly-cli","__idx":5},"children":["Execute the workflow with Redocly CLI"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.npmjs.com/package/@redocly/cli"},"children":["@redocly/cli"]}," is an open-source tool that can execute Arazzo descriptions with the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["respect"]}," command:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"npx @redocly/cli respect redocly-cafe-api.arazzo.yaml\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The workflow targets the server defined in the OpenAPI description, so you do not need to provide one via the command line."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The full output is useful for debugging, but the most important lines are the checks near the end of the step:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The success criteria check passes because the API returns status code ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["200"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The status code and content type checks pass because the response matches the documented response metadata."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The schema check ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["fails"]}," because the response body shape does not match the documented schema."]}]},{"$$mdtype":"Tag","name":"details","attributes":{},"children":[{"$$mdtype":"Tag","name":"summary","attributes":{},"children":["Respect execution output"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"    Running workflow redocly-cafe-api.arazzo.yaml / menu-items-workflow \n \n  ✗ GET /menu - step get-products \n\n    Request URL: http://localhost:4096/menu?limit=1\n    Request Headers:\n      accept: application/json, application/problem+json \n \n\n    Response status code: 200\n    Response time: 17 ms\n    Response Headers:\n      access-control-allow-credentials: true\n      connection: keep-alive\n      content-length: 435\n      content-type: application/json; charset=utf-8\n      date: Wed, 29 Apr 2026 12:00:44 GMT\n      etag: W/\"1b3-id35eE7Zv3L2+3iA/a3QCfYtLb0\"\n      keep-alive: timeout=5\n      vary: Origin\n      x-powered-by: Express\n    Response Size: 435 bytes\n    Response Body:\n      {\n        \"object\": \"list\",\n        \"page\": {\n          \"startCursor\": \"ixCALWlkOnByZF8wMDAwMDAwMDAwc2VlZHRyYW1zMDAwMDAwMAM\",\n          \"endCursor\": \"ixCALWlkOnByZF8wMDAwMDAwMDAwc2VlZHRyYW1zMDAwMDAwMAM\",\n          \"hasNextPage\": true,\n          \"hasPrevPage\": false,\n          \"limit\": 1,\n          \"total\": 5\n        },\n        \"items\": [\n          {\n            \"id\": \"prd_0000000000seedtrams0000000\",\n            \"name\": \"tiramisu\",\n            \"price\": 13000,\n            \"category\": \"dessert\",\n            \"createdAt\": \"2026-04-29T10:00:50.610Z\",\n            \"updatedAt\": \"2026-04-29T10:00:50.610Z\",\n            \"object\": \"menuItem\",\n            \"calories\": 450\n          }\n        ]\n      } \n \n    ✓ success criteria check - $statusCode == 200\n    ✓ status code check - $statusCode in [200, 400, 500]\n    ✓ content-type check\n    ✗ schema check \n\n  Summary for redocly-cafe-api.arazzo.yaml\n  \n  Workflows: 1 failed, 1 total\n  Steps: 1 failed, 1 total\n  Checks: 3 passed, 1 failed, 4 total\n  Time: 58ms \n","lang":"bash"},"children":[]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In addition to the success criterion declared in the Arazzo file, Respect performed three additional checks automatically:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status code check"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["content-type check"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["schema check"]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Because the workflow step is connected to an OpenAPI description, ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://www.npmjs.com/package/@redocly/cli"},"children":["@redocly/cli"]}," verifies that the API returns a documented status code, the expected content type, and a response body that matches the documented schema."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"understand-the-schema-failure","__idx":6},"children":["Understand the schema failure"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Switch back to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly-cafe-api.yaml"]}," in the right panel."," ","The failed schema check reports the following message:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"text","header":{"controls":{"copy":{}}},"source":"| ^^ 👈🏽  type must be array\n","lang":"text"},"children":[]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"schema-failure","heading":"Spot the mismatch"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The OpenAPI description declares ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MenuItemList"]}," as an ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["array"]},", but the actual API response is a paginated ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["object"]}," with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["object"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["page"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["items"]}," properties."," ","This is the intentional discrepancy in the example."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Respect made this drift visible immediately, without anyone having to read both the OpenAPI description and the API output side-by-side."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"fix-the-schema","__idx":7},"children":["Fix the schema"]},{"$$mdtype":"Tag","name":"CodeStep","attributes":{"id":"schema-fix","heading":"Updated MenuItemList schema"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly-cafe-api.yaml"]},", change ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MenuItemList"]}," from an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["array"]}," to an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["object"]}," with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["object"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["page"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["items"]}," properties so the schema matches the response the API actually returns."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Compare the highlighted block in the right panel with the corrected version below:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"MenuItemList:\n  type: object\n  properties:\n    object:\n      type: string\n      const: list\n      description: Entity name.\n    page:\n      $ref: '#/components/schemas/Page'\n    items:\n      type: array\n      items:\n        $ref: '#/components/schemas/MenuItem'\n  required:\n    - object\n    - page\n    - items\n","lang":"yaml"},"children":[]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Re-run the workflow to confirm that all checks now pass:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"npx @redocly/cli respect redocly-cafe-api.arazzo.yaml\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After the schema is updated, the response body matches the documented contract."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"practical-applications","__idx":8},"children":["Practical applications"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After you create and verify an Arazzo workflow locally, you can use it in several ways:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Include the workflow in a CI/CD pipeline to keep API documentation synchronized with actual API behavior:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"# Spawn your API instance, then run the workflow\nnpx @redocly/cli respect redocly-cafe-api.arazzo.yaml --verbose\n","lang":"bash"},"children":[]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Automate routine API workflows for development and QA tasks."]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["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."]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"summary","__idx":9},"children":["Summary"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Arazzo provides a standard way to describe API workflows declaratively."," ","Respect uses those workflows to run API contract tests against real API behavior."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["With this approach, teams can maintain API test coverage, detect documentation drift earlier, and share executable API workflows across engineering, QA, and documentation teams."]}]}]},"headings":[{"value":"Test API contracts using Redocly Respect","id":"test-api-contracts-using-redocly-respect","depth":1},{"value":"The problem","id":"the-problem","depth":2},{"value":"Prerequisites","id":"prerequisites","depth":2},{"value":"Explore the OpenAPI description","id":"explore-the-openapi-description","depth":2},{"value":"Create an Arazzo description","id":"create-an-arazzo-description","depth":2},{"value":"Execute the workflow with Redocly CLI","id":"execute-the-workflow-with-redocly-cli","depth":2},{"value":"Understand the schema failure","id":"understand-the-schema-failure","depth":2},{"value":"Fix the schema","id":"fix-the-schema","depth":2},{"value":"Practical applications","id":"practical-applications","depth":2},{"value":"Summary","id":"summary","depth":2}],"frontmatter":{"markdown":{"toc":{"hide":true}},"footer":{"hide":true},"seo":{"title":"Test API contracts using Redocly Respect"}},"lastModified":"2026-05-22T11:37:22.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/learn/arazzo/practical-example-series/api-contract-testing-01","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}