Synthetic Data Generation

Generate privacy-safe synthetic datasets for AI development.

Synthetic Data with AI Developer Edition generates realistic, privacy-safe datasets for AI training, testing, and development. No real PII is used, while maintaining realistic patterns, distributions, and correlations.

Key Benefits

Using Synthetic Data with AI Developer Edition offers the following advantages for building and testing AI applications without exposing real data.

  • Scales instantly - Create thousands of variations of data on demand.
  • Preserves privacy - No real PII while maintaining realistic patterns.
  • Enables domain specialization - Tailored datasets for finance, healthcare, HR, and other domains.
  • Test safely - Validate agents before hitting production with realistic synthetic data.
  • Maintains correlations - Statistical relationships between fields are preserved.

Use Cursor to Generate Synthetic Data

The following examples show how to prompt Cursor to generate synthetic datasets across different domains, from simple employee records to complex fraud scenarios with edge cases.

Setup Instructions

Cursor Prompt:

In Cursor’s AI chat, enter the following prompt:

Using AI Developer Edition, set up synthetic data generation for my project. I need to generate privacy-safe test data for HR analytics.

Cursor generates the configuration:

import requests

SYNTHETIC_DATA_URL = "http://localhost:8095/pty/syntheticdata/v2"

def generate_synthetic_data(schema: dict, rows: int, domain: str = "general") -> dict:
    """Generate synthetic data using the Synthetic Data API."""
    payload = {
        "schema": schema,
        "rows": rows,
        "domain": domain
    }
    response = requests.post(f"{SYNTHETIC_DATA_URL}/synthesize", json=payload)
    return response.json()

Best Practices

Following are the guidelines to generate synthetic data. They ensure consistent, reliable, and privacy-safe results across your AI development workflows.

  1. Always use synthetic data for testing - Never use real production data in development
  2. Set seeds for reproducibility - Use seed parameter for consistent test datasets
  3. Include edge cases - Enable edge_cases=True for boundary value testing
  4. Validate distributions - Check that generated data matches expected patterns
  5. Version your schemas - Track data generation schemas in version control
  6. Use domain-specific generation - Specify domain for realistic correlations

Example 1: Generate 1000 Rows of Employee Table

This example generates a realistic HR employee dataset with department based salary distributions, performance scores, and demographic fields. Use it to test HR analytics pipelines without exposing real employee data. The output you receive might not match the examples provided here.

Cursor Prompt:

In Cursor’s AI chat, enter the following prompt:

Using AI Developer Edition, generate 1000 employee records for testing my HR analytics application. Include realistic salary distributions by department, performance scores, and demographic correlations.

Implementation

"""
Synthetic Data Generation: Employee Table (1000 rows)
Using Protegrity AI Developer Edition
"""
import requests
import pandas as pd

SYNTHETIC_DATA_URL = "http://localhost:8095/pty/syntheticdata/v2"

# Define schema for employee data
employee_schema = {
    "EmployeeID": {"type": "identifier", "format": "E{seq:4}"},
    "Name": {"type": "person_name", "locale": "en_US"},
    "Email": {"type": "email", "domain": "company.com"},
    "SSN": {"type": "ssn", "format": "###-##-####"},
    "Phone": {"type": "phone", "format": "US"},
    "Department": {
        "type": "category",
        "values": ["Engineering", "Sales", "Marketing", "HR", "Finance", "Operations"],
        "weights": [0.30, 0.20, 0.15, 0.08, 0.12, 0.15]
    },
    "Salary": {
        "type": "numeric",
        "distribution": "normal",
        "range_by_category": {
            "field": "Department",
            "Engineering": {"mean": 165000, "std": 25000},
            "Sales": {"mean": 130000, "std": 20000},
            "Marketing": {"mean": 120000, "std": 18000},
            "HR": {"mean": 105000, "std": 15000},
            "Finance": {"mean": 140000, "std": 22000},
            "Operations": {"mean": 95000, "std": 15000}
        }
    },
    "PerformanceScore": {"type": "numeric", "distribution": "normal", "mean": 3.5, "std": 0.7, "min": 1.0, "max": 5.0},
    "YearsAtCompany": {"type": "numeric", "distribution": "exponential", "lambda": 0.25, "max": 30},
    "HireDate": {"type": "date", "range": ["2010-01-01", "2026-06-01"]}
}

