All guidesIntegration

Mock Servers: A Free Hosted Mock URL for Every API Spec

Every OpenAPI, Swagger, and GraphQL spec on Outworx Docs gets a free hosted mock URL the moment you upload it. Walk through Prefer headers, stateful overrides, GraphQL support, per-version routing, the activity feed, and the diagnostic headers we ship with every response.

May 1, 20269 min read

Every API spec on Outworx Docs gets a free hosted mock URL the moment you upload it. Point your client at that URL and the responses come from the spec itself — examples, schemas, GraphQL types — so frontend work, integration tests, and SDK demos can run before the real backend exists. No CLI, no proxy, no separate "mock service" subscription.

This guide is the full reference: URL conventions, the Prefer header, stateful overrides, GraphQL support, per-version routing, the activity feed, and the diagnostic headers we ship with every response.

Prerequisites

  • An Outworx Docs project with at least one OpenAPI 3, Swagger 2, or GraphQL SDL spec uploaded
  • The project must be public and not password-protected — the mock URL inherits the same access gate as the rendered docs

If your project is private the mock route returns 404 to anonymous traffic. Flip Make documentation publicly accessible under Settings → General to enable mocking.

Step 1: Find your mock URL

Open any project in the dashboard and click the Mock tab. The Overview sub-tab shows the base URL for your project:

https://docs.outworx.io/mock/<your-slug>

For an OpenAPI/Swagger spec, append the path you'd hit on the real API:

curl https://docs.outworx.io/mock/acme/users/42

For a GraphQL spec, post to /graphql:

curl https://docs.outworx.io/mock/acme/graphql \
  -H 'content-type: application/json' \
  -d '{"query":"{ user(id: \"42\") { id name } }"}'

GraphQL also accepts GET ?query=... for quick browser testing.

Step 2: How responses are synthesised

The mock engine walks the spec to build a response, in this priority order:

  1. A matching stateful override (covered in step 4).
  2. A named example from the operation's examples map — picked by Prefer: example=<name>, random, or sequential.
  3. The first example field declared on the response or schema.
  4. A schema walk — every property gets a sensible value from its type, format, enum, or pattern. $ref, allOf, and oneOf are resolved.
  5. An empty body if the response defines no schema (e.g. 204).

Every response carries an X-Mock-Synth header that tells you which path was taken: override, example:<name>, example:random, example:sequential, schema, or empty. When a request misses the spec entirely you get X-Mock-Synth: fallback with a 404.

Step 3: Steer responses with the Prefer header

RFC 7240 defines Prefer as a way for clients to nudge servers — we use it as the steering wheel for mock responses:

| Header | Effect | | ------------------------------- | ------------------------------------------------------------------- | | Prefer: code=404 | Return the operation's 404 response instead of its 200. | | Prefer: example=randomized | Pick a random named example each call (see note below). | | Prefer: example=sequential | Round-robin through the examples — handy for pagination tests. | | Prefer: example=user-not-found| Return the example named user-not-found. |

Stack them with commas: Prefer: code=400, example=invalid-email.

The sequential counter is per (project, version, path, method, status) and stored in Redis with a 24-hour TTL — restart-safe across deploys without leaking state forever.

A note on random: with five examples you'd expect even distribution, but small-sample runs of three or four calls regularly bunch up. That's normal — the rolling distribution evens out across ~30 calls.

Step 4: Stateful overrides

Examples are static. Real apps need to demo states — "what does the UI look like when the user is rate-limited?" or "what happens if the order is in pending_review?" The Mock → Overrides sub-tab is where you set those up.

An override is a rule: match these requests, return this response. Each override lives at a specific endpoint (or * to match across all of them) and has:

  • Status code and response body (any JSON).
  • Latency in ms — useful for testing loading states.
  • Priority — higher numbers win when multiple overrides match. Ties break by most-recently-updated.
  • Optional matchers: query parameters, request headers, request body shape, GraphQL operation name.
  • Optional version scoping — restrict an override to one version of the spec.

The matcher set is deeply partial: { "user": { "role": "admin" } } matches any body that contains user.role === "admin", regardless of what else is there. Headers and query strings work the same way. First match wins, sorted by priority desc.

The fastest way to create one is the Duplicate button on an existing override — clones every field including matchers so you can tweak one knob without re-typing the rest.

