Back to landing

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.

text
Cloud Dashboard
  -> Project configuration
  -> API token
  -> Local runtime
  -> Running mock backend

Use 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:

  1. Create an account.
  2. Create a project.
  3. Add at least one resource.
  4. Generate an API token.
  5. Start the local runtime with the CLI.
  6. Send requests to the local mock backend.

Example

Create a resource for users with a collection response:

TypeScriptschema
interface User {
  id: string;
  name: string;
  email: string;
  active: boolean;
}

type MockApiStudioResponse = User[];

Start the local runtime for your project:

bash
npx mock-api-studio-cli start customer-portal

The runtime starts an Express server on your machine. You can then call generated routes such as:

http
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, and bookings.
  • Add shared types when multiple resources use the same entities.
  • Generate a new API token if a saved CLI token becomes invalid.
  • 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:

  1. You define resources, schemas, relationships, authentication, and runtime settings in a project.
  2. You generate an API token for the CLI.
  3. The CLI syncs the project configuration from the cloud dashboard.
  4. The runtime parses TypeScript response schemas.
  5. The runtime generates mock data and starts a local Express server.
  6. 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

text
Project: Customer Portal

Resources:
  /users
  /orders
  /products

Runtime:
  Generated data
  CRUD routes
  Query behavior
  Optional auth simulation
  Swagger docs

Best 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:

http
GET    /orders
GET    /orders/{id}
POST   /orders
PUT    /orders/{id}
PATCH  /orders/{id}
DELETE /orders/{id}

A single-object resource exposes root operations only:

http
GET    /profile
POST   /profile
PUT    /profile
PATCH  /profile
DELETE /profile

Only 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:

TypeScriptschema
interface Order {
  id: string;
  status: "draft" | "paid" | "shipped";
  total: number;
  customerEmail: string;
}

type MockApiStudioResponse = Order[];

Single-object example:

TypeScriptschema
interface Profile {
  id: string;
  displayName: string;
  email: string;
}

type MockApiStudioResponse = Profile;

Array syntax is also supported:

TypeScriptschema
type MockApiStudioResponse = Array<Order>;

Shared-types-only endpoint example:

TypeScriptschema
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 id fields 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.
  • 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:

TypeScriptschema
type MockApiStudioResponse = SomeType;

or:

TypeScriptschema
type MockApiStudioResponse = SomeType[];

SomeType can be declared directly in the endpoint response editor or in Shared Types.

Supported schema shapes include:

  • string
  • number
  • boolean
  • Optional fields
  • String literal unions
  • Enums
  • Arrays
  • Nested object literals
  • Referenced interfaces
  • Referenced type aliases
  • Referenced enums

Example

TypeScriptschema
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, and price so 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

TypeScriptschema
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:

TypeScriptschema
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.price
  • commerce.productName
  • datatype.boolean
  • date.birthdate
  • date.recent
  • internet.email
  • internet.ipv4
  • internet.url
  • internet.userName
  • location.city
  • location.country
  • location.streetAddress
  • lorem.paragraph
  • lorem.sentence
  • lorem.words
  • number.float
  • number.int
  • person.firstName
  • person.fullName
  • person.lastName
  • phone.number
  • string.uuid

Example

TypeScriptschema
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:

text
/customers
/orders
/customers/{customerId}/orders

The 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:

