Skip to content

Configuration Reference

Complete reference for mockd configuration files.

mockd supports YAML and JSON configuration files. The version field is required.

Terminal window
mockd serve --config mocks.yaml
mockd serve --config mocks.json
version: "1.0"
mocks:
- id: string
name: string
type: http | websocket | graphql | grpc | mqtt | soap | oauth
enabled: boolean
http: { ... } # if type: http
websocket: { ... } # if type: websocket
graphql: { ... } # if type: graphql
grpc: { ... } # if type: grpc
mqtt: { ... } # if type: mqtt
soap: { ... } # if type: soap
oauth: { ... } # if type: oauth
serverConfig: { ... } # Optional server settings
statefulResources: [ ... ] # Optional CRUD resources
tables: [ ... ] # Optional stateful data tables
extend: [ ... ] # Optional mock-to-table bindings
imports: [ ... ] # Optional spec imports with namespacing
customOperations: [ ... ] # Optional multi-step operations
FieldTypeRequiredDescription
versionstringYesConfig version (e.g., "1.0")
mocksarrayYesMock definitions
serverConfigobjectNoServer configuration
statefulResourcesarrayNoStateful CRUD resources (low-level)
tablesmapNoNamed data stores (pure data, no routing)
extendarrayNoBindings from mocks to tables (action + table reference)
importsarrayNoImport external specs (OpenAPI, WSDL) with namespace prefixes
customOperationsarrayNoMulti-step custom operations with expression evaluation

All mock types share common fields:

mocks:
- id: unique-mock-id
name: "Human-readable name"
description: "Optional description"
type: http
enabled: true
parentId: "" # Folder ID (optional)
metaSortKey: 0 # Sort order (optional)
http: { ... } # Type-specific configuration
FieldTypeRequiredDefaultDescription
idstringNoAuto-generatedUnique identifier
typestringNoInferredMock type: http, websocket, graphql, grpc, mqtt, soap, oauth
namestringNoHuman-readable name
descriptionstringNoLonger description
enabledbooleanNotrueWhether mock is active
parentIdstringNoFolder ID for organization
metaSortKeynumberNoManual ordering within folder
workspaceIdstringNoWorkspace this mock belongs to (set automatically by workspace context)

HTTP mocks match incoming requests and return configured responses.

mocks:
- id: get-users
name: Get Users
type: http
enabled: true
http:
priority: 0
matcher:
method: GET
path: /api/users
headers:
Authorization: "Bearer *"
queryParams:
status: active
response:
statusCode: 200
headers:
Content-Type: application/json
body: '{"users": []}'
delayMs: 100
FieldTypeDescription
priorityintegerMatch priority (higher = matches first)
matcherobjectRequest matching criteria
responseobjectResponse definition
sseobjectServer-Sent Events config (instead of response)
chunkedobjectChunked transfer config (instead of response)
validationobjectRequest validation (see Validation)
FieldTypeDescription
methodstringHTTP method (GET, POST, PUT, DELETE, PATCH, etc.)
pathstringURL path (supports {param} syntax for path parameters)
pathPatternstringRegex pattern for URL path
headersmapHeader matchers (exact match or glob patterns with *)
queryParamsmapQuery parameter matchers (exact match)
bodyContainsstringBody must contain this string
bodyEqualsstringBody must equal this string exactly
bodyPatternstringBody must match this regex pattern
bodyJsonPathmapJSONPath matchers (path: expected value)
mtlsobjectmTLS client certificate matching
# Exact match
path: /api/users
# Path parameters
path: /api/users/{id}
path: /api/{resource}/{id}
# Greedy path parameter (matches multiple segments)
path: /api/files/{path:.*}
# Regex pattern
pathPattern: "/api/users/[0-9]+"
FieldTypeDefaultDescription
statusCodeinteger200HTTP status code
headersmap{}Response headers
bodystring""Response body (supports templates)
bodyFilestringLoad body from file path
delayMsinteger0Response delay in milliseconds
seedinteger0Deterministic seed for faker/random output (0 = random)
matcher:
mtls:
cn: "client.example.com" # Common Name pattern
ou: "Engineering" # Organizational Unit pattern
o: "Example Corp" # Organization pattern
san:
dns: "*.example.com" # DNS SAN pattern
email: "*@example.com" # Email SAN pattern
ip: "10.0.0.*" # IP SAN pattern
http:
matcher:
method: GET
path: /events
sse:
events:
- type: update
data: '{"status": "connected"}'
id: "1"
- type: update
data: '{"status": "processing"}'
delay: 1000
timing:
fixedDelay: 1000 # ms between events
initialDelay: 0 # ms before first event
lifecycle:
maxEvents: 10 # max events before closing
timeout: 60000 # connection timeout ms
keepaliveInterval: 15 # keepalive interval in seconds
resume:
enabled: true # support Last-Event-ID
bufferSize: 100 # events to buffer
http:
matcher:
method: GET
path: /stream
chunked:
chunkSize: 1024 # bytes per chunk
chunkDelay: 100 # ms between chunks
data: "..." # data to stream
dataFile: ./large.json # or load from file
format: ndjson # optional: ndjson format
ndjsonItems: # for ndjson format
- {"id": 1}
- {"id": 2}

