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.

1

Create a Session

Upload your schema file to create a new session:

bash
curl -X POST https://api.monody.dev/sessions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "schema=@interface.ts" \
  -F "name=my-project"
2

Generate Mock Data

Use your session ID to generate realistic mock data:

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

  1. Sign up for a Monody account
  2. Navigate to your dashboard
  3. Go to API Keys section
  4. Generate a new API key
  5. 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:

bash
# .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

http
Authorization: Bearer YOUR_API_KEY

Example Request

bash
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.

POST
/sessions

Create a new session by uploading your schema file.

Parameters

ParameterTypeRequiredDescription
schemafileYesSchema file (.ts, .json, or .js)
namestringYesName for your session
descriptionstringNoOptional description

Response

json
{
  "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"
  ]
}
GET
/sessions/{sessionId}

Retrieve information about a specific session.

bash
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.

GET
/{endpoint}?sessionId={sessionId}

Generate mock data for a specific endpoint.

Query Parameters

ParameterTypeDefaultDescription
sessionIdstring-Your session ID (required)
countnumber10Number of items to generate (1-100)
seedstringrandomSeed for reproducible data
localestringenLocale for generated data

Example Response

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

interface.ts

JSON Schema

Use db.json files with sample data structure

db.json

Zod Models

Upload Zod schema definitions

schema.js

TypeScript Interface Example

typescript
// 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

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

javascript
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.

HTTP Status Codes
Status CodeMeaningDescription
200OKRequest successful
201CreatedResource created successfully
400Bad RequestInvalid request parameters
401UnauthorizedInvalid or missing API key
403ForbiddenInsufficient permissions
404Not FoundResource not found
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer error occurred

Error Response Format

All error responses follow this consistent format:

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

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

Invalid Schema

The uploaded schema file contains syntax errors or is not in a supported format.

SESSION_NOT_FOUND

Session Not Found

The specified session ID does not exist or has expired.

RATE_LIMIT_EXCEEDED

Rate Limit Exceeded

You have exceeded the rate limit. Implement exponential backoff and retry later.

INSUFFICIENT_TOKENS

Insufficient Tokens

Your account doesn't have enough tokens to complete this request. Purchase more tokens to continue.

Error Handling Best Practices

javascript
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

javascript
// 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

javascript
// 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

python
# 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

python
# 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

bash
curl -X POST https://api.monody.dev/sessions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "schema=@interface.ts" \
  -F "name=my-project"

Generate Data

bash
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.

javascript
// 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.

javascript
// 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.

javascript
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