json
{
  "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.

http
GET /customers/{customerId}/orders

The runtime:

  1. Checks that the parent customer exists.
  2. Returns 404 if the parent is missing.
  3. Lists order records.
  4. Returns only orders where order.customerId matches 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.

http
DELETE /customers/{customerId}

If orders still reference that customer, the response is:

json
{
  "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, or orderId.
  • 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.

json
{
  "data": [],
  "meta": {
    "hasNextPage": false,
    "hasPrevPage": false,
    "limit": 25,
    "page": 1,
    "total": 0,
    "totalPages": 0
  }
}

Pagination parameter names can be configured. The default shape is:

text
page=1
limit=25

When endpoint pagination is disabled, a collection response returns only data.

json
{
  "data": []
}

Search matches record values, including nested values. It does not intentionally match object keys.

http
GET /products?search=laptop

Sorting

Sorting is allowed only for configured sortable fields.

http
GET /products?sortBy=name&order=asc
GET /products?sortBy=name&order=desc

If 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:

json
{
  "email": "demo@example.com",
  "password": "password123"
}

Example response:

json
{
  "token": "local_mock_token",
  "user": {
    "id": "user_001",
    "email": "demo@example.com"
  }
}

Use the token on protected resource requests:

http
Authorization: Bearer local_mock_token

If 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:

json
{
  "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:

http
GET /docs
GET /openapi.json

Swagger uses the project name as the API title:

text
Customer Portal (by Mock API Studio)

Runtime controls

Runtime control routes live under /_mock.

List registered resources:

http
GET /_mock/resources

Reset generated mock data:

http
POST /_mock/reset

Update runtime config:

http
PUT /_mock/config

Supported runtime config patch fields:

json
{
  "errorRate": 0,
  "latencyMs": 0,
  "recordCountPerResource": 20,
  "seed": 123
}

Generate a runtime resource from posted interface source:

http
POST /_mock/generate

Example body:

json
{
  "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:

text
mock-api-studio-cli

The executable command is:

text
mock-api-studio

Interactive mode

Run the CLI without a project slug:

bash
npx mock-api-studio-cli

Interactive 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:

bash
npx mock-api-studio-cli start customer-portal

The shorthand form is also supported:

bash
npx mock-api-studio-cli customer-portal

Override the project port:

bash
npx mock-api-studio-cli start customer-portal --port 4500

Pass a token for one command:

bash
npx mock-api-studio-cli start customer-portal --token your_token_here

Token resolution

For direct startup, the CLI resolves tokens in this order:

  1. --token
  2. Local config
  3. MOCK_API_TOKEN

The saved local config file is:

text
~/.mock-api-studio/config.json

For tests or custom setups, change the config directory with:

bash
MOCK_API_STUDIO_CONFIG_DIR=/custom/path

Backend URL

The CLI reads the dashboard backend base URL from:

bash
MOCK_API_BASE_URL

Account commands

Show the account associated with the saved token:

bash
npx mock-api-studio-cli whoami

Remove the saved token:

bash
npx mock-api-studio-cli logout

Best Practices

  • Use interactive mode the first time you connect a machine.
  • Use --token in 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:

text
/customers
/orders

Relationship:

text
Parent: /customers
Child: /orders
Parent key: id
Child foreign key: customerId
Type: one-to-many

Shared type

TypeScriptschema
export interface Money {
  amount: number;
  currency: "USD" | "EUR" | "GBP";
}

Customer resource

TypeScriptschema
interface Customer {
  id: string;
  name: string;
  email: string;
  active: boolean;
}

type MockApiStudioResponse = Customer[];

Order resource

TypeScriptschema
interface Order {
  id: string;
  customerId: string;
  status: "draft" | "paid" | "shipped";
  total: Money;
  createdAt: string;
}

type MockApiStudioResponse = Order[];

Runtime behavior

The runtime can serve:

http
GET /customers
GET /customers/{id}
GET /orders
GET /orders/{id}
GET /customers/{customerId}/orders

Generated orders will reference real generated customers. Deleting a customer with existing orders returns 409 Conflict.

Start the runtime

bash
npx mock-api-studio-cli start commerce-demo

FAQ

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.

bash
npx mock-api-studio-cli logout
npx mock-api-studio-cli

Or:

bash
npx mock-api-studio-cli start customer-portal --token your_token_here

Port is already in use

Start the runtime on another port:

bash
npx mock-api-studio-cli start customer-portal --port 4500

You 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 MockApiStudioResponse to 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.