Skip to main content

Authored by clicking, shipped with the docs.

A scenario is a named, replayable sequence of requests — 100% declarative. There is no scripting hook anywhere, which is precisely what makes scenarios serializable, shareable and exportable. This guide is the authoring workflow, end to end; for what scenarios are and why, start at the feature page.

Capture, don’t write

Send a request in the try-it console, then “Add to a scenario”; the same action exists on any history entry. A scenario grows step by step out of requests that actually ran — at no point is there JSON to write by hand.

Chain by clicking the response

In the scenario view, the last response is clickable: click a key to turn it into a variable ({{petId}} ← /id) or an assertion. When a later step needs a variable no earlier step produces, the suggestion to extract one comes from the missing variable itself. Assertions come from the observed response or from the declared schema, the same way — by clicking.

Before anything is sent, the prerequisites panel answers “why will this fail”: missing variables, missing credentials, steps whose inputs nothing produces yet.

What a step can carry

Everything a step declares is data, never code — which is exactly what keeps scenarios serializable:

  • Extractions — by pointer ({{petId}} ← /id) or by a JSONPath query (RFC 9535), where the first matched node wins. An extraction marked sensitive is masked like any credential. One marked persist is written into the active environment at the end of a successful run — deliberately allowed even under environmentsLocked, because the config governs the environment’s structure, not the values a run produces.
  • Assertions — four operators: exists, equals (loose), regex (unanchored), and matches — an RFC 9535 JSONPath that passes when it selects at least one node.
  • timeout — per step, in milliseconds; the runner cancels the send past it.
  • continueOnFailure — a failed step normally stops “Run all”; with this flag the sequence keeps going and the report names the steps that failed.
  • Inputsscenario.inputs declares named defaults; the environment overrides an input of the same name, and a value produced during the run overrides both.

Run it two ways

“Run all” unrolls the sequence and renders a per-step report — status, duration, extracted values, a history link per step. “Step by step” loads each step into the real try-it and lets the reader send it: an authored scenario becomes an interactive tutorial. In both modes, a missing variable blocks the step; the {{literal}} is never sent.

Ship it with the docs

Export the scenario as a JSON file, commit it, declare it:

{ "scenarios": [{ "id": "onboarding", "title": "Onboarding", "url": "/scenarios/onboarding.json" }] }

Declared scenarios are read-only for the reader (“Duplicate” makes a local, editable copy) and load lazily, on open — except a pinned one, whose file is fetched when the home page loads. pinned: true features that scenario on the home page with its description and steps — typically the auth flow you want at hand on arrival. In multi-spec, declare scenarios only on specs[] entries: a scenario references operations of one specific spec.

A scenarios[] entry takes either the app’s own export format or an Arazzo workflow document (1.0 or 1.1), by url or as an inline document — so the file your CI already runs can be declared as it stands, and each of its workflows renders as a scenario:

{ "scenarios": [{ "id": "payments", "url": "/workflows/payments.arazzo.yaml" }] }

Share it

A scenario travels as a JSON file or a #/scenario-import?d=… link. Import always shows a preview first and never runs anything automatically. A scenario file never contains a sensitive value — credentials stay environment {{var}}s, and stay home.

Local scenarios are capped at 200 per spec. Past the cap, creation is refused with an actionable message — export or delete first — never a silent eviction: a scenario is the reader’s work, not a cache.

Exchange Arazzo

Scenarios speak Arazzo, the OpenAPI Initiative’s workflow format: imports accept 1.0 and 1.1 documents, exports write 1.1.0 — steps, outputs, successCriteria, and $response.body#/id-style runtime expressions. One workflow of an imported document (JSON or YAML) becomes one scenario, and whatever the model cannot express is listed at import, never dropped silently — constructs the app cannot run (nested workflows, retry/goto actions, AsyncAPI steps) render with a “partial support” badge naming each.

The Export menu on a scenario page offers three take-aways: the scenario file, a share link, and the Arazzo document.

Hand it to your CI

Every scenario page carries an “Automate this scenario” panel: pick a runner and a CI platform, and it generates a ready-to-commit job that runs the scenario’s Arazzo document on a schedule — in someone else’s CI, with someone else’s runner. Two runners today, Redocly Respect (npx @redocly/cli respect) and Jentic’s Arazzo Runner (pip install arazzo-runner); two platforms, GitHub Actions and GitLab CI.

.github/workflows/create-a-payment.yml
name: Create a payment
on:
  workflow_dispatch:
  schedule:
    - cron: '0 6 * * *'
jobs:
  create-a-payment:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
      - name: Run the workflow
        run: |
          npx @redocly/cli@latest respect arazzo/create-a-payment.arazzo.json \
            --workflow create-payment \
            --input auth.token="$AUTH_TOKEN"
        env:
          AUTH_TOKEN: ${{ secrets.AUTH_TOKEN }}

The job carries variable names wired to your CI’s secret store, never values — the panel lists the names to define and the snippet contains none of what your environment holds. A scenario declared by url generates a job that fetches the served document instead (curl -fsSL …): the file you own, nothing to commit and nothing to keep in step.

Before you copy anything, the panel names what might not survive the trip: Respect states it reads Arazzo 1.0.1, so a 1.1 document gets a version warning plus a per-construct one (the Selector Objects 1.1 extracts values with); Arazzo Runner states no revision, and the panel says exactly that instead of guessing. An authored document gets its own honest note — it may describe more than this documentation runs.

The panel works on your local scenarios too, not just declared ones. And the boundary is stated in the product itself: “This documentation stays a static page — it schedules nothing and runs nothing on your behalf.” The GitHub job wakes daily (0 6 * * * — edit the cron to taste); on GitLab, scheduling lives in CI/CD → Schedules. features: { "ci": false } removes the panel — the Arazzo export stays.

Or switch the whole thing off

features: { "scenarios": false } removes the feature entirely — nav section, capture buttons, home card, routes, search index. Local scenarios already in the reader’s browser stay in the database, intact, for the day it is re-enabled.