# Generate synthetic data via API
response = requests.post(
    f"{SYNTHETIC_DATA_URL}/synthesize",
    json={"schema": employee_schema, "rows": 1000, "seed": 42}
)
employees = pd.DataFrame(response.json()["data"])

print(f"   Generated {len(employees)} synthetic employee records")
print(f"   Departments: {employees['Department'].nunique()}")
print(f"   Avg Salary: ${employees['Salary'].mean():,.0f}")
print(f"   Salary Range: ${employees['Salary'].min():,} - ${employees['Salary'].max():,}")
print("\n   Sample Records:")
print(employees[["EmployeeID", "Name", "Email", "SSN", "Salary", "Department"]].head())

Output

   Generated 1000 synthetic employee records
   Departments: 6
   Avg Salary: $135,420
   Salary Range: $68,000 - $225,000
   Sample Records:
  EmployeeID          Name                Email         SSN   Salary  Department
0      E1001  Sarah Johnson  sarah.j@company.com  123-45-6789  170000  Engineering
1      E1002   James Smith  james.s@company.com  987-65-4321  130000        Sales
2      E1003  Maria Garcia  maria.g@company.com  456-78-9012  115000    Marketing
3      E1004    David Chen  david.c@company.com  234-56-7890  142000      Finance
4      E1005   Emily Brown  emily.b@company.com   345-67-8901   98000   Operations

Example 2: Generate 1000 Rows of IMDB Database

This example generates a synthetic movie dataset with realistic genre distributions, correlated ratings, and budget-to-revenue relationships. Use it to build and test recommendation engines or media analytics models without relying on licensed data.

Cursor Prompt:

In Cursor’s AI chat, enter the following prompt:

Using AI Developer Edition, generate 1000 synthetic IMDB movie records with realistic rating distributions, genre correlations, and revenue patterns.

Implementation:

"""
Synthetic Data Generation: IMDB Database (1000 rows)
"""
import requests
import pandas as pd

SYNTHETIC_DATA_URL = "http://localhost:8095/pty/syntheticdata/v2"

imdb_schema = {
    "MovieID": {"type": "identifier", "format": "tt{seq:7}"},
    "Title": {"type": "text", "domain": "movie_title"},
    "Year": {"type": "numeric", "distribution": "uniform", "min": 1990, "max": 2026},
    "Genre": {
        "type": "category",
        "values": ["Action", "Drama", "Comedy", "Thriller", "Sci-Fi", "Horror", "Romance"],
        "weights": [0.20, 0.25, 0.18, 0.15, 0.10, 0.07, 0.05]
    },
    "Rating": {"type": "numeric", "distribution": "normal", "mean": 6.5, "std": 1.2, "min": 1.0, "max": 10.0},
    "Votes": {"type": "numeric", "distribution": "lognormal", "mean": 50000, "std": 100000},
    "Director": {"type": "person_name"},
    "Budget_USD": {"type": "numeric", "distribution": "lognormal", "mean": 50000000, "std": 80000000},
    "Revenue_USD": {"type": "numeric", "correlation": {"field": "Budget_USD", "factor": 2.5, "noise": 0.8}},
    "Runtime_Min": {"type": "numeric", "distribution": "normal", "mean": 120, "std": 25, "min": 60, "max": 240}
}

response = requests.post(
    f"{SYNTHETIC_DATA_URL}/synthesize",
    json={"schema": imdb_schema, "rows": 1000}
)
movies = pd.DataFrame(response.json()["data"])
print(f"   Generated {len(movies)} synthetic movie records")

