Mock API Studio Documentation
Mock API Studio helps frontend and product teams design realistic mock APIs in a cloud dashboard and run those APIs locally as a backend during development.
The dashboard stores configuration. The npm runtime runs on your machine. The cloud service is not the mock server.
Cloud Dashboard
-> Project configuration
-> API token
-> Local runtime
-> Running mock backendUse Mock API Studio when you need a backend-like API before the real backend is available, when you want repeatable generated data, or when you need to test authentication, latency, errors, pagination, sorting, and CRUD behavior locally.
Quick Start
Overview
A project is the configuration for one local mock backend. It can contain multiple resources, shared TypeScript types, authentication behavior, query settings, runtime settings, and relationships.
The shortest path to a running mock backend is:
- Create an account.
- Create a project.
- Add at least one resource.
- Generate an API token.
- Start the local runtime with the CLI.
- Send requests to the local mock backend.
Example
Create a resource for users with a collection response:
interface User {
id: string;
name: string;
email: string;
active: boolean;
}
type MockApiStudioResponse = User[];Start the local runtime for your project:
npx mock-api-studio-cli start customer-portalThe runtime starts an Express server on your machine. You can then call generated routes such as:
GET /users
GET /users/{id}
POST /users
PATCH /users/{id}
DELETE /users/{id}Best Practices
- Start with one resource and confirm the runtime starts before modeling the full API.
- Use realistic resource names such as
users,orders,products, andbookings. - Add shared types when multiple resources use the same entities.
- Generate a new API token if a saved CLI token becomes invalid.
Related Topics
- Architecture
- Projects
- Resources
- CLI Reference
- Troubleshooting
Architecture
Overview
Mock API Studio has two main parts:
- Cloud Dashboard: stores project configuration and account state.
- Local Runtime: runs the mock backend locally from synced project configuration.
The runtime is the server your frontend talks to during development. It is started by the npm package and runs on your own machine.
Why it exists
Mock APIs are most useful when they behave like a real backend but remain easy to control. Keeping configuration in the dashboard makes projects easier to manage. Running the backend locally keeps development fast, private, and independent from cloud uptime.
How it works
The workflow is:
- You define resources, schemas, relationships, authentication, and runtime settings in a project.
- You generate an API token for the CLI.
- The CLI syncs the project configuration from the cloud dashboard.
- The runtime parses TypeScript response schemas.
- The runtime generates mock data and starts a local Express server.
- Your frontend, API client, or test suite sends requests to that local server.
The runtime also keeps local SQLite state for synced projects, so mutations can persist across local server restarts until the schema or endpoint settings change.
Example
Project: Customer Portal
Resources:
/users
/orders
/products
Runtime:
Generated data
CRUD routes
Query behavior
Optional auth simulation
Swagger docsBest Practices
- Treat the dashboard as configuration, not as the live API.
- Treat the local runtime as the backend your frontend consumes.
- Keep project settings close to the behavior your real backend will eventually expose.
- Use deterministic seeds when you need repeatable demo or test data.
Projects
Overview
A project is the top-level container for a mock backend. It groups resources, shared types, query configuration, authentication simulation, relationship definitions, and runtime behavior.
Create a separate project for each API surface you want to run independently.
Why it exists
Most products have more than one backend shape over time: an admin API, a storefront API, a mobile API, or an integration API. Projects keep those configurations separate so each local runtime can start with the correct routes and settings.
How it works
Each project has:
- A name and generated slug.
- Optional description.
- Local mock port.
- Shared TypeScript declarations.
- Resources and response schemas.
- Query parameter configuration.
- Authentication simulation settings.
- Mock server runtime settings.
- Relationship definitions.
The project slug identifies which project the CLI should sync.
Usage
Use a project to model one local backend. Add resources for each endpoint group, configure runtime behavior, generate a token, and start the project through the CLI.
Best Practices
- Keep one project focused on one API surface.
- Use the project description to explain what frontend or workflow the mock backend supports.
- Choose a local port that does not conflict with your frontend dev server.
- Keep shared types in the project when multiple resources reference the same entity.
Resources
Overview
A resource is a mock endpoint group. It combines a route path, enabled HTTP operations, a TypeScript response schema, optional endpoint settings, and optional sortable fields.
Resources can model collections such as users, products, orders, invoices, or bookings. They can also model a single object such as a profile or account summary.
Why it exists
Frontend applications usually need realistic endpoint behavior before backend endpoints are ready. Resources let you define that behavior from TypeScript types instead of writing a custom mock server by hand.
How it works
A collection resource exposes collection and item operations:
GET /orders
GET /orders/{id}
POST /orders
PUT /orders/{id}
PATCH /orders/{id}
DELETE /orders/{id}A single-object resource exposes root operations only:
GET /profile
POST /profile
PUT /profile
PATCH /profile
DELETE /profileOnly enabled operations are available. Disabled operations return an error from the local runtime.
Usage
Define the endpoint response with the required MockApiStudioResponse type alias. This alias is mandatory: it binds the resource path to the actual response data shape that the local runtime parses and serves.
The interface definition itself is optional in the endpoint response editor. If the interface already exists in project Shared Types, the endpoint response editor only needs the MockApiStudioResponse alias that references it.
Collection example:
interface Order {
id: string;
status: "draft" | "paid" | "shipped";
total: number;
customerEmail: string;
}
type MockApiStudioResponse = Order[];Single-object example:
interface Profile {
id: string;
displayName: string;
email: string;
}
type MockApiStudioResponse = Profile;Array syntax is also supported:
type MockApiStudioResponse = Array<Order>;Shared-types-only endpoint example:
type MockApiStudioResponse = Order[];In that example, Order must be declared in Shared Types. The endpoint editor still needs MockApiStudioResponse because that is the binding the runtime reads.
Best Practices
- Use plural resource paths for collections, such as
/orders. - Use single-object resources only for root objects such as
/profile. - Keep top-level
idfields as strings when you want stable item routes. - Enable only the operations your real API is expected to support.
- Configure sortable fields only for primitive top-level fields.
Related Topics
- Schema Authoring
- Data Generation
- Query Behavior
- Relationships
Schema Authoring
Overview
Mock API Studio parses TypeScript source and uses it to generate mock records. The required root response alias, MockApiStudioResponse, tells the runtime whether a resource returns a collection or a single object.
How it works
The runtime combines project shared types with a resource schema, parses the resulting TypeScript declarations, infers field types, applies semantic hints, and generates data.
Every endpoint response schema must include:
type MockApiStudioResponse = SomeType;or:
type MockApiStudioResponse = SomeType[];SomeType can be declared directly in the endpoint response editor or in Shared Types.
Supported schema shapes include:
stringnumberboolean- Optional fields
- String literal unions
- Enums
- Arrays
- Nested object literals
- Referenced interfaces
- Referenced type aliases
- Referenced enums
Example
enum Plan {
Free = "free",
Pro = "pro"
}
interface Subscription {
id: string;
customerEmail: string;
plan: Plan;
active: boolean;
renewalDate?: string;
}
type MockApiStudioResponse = Subscription[];Best Practices
- Keep resource schemas focused on response shape.
- Prefer explicit names such as
customerEmail,createdAt, andpriceso semantic data generation can infer realistic values. - Use shared types when multiple resources reuse the same entity.
- Avoid deeply nested response structures when the real API is flat.
Shared Types
Overview
Shared types are TypeScript declarations available to every resource in a project. They help keep schemas consistent when multiple resources reuse the same entities.
Why it exists
Without shared types, each resource has to redefine common shapes such as customers, addresses, money values, and order items. Shared types keep those definitions in one place.
How it works
Shared declarations are combined with each resource schema before parsing. A resource can reference any supported interface, enum, or type alias from the project Shared Types.
Shared Types do not replace MockApiStudioResponse. The endpoint response editor must still include type MockApiStudioResponse = ... so the runtime knows which shared type is the response root for that endpoint.
Example
export interface Address {
id: string;
street: string;
city: string;
country: string;
postalCode: string;
}
export interface Customer {
id: string;
name: string;
email: string;
address: Address;
}A resource can then use the shared entity:
type MockApiStudioResponse = Customer[];The Customer interface does not need to be repeated in the endpoint response editor when it already exists in Shared Types.
Best Practices
- Put common domain entities in shared types.
- Keep endpoint-specific response wrappers inside the resource schema.
- Update shared types carefully because multiple resources may depend on them.
Data Generation
Overview
The local runtime generates mock records from TypeScript schemas. Generated values use field types, field names, semantic hints, and optional runtime settings.
Why it exists
Useful mock APIs need realistic data. A list of orders should contain statuses, totals, dates, and customer emails that look plausible enough for frontend development, demos, and integration tests.
How it works
For each collection resource, the runtime generates a configurable number of records. For single-object resources, it generates one object.
Generated data supports common semantic field names:
- Email.
- Full name.
- First name.
- Last name.
- Phone.
- Address.
- City.
- Country.
- URL.
- UUID.
- Date.
- Datetime.
- Price.
- Percentage.
- Paragraph.
- Sentence.
Supported explicit Faker mapping families include:
commerce.pricecommerce.productNamedatatype.booleandate.birthdatedate.recentinternet.emailinternet.ipv4internet.urlinternet.userNamelocation.citylocation.countrylocation.streetAddresslorem.paragraphlorem.sentencelorem.wordsnumber.floatnumber.intperson.firstNameperson.fullNameperson.lastNamephone.numberstring.uuid
Example
interface Product {
id: string;
name: string;
price: number;
category: "laptops" | "phones" | "accessories";
inStock: boolean;
}
type MockApiStudioResponse = Product[];This schema can generate product-like names, numeric prices, enum categories, and boolean inventory states.
Best Practices
- Use meaningful field names for better generated values.
- Set a seed when you need stable records between runs.
- Override endpoint record count when one resource needs more or fewer records than the project default.
- Regenerate local data after meaningful schema or endpoint-setting changes.
Relationships
Overview
Relationships connect two flat resources without nesting child data inside parent records.
A common example is customers and orders:
/customers
/orders
/customers/{customerId}/ordersThe customer and order records remain in separate collections. The relationship tells the runtime how to connect them.
Why it exists
Real APIs often expose nested resources. A frontend may need all orders for a customer, all products for a company, or all items for an order. Relationships let the runtime model these flows without duplicating datasets.
How it works
A relationship stores:
- Parent resource, such as
/customers. - Child resource, such as
/orders. - Relationship type: one-to-one, one-to-many, or many-to-one.
- Parent key, usually
id. - Child foreign key, such as
customerId.
Child records stay flat:
{
"id": "order_001",
"customerId": "customer_001",
"status": "paid",
"total": 149
}When the runtime receives a nested request, it validates the parent and filters the child collection.
GET /customers/{customerId}/ordersThe runtime:
- Checks that the parent customer exists.
- Returns
404if the parent is missing. - Lists order records.
- Returns only orders where
order.customerIdmatches the{customerId}path value.
Generated relational data preserves referential integrity. Parent records are generated first, their keys are collected, and child foreign keys are assigned from real parent values.
Delete behavior
Relationship deletes are restricted. If a parent record still has child records that reference it, the runtime returns 409 Conflict instead of deleting the parent and leaving orphaned children.
DELETE /customers/{customerId}If orders still reference that customer, the response is:
{
"error": "Cannot delete record because related records in /orders still reference it."
}Best Practices
- Use relationships for ownership or belonging, such as customer orders or company employees.
- Keep foreign keys as top-level primitive fields.
- Use clear foreign key names such as
customerId,companyId, ororderId. - Prefer relationships over physically nested arrays when the real API exposes separate resources.
Query Behavior
Overview
The runtime can apply pagination, search, and sorting to collection responses. Query behavior can be configured at the project level, and endpoint settings can override some resource-specific behavior.
Pagination
When pagination is enabled, collection responses include data and meta.
{
"data": [],
"meta": {
"hasNextPage": false,
"hasPrevPage": false,
"limit": 25,
"page": 1,
"total": 0,
"totalPages": 0
}
}Pagination parameter names can be configured. The default shape is:
page=1
limit=25When endpoint pagination is disabled, a collection response returns only data.
{
"data": []
}Search
Search matches record values, including nested values. It does not intentionally match object keys.
GET /products?search=laptopSorting
Sorting is allowed only for configured sortable fields.
GET /products?sortBy=name&order=asc
GET /products?sortBy=name&order=descIf a request sorts by a field that is not configured, the runtime returns 400.
Best Practices
- Configure query names to match the API your frontend expects.
- Keep sortable fields primitive and top-level.
- Disable pagination for resources that should always return full collections.
Authentication Simulation
Overview
Authentication simulation lets the local runtime protect mock resources while keeping auth routes public.
Supported auth modes are:
- Bearer token.
- API key.
- Basic auth.
Why it exists
Frontend applications often need to test protected routes, login flows, authorization headers, and unauthorized states before backend auth is complete.
Bearer token auth
Bearer auth can expose configurable register, login, and logout routes. A login route accepts credentials and returns a token with a mock user.
Example login request:
{
"email": "demo@example.com",
"password": "password123"
}Example response:
{
"token": "local_mock_token",
"user": {
"id": "user_001",
"email": "demo@example.com"
}
}Use the token on protected resource requests:
Authorization: Bearer local_mock_tokenIf credential validation is enabled, login succeeds only for registered mock users with matching passwords. If validation is disabled, login can create a mock user automatically.
API key auth
API key auth can read a key from either a header or a query parameter. If an expected value is configured, the provided key must match it. If no expected value is configured, key presence is enough.
Basic auth
Basic auth validates the standard Authorization: Basic ... header. If username or password values are configured, incoming credentials must match them.
Swagger usage
Generated Swagger docs include auth configuration for protected resources. For bearer auth, call the configured login or register route, copy the returned token, authorize in Swagger, and then try protected resource routes.
Best Practices
- Use bearer auth when your real app expects JWT-style authorization.
- Use API keys for server-to-server or integration-style APIs.
- Use Basic auth only when your real API needs that behavior.
- Keep mock auth settings aligned with your frontend auth assumptions.
Runtime Settings
Overview
Runtime settings control how the local mock backend behaves after sync.
Settings include:
- Default generated record count.
- Latency simulation.
- Error-rate simulation.
- Seed for deterministic generated data.
- Local mock port.
Latency
Latency adds a fixed response delay to local runtime requests. Use it to test loading states and slow network behavior.
Error rate
Error rate injects probabilistic failures into local responses. When an injected failure occurs, the runtime returns:
{
"error": "Injected mock failure."
}The response status is 503.
Seed
Seed makes generated data deterministic. Use the same seed to regenerate predictable records.
Best Practices
- Use latency to verify loading and skeleton states.
- Use error rate to test retry and error UI.
- Use a seed for demos, screenshots, and repeatable tests.
- Use a different port when another local service is already running.
Local Runtime
Overview
The local runtime is an Express server started by the CLI. It turns synced project configuration into a working mock backend.
It includes:
- Generated data from TypeScript schemas.
- CRUD resource routes.
- Nested relationship routes.
- Optional auth simulation.
- Query behavior.
- Latency and error simulation.
- SQLite persistence.
- Swagger UI.
- OpenAPI JSON.
- Runtime control routes.
Documentation routes
Every local runtime exposes Swagger UI and OpenAPI JSON:
GET /docs
GET /openapi.jsonSwagger uses the project name as the API title:
Customer Portal (by Mock API Studio)Runtime controls
Runtime control routes live under /_mock.
List registered resources:
GET /_mock/resourcesReset generated mock data:
POST /_mock/resetUpdate runtime config:
PUT /_mock/configSupported runtime config patch fields:
{
"errorRate": 0,
"latencyMs": 0,
"recordCountPerResource": 20,
"seed": 123
}Generate a runtime resource from posted interface source:
POST /_mock/generateExample body:
{
"interfaceSource": "interface Product { id: string; name: string; }",
"options": {
"recordCountPerResource": 10
}
}Best Practices
- Restart the runtime after changing schema, endpoint settings, relationships, or auth behavior.
- Reset local data when schema changes should replace old records.
- Use Swagger for quick manual testing.
- Use OpenAPI JSON when you need machine-readable API metadata.
CLI Reference
Overview
The CLI syncs project configuration and starts the local runtime.
The npm package name is:
mock-api-studio-cliThe executable command is:
mock-api-studioInteractive mode
Run the CLI without a project slug:
npx mock-api-studio-cliInteractive mode can:
- Prompt for an API token on first run.
- Save the token locally.
- Validate the token.
- List available projects.
- Start the selected project.
Start a project
Start a project by slug:
npx mock-api-studio-cli start customer-portalThe shorthand form is also supported:
npx mock-api-studio-cli customer-portalOverride the project port:
npx mock-api-studio-cli start customer-portal --port 4500Pass a token for one command:
npx mock-api-studio-cli start customer-portal --token your_token_hereToken resolution
For direct startup, the CLI resolves tokens in this order:
--token- Local config
MOCK_API_TOKEN
The saved local config file is:
~/.mock-api-studio/config.jsonFor tests or custom setups, change the config directory with:
MOCK_API_STUDIO_CONFIG_DIR=/custom/pathBackend URL
The CLI reads the dashboard backend base URL from:
MOCK_API_BASE_URLAccount commands
Show the account associated with the saved token:
npx mock-api-studio-cli whoamiRemove the saved token:
npx mock-api-studio-cli logoutBest Practices
- Use interactive mode the first time you connect a machine.
- Use
--tokenin temporary environments where you do not want to save credentials. - Use environment variables in scripts and CI-like workflows.
Complete Example
Goal
Build a local mock backend for a commerce frontend with customers and orders.
Project model
Resources:
/customers
/ordersRelationship:
Parent: /customers
Child: /orders
Parent key: id
Child foreign key: customerId
Type: one-to-manyShared type
export interface Money {
amount: number;
currency: "USD" | "EUR" | "GBP";
}Customer resource
interface Customer {
id: string;
name: string;
email: string;
active: boolean;
}
type MockApiStudioResponse = Customer[];Order resource
interface Order {
id: string;
customerId: string;
status: "draft" | "paid" | "shipped";
total: Money;
createdAt: string;
}
type MockApiStudioResponse = Order[];Runtime behavior
The runtime can serve:
GET /customers
GET /customers/{id}
GET /orders
GET /orders/{id}
GET /customers/{customerId}/ordersGenerated orders will reference real generated customers. Deleting a customer with existing orders returns 409 Conflict.
Start the runtime
npx mock-api-studio-cli start commerce-demoFAQ
Is the cloud dashboard the mock server?
No. The dashboard stores configuration. The mock backend runs locally through the npm runtime.
Can existing projects work without relationships?
Yes. Relationships are optional. Projects without relationships keep independent resource behavior.
Does the runtime generate nested objects for relationships?
No. Relationship data stays flat. Child records use foreign keys such as customerId.
Does deleting a parent delete child records?
No. The first relationship implementation uses restrict behavior. Parent deletes are blocked when child records still reference the parent.
Can I customize query parameter names?
Yes. Pagination, search, sort field, sort direction, and direction values can be configured at the project level.
Can I test protected routes locally?
Yes. The runtime supports bearer token, API key, and Basic auth simulation.
Troubleshooting
Invalid or expired API token
Generate a new API token, then either log out of the CLI or pass the token directly.
npx mock-api-studio-cli logout
npx mock-api-studio-cliOr:
npx mock-api-studio-cli start customer-portal --token your_token_herePort is already in use
Start the runtime on another port:
npx mock-api-studio-cli start customer-portal --port 4500You can also update the project local mock port.
Project has no resources
Add at least one resource before starting the runtime. A project without resources has no routes to serve.
Invalid schema
Check that the resource schema:
- Contains supported TypeScript declarations.
- References only known local or shared types.
- Includes the required
type MockApiStudioResponse = ...alias. - Uses
MockApiStudioResponseto reference either a local interface or an interface from Shared Types. - Uses a collection response for collection endpoints or a single response for single-object endpoints.
Endpoint settings appear stale locally
Restart the local runtime after changing endpoint settings. If the CLI prompts to reset and regenerate local data, choose reset when the old records should be replaced.
Non-interactive CLI runs regenerate automatically when schemas or endpoint settings change.
Search returns unexpected records
Search matches stringified record values, including nested values. A result may match a nested field value even if the top-level field you are viewing does not visibly contain the term.
Sorting returns a 400 error
The requested sort field is not configured as sortable for that endpoint. Configure sorting only for valid primitive top-level fields.
Nested route returns 404
Confirm that:
- The parent record exists.
- The relationship uses the correct parent resource.
- The relationship uses the correct child resource.
- The child foreign key matches the parent key value.
Parent delete returns 409
The parent still has child records that reference it. Delete or update the child records first, then retry the parent delete.
Swagger protected routes return unauthorized
For bearer auth, call the configured login or register route, copy the returned token, authorize in Swagger, and retry the protected route.
For API key or Basic auth, provide the configured key or credentials.