WebSocket mocks handle bidirectional message communication.

mocks:
- id: chat-ws
name: Chat WebSocket
type: websocket
enabled: true
websocket:
path: /ws/chat
subprotocols:
- chat
- json
requireSubprotocol: false
echoMode: true
maxMessageSize: 65536
idleTimeout: "5m"
maxConnections: 100
heartbeat:
enabled: true
interval: "30s"
timeout: "10s"
matchers:
- match:
type: exact
value: "ping"
response:
type: text
value: "pong"
- match:
type: json
path: "$.type"
value: "join"
response:
type: json
value:
type: "joined"
message: "Welcome!"
defaultResponse:
type: json
value:
type: "echo"
message: "{{message}}"
FieldTypeDefaultDescription
pathstringRequiredWebSocket upgrade path
subprotocolsarray[]Supported subprotocols
requireSubprotocolbooleanfalseRequire matching subprotocol
echoModebooleanfalseEcho received messages
maxMessageSizeinteger65536Max message size (bytes)
idleTimeoutstringConnection idle timeout
maxConnectionsinteger0Max concurrent connections (0 = unlimited)
heartbeatobjectPing/pong keepalive config
matchersarray[]Message matching rules
defaultResponseobjectResponse when no matcher matches
scenarioobjectScripted message sequence
FieldTypeDescription
typestringMatch type: exact, contains, regex, json
valuestringValue to match
pathstringJSONPath for json type
messageTypestringFilter by message type: text, binary
FieldTypeDescription
typestringResponse type: text, json, binary
valueanyResponse content (string or object for json)
delaystringDelay before sending (e.g., “100ms”)
FieldTypeDefaultDescription
enabledbooleanfalseEnable ping/pong
intervalstring"30s"Ping interval
timeoutstring"10s"Pong timeout
websocket:
scenario:
name: "onboarding"
loop: false
resetOnReconnect: true
steps:
- type: send
message:
type: json
value: {"type": "welcome"}
- type: wait
duration: "1s"
- type: expect
match:
type: json
path: "$.type"
value: "ready"
timeout: "10s"
optional: false

GraphQL mocks provide a full GraphQL API endpoint.

mocks:
- id: graphql-api
name: GraphQL API
type: graphql
enabled: true
graphql:
path: /graphql
introspection: true
schema: |
type Query {
users: [User!]!
user(id: ID!): User
}
type User {
id: ID!
name: String!
email: String!
}
resolvers:
Query.users:
response:
- id: "1"
name: "Alice"
email: "alice@example.com"
Query.user:
response:
id: "1"
name: "Alice"
email: "alice@example.com"
FieldTypeDefaultDescription
pathstringRequiredGraphQL endpoint path
schemastringInline SDL schema
schemaFilestringPath to .graphql schema file
introspectionbooleanfalseEnable introspection queries
resolversmap{}Field resolver configurations
subscriptionsmap{}Subscription configurations

Resolvers are keyed by Type.field:

resolvers:
Query.users:
response:
- { id: "1", name: "Alice" }
- { id: "2", name: "Bob" }
delay: "100ms"
Query.user:
# Match specific arguments
match:
args:
id: "1"
response:
id: "1"
name: "Alice"
Mutation.createUser:
response:
id: "{{uuid}}"
name: "New User"
Query.error:
error:
message: "Something went wrong"
path: ["error"]
extensions:
code: "INTERNAL_ERROR"

gRPC mocks provide a gRPC service endpoint.

