Transforms
Patch live API response bodies with stacked rules: wildcards, relative dates, seeded fakes, array jobs, and live preview - without replacing the whole mock.
On this page
Transforms patch the JSON (or text) body of a response after FlowMock has already resolved a mock or fetched upstream. They do not set status codes, headers, or delays - those stay on mocks. Pair a mock with a transform when you need an error state and a body tweak.
When to use a transform
| Job | Use |
|---|---|
| Full replacement response (empty cart JSON, 500 body) | Mock |
| Change one nested field on live upstream data | Transform |
| Empty or pad a list for empty-state / stress UI | Transform (clearArray, truncateArray, repeatToLength) |
| Force a 429 + Retry-After | Mock (status + headers); optional transform for body |
| Same fake email for every teammate in a scenario | Transform fake value + scenario seed / frozen clock |
How they stack
Unlike mocks (one winner), every matching transform runs:
- Global transforms (oldest first)
- Active scenario transforms (scenario membership order)
- Session transforms (oldest first)
Later writes to the same field win. Request targeting (method, path, matchers) only decides whether a transform matches - not which one "wins."
Field paths
| Path | Meaning |
|---|---|
status | Bare name - walks every object in the tree |
meta.version | Dotted path; fans into arrays at each segment |
tasks.*.priority | Explicit wildcard over array items |
tasks[0].id / tasks[-1].id | Index / last item |
tasks[?status=='open'].priority | Filter items, then set a field |
On Set field, enable Create missing nested path when intermediate objects should be created. Wildcards never invent array items.
Values (Tier 1)
When the action is Set field:
- Literal - JSON (
42,"42",true). The editor shows the parsed type so you do not confuse numbers and strings. - Expression - curated helpers, for example:
now,now+3d,now-1hnow | date:'iso',now | date:'epoch',now | date:'epochMs'value + 10,mask,redact,length(32)fake.email,req.query.id,req.body.userId
- Fake data - seeded
uuid,name,email,address,phone,company. Same scenario + field → same value for every teammate.
Frozen clock
On a scenario, freeze the clock so now expressions stay stable while you share the scenario. Fake generators use the scenario id as seed unless you override it.
Array actions
- Clear array - empty-state testing
- Truncate array - keep the first N items
- Repeat array to length - pad/repeat for stress
- Remove matching items - drop items that match rule conditions
Live preview and logs
In the transform editor, paste (or edit) a sample body and see a before / after diff as you change rules. Click a field path chip to fill the rule path. Custom scripts are skipped in preview — they only run on the proxy when a request hits.
In Traffic log detail, an applied transform trace lists which transform ids ran and which rule indexes fired (plus expression/script errors).
Custom scripts (Team+)
Most transform jobs are covered by Set field, expressions, fakes, and array actions. Use a Custom script rule when you need something those cannot express — for example filtering with nested logic, rewriting several fields together, or shaping the response from request data in a non-trivial way.
Contract
Your script must define a transform function. FlowMock calls it with one argument and uses the return value as the new response body:
function transform({ body, req, ctx }) {
// mutate body (or build a new object)
return body;
}| Argument | What it is |
|---|---|
body | Parsed JSON response body (after mock or upstream). Mutate it in place or return a new value. |
req | Inbound request: method, path, query (string map), body (parsed when JSON), pathParams. May be null if unavailable. |
ctx.now | Current time as an ISO string. Uses the scenario frozen clock when one is set. |
ctx.seed | Seed string from the active scenario (or session) — useful for stable demo ids. |
Scripts run on a dedicated Cloudflare Sandbox worker via service binding (remote in local dev — no Docker needed on your machine). The editor live preview does not execute custom scripts (other rule types still preview normally).
Examples
Overwrite a field
function transform({ body }) {
body.status = "failed";
return body;
}Filter a list
function transform({ body }) {
body.items = (body.items ?? []).filter((item) => item.status === "open");
return body;
}Echo request data into the response
function transform({ body, req }) {
body.echoUserId = req?.query?.userId ?? req?.body?.userId ?? null;
return body;
}Stable timestamp and id from scenario context
function transform({ body, ctx }) {
body.updatedAt = ctx.now;
body.demoId = `demo-${ctx.seed}`;
return body;
}In the transform editor, use the example chips under the script to insert these starters.
Failures
If the script throws or returns something FlowMock cannot serialize, the response body is left unchanged. The error is recorded on the applied transform trace in Traffic log detail so you can debug without breaking the client.
Prefer Set field / expressions / fakes when they cover the job — they preview in the editor and avoid script isolation cost.
Related
- Mocks and overrides - status, headers, delay, full body replace
- Scenarios - bundle transforms with mocks; freeze the clock
- How it works - proxy lifecycle
- Awareness headers - see the transform count on the response itself