Monody Documentation
Generate realistic mock data from your schema definitions with AI-powered intelligence.
Quick Setup
Get started in under 2 minutes with our simple API
Smart Data
AI generates realistic data with proper relationships
Multiple Formats
Support for TypeScript, JSON Schema, and Zod models
New to Monody?
Start with our Quick Start guide to create your first mock API in minutes.
Quick Start
Get up and running with Monody in just a few steps. This guide will walk you through creating your first mock API.
Create a Session
Upload your schema file to create a new session:
curl -X POST https://api.monody.dev/sessions \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "schema=@interface.ts" \
-F "name=my-project"
Generate Mock Data
Use your session ID to generate realistic mock data:
curl "https://api.monody.dev/users?sessionId=mf_abc123xyz&count=10" \
-H "Authorization: Bearer YOUR_API_KEY"
You're Ready!
Your mock API is now ready to use. The generated data will be consistent and realistic, following the structure defined in your schema.
Installation
API Key Setup
First, you'll need to get your API key from the Monody dashboard:
- Sign up for a Monody account
- Navigate to your dashboard
- Go to API Keys section
- Generate a new API key
- Copy and store it securely
Security Note
Never expose your API key in client-side code. Always use environment variables or secure storage.
Environment Variables
Set up your environment variables:
# .env
MONODY_API_KEY=your_api_key_here
MONODY_BASE_URL=https://api.monody.dev
Authentication
Monody uses API key authentication. Include your API key in the Authorization header of all requests.
Header Format
Authorization: Bearer YOUR_API_KEY
Example Request
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://api.monody.dev/sessions
Authentication Errors
If you receive a 401 Unauthorized error, check that your API key is correct and properly formatted in the Authorization header.
Sessions API
Sessions are the foundation of Monody. A session contains your schema definition and generates consistent mock data based on your uploaded schema.
Create a new session by uploading your schema file.
Parameters
Parameter | Type | Required | Description |
---|---|---|---|
schema | file | Yes | Schema file (.ts, .json, or .js) |
name | string | Yes | Name for your session |
description | string | No | Optional description |
Response
{
"sessionId": "mf_abc123xyz",
"name": "my-project",
"status": "ready",
"createdAt": "2024-12-12T10:00:00Z",
"expiresAt": "2024-12-25T10:00:00Z",
"tokensUsed": 15,
"endpoints": [
"/users",
"/posts",
"/comments"
]
}
Retrieve information about a specific session.
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://api.monody.dev/sessions/mf_abc123xyz
Data Generation
Once you have a session, you can generate mock data for any of the entities defined in your schema.
Generate mock data for a specific endpoint.
Query Parameters
Parameter | Type | Default | Description |
---|---|---|---|
sessionId | string | - | Your session ID (required) |
count | number | 10 | Number of items to generate (1-100) |
seed | string | random | Seed for reproducible data |
locale | string | en | Locale for generated data |
Example Response
{
"data": [
{
"id": 1,
"name": "Sarah Chen",
"email": "sarah.chen@example.com",
"role": "developer",
"active": true,
"joinedAt": "2024-01-15T09:30:00Z",
"profile": {
"avatar": "https://i.pravatar.cc/150?u=1",
"bio": "Full-stack developer with 5+ years experience"
}
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 25,
"hasNext": true
},
"tokensUsed": 3
}
Schema Upload
Monody supports multiple schema formats to define your data structure. Choose the format that best fits your workflow.
TypeScript Interfaces
Upload .ts files with interface definitions
JSON Schema
Use db.json files with sample data structure
Zod Models
Upload Zod schema definitions
TypeScript Interface Example
// interface.ts
interface User {
id: number;
name: string;
email: string;
avatar?: string;
createdAt: Date;
posts: Post[];
}
interface Post {
id: number;
title: string;
content: string;
authorId: number;
author: User;
publishedAt: Date;
tags: string[];
}
JSON Schema Example
{
"users": [
{
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"avatar": "https://example.com/avatar.jpg",
"createdAt": "2024-01-01T00:00:00Z",
"posts": []
}
],
"posts": [
{
"id": 1,
"title": "Sample Post",
"content": "This is a sample post content",
"authorId": 1,
"publishedAt": "2024-01-01T00:00:00Z",
"tags": ["sample", "demo"]
}
]
}
Zod Schema Example
import { z } from 'zod';
const UserSchema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
avatar: z.string().url().optional(),
createdAt: z.date(),
posts: z.array(z.lazy(() => PostSchema))
});
const PostSchema = z.object({
id: z.number(),
title: z.string(),
content: z.string(),
authorId: z.number(),
author: UserSchema,
publishedAt: z.date(),
tags: z.array(z.string())
});
export { UserSchema, PostSchema };
Upload Tips
- • File size limit: 10MB
- • Supported formats: .ts, .json, .js
- • Use descriptive names for better AI understanding
- • Include relationships between entities
Error Handling
Monody uses standard HTTP status codes and provides detailed error messages to help you debug issues quickly.
Status Code | Meaning | Description |
---|---|---|
200 | OK | Request successful |
201 | Created | Resource created successfully |
400 | Bad Request | Invalid request parameters |
401 | Unauthorized | Invalid or missing API key |
403 | Forbidden | Insufficient permissions |
404 | Not Found | Resource not found |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Server Error | Server error occurred |
Error Response Format
All error responses follow this consistent format:
{
"error": {
"code": "INVALID_SCHEMA",
"message": "The uploaded schema contains syntax errors",
"details": {
"line": 15,
"column": 8,
"description": "Expected ';' after property declaration"
},
"timestamp": "2024-12-12T10:00:00Z",
"requestId": "req_abc123xyz"
}
}
Common Error Codes
Invalid API Key
The provided API key is invalid or has been revoked. Check your API key and ensure it's correctly formatted.
Invalid Schema
The uploaded schema file contains syntax errors or is not in a supported format.
Session Not Found
The specified session ID does not exist or has expired.
Rate Limit Exceeded
You have exceeded the rate limit. Implement exponential backoff and retry later.
Insufficient Tokens
Your account doesn't have enough tokens to complete this request. Purchase more tokens to continue.
Error Handling Best Practices
async function handleApiRequest(url, options) {
try {
const response = await fetch(url, options);
if (!response.ok) {
const error = await response.json();
switch (error.error.code) {
case 'RATE_LIMIT_EXCEEDED':
// Implement exponential backoff
await new Promise(resolve => setTimeout(resolve, 1000));
return handleApiRequest(url, options);
case 'INSUFFICIENT_TOKENS':
throw new Error('Please purchase more tokens to continue');
case 'INVALID_API_KEY':
throw new Error('Invalid API key. Please check your credentials');
default:
throw new Error(error.error.message);
}
}
return await response.json();
} catch (error) {
console.error('API request failed:', error);
throw error;
}
}
JavaScript Examples
Node.js Client
// monody-client.js
const fetch = require('node-fetch');
const FormData = require('form-data');
const fs = require('fs');
class MonodyClient {
constructor(apiKey, baseUrl = 'https://api.monody.dev') {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
}
async createSession(schemaPath, name, description) {
const formData = new FormData();
formData.append('schema', fs.createReadStream(schemaPath));
formData.append('name', name);
if (description) {
formData.append('description', description);
}
const response = await fetch(`${this.baseUrl}/sessions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
...formData.getHeaders()
},
body: formData
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Failed to create session: ${error.error.message}`);
}
return response.json();
}
async generateData(endpoint, sessionId, options = {}) {
const params = new URLSearchParams({
sessionId,
count: options.count || 10,
...(options.seed && { seed: options.seed }),
...(options.locale && { locale: options.locale })
});
const response = await fetch(
`${this.baseUrl}/${endpoint}?${params}`,
{
headers: {
'Authorization': `Bearer ${this.apiKey}`
}
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(`Failed to generate data: ${error.error.message}`);
}
const result = await response.json();
return result.data;
}
async getSession(sessionId) {
const response = await fetch(`${this.baseUrl}/sessions/${sessionId}`, {
headers: {
'Authorization': `Bearer ${this.apiKey}`
}
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Failed to get session: ${error.error.message}`);
}
return response.json();
}
}
// Usage example
async function main() {
const client = new MonodyClient(process.env.MONODY_API_KEY);
try {
// Create session
const session = await client.createSession(
'./schema/interface.ts',
'blog-api',
'Blog API mock data'
);
console.log('Session created:', session.sessionId);
// Generate data
const users = await client.generateData('users', session.sessionId, {
count: 15,
locale: 'en'
});
const posts = await client.generateData('posts', session.sessionId, {
count: 50,
seed: 'blog-posts-v1'
});
console.log(`Generated ${users.length} users and ${posts.length} posts`);
// Save to files
fs.writeFileSync('./data/users.json', JSON.stringify(users, null, 2));
fs.writeFileSync('./data/posts.json', JSON.stringify(posts, null, 2));
} catch (error) {
console.error('Error:', error.message);
}
}
main();
Browser Usage
// browser-client.js
class MonodyBrowserClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.monody.dev';
}
async createSessionFromFile(fileInput, name) {
const file = fileInput.files[0];
if (!file) {
throw new Error('No file selected');
}
const formData = new FormData();
formData.append('schema', file);
formData.append('name', name);
const response = await fetch(`${this.baseUrl}/sessions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`
},
body: formData
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error.message);
}
return response.json();
}
async generateData(endpoint, sessionId, count = 10) {
const params = new URLSearchParams({
sessionId,
count: count.toString()
});
const response = await fetch(
`${this.baseUrl}/${endpoint}?${params}`,
{
headers: {
'Authorization': `Bearer ${this.apiKey}`
}
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error.message);
}
const result = await response.json();
return result.data;
}
}
// HTML usage example
/*
<input type="file" id="schemaFile" accept=".ts,.json,.js">
<button onclick="uploadAndGenerate()">Generate Data</button>
<div id="results"></div>
<script>
const client = new MonodyBrowserClient('your-api-key');
async function uploadAndGenerate() {
try {
const fileInput = document.getElementById('schemaFile');
const session = await client.createSessionFromFile(fileInput, 'web-demo');
const users = await client.generateData('users', session.sessionId, 5);
document.getElementById('results').innerHTML =
'<pre>' + JSON.stringify(users, null, 2) + '</pre>';
} catch (error) {
console.error('Error:', error);
alert('Error: ' + error.message);
}
}
</script>
*/
Python Examples
Python Client Class
# monody_client.py
import requests
import json
from typing import Dict, List, Optional, Any
from pathlib import Path
class MonodyClient:
def __init__(self, api_key: str, base_url: str = "https://api.monody.dev"):
self.api_key = api_key
self.base_url = base_url
self.session = requests.Session()
self.session.headers.update({
'Authorization': f'Bearer {api_key}'
})
def create_session(self, schema_path: str, name: str, description: Optional[str] = None) -> Dict[str, Any]:
"""Create a new Monody session by uploading a schema file."""
with open(schema_path, 'rb') as schema_file:
files = {'schema': schema_file}
data = {'name': name}
if description:
data['description'] = description
response = self.session.post(f'{self.base_url}/sessions', files=files, data=data)
if not response.ok:
error_data = response.json()
raise Exception(f"Failed to create session: {error_data['error']['message']}")
return response.json()
def generate_data(self, endpoint: str, session_id: str, count: int = 10,
seed: Optional[str] = None, locale: str = 'en') -> List[Dict[str, Any]]:
"""Generate mock data for a specific endpoint."""
params = {
'sessionId': session_id,
'count': count,
'locale': locale
}
if seed:
params['seed'] = seed
response = self.session.get(f'{self.base_url}/{endpoint}', params=params)
if not response.ok:
error_data = response.json()
raise Exception(f"Failed to generate data: {error_data['error']['message']}")
result = response.json()
return result['data']
def get_session(self, session_id: str) -> Dict[str, Any]:
"""Get information about a specific session."""
response = self.session.get(f'{self.base_url}/sessions/{session_id}')
if not response.ok:
error_data = response.json()
raise Exception(f"Failed to get session: {error_data['error']['message']}")
return response.json()
def save_data_to_file(self, data: List[Dict[str, Any]], filename: str):
"""Save generated data to a JSON file."""
with open(filename, 'w') as f:
json.dump(data, f, indent=2, default=str)
# Usage example
def main():
import os
client = MonodyClient(os.getenv('MONODY_API_KEY'))
try:
# Create session
session = client.create_session(
schema_path='./schemas/blog_schema.ts',
name='blog-api-python',
description='Blog API for Python integration'
)
print(f"Session created: {session['sessionId']}")
# Generate different types of data
users = client.generate_data('users', session['sessionId'], count=20)
posts = client.generate_data('posts', session['sessionId'], count=100, seed='blog-v1')
comments = client.generate_data('comments', session['sessionId'], count=500)
print(f"Generated {len(users)} users, {len(posts)} posts, {len(comments)}")
# Save to files
client.save_data_to_file(users, 'users.json')
client.save_data_to_file(posts, 'posts.json')
client.save_data_to_file(comments, 'comments.json')
# Print sample data
print("\nSample user:")
print(json.dumps(users[0], indent=2, default=str))
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
main()
Django Integration
# django_monody.py
from django.conf import settings
from django.core.management.base import BaseCommand
from django.apps import apps
import json
import os
from monody_client import MonodyClient
class MonodyDjangoIntegration:
def __init__(self):
self.client = MonodyClient(settings.MONODY_API_KEY)
self.session_id = None
def create_session_from_models(self, app_name: str):
"""Create a TypeScript interface from Django models."""
app_config = apps.get_app_config(app_name)
models = app_config.get_models()
interfaces = []
for model in models:
interface_lines = [f"interface {model.__name__} {{"]
for field in model._meta.fields:
field_type = self._get_typescript_type(field)
interface_lines.append(f" {field.name}: {field_type};")
interface_lines.append("}")
interfaces.append("\n".join(interface_lines))
schema_content = "\n\n".join(interfaces)
# Save to temporary file
schema_path = f"/tmp/{app_name}_schema.ts"
with open(schema_path, 'w') as f:
f.write(schema_content)
# Create session
session = self.client.create_session(
schema_path=schema_path,
name=f"{app_name}-django-models"
)
self.session_id = session['sessionId']
os.remove(schema_path) # Clean up
return session
def _get_typescript_type(self, field):
"""Convert Django field types to TypeScript types."""
field_type = type(field).__name__
type_mapping = {
'CharField': 'string',
'TextField': 'string',
'EmailField': 'string',
'URLField': 'string',
'IntegerField': 'number',
'FloatField': 'number',
'DecimalField': 'number',
'BooleanField': 'boolean',
'DateField': 'Date',
'DateTimeField': 'Date',
'ForeignKey': 'number', # Assuming ID reference
'OneToOneField': 'number',
'ManyToManyField': 'number[]',
}
return type_mapping.get(field_type, 'any')
def populate_test_data(self, model_name: str, count: int = 50):
"""Generate and return test data for a specific model."""
if not self.session_id:
raise Exception("No active session. Create a session first.")
endpoint = model_name.lower() + 's' # Simple pluralization
return self.client.generate_data(endpoint, self.session_id, count=count)
# Django management command
class Command(BaseCommand):
help = 'Generate test data using Monody'
def add_arguments(self, parser):
parser.add_argument('app_name', type=str, help='Django app name')
parser.add_argument('--count', type=int, default=50, help='Number of records to generate')
def handle(self, *args, **options):
integration = MonodyDjangoIntegration()
try:
# Create session from Django models
session = integration.create_session_from_models(options['app_name'])
self.stdout.write(f"Created session: {session['sessionId']}")
# Get all models from the app
app_config = apps.get_app_config(options['app_name'])
models = app_config.get_models()
for model in models:
model_name = model.__name__
data = integration.populate_test_data(model_name, options['count'])
# Save to fixture file
fixture_path = f"fixtures/{model_name.lower()}_test_data.json"
os.makedirs('fixtures', exist_ok=True)
with open(fixture_path, 'w') as f:
json.dump(data, f, indent=2, default=str)
self.stdout.write(
self.style.SUCCESS(
f"Generated {len(data)} {model_name} records -> {fixture_path}"
)
)
except Exception as e:
self.stdout.write(self.style.ERROR(f"Error: {e}"))
cURL Examples
Create Session
curl -X POST https://api.monody.dev/sessions \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "schema=@interface.ts" \
-F "name=my-project"
Generate Data
curl "https://api.monody.dev/users?sessionId=mf_abc123xyz&count=10" \
-H "Authorization: Bearer YOUR_API_KEY"
Best Practices
Schema Design
- • Use descriptive interface and property names
- • Include JSDoc comments for better context
- • Define relationships clearly between entities
- • Use union types for enums and specific values
- • Consider optional properties with ? syntax
Performance
- • Cache session IDs to avoid recreating sessions
- • Use appropriate count parameters (don't over-fetch)
- • Implement proper error handling and retries
- • Use seeds for reproducible test data
- • Consider pagination for large datasets
Security
- • Never expose API keys in client-side code
- • Use environment variables for configuration
- • Implement rate limiting in your applications
- • Regularly rotate your API keys
- • Monitor API usage and set up alerts
API Usage Patterns
Session Management
Create sessions once and reuse them for multiple data generation requests. Sessions are valid for 14 days.
// Good: Reuse session
const session = await client.createSession(schema, 'my-project');
const users = await client.generateData('users', session.sessionId);
const posts = await client.generateData('posts', session.sessionId);
// Avoid: Creating multiple sessions for the same schema
const session1 = await client.createSession(schema, 'users');
const session2 = await client.createSession(schema, 'posts'); // Unnecessary
Data Consistency
Use seeds to generate consistent data across different requests and environments.
// Generate consistent test data
const testUsers = await client.generateData('users', sessionId, {
count: 10,
seed: 'test-suite-v1'
});
// Same seed will always generate the same data
const sameUsers = await client.generateData('users', sessionId, {
count: 10,
seed: 'test-suite-v1'
}); // Identical to testUsers
Error Recovery
Implement exponential backoff for rate limiting and proper error handling for different scenarios.
async function generateDataWithRetry(endpoint, sessionId, options, maxRetries = 3) {
let retries = 0;
let delay = 1000; // Start with 1 second
while (retries < maxRetries) {
try {
return await client.generateData(endpoint, sessionId, options);
} catch (error) {
if (error.code === 'RATE_LIMIT_EXCEEDED' && retries < maxRetries - 1) {
await new Promise(resolve => setTimeout(resolve, delay));
delay *= 2; // Exponential backoff
retries++;
} else {
throw error;
}
}
}
}
Troubleshooting
Common Issues
- • Invalid API key
- • Incorrect schema format
- • Session ID not found
- • Rate limit exceeded
- • Insufficient tokens
API Key Problems
If you're getting 401 Unauthorized errors, double-check your API key:
- Ensure the API key is correct
- Verify it hasn't been revoked
- Check for typos or extra spaces
Schema Upload Errors
If your schema upload fails, consider these points:
- Check for syntax errors in your schema
- Ensure it's a supported format (.ts, .json, .js)
- Verify the file size is within the limit (10MB)
Session ID Issues
If you're getting "Session Not Found" errors:
- Ensure the session ID is correct
- Verify the session hasn't expired (sessions are valid for 14 days)
Rate Limiting
If you're hitting rate limits (429 Too Many Requests):
- Implement exponential backoff and retry
- Optimize your API usage to reduce requests
Insufficient Tokens
If you're getting "Insufficient Tokens" errors:
- Purchase more tokens to continue using the API