A comprehensive fake REST API service for developers to test against, built with Node.js, Express, TypeScript, and PostgreSQL. Features include rate limiting, validation, realistic data, and advanced filtering capabilities.
Live Demo: https://apimocker.com
You can test it out with my API probe tool - https://apiprobe.dev
- Hosted Base URL: https://apimocker.com
- All responses are JSON and support pagination, filtering, and sorting.
- Users
- GET
https://apimocker.com/users - GET
https://apimocker.com/users/1 - GET
https://apimocker.com/users/1/posts - GET
https://apimocker.com/users/1/todos - GET
https://apimocker.com/users/search?q=john
- GET
- Posts
- GET
https://apimocker.com/posts - GET
https://apimocker.com/posts/1 - GET
https://apimocker.com/posts?userId=1&_page=1&_limit=10 - GET
https://apimocker.com/posts/search?q=development&_sort=id&_order=desc&_page=1&_limit=5
- GET
- Todos
- GET
https://apimocker.com/todos - GET
https://apimocker.com/todos/1 - GET
https://apimocker.com/todos?completed=true&_page=1&_limit=10 - GET
https://apimocker.com/todos/search?q=review
- GET
- Comments
- GET
https://apimocker.com/comments - GET
https://apimocker.com/comments/1 - GET
https://apimocker.com/comments?postId=1&_page=1&_limit=5 - GET
https://apimocker.com/comments/search?q=great
- GET
- Pagination:
_page,_limit - Sorting:
_sort,_order(e.g.,_sort=title&_order=asc) - Text search:
field_like(e.g.,title_like=web) - Response delay (simulate latency):
_delay=2000
- GET
https://apimocker.com/health
- Full CRUD Operations - Create, Read, Update, Delete for all resources
- PATCH Method Support - Partial updates for posts and todos
- Advanced Filtering -
_like,_sort,_orderparameters withX-Total-Countheaders - Global Search - Search across all resources with type filtering
- Response Delay Simulation -
_delayparameter for testing loading states - Error Simulation - Dedicated endpoints for testing error handling
- Realistic Data - 10 users, 100 posts, 200 todos, 500 comments with realistic content
- Rate Limiting - Configurable limits to prevent abuse
- Input Validation - Comprehensive validation for all endpoints
- Pagination - Built-in pagination support with
_pageand_limit - Daily Reset - Automatic database reset at midnight UTC
- Comprehensive Logging - Request/response logging with Winston
- TypeScript - Full type safety throughout the application
- Prisma ORM - Type-safe database operations
- Neon PostgreSQL - Cloud-hosted database
- Backend: Node.js, Express.js
- Language: TypeScript
- Database: PostgreSQL (Neon)
- ORM: Prisma
- Validation: express-validator
- Rate Limiting: express-rate-limit
- Logging: Winston
- Security: Helmet, CORS
- Scheduling: node-cron
- Node.js 18+
- npm or yarn
- Neon PostgreSQL database
-
Clone the repository
git clone <repository-url> cd apimocker
-
Install dependencies
npm install
-
Set up environment variables Create a
.envfile in the root directory:# Database DATABASE_URL="postgresql://username:password@host/database?sslmode=require" # Server PORT=8000 NODE_ENV=development # Rate Limiting RATE_LIMIT_WINDOW_MS=86400000 # 24 hours RATE_LIMIT_MAX_WRITES=100 # 100 writes per day per IP # Logging LOG_LEVEL=info
-
Generate Prisma client
npm run db:generate
-
Push database schema
npm run db:push
-
Seed the database
npm run db:seed
-
Start the server
npm run dev
The API will be available at http://localhost:8000
http://localhost:8000
http://localhost:8000/
A beautiful web interface with API documentation and quick testing links.
http://localhost:8000/api
Search across all resources with the global search endpoint:
GET /search?q=development&type=postsParameters:
q(required): Search querytype(optional): Resource type (users, posts, todos, comments, all)_delay(optional): Response delay in milliseconds
Test loading states by adding delays to any request:
GET /posts?_delay=2000Test error handling with dedicated error endpoints:
GET /error/404
GET /error/500
GET /error/validation
GET /error/timeoutGET /healthResponse:
{
"status": "OK",
"timestamp": "2024-01-15T10:30:00.000Z",
"uptime": 3600
}GET /usersQuery Parameters:
_page(optional): Page number (default: 1)_limit(optional): Items per page (default: 10, max: 100)
Example:
GET /users?_page=1&_limit=5Response:
{
"data": [
{
"id": 1,
"name": "John Doe",
"username": "johndoe",
"email": "[email protected]",
"phone": "+1-555-0123",
"website": "https://johndoe.dev",
"address": {
"street": "123 Main St",
"suite": "Apt 4B",
"city": "New York",
"zipcode": "10001",
"geo": { "lat": "40.7128", "lng": "-74.0060" }
},
"company": {
"name": "Tech Solutions Inc",
"catchPhrase": "Innovating the future",
"bs": "harness real-time e-markets"
},
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 5,
"total": 10,
"totalPages": 2,
"hasNext": true,
"hasPrev": false
}
}GET /users/:idExample:
GET /users/1POST /users
Content-Type: application/jsonRequest Body:
{
"name": "New User",
"username": "newuser",
"email": "[email protected]",
"phone": "+1-555-0123",
"website": "https://newuser.com",
"address": {
"street": "123 Main St",
"suite": "Apt 4B",
"city": "New York",
"zipcode": "10001",
"geo": { "lat": "40.7128", "lng": "-74.0060" }
},
"company": {
"name": "Company Name",
"catchPhrase": "Company catchphrase",
"bs": "Company business statement"
}
}PUT /users/:id
Content-Type: application/jsonExample:
PUT /users/1
{
"name": "Updated Name"
}DELETE /users/:idExample:
DELETE /users/1GET /users/:id/postsQuery Parameters:
_page(optional): Page number (default: 1)_limit(optional): Items per page (default: 10)
Example:
GET /users/1/posts?_page=1&_limit=5GET /users/:id/todosQuery Parameters:
_page(optional): Page number (default: 1)_limit(optional): Items per page (default: 10)
Example:
GET /users/1/todos?_page=1&_limit=5GET /postsQuery Parameters:
_page(optional): Page number (default: 1)_limit(optional): Items per page (default: 10)userId(optional): Filter by user ID
Example:
GET /posts?userId=1&_page=1&_limit=5Response:
{
"data": [
{
"id": 1,
"title": "Getting Started with Modern Web Development",
"body": "This is a comprehensive article about getting started with modern web development...",
"userId": 1,
"user": {
"id": 1,
"name": "John Doe",
"username": "johndoe",
"email": "[email protected]"
},
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 5,
"total": 100,
"totalPages": 20,
"hasNext": true,
"hasPrev": false
}
}GET /posts/:idPOST /posts
Content-Type: application/jsonRequest Body:
{
"title": "New Post Title",
"body": "This is the content of the new post..."
}Note: userId is optional and defaults to user ID 1 if not provided.
PUT /posts/:id
Content-Type: application/jsonDELETE /posts/:idGET /todosQuery Parameters:
_page(optional): Page number (default: 1)_limit(optional): Items per page (default: 10)userId(optional): Filter by user IDcompleted(optional): Filter by completion status (true/false)
Example:
GET /todos?completed=true&userId=1&_page=1&_limit=5Response:
{
"data": [
{
"id": 1,
"title": "Review pull requests",
"completed": true,
"userId": 1,
"user": {
"id": 1,
"name": "John Doe",
"username": "johndoe",
"email": "[email protected]"
},
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 5,
"total": 200,
"totalPages": 40,
"hasNext": true,
"hasPrev": false
}
}GET /todos/:idPOST /todos
Content-Type: application/jsonRequest Body:
{
"title": "New Todo Item",
"description": "Optional description for the todo item",
"completed": false
}Note: userId and description are optional. userId defaults to user ID 1 if not provided.
PUT /todos/:id
Content-Type: application/jsonDELETE /todos/:idGET /commentsQuery Parameters:
_page(optional): Page number (default: 1)_limit(optional): Items per page (default: 10)postId(optional): Filter by post IDname_like(optional): Search by commenter nameemail_like(optional): Search by email
Example:
GET /comments?postId=1&_page=1&_limit=5Response:
{
"data": [
{
"id": 1,
"name": "John Doe",
"email": "[email protected]",
"body": "Great article! This really helped me understand the concepts better.",
"postId": 1,
"post": {
"id": 1,
"title": "Getting Started with Modern Web Development"
},
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 5,
"total": 500,
"totalPages": 100,
"hasNext": true,
"hasPrev": false
}
}GET /comments/:idPOST /comments
Content-Type: application/jsonRequest Body:
{
"name": "Commenter Name",
"email": "[email protected]",
"body": "This is a comment on the post",
"postId": 1
}PUT /comments/:id
Content-Type: application/jsonDELETE /comments/:idApiMocker supports powerful filtering, sorting, and querying capabilities:
_pageorpage: Page number (default: 1)_limitorlimit: Items per page (default: 10, max: 100)
_sort: Field to sort by (e.g.,title,id,createdAt)_order: Sort order (ascordesc)
field_like: Partial text matching (case-insensitive)title_like=web- Search posts with "web" in titlename_like=john- Search users with "john" in namebody_like=development- Search posts with "development" in body
X-Total-Count: Total number of items (for pagination)
Basic pagination:
GET /posts?_page=2&_limit=5Sorting:
GET /posts?_sort=title&_order=ascText search:
GET /posts?title_like=developmentCombined filtering:
GET /todos?completed=true&userId=1&_sort=title&_order=desc&_page=1&_limit=10With delay simulation:
GET /posts?title_like=web&_delay=2000ApiMocker implements a sophisticated rate limiting system to prevent abuse while allowing legitimate usage:
- Limit: 100 write operations per day per IP address
- Window: 24 hours (configurable via
RATE_LIMIT_WINDOW_MS) - Reset: Daily at midnight UTC
- Limit: 1000 requests per 15 minutes per IP address
- Window: 15 minutes
- Reset: Automatically after the time window
When rate limits are exceeded, the API returns:
{
"error": "Too Many Requests",
"message": "Write limit exceeded. Maximum 100 write operations per day per IP.",
"resetTime": "2024-01-16T00:00:00.000Z"
}HTTP Status: 429 Too Many Requests
The API includes rate limit information in response headers:
X-RateLimit-Limit: Maximum requests allowedX-RateLimit-Remaining: Remaining requests in current windowX-RateLimit-Reset: Time when the rate limit resets
All endpoints include comprehensive input validation:
- name: Required, 1-100 characters
- username: Required, 3-50 characters, alphanumeric + underscore only
- email: Required, valid email format
- phone: Optional, valid phone number
- website: Optional, valid URL
- address: Optional, must be an object
- company: Optional, must be an object
- title: Required, 1-200 characters
- body: Required, 1-5000 characters
- userId: Optional, positive integer (defaults to user ID 1 if not provided)
- title: Required, 1-200 characters
- description: Optional, 1-1000 characters
- completed: Optional, boolean value
- userId: Optional, positive integer (defaults to user ID 1 if not provided)
{
"error": "Validation Error",
"message": "Invalid input data",
"details": [
{
"type": "field",
"value": "",
"msg": "Name is required and must be between 1 and 100 characters",
"path": "name",
"location": "body"
}
]
}The database automatically resets at midnight UTC every day:
- All existing data is cleared
- Fresh seed data is inserted
- 10 users, 100 posts, and 200 todos are created
- Reset includes realistic data with proper relationships
This ensures a consistent testing environment and prevents data accumulation.
ApiMocker uses Winston for comprehensive logging:
logs/error.log: Error-level logs onlylogs/combined.log: All logs
- Request Details: Method, URL, IP, User-Agent, timestamp
- Response Details: Status code, duration, content length
- Error Details: Stack traces, error messages
- Database Operations: Connection status, seeding events
{
"level": "info",
"message": "Request completed",
"method": "GET",
"url": "/users",
"statusCode": 200,
"duration": "45ms",
"timestamp": "2024-01-15T10:30:00.000Z",
"service": "apimocker"
}# Development
npm run dev # Start development server
npm run build # Build TypeScript
npm run start # Start production server
# Database
npm run db:generate # Generate Prisma client
npm run db:push # Push schema to database
npm run db:seed # Seed database with sample data
npm run db:reset # Reset and reseed database
npm run db:studio # Open Prisma Studio
# Testing
npm test # Run all tests
npm run test:watch # Run tests in watch mode
npm run test:coverage # Run tests with coverage
npm run test:integration # Run only integration tests
npm run test:unit # Run only unit testsapimocker/
βββ src/
β βββ controllers/
β β βββ genericController.ts # Generic CRUD controller
β βββ middleware/
β β βββ errorHandler.ts # Error handling middleware
β β βββ rateLimiter.ts # Rate limiting middleware
β β βββ requestLogger.ts # Request logging middleware
β β βββ validation.ts # Input validation middleware
β βββ routes/
β β βββ users.ts # User routes
β β βββ posts.ts # Post routes
β β βββ todos.ts # Todo routes
β βββ scripts/
β β βββ seed.ts # Database seeding
β β βββ reset.ts # Database reset
β βββ utils/
β β βββ logger.ts # Winston logger configuration
β β βββ cronJobs.ts # Daily reset scheduling
β βββ lib/
β β βββ prisma.ts # Prisma client initialization
β βββ index.ts # Main application file
βββ prisma/
β βββ schema.prisma # Database schema
βββ logs/ # Log files (auto-generated)
βββ .env # Environment variables
βββ package.json
βββ tsconfig.json
βββ README.md
| Variable | Description | Default |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | Required |
PORT |
Server port | 8000 |
NODE_ENV |
Environment (development/production) | development |
RATE_LIMIT_WINDOW_MS |
Rate limit window in milliseconds | 86400000 (24h) |
RATE_LIMIT_MAX_WRITES |
Maximum write operations per day per IP | 100 |
LOG_LEVEL |
Logging level (error, warn, info, debug) | info |
The application uses three main models:
- User: Personal information, contact details, address, company
- Post: Blog posts with title, body, and user relationship
- Todo: Task items with title, completion status, and user relationship
All models include timestamps and proper foreign key relationships.
-
Set environment variables
NODE_ENV=production DATABASE_URL=your_production_database_url
-
Build the application
npm run build
-
Start the server
npm start
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 8000
CMD ["npm", "start"]ApiMocker includes a comprehensive testing suite with both integration and unit tests.
-
Set up test environment:
# Create test database createdb apimocker_test # Set up test environment variables cp .env.example .env.test # Edit .env.test with test database URL
-
Run tests:
# Run all tests npm test # Run with coverage npm run test:coverage # Run specific test types npm run test:integration npm run test:unit
- Integration Tests: Full API endpoint testing with real database operations
- Unit Tests: Individual component testing with mocked dependencies
- Manual Testing: Example scripts for manual API testing
The test suite covers:
- β All CRUD operations for Users, Posts, and Todos
- β Pagination and filtering
- β Input validation and error handling
- β Rate limiting enforcement
- β Database relationships
- β Edge cases and boundary conditions
For detailed testing information, see tests/README.md.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
This project is licensed under the MIT License.
For issues, questions, or contributions:
- Create an issue on GitHub
- Check the documentation
- Review the API endpoints
ApiMocker - Your reliable fake API for development and testing! π―
