The Decoy mock server serves dynamic API responses based on OpenAPI v3 specifications. When a spec is loaded at startup, the server validates incoming requests against it and returns mock responses with template-rendered examples.
Start the server with:
decoy server rest start -f spec.yamlThe /mock endpoint accepts any HTTP method and path. It strips the /mock prefix and matches the remainder against the routes defined in the loaded OpenAPI v3 spec. The request is validated against the spec before a response is returned.
The server selects a response from the OpenAPI spec in this order:
- Response — If
?decoy-response=is provided, that response key is used (e.g.200,4xx). Otherwise the first response is used. - Content type — If
?decoy-content-type=is provided, that media type is used. Falls back to theContent-Typerequest header, then the first content type in the response. - Example — If
?decoy-example=is provided, that example key is used. Otherwise the first example is used.
If the selected example value is a string and the content type is text/* or decoy-parse is not explicitly disabled, the string is rendered through the Decoy template engine with the following context:
{
"Request": {
"Method": "GET",
"QueryParams": {"page": "1"},
"Path": "/users",
"Header": {"Authorization": "Bearer ..."},
"Body": null,
"Content-Type": "application/json"
},
"Response": {
"ContentType": "application/json",
"StatusCode": 200,
"Example": "userResponse"
}
}This allows dynamic responses. For example, given an OpenAPI example value of:
{"id": {{randomInt 1 1000}}, "name": "{{randomName}} {{randomLastName}}", "page": {{.Request.QueryParams.page}}}
The response would be rendered as something like:
{"id": 742, "name": "Priya Bell", "page": 1}If an example uses externalValue, the server supports the decoy:// URL scheme to reference a stored template:
examples:
userResponse:
externalValue: decoy://user-templateThis loads the template named user-template from the decoy storage and uses its content as the example value.
| Parameter | Description |
|---|---|
decoy-response |
Select a specific response by status code key (e.g. 200, 4xx, default) |
decoy-content-type |
Select a specific response content type (e.g. application/json) |
decoy-example |
Select a specific example by name |
decoy-parse |
Set to false to disable template rendering on the example value |
| Key | Type | Description |
|---|---|---|
.Request.Method |
string |
HTTP method of the incoming request |
.Request.QueryParams |
map[string]any |
Query parameters (single values are strings, repeated params are arrays) |
.Request.Path |
string |
Raw request path |
.Request.Header |
map[string]any |
Request headers (single values are strings, repeated headers are arrays) |
.Request.Body |
any |
Parsed JSON body, or raw string for non-JSON content types |
.Request.Content-Type |
string |
Content-Type header from the request |
.Response.ContentType |
string |
The selected response content type |
.Response.StatusCode |
int |
The selected response status code |
.Response.Example |
string |
The selected example name |
Given this OpenAPI spec:
openapi: "3.0.0"
info:
title: Users API
version: "1.0"
paths:
/users/{id}:
get:
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
200:
description: User details
content:
application/json:
examples:
default:
value: |
{"id": {{.Request.Path}}, "name": "{{randomName}} {{randomLastName}}", "requestedId": {{index .Request.QueryParams "id"}}}A request to GET /mock/users/42 would return:
{"id": "/users/42", "name": "Aaron Rivera", "requestedId": "42"}