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
- Open an endpoint and choose the Variants tab. The endpoint has to be saved first.
- Select Add variant, name it (for example
card-declined), and set its status, headers and body. - Under When, add a condition: Header
X-Cardequals4000000000000002. - 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-declinedEvery 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:
| Source | Example | Notes |
|---|---|---|
| Header | X-Card | Header names ignore case. |
| Query param | status | A repeated parameter matches if any of its values does. |
| Path param | id | Named in the route, e.g. :id in /orders/:id. |
| Cookie | session | The raw cookie value. |
| Body field | customer.email | A dot path into a JSON or form body. Array items by index: items.0.sku. |
and compares it with:
| Operator | Matches when |
|---|---|
| equals / does not equal | An exact, case-sensitive match. |
| contains / does not contain | Part of the value. |
| starts with / ends with | The start or end of the value. |
| is one of | Any value in a comma-separated list, e.g. paid, refunded. |
| is present / is missing | Whether the header, parameter, cookie or field exists at all. |
| >, ≥, <, ≤ | Numeric. False when either side isn't a number. |
| matches regex | An 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 responseNames 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:
| Step | What happens |
|---|---|
| Route matching | No matching route returns 404. |
| Status faults | An X-APIMock-Fault status or a fault rule replaces any response. |
| Require auth | A missing Authorization header returns 401. |
| Request validation | A body that fails the imported schema returns 422. |
| Response variants | The variant (or the default response) is chosen here. |
| Delay | The chosen response's delay, plus any injected latency. |
| Payload faults | nullify, 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 exampleWithout 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
| Limit | Value |
|---|---|
| Variants per endpoint | 20 |
| Conditions per variant | 10 |
| Variant body | 64 KiB |
| Response headers per variant | 20 |
| Regex pattern length | 200 characters |
| Compared length of a request value | First 4 KB |
| Values in an is one of list | 50 |
| Variant delay | 30 seconds |