Output

   Generated 1000 synthetic movie records

   Sample Records:
     MovieID             Title  Year     Genre  Rating   Votes      Director  Budget_USD  Revenue_USD  Runtime_Min
    0  tt0000001      The Last Run  2018    Action     7.2  182400   James Carter    42000000    98000000          118
    1  tt0000002   Broken Horizons  2003     Drama     6.8   64200    Maria Lopez    15000000    31000000          134
    2  tt0000003    One More Night  2011    Comedy     5.9   27800   David Nguyen     8500000    19000000           97
    3  tt0000004     Dark Interval  1997  Thriller     7.5  310500   Anna Fischer    61000000   145000000          122
    4  tt0000005  Signal and Noise  2022    Sci-Fi     6.4   91300  Thomas Wright    95000000   212000000          141

Example 3: Advanced - Synthetic Transaction + Fraud Data (5000 rows)

This example generates a large-scale payment transaction dataset with built-in fraud patterns and edge cases, including high-value spikes, rapid repeated transactions, and geolocation mismatches. Use it to train and validate fraud detection models without using real customer or payment data.

Cursor Prompt:

In Cursor’s AI chat, enter the following prompt:

Using AI Developer Edition, generate synthetic transaction data (5000 rows) with customers and payments. Include normal and fraud patterns. Add edge cases: high-amount spikes, repeated rapid transactions, mismatched geolocation, nulls, boundary values. Output as CSV with clear schema.

Implementation:

"""
Advanced Synthetic Data: Transaction + Fraud Scenarios (5000 rows)
For agent training on fraud detection patterns
"""
import requests
import pandas as pd

SYNTHETIC_DATA_URL = "http://localhost:8095/pty/syntheticdata/v2"
# Define transaction schema with fraud patterns
transaction_schema = {
    "TransactionID": {"type": "identifier", "format": "TXN-{uuid:8}"},
    "CustomerID": {"type": "identifier", "format": "CUST-{seq:5}", "unique_count": 500},
    "CustomerName": {"type": "person_name"},
    "CardNumber": {"type": "credit_card", "format": "tokenized"},
    "Amount": {
        "type": "numeric",
        "distribution": "mixed",
        "normal": {"mean": 85, "std": 50, "weight": 0.92},
        "spike": {"min": 5000, "max": 50000, "weight": 0.03},  # High-amount edge cases
        "boundary": {"values": [0.01, 0.00, 9999.99, 10000.00], "weight": 0.02},
        "null": {"weight": 0.03}  # Missing values
    },
    "Currency": {"type": "category", "values": ["USD", "EUR", "GBP", "JPY"], "weights": [0.60, 0.20, 0.12, 0.08]},
    "MerchantID": {"type": "identifier", "format": "MERCH-{seq:4}", "unique_count": 200},
    "MerchantCategory": {
        "type": "category",
        "values": ["retail", "food", "travel", "entertainment", "electronics", "fuel"],
        "weights": [0.25, 0.20, 0.15, 0.15, 0.15, 0.10]
    },
    "Timestamp": {
        "type": "datetime",
        "range": ["2025-01-01T00:00:00", "2026-06-30T23:59:59"],
        "patterns": {
            "normal": {"distribution": "uniform", "weight": 0.90},
            "rapid_burst": {"interval_seconds": 5, "count": 3, "weight": 0.05},  # Rapid repeated
            "late_night": {"hours": [1, 2, 3, 4], "weight": 0.05}  # Unusual timing
        }
    },
    "Location_Country": {"type": "category", "values": ["US", "UK", "DE", "JP", "BR", "NG"]},
    "Location_City": {"type": "location_city", "correlated_with": "Location_Country"},
    "IP_Country": {
        "type": "category",
        "correlation": {
            "field": "Location_Country",
            "match_rate": 0.85,  # 85% match = normal, 15% mismatch = suspicious
            "mismatch_pool": ["RU", "CN", "VN", "KP"]  # Geolocation mismatch
        }
    },
    "DeviceID": {"type": "identifier", "format": "DEV-{hex:12}"},
    "IsFraud": {
        "type": "label",
        "rules": [
            {"condition": "Amount > 5000 AND IP_Country != Location_Country", "probability": 0.85},
            {"condition": "rapid_burst == True", "probability": 0.70},
            {"condition": "late_night == True AND Amount > 1000", "probability": 0.60},
            {"condition": "default", "probability": 0.02}  # 2% base fraud rate
        ]
    },
    "FraudType": {
        "type": "category",
        "conditional_on": "IsFraud",
        "values_if_true": ["card_stolen", "account_takeover", "synthetic_identity", "friendly_fraud"],
        "value_if_false": None
    }
}
# Generate with edge cases
response = requests.post(
    f"{SYNTHETIC_DATA_URL}/synthesize",
    json={"schema": transaction_schema, "rows": 5000, "edge_cases": True, "seed": 42}
)
transactions = pd.DataFrame(response.json()["data"])
# Save as CSV
transactions.to_csv("synthetic_transactions.csv", index=False)
# Summary statistics
print(f"   Generated {len(transactions)} synthetic transactions")
print(f"   Customers: {transactions['CustomerID'].nunique()}")
print(f"   Fraud rate: {transactions['IsFraud'].mean():.1%}")
print(f"   Null amounts: {transactions['Amount'].isna().sum()}")
print(f"   High-value (>$5000): {(transactions['Amount'] > 5000).sum()}")
print(f"   Geo mismatches: {(transactions['IP_Country'] != transactions['Location_Country']).sum()}")
print("\n   Schema:")
print(transactions.dtypes.to_string())
print("\n   Fraud Breakdown:")
print(transactions[transactions['IsFraud'] == True]['FraudType'].value_counts().to_string())

