Seed recorded API mocks from OpenAPI specs
Wraith’s primary workflow is record -> synthesize -> verify, with no spec required. But when you do have an OpenAPI 3.x spec, you can use it two ways:
- Seed: generate a scenario plan from the spec and (optionally) execute it against a live API to produce recordings.
- Measure coverage: compare what’s in your recordings to what the spec declares, and surface the gaps.
Both are additive - they complement recording, they don’t replace it. The recorded behaviour still wins for synthesis.
wraith explore
Section titled “wraith explore”wraith explore --from-openapi petstore.yamlParses the spec and prints a scenario plan: a structured list of request sequences that together exercise every operation. No network, no writes - just a plan you can review.
With --against <url>, the plan is executed:
wraith explore --from-openapi petstore.yaml \ --against https://petstore.example.com \ --header "Authorization: Bearer $TOKEN"Each scenario’s steps are sent via async reqwest. The output reports per-step outcomes (match, mismatch, error) alongside the plan.
| Flag | Description |
|---|---|
--from-openapi | Path to spec (YAML or JSON) |
--against | Optional live URL to execute scenarios against |
--header | Repeatable "Name: Value" headers for auth |
--max-scenarios | Cap the number of scenarios (safety bound) |
--record | Capture executed exchanges as a WREC session (requires --against and --twin) |
--twin | Twin to record into (twins/<NAME>/recordings/sessions/<run-id>/) |
--tag | Extra session tags, in addition to the automatic explore + synthetic tags |
--format | Output format: pretty, text, json (auto-detects) |
JSON output shape
Section titled “JSON output shape”{ "api_title": "Petstore", "count": 4, "operations_covered": 3, "scenarios": [ { "name": "petstore.pets.crud_lifecycle", "category": "crud_lifecycle", "step_count": 3, "entities": ["pet"], "priority": 1 } ], "plan": { "...": "full ScenarioPlan" }, "execution": { "base_url": "https://petstore.example.com", "total_steps": 7, "matched_steps": 5, "mismatched_steps": 1, "error_steps": 1, "results": [ { "scenario": "petstore.pets.crud_lifecycle", "steps": [ { "method": "GET", "path": "/pets/{id}", "expected_status": 200, "observed_status": 200, "outcome": "match" } ] } ] }, "advice": [{ "level": "info", "type": "plan-only", "message": "..." }]}execution is present only when --against is set.
Preview vs. recording
Section titled “Preview vs. recording”By default --against does not capture WRECs — it’s a preview / smoke check, useful for “does this spec actually describe the service” or “which operations are live?”
Since v0.17.0, add --record --twin <name> and the executed scenarios are captured as a normal recording session — same scrub-on-write pipeline as wraith record, tagged explore + synthetic for provenance — ready for wraith synth:
# Twin a service from synthetic traffic only (no real data ever touches it)wraith init myapi --base-url https://staging.example.comwraith explore --from-openapi spec.yaml \ --against https://staging.example.com \ --record --twin myapiwraith synth myapiwraith check myapiThis is the data-safety shortcut: for services where recording real traffic is blocked, drive a safe environment with synthesized requests and twin the shapes. It doesn’t replace real-traffic fidelity — synthesized scenarios exercise the spec’s happy paths, not your production distribution — but it gets a usable twin with zero exposure. For real recordings, wraith record remains the tool:
# 1. Preview: does the spec match reality?wraith explore --from-openapi petstore.yaml --against https://api.example.com
# 2. Record: capture real traffic for the twinwraith record myapi --port 8080# ... exercise the API through the proxy ...
# 3. Cover: which operations from the spec are in the recordings?wraith coverage myapi --openapi petstore.yamlwraith coverage --openapi
Section titled “wraith coverage --openapi”Extends the existing coverage command to compute spec-vs-recordings gap.
wraith coverage myapi --openapi petstore.yamlWalks every recorded session and matches request paths against spec templates (treating {param} as wildcards). Reports what’s covered and what isn’t:
{ "coverage": { "route_coverage": { "...existing...": "..." }, "state_coverage": null, "spec_coverage": { "api_title": "Petstore", "covered_count": 2, "total_count": 3, "percentage": 0.667, "uncovered_operations": [ { "method": "GET", "path": "/pets/{id}" } ], "manifest": { "...": "full CoverageManifest" } } }, "advice": [ { "level": "info", "type": "spec-coverage-primary", "message": "Route coverage reflects synthesized twin; spec coverage reflects the raw API surface in recordings." } ]}The pre-existing route_coverage field is unchanged - it reports coverage against the synthesized twin’s routes. The new spec_coverage reports coverage against the raw API surface declared in the spec. They answer different questions:
route_coverageasks: how much of my twin is exercised by my tests?spec_coverageasks: how much of the real API surface is in my recordings?
Both are useful; both ship side by side.
When to use OpenAPI seed mode
Section titled “When to use OpenAPI seed mode”- You have a spec and want a smoke check against a staging or preview deployment before committing to a recording run.
- You want to quantify your recording coverage (“we have WRECs for 42 of the 68 documented operations, here’s the gap list”).
- You’re onboarding a new API and want a starting plan for what to exercise.
When not to use it:
- The spec is aspirational and doesn’t match reality. (Most public specs are.) Record the real traffic; the spec lies.
wraith explore --againstwill surface this quickly. - You already have thorough recordings. Nothing to add.
OpenAPI security schemes are surfaced in the plan but wraith doesn’t automatically source credentials - pass them via --header at execution time:
wraith explore --from-openapi stripe.yaml \ --against https://api.stripe.com \ --header "Authorization: Bearer $STRIPE_KEY"For schemes beyond Bearer / API key (OAuth flows, signed requests), you’ll typically want to record real traffic anyway.