Test complete frontend flows with a stateful CRUD mock API
Create realistic test records, exercise create and edit flows, restore seed data, and share a temporary CRUD API with clear access and lifecycle controls.
Why a fixed JSON response is sometimes not enough
A static mock works well when you need to render a list or check an error message. It becomes less useful when the interface lets someone add a task, change its status and delete it. Returning the same list after every request hides bugs: the UI may appear to save successfully even though its next read loses the change.
A stateful CRUD mock keeps a small collection behind an HTTP endpoint. Creating an item changes later reads, updating changes that item, and deleting makes it unavailable. That gives a frontend team a more realistic integration target before the application backend is ready. Keep static mocks for fixed response shapes, latency and failure cases; use a mutable collection when the interaction depends on earlier requests.
Begin with a deliberate, repeatable seed
Choose a short collection path such as /tasks and a JSON array of synthetic records. Include the field types your interface actually renders: a string title, a numeric priority, a boolean flag or a nested display object. Give records stable string IDs when you need recognizable routes; missing seed IDs receive deterministic values. Do not paste customer records into a shared testing service.
A useful seed contains a few distinct cases rather than hundreds of identical rows. A long name can expose layout problems; an empty optional value can exercise a fallback; different statuses can test filters in your application. The workbench validates seed structure before creation and shows the live records in a table after the endpoint is ready.
{
"name": "Tasks API",
"routes": [],
"crud": {
"path": "/tasks",
"seed": [
{
"id": "task_1",
"name": "Review the checkout",
"status": "todo"
}
]
}
}Exercise the same requests your application will send
GET on the collection returns data, total, limit, offset and revision. Request an item by appending its ID. POST adds a record and returns HTTP 201 with the created object, including a generated string ID when you omit one. PUT replaces the item’s fields, while PATCH merges top-level fields; nested objects are replaced as values rather than recursively merged. DELETE returns 204, and a later read returns 404.
Collection reads accept limit and offset, a case-insensitive q search across serialized record content, and a top-level sort field with order=asc or desc. This deliberately small contract is easy to use from a web application. It does not infer database filters, resolve relationships or execute a query language. Inspect the actual list response instead of assuming the API returns a bare array.
Make concurrent edits visible
Two developers can read the same record and then submit different edits. Without a guard, a later replacement can silently discard the earlier change. Each collection has a revision that advances after successful mutations and resets. Send the revision you read in X-Mock-If-Revision when writing; if another request has changed the collection, the server returns 409 and the current revision.
The workbench uses this guard for record writes. A conflict keeps your draft available while refreshing the collection, allowing you to inspect the current record before trying again. The guard applies to the whole collection, so even an edit to a different item can trigger a refresh. That conservative behavior keeps the model understandable for a small temporary sandbox.
Turn a manual check into a reusable lifecycle test
The scenario action builds a five-step test that creates a temporary record, captures its generated ID, reads it, changes its status, deletes it and expects a 404 afterward. The configuration contains a declared-secret placeholder for private access, never the access token itself. Loading the draft does not send requests. Supply the caller credential separately and review the sequence before running it.
The normal successful sequence cleans up its own record. If a request fails and execution stops, the test record may remain; inspect the table and delete it or restore the seed. Reset intentionally discards all live changes, so coordinate with anyone sharing the endpoint. Hosted scenario runners require a public network destination and cannot target localhost Docker addresses; direct HTTP clients and the platform MCP caller can exercise local deployments.