Output CSV Schema

TransactionID,CustomerID,CustomerName,CardNumber,Amount,Currency,MerchantID,
MerchantCategory,Timestamp,Location_Country,Location_City,IP_Country,DeviceID,
IsFraud,FraudType
TXN-a8f2e301,CUST-00142,John Smith,TKN-4532-XXXX,85.40,USD,MERCH-0023,retail,
2025-03-15T14:22:00,US,New York,US,DEV-a1b2c3d4e5f6,False,
TXN-b9c3f402,CUST-00142,John Smith,TKN-4532-XXXX,8500.00,USD,MERCH-0156,electronics,
2025-03-15T14:22:05,US,New York,RU,DEV-x9y8z7w6v5u4,True,card_stolen

Example 4: Healthcare Domain - Patient Records

This example generates synthetic patient records with clinically correlated diagnoses, medications, and lab results. Use it to develop and test healthcare AI applications while maintaining full HIPAA compliance with no real patient data involved.

Cursor Prompt:

In Cursor’s AI chat, enter the following prompt:

Using AI Developer Edition, generate 2000 synthetic patient records for a healthcare AI application. Include diagnoses, medications, lab results with realistic medical correlations.

Implementation:

"""
Synthetic Data: Healthcare Patient Records
"""
import requests
import pandas as pd

SYNTHETIC_DATA_URL = "http://localhost:8095/pty/syntheticdata/v2"

patient_schema = {
    "PatientID": {"type": "identifier", "format": "PAT-{seq:6}"},
    "Name": {"type": "person_name"},
    "DOB": {"type": "date", "range": ["1940-01-01", "2005-12-31"]},
    "SSN": {"type": "ssn"},
    "MRN": {"type": "identifier", "format": "MRN-{seq:8}"},
    "Diagnosis_ICD10": {
        "type": "medical_code",
        "system": "ICD-10",
        "common_codes": ["E11.9", "I10", "J06.9", "M54.5", "F32.1"]
    },
    "Medication": {"type": "medication", "correlated_with": "Diagnosis_ICD10"},
    "Lab_Glucose": {"type": "lab_value", "unit": "mg/dL", "range": [70, 300]},
    "Lab_HbA1c": {"type": "lab_value", "unit": "%", "range": [4.0, 14.0]},
    "Insurance_ID": {"type": "identifier", "format": "INS-{alphanum:10}"},
    "Provider": {"type": "person_name", "prefix": "Dr."}
}

response = requests.post(
    f"{SYNTHETIC_DATA_URL}/synthesize",
    json={"schema": patient_schema, "rows": 2000, "domain": "healthcare"}
)
patients = pd.DataFrame(response.json()["data"])

Last modified : August 04, 2026