Docs menu · Response variants

APIMock documentation

Response variants

One endpoint can return different responses depending on the request: a 402 when the card number is a test decline, a 404 for an unknown id, a slow response one time in five. Each variant has its own status, headers and body, and conditions that decide when it's served. Requests that match no variant get the endpoint's own response.

Updated

Quick start

  1. Open an endpoint and choose the Variants tab. The endpoint has to be saved first.
  2. Select Add variant, name it (for example card-declined), and set its status, headers and body.
  3. Under When, add a condition: Header X-Card equals 4000000000000002.
  4. Select Save variants, then use Test a request at the bottom of the tab to see which response a request would get, condition by condition.
curl -i -X POST https://<your-workspace>.apimock.dev/api/payments \
  -H "X-Card: 4000000000000002"

HTTP/2 402
x-apimock-variant: card-declined

Every response from an endpoint with variants names what it served in the X-APIMock-Variant header (default for the endpoint's own response), and so does its entry in Request History.

Conditions

A variant matches when all of its conditions match. A variant with no conditions matches every request. Each condition reads one value from the request:

SourceExampleNotes
HeaderX-CardHeader names ignore case.
Query paramstatusA repeated parameter matches if any of its values does.
Path paramidNamed in the route, e.g. :id in /orders/:id.
CookiesessionThe raw cookie value.
Body fieldcustomer.emailA dot path into a JSON or form body. Array items by index: items.0.sku.

and compares it with:

OperatorMatches when
equals / does not equalAn exact, case-sensitive match.
contains / does not containPart of the value.
starts with / ends withThe start or end of the value.
is one ofAny value in a comma-separated list, e.g. paid, refunded.
is present / is missingWhether the header, parameter, cookie or field exists at all.
>, ≥, <, ≤Numeric. False when either side isn't a number.
matches regexAn RE2 pattern, found anywhere in the value unless you anchor it with ^ and $.

does not equal and does not contain also match when the value is missing. Regex uses RE2 syntax, which runs in linear time, so it has no backreferences or lookaround. A request body is only read when a variant needs it; one larger than 1 MiB gets a 413 on such endpoints.

Choosing a response

Each endpoint has a selection mode:

  • First match wins (the default) serves the first variant, in list order, whose conditions all match. Use the arrows to reorder.
  • Random by weight picks among the matching variants by their weight, a percentage. The rest of the traffic gets the endpoint's own response, so one variant weighted 20 fails one request in five. Weights can add up to at most 100.

A request can skip all of this and name the response it wants. This is the easiest way to pin an end-to-end test to one case:

X-APIMock-Variant: card-declined   # this variant, whatever its conditions
X-APIMock-Variant: default         # the endpoint's own response

Names ignore case. An unknown name returns 400 with the valid names, in the body and in an X-APIMock-Variant-Error header, so a typo can't make a test pass by accident. Browsers can send and read both headers.

What a variant changes

A variant is a whole alternative response: its status, content type, body and delay replace the endpoint's, and its headers replace the endpoint's custom headers rather than adding to them. Turn on Template to render the body with the response template syntax. Variants don't apply to a Resource's generated CRUD routes.

Variants are chosen after the checks that can reject a request:

StepWhat happens
Route matchingNo matching route returns 404.
Status faultsAn X-APIMock-Fault status or a fault rule replaces any response.
Require authA missing Authorization header returns 401.
Request validationA body that fails the imported schema returns 422.
Response variantsThe variant (or the default response) is chosen here.
DelayThe chosen response's delay, plus any injected latency.
Payload faultsnullify, drop_field and empty apply to whichever response was chosen.

See Fault injection for the X-APIMock-Fault header and fault rules.

From OpenAPI examples

When you import an OpenAPI or Swagger spec, each operation serves its main example, and its other examples become variants: other named examples of the same response, and the example of each other status code. They're selected the way the Prism mock server does it, with a Prefer header:

Prefer: example=notFound   # another named example
Prefer: code=404           # another status's example

Without that header, imported endpoints behave as before. Re-importing the spec updates its variants and keeps any you added yourself.

With AI agents

Through the MCP server, create_endpoint and update_endpoint accept selection_mode and response_variants (the list is replaced as a whole, and a variant keeps its id while its name stays the same). simulate_request shows which response a request would get, without sending it.

{
  "workspace": "acme",
  "method": "POST",
  "route": "/api/payments",
  "response_body": "{\"status\": \"succeeded\"}",
  "response_status": 201,
  "response_variants": [
    {
      "name": "card-declined",
      "status": 402,
      "content_type": "application/json",
      "body": "{\"error\": \"card_declined\"}",
      "conditions": [
        { "source": "header", "key": "X-Card", "operator": "equals", "value": "4000000000000002" }
      ]
    }
  ]
}

Limits

LimitValue
Variants per endpoint20
Conditions per variant10
Variant body64 KiB
Response headers per variant20
Regex pattern length200 characters
Compared length of a request valueFirst 4 KB
Values in an is one of list50
Variant delay30 seconds