When an override fires the response includes X-Mock-Synth: override, X-Mock-Override-Id: <uuid>, and the body you defined. The activity feed (next step) tags the request with the override's name so you can audit which rule ran.

Step 5: GraphQL overrides

GraphQL doesn't have paths, so the override matcher takes a match_graphql_operation field instead. Set it to the operation name (query MyQuery, mutation CreatePost) and any request whose operationName matches gets the override response.

Combine that with match_body to match on variables: an override with match_graphql_operation: "GetUser" and match_body: { "variables": { "id": "42" } } only fires for that specific user lookup.

If no override matches, the GraphQL executor runs against the SDL — fields resolve to type-appropriate defaults (string, int, bool, enum first value, list of one) and your selection set is honoured. Custom scalars come back as strings unless you've put an example directive on them in the SDL.

Step 6: Multi-version projects

If every version of your project uses the same kind of spec (all OpenAPI, all Swagger, all GraphQL) the base URL https://docs.outworx.io/mock/<slug> resolves to the default version — there's only one route to remember.

If you mix REST and GraphQL versions, the base URL splits per-version because the routing differs:

  • https://docs.outworx.io/mock/<slug>/v2/users/42 — REST version v2
  • https://docs.outworx.io/mock/<slug>/v1/graphql — GraphQL version v1

The Overview sub-tab shows exactly which URLs you have. Hit the wrong one and we return a 400 with a hint and an alternativeVersions list pointing at the right format-aware URL.

Step 7: Disable specific operations

Sometimes you want most of your API mocked but a handful of dangerous endpoints (anything that would hit Stripe, send mail, or charge a card) to come back 501 instead. The Endpoints sub-tab lists every operation with a per-version toggle — flip the switch and that operation returns 501 Not Implemented with X-Mock-Synth: disabled.

Disabled state is per-version — POST /payments/charge can be mocked in v1 and disabled in v2.

Step 8: Watch the activity feed

Every mock request is logged: method, path, status, latency, override id (if any), X-Mock-Synth value, and the requesting IP's country. The Activity sub-tab shows the last 200 in real-time. The Overview sub-tab shows a 7-day usage summary so you can spot when traffic spikes — useful when an integration partner starts hammering your mock instead of the real API.

Step 9: Plan limits

Free includes:

  • 10,000 mock requests / month across the whole project.
  • 5 stateful overrides active at once.
  • 24-hour activity log retention.

Pro: 100,000 mock req/mo, 50 overrides, 30-day retention.

Business: unlimited everything, 90-day retention.

When you hit the cap, requests get 429 Too Many Requests with Retry-After. The cap resets at the start of every UTC month.

Try It panel — running mocks from the docs page

The Try It panel at the top of every endpoint reference page now has a Mock toggle. Flip it on and the request goes to your mock URL with all your Prefer headers attached. The response panel shows the X-Mock-Synth value as a coloured badge so readers can see at a glance whether they hit a real example, a synthesised schema, or a custom override.

GraphQL operations get the same treatment via a query/variables/operation-name editor — same toggle, same badge. It's the fastest way to demo "here's what this endpoint returns" without leaving the docs page.

Diagnostic headers reference

| Header | Meaning | | ----------------------- | ---------------------------------------------------------- | | X-Mock-Synth | override, example:<name>, example:random, example:sequential, schema, empty, disabled, fallback | | X-Mock-Override-Id | UUID of the override that fired (only when synth=override) | | X-Mock-Version | Which version of the spec served the response | | X-Mock-Operation-Id | The operation id from the spec — handy for log correlation | | X-Mock-Latency-Ms | Server-side latency including any latency_ms from an override |

CORS is wide open (Access-Control-Allow-Origin: *, no credentials) — the mock URL is meant to be hit from any browser, frontend dev server, or Postman tab. The threat model is the same as the public docs: nothing private goes through it, no auth, no shared state across projects.

What this replaces

If you were running Prism locally, paying Apidog for hosted mocks, or maintaining a mocks/ directory of hand-written Express handlers — this is the integrated version. Spec uploads become live mock URLs automatically, overrides give you the dynamic-state escape hatch when examples aren't enough, and the activity feed plus Try It integration mean the docs and the mock are the same surface.

Open any project's Mock tab to grab your URL. The first request takes about 30ms and you're already mocking.

Ship your API docs in under a minute.

Upload your OpenAPI, Swagger, or GraphQL spec and get beautiful hosted docs with AI chat and a per-project MCP server — free forever for 2 projects.