mocks:
- id: grpc-greeter
name: Greeter Service
type: grpc
enabled: true
grpc:
port: 50051
reflection: true
protoFile: |
syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloStream (HelloRequest) returns (stream HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
services:
helloworld.Greeter:
methods:
SayHello:
response:
message: "Hello, World!"
SayHelloStream:
responses:
- message: "Hello 1"
- message: "Hello 2"
- message: "Hello 3"
streamDelay: "500ms"
FieldTypeDefaultDescription
portintegerRequiredgRPC server port
protoFilestringInline proto definition
protoFilesarrayPaths to .proto files
importPathsarrayProto import paths
reflectionbooleanfalseEnable gRPC reflection
servicesmap{}Service configurations
services:
package.Service:
methods:
MethodName:
response: # Single response
field: value
responses: # Multiple responses (streaming)
- { field: value1 }
- { field: value2 }
delay: "100ms" # Response delay
streamDelay: "50ms" # Delay between stream messages
match: # Request matching
metadata:
authorization: "Bearer *"
request:
field: expected_value
error:
code: "NOT_FOUND"
message: "Resource not found"
details:
type: "ErrorInfo"

MQTT mocks provide an MQTT broker.

mocks:
- id: mqtt-broker
name: IoT MQTT Broker
type: mqtt
enabled: true
mqtt:
port: 1883
tls:
enabled: false
certFile: ./certs/mqtt.crt
keyFile: ./certs/mqtt.key
auth:
enabled: false
users:
- username: device
password: secret123
acl:
- topic: "sensors/#"
access: publish
- topic: "commands/#"
access: subscribe
topics:
- topic: sensors/temperature
qos: 1
retain: true
messages:
- payload: '{"temp": 22, "unit": "celsius"}'
interval: "5s"
repeat: true
- topic: commands/device/+
qos: 1
onPublish:
response:
payload: '{"status": "ack"}'
forward: responses/device
FieldTypeDefaultDescription
portintegerRequiredMQTT broker port
tlsobjectTLS configuration
authobjectAuthentication configuration
topicsarray[]Topic configurations
FieldTypeDefaultDescription
topicstringRequiredTopic pattern (supports + and # wildcards)
qosinteger0Quality of Service (0, 1, 2)
retainbooleanfalseRetain last message
messagesarrayMessages to publish
onPublishobjectHandler for received messages
deviceSimulationobjectSimulate multiple devices
FieldTypeDescription
payloadstringMessage payload (supports templates)
delaystringInitial delay before sending
intervalstringRepeat interval
repeatbooleanWhether to repeat

SOAP mocks provide SOAP/WSDL service endpoints.

mocks:
- id: soap-service
name: Calculator Service
type: soap
enabled: true
soap:
path: /soap/calculator
wsdlFile: ./calculator.wsdl # or inline with wsdl:
operations:
Add:
soapAction: "http://example.com/Add"
response: |
<AddResponse>
<AddResult>{{xpath://Add/a}}</AddResult>
</AddResponse>
delay: "50ms"
match:
xpath:
"//a": "10"
fault:
code: "Server.InvalidInput"
message: "Invalid input provided"
detail: "<errorCode>1001</errorCode>"
FieldTypeDescription
pathstringSOAP endpoint path
wsdlstringInline WSDL definition
wsdlFilestringPath to WSDL file
operationsmapOperation configurations
FieldTypeDescription
soapActionstringSOAPAction header value
responsestringXML response body
delaystringResponse delay
matchobjectXPath-based request matching
faultobjectSOAP fault response
statefulResourcestringName of stateful resource for CRUD operations
statefulActionstringCRUD action: get, list, create, update, patch, delete, custom

Note: When statefulResource is set, the operation gets its response from the stateful resource — response and fault fields are not required. statefulResource and statefulAction must be set together.


Custom operations compose reads, writes, and expression-evaluated transforms against stateful resources.

version: "1.0"
customOperations:
- name: TransferFunds
consistency: atomic
steps:
- type: read
resource: accounts
id: "input.sourceId"
as: source
- type: read
resource: accounts
id: "input.destId"
as: dest
- type: update
resource: accounts
id: "input.sourceId"
set:
balance: "source.balance - input.amount"
- type: update
resource: accounts
id: "input.destId"
set:
balance: "dest.balance + input.amount"
response:
status: '"completed"'
FieldTypeRequiredDescription
namestringYesUnique operation name
consistencystringNoExecution mode: best_effort (default) or atomic (rollback-on-failure, no isolation guarantees)
stepsarrayYesOrdered sequence of steps
responsemapNoField → expression map for building the result
FieldTypeDescription
typestringStep type: read, create, update, delete, set, list, validate
resourcestringStateful resource name (for read/create/update/delete/list)
idstringExpression resolving to item ID (for read/update/delete)
asstringVariable name to store the result (required for read/list, optional for create/update)
setmapField → expression map (for create/update)
varstringVariable name (for set steps)
valuestringExpression value (for set steps)
filtermapField → expression map for filtering items (for list steps)
conditionstringBoolean expression (for validate steps — halts operation if false)
errorMessagestringError message returned when validate fails
errorStatusintegerHTTP status code for validate failures (default: 400)

Expressions use expr-lang/expr syntax. The environment includes input (request data) and variables from prior steps (from as and set.var).

String literals in expressions: To set a field to a literal string value, wrap the string in inner quotes: '"succeeded"'. Without inner quotes (e.g., "succeeded"), expr-lang treats the value as a variable reference. See the Custom Operations guide for details and examples.

Use mockd stateful custom validate --file <op.yaml> to preflight custom operations before registering them. Add --strict to fail on warnings (for example, empty set maps). For stronger preflight checks, provide sample input and run --check-expressions-runtime with --fixtures-file to evaluate expressions without writing state.


Server settings can be included in the config file.

Note: Port settings (httpPort, httpsPort, adminPort) from config files are currently overridden by CLI flags. Use --port and --admin-port flags to set ports:

Terminal window
mockd serve --config myconfig.yaml --port 4280 --admin-port 4290
version: "1.0"
serverConfig:
httpPort: 4280
httpsPort: 4283
adminPort: 4290
logRequests: true
maxLogEntries: 1000
maxBodySize: 10485760 # 10MB
readTimeout: 30 # seconds
writeTimeout: 30 # seconds
tls:
enabled: false
certFile: ./certs/server.crt
keyFile: ./certs/server.key
autoGenerateCert: true
mtls:
enabled: false
clientAuth: "require-and-verify"
caCertFile: ./certs/ca.crt
allowedCNs:
- "client.example.com"
mocks: [...]
FieldTypeDefaultDescription
httpPortinteger4280HTTP server port (0 = disabled)
httpsPortinteger0HTTPS server port (0 = disabled)
adminPortinteger4290Admin API port
managementPortinteger4281Engine management API port (internal)
logRequestsbooleantrueEnable request logging
maxLogEntriesinteger1000Max log entries to retain
maxBodySizeinteger10485760Max request body size (bytes)
readTimeoutinteger30HTTP read timeout (seconds)
writeTimeoutinteger30HTTP write timeout (seconds)
maxConnectionsinteger0Max concurrent HTTP connections (0 = unlimited)

The managementPort is used for internal communication between the Admin API and the mock engine. In standalone mode, you typically don’t need to configure this.

FieldTypeDefaultDescription
enabledbooleanfalseEnable TLS/HTTPS
certFilestringPath to certificate file
keyFilestringPath to private key file
autoGenerateCertbooleanfalseAuto-generate self-signed cert
FieldTypeDefaultDescription
enabledbooleanfalseEnable mTLS
clientAuthstring"none"Client auth mode
caCertFilestringCA certificate file
caCertFilesarrayMultiple CA certificate files
allowedCNsarrayAllowed client Common Names
allowedOUsarrayAllowed Organizational Units

Client auth modes:

  • none - No client certificate requested
  • request - Client certificate requested but not required
  • require - Client certificate required but not verified
  • verify-if-given - Verify client certificate if provided
  • require-and-verify - Require and verify client certificate

Configure Cross-Origin Resource Sharing for the mock server.

serverConfig:
cors:
enabled: true
allowOrigins:
- "http://localhost:3000"
- "https://app.example.com"
allowMethods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
allowHeaders:
- Content-Type
- Authorization
- X-Requested-With
exposeHeaders:
- X-Request-ID
allowCredentials: false
maxAge: 86400
FieldTypeDefaultDescription
enabledbooleantrueEnable CORS handling
allowOriginsarray["http://localhost:*"]Allowed origins (use ["*"] for any)
allowMethodsarray[GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD]Allowed HTTP methods
allowHeadersarray[Content-Type, Authorization, X-Requested-With, Accept, Origin]Allowed request headers
exposeHeadersarray[]Headers browsers can access
allowCredentialsbooleanfalseAllow credentials (cannot use with * origin)
maxAgeinteger86400Preflight cache duration (seconds)

Default behavior: When not configured, mockd allows requests from localhost origins only. This is secure for local development while preventing cross-origin attacks.

Wildcard origins:

cors:
allowOrigins: ["*"] # Allow any origin (not recommended for production)

Note: When allowCredentials: true, you cannot use wildcard origins.

Configure rate limiting for the mock server.

serverConfig:
rateLimit:
enabled: true
requestsPerSecond: 1000
burstSize: 2000
trustedProxies:
- "10.0.0.0/8"
- "172.16.0.0/12"
FieldTypeDefaultDescription
enabledbooleanfalseEnable rate limiting
requestsPerSecondfloat1000Requests per second limit
burstSizeinteger2000Maximum burst size (token bucket)
trustedProxiesarray[]CIDR ranges for trusted proxies

How it works: Rate limiting uses a token bucket algorithm. The bucket fills at requestsPerSecond rate up to burstSize tokens. Each request consumes one token.

Trusted proxies: When set, mockd trusts X-Forwarded-For headers from these IP ranges for accurate client IP detection.

Example: Strict rate limiting for load testing:

serverConfig:
rateLimit:
enabled: true
requestsPerSecond: 100
burstSize: 150

Configure chaos injection in the config file. Chaos settings can also be managed at runtime via the CLI (mockd chaos enable) or Admin API (PUT /chaos).

serverConfig:
chaos:
enabled: true
latency:
min: "50ms"
max: "200ms"
probability: 1.0
errorRate:
probability: 0.1
statusCodes: [500, 502, 503]
defaultCode: 503

For advanced path-scoped rules with stateful fault types:

serverConfig:
chaos:
enabled: true
rules:
- pathPattern: "/api/payments/.*"
faults:
- type: circuit_breaker
probability: 1.0
circuitBreaker:
failureThreshold: 5
recoveryTimeout: "30s"
halfOpenRequests: 2
tripStatusCode: 503
- pathPattern: "/api/.*"
faults:
- type: latency
probability: 0.5
latency:
min: "50ms"
max: "200ms"
FieldTypeDefaultDescription
enabledbooleanfalseEnable chaos injection
latencyobjectGlobal latency settings
latency.minstringMinimum latency (Go duration)
latency.maxstringMaximum latency (Go duration)
latency.probabilityfloat1.0Probability of applying latency
errorRateobjectGlobal error injection settings
errorRate.probabilityfloat0Probability of error response
errorRate.statusCodesarray[500]Status codes to randomly choose from
errorRate.defaultCodeinteger500Default error status code
rulesarrayPath-scoped chaos rules
rules[].pathPatternstringRegex pattern to match request paths
rules[].faultsarrayFault definitions for matched paths

Fault types: latency, error, timeout, corrupt_body, empty_response, slow_body, connection_reset, partial_response, circuit_breaker, retry_after, progressive_degradation, chunked_dribble

See the Chaos Engineering guide for detailed usage and examples.


Tables are named data stores — pure in-memory collections with no routing or HTTP endpoints attached. Tables hold seed data and are referenced by extend bindings to wire mock endpoints to CRUD actions.

version: "1.0"
tables:
- name: users
idField: id
seedData:
- id: "1"
name: "Alice"
email: "alice@example.com"
- id: "2"
name: "Bob"
email: "bob@example.com"
- name: products
idField: sku
seedData:
- sku: "WIDGET-001"
name: "Blue Widget"
price: 29.99
mocks: []
FieldTypeDefaultDescription
idFieldstring"id"Field name for resource ID
idStrategystring"uuid"ID generation strategy: uuid (36-char UUID v4), prefix (prefix + 16 hex chars), ulid (26-char time-sortable), sequence (auto-incrementing integer), short (16 hex chars)
idPrefixstring""Prefix for generated IDs (when idStrategy: prefix, e.g., "cus_")
parentFieldstring""Foreign key field for sub-resource filtering by parent
maxItemsinteger0Max items in the table (0 = unlimited)
seedDataarray[]Initial data to load
validationobjectValidation rules (see Validation)
responseobjectResponse transform config (see Response Transform)
relationshipsmap{}Field-to-table mappings for ?expand[] support

Each table has a name field (e.g., users, products). Internally, tables are converted into statefulResources entries — but unlike the legacy statefulResources + basePath pattern, tables never auto-generate HTTP endpoints. All routing is explicit via extend.

Tables and extend bindings support a response field that controls how stateful data is shaped before it’s returned to clients. Binding-level overrides replace (not merge with) the table default.

tables:
- name: customers
response:
timestamps:
format: unix
fields:
createdAt: created
updatedAt: updated
fields:
inject: { object: customer, livemode: false }
hide: [updatedAt]
rename: { firstName: first_name }
wrapAsList:
items:
url: "/v1/customers/{{id}}/items"
list:
dataField: data
extraFields: { object: list, has_more: false }
metaFields: { total: total_count }
hideMeta: true
create:
status: 200
delete:
status: 200
preserve: true
body:
id: "{{item.id}}"
object: customer
deleted: true
errors:
wrap: error
fields: { message: message, type: type, code: code }
inject: { doc_url: "https://docs.example.com" }
typeMap: { NOT_FOUND: invalid_request_error }
codeMap: { NOT_FOUND: resource_missing }
FieldTypeDescription
timestampsobjectTimestamp format and field renaming
fieldsobjectField injection, hiding, renaming, and array wrapping
listobjectList envelope customization (HTTP-specific)
createobjectCreate verb override (status code)
deleteobjectDelete verb override (status, body, preserve)
errorsobjectError response format customization
FieldTypeDefaultDescription
formatstring"rfc3339"Output format: unix (epoch seconds), iso8601 (RFC3339 string), rfc3339 (no-op), none (remove timestamps)
fieldsmap{}Rename timestamp keys. Keys: createdAt, updatedAt. Values: output names.
FieldTypeDefaultDescription
injectmap{}Static key-value pairs added to every item response
hidearray[]Field names to remove from responses (data still stored)
renamemap{}Key renames applied to responses (key: original, value: output)
wrapAsListmap{}Array fields to wrap in {object: "list", data: [...], has_more: false} envelopes. Value is a ListWrapConfig with optional url template.

ListWrapConfig:

FieldTypeDescription
urlstringURL template for the sub-resource list. Supports {{fieldName}} substitution from the parent item.
FieldTypeDefaultDescription
dataFieldstring"data"Key for the items array in the list envelope
extraFieldsmap{}Static fields on the list envelope (including null values). All values are passed through as-is except has_more, which is dynamically computed from pagination state.
metaFieldsmap{}Rename pagination meta keys: total, limit, offset, count
hideMetabooleanfalseOmit pagination metadata entirely
FieldTypeDefaultDescription
statusinteger201HTTP status code for create responses
FieldTypeDefaultDescription
statusinteger204HTTP status code for delete responses
bodymapnilResponse body template. Supports {{item.fieldName}} substitution from the deleted item.
preservebooleanfalseSoft delete: return the configured response but keep the item in the store
FieldTypeDefaultDescription
wrapstring""Nest the error object under this key (e.g., "error" produces {"error":{...}})
fieldsmap{}Map mockd error fields (message, code, type, resource, id, field) to custom names
injectmap{}Static fields on every error response
typeMapmap{}Map error codes (NOT_FOUND, CONFLICT, VALIDATION_ERROR, CAPACITY_EXCEEDED, INTERNAL_ERROR) to custom type strings
codeMapmap{}Map error codes to custom code strings

Transform execution order: rename > hide > wrapAsList > timestamps > inject. See the Response Transforms guide for detailed examples and the full Stripe digital twin walkthrough.


Extend bindings wire mock endpoints to tables. Each binding references a mock (by id), a table, and an action to perform.

version: "1.0"
tables:
- name: users
seedData:
- id: "1"
name: "Alice"
mocks:
- id: list-users
type: http
http:
matcher:
method: GET
path: /api/users
response:
statusCode: 200
- id: create-user
type: http
http:
matcher:
method: POST
path: /api/users
response:
statusCode: 201
- id: get-user
type: http
http:
matcher:
method: GET
path: /api/users/{id}
response:
statusCode: 200
extend:
- mock: list-users
table: users
action: list
- mock: create-user
table: users
action: create
- mock: get-user
table: users
action: get
FieldTypeRequiredDescription
mockstringYesID of the mock to bind
tablestringYesName of the table to operate on
actionstringYesCRUD action: list, get, create, update, patch, delete, custom
operationstringNoOperation name (required when action: custom)
responseobjectNoResponse transform override for this binding (see Response Transform). Replaces (does not merge with) the table default.
ActionDescription
listList all items in the table
getGet a single item by ID (extracted from path parameter)
createCreate a new item from the request body
updateFully replace an item (PUT semantics — replaces all fields). Missing fields are removed from the stored item.
patchPartially update an item (PATCH semantics — merges sent fields into existing item). Works with any HTTP method. Use this for POST-as-update endpoints (e.g., Stripe) where only fields present in the body are updated.
deleteDelete an item by ID
customExecute a named custom operation (requires operation field)

To trigger a custom operation from a mock endpoint, use action: custom with an operation field:

extend:
- mock: transfer-endpoint
table: accounts
action: custom
operation: TransferFunds

Imports load external API specifications (OpenAPI, WSDL) and generate mocks with a namespace prefix. This is useful for creating digital twins of third-party APIs.

version: "1.0"
imports:
- path: ./stripe-openapi.yaml
as: stripe
format: openapi
tables:
- name: customers
seedData:
- id: "cus_001"
name: "Alice"
extend:
- mock: stripe.ListCustomers
table: customers
action: list
FieldTypeRequiredDescription
pathstringYes*Local file path to the spec (resolved relative to the config file). Exactly one of path or url must be set.
urlstringYes*Remote URL to fetch the spec from. Exactly one of path or url must be set.
asstringNoNamespace prefix for generated mock IDs (e.g., stripe). Imported mocks get {as}.{operationId}. If empty, the raw operationId is used.
formatstringNoSpec format (auto-detected if omitted): openapi, wsdl

Imported mocks receive IDs prefixed with the namespace using dot notation (e.g., stripe.ListCustomers). You can then reference these IDs in extend bindings to wire them to your tables.

Endpoints that are NOT bound via extend remain as static schema-generated mocks — they return example responses from the spec without any stateful behavior. Use mockd list on a running server to discover all generated mock IDs and their operationIds.


Stateful resources are the low-level internal representation of data stores. In most cases, you should use tables and extend bindings instead — they provide a cleaner separation between data and routing.

The statefulResources field is still supported for backward compatibility and for the CLI mockd stateful add workflow. Tables are converted into statefulResources entries internally.

version: "1.0"
statefulResources:
- name: users
idField: id
parentField: ""
seedData:
- id: "1"
name: "Alice"
email: "alice@example.com"
- id: "2"
name: "Bob"
email: "bob@example.com"
mocks: []
FieldTypeDefaultDescription
namestringRequiredResource name (e.g., “users”)
idFieldstring"id"Field name for resource ID
parentFieldstringParent FK field for nested resources
seedDataarray[]Initial data to load
validationobjectValidation rules (see Validation)

Stateful resources and HTTP mocks support field-level request validation.

FieldTypeDefaultDescription
modestring"strict"Validation mode: strict, warn, permissive
autobooleanfalseAuto-infer rules from seed data
requiredarray[]Required field names (shared)
fieldsmap{}Field validators (shared)
pathParamsmap{}Path parameter validators
onCreateobjectCreate-specific validation
onUpdateobjectUpdate-specific validation
schemaobjectInline JSON Schema
schemaRefstringPath to JSON Schema file
FieldTypeDefaultDescription
modestring"strict"Validation mode: strict, warn, permissive
failStatusinteger400HTTP status code for failures
requiredarray[]Required field names
fieldsmap{}Field validators
pathParamsmap{}Path parameter validators
queryParamsmap{}Query parameter validators
headersmap{}Header validators
schemaobjectInline JSON Schema
schemaRefstringPath to JSON Schema file
FieldTypeDescription
typestringExpected type: string, number, integer, boolean, array, object
requiredbooleanField must be present
nullablebooleanAllow null values
minLengthintegerMinimum string length
maxLengthintegerMaximum string length
patternstringRegex pattern for strings
formatstringFormat: email, uuid, date, datetime, uri, ipv4, ipv6, hostname
minnumberMinimum value (inclusive)
maxnumberMaximum value (inclusive)
exclusiveMinnumberMinimum value (exclusive)
exclusiveMaxnumberMaximum value (exclusive)
minItemsintegerMinimum array items
maxItemsintegerMaximum array items
uniqueItemsbooleanArray items must be unique
itemsobjectFieldValidator for array items
enumarrayAllowed values
propertiesmapNested object validators
messagestringCustom error message

Use dot notation for nested object fields:

fields:
"address.city":
type: string
required: true
"address.zipCode":
type: string
pattern: "^[0-9]{5}$"
"items.sku":
type: string
required: true

For arrays, the field after the dot applies to each array item:

  • items.sku validates the sku field in each item of the items array

See the Validation Guide for comprehensive examples.


Response bodies support template variables. Templates work in all protocols (HTTP, GraphQL, gRPC, SOAP, WebSocket, SSE, MQTT).

body: |
{
"id": "{{request.pathParam.id}}",
"query": "{{request.query.search}}",
"header": "{{request.header.Authorization}}",
"body": {{request.body}},
"field": "{{jsonPath request.body '$.field'}}",
"timestamp": "{{now}}",
"uuid": "{{uuid}}",
"name": "{{faker.name}}",
"email": "{{faker.email}}",
"card": "{{faker.creditCard}}",
"random": {{randomInt 1 100}}
}
VariableDescription
{{request.method}}HTTP method
{{request.path}}Request path
{{request.url}}Full URL
{{request.pathParam.name}}Path parameter value
{{request.query.name}}Query parameter value
{{request.header.Name}}Request header value
{{request.body}}Full request body (raw)
{{jsonPath request.body '$.path'}}JSONPath extraction
{{now}}ISO 8601 timestamp
{{timestamp}}Unix timestamp (seconds)
{{timestamp.iso}}ISO timestamp (RFC3339Nano UTC)
{{timestamp.unix_ms}}Unix timestamp (milliseconds)
{{uuid}}Random UUID
{{uuid.short}}Short random ID (hex)
{{randomInt min max}}Random integer (alias for random.int)
{{randomFloat min max}}Random float (alias for random.float)
{{randomString length}}Random alphanumeric string (alias for random.string)
{{sequence("name")}}Auto-incrementing counter
{{upper value}}Uppercase string
{{lower value}}Lowercase string
{{default value fallback}}Default if empty

Generate realistic sample data in response bodies. See the Response Templating guide for full details and example output.

CategoryTypes
Basicname, firstName, lastName, email, phone, company, address, word, sentence, words, words(n), boolean, uuid
Internetipv4, ipv6, macAddress, userAgent, url
FinancecreditCard, creditCardExp, cvv, currencyCode, currency, iban, price
CommerceproductName, color, hexColor
Identityssn, passport, jobTitle
Geolatitude, longitude
Textslug
DatamimeType, fileExtension

Usage: {{faker.name}}, {{faker.creditCard}}, {{faker.words(5)}}, etc.

See mockd help templating for the complete reference.


version: "1.0"
serverConfig:
httpPort: 4280
adminPort: 4290
logRequests: true
mocks:
# HTTP mock
- id: health-check
name: Health Check
type: http
enabled: true
http:
matcher:
method: GET
path: /health
response:
statusCode: 200
body: '{"status": "ok"}'
# HTTP with path parameters
- id: get-user
name: Get User
type: http
enabled: true
http:
matcher:
method: GET
path: /api/users/{id}
response:
statusCode: 200
headers:
Content-Type: application/json
body: |
{
"id": "{{request.pathParam.id}}",
"name": "User {{request.pathParam.id}}"
}
# WebSocket
- id: ws-echo
name: Echo WebSocket
type: websocket
enabled: true
websocket:
path: /ws/echo
echoMode: true
# GraphQL
- id: graphql
name: GraphQL API
type: graphql
enabled: true
graphql:
path: /graphql
introspection: true
schema: |
type Query {
hello: String!
}
resolvers:
Query.hello:
response: "Hello, World!"
# Stateful CRUD via tables + extend
- id: list-posts
type: http
http:
matcher:
method: GET
path: /api/posts
response:
statusCode: 200
- id: create-post
type: http
http:
matcher:
method: POST
path: /api/posts
response:
statusCode: 201
- id: get-post
type: http
http:
matcher:
method: GET
path: /api/posts/{id}
response:
statusCode: 200
tables:
- name: posts
seedData:
- id: "1"
title: "First Post"
content: "Hello, World!"
extend:
- mock: list-posts
table: posts
action: list
- mock: create-post
table: posts
action: create
- mock: get-post
table: posts
action: get
  • CLI Reference - Command-line options
  • Request Matching - Matching patterns
  • mockd help config - Built-in configuration help
  • mockd help templating - Template variable reference
  • mockd init --template list - Available templates