Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Server API

SyntheticData provides a server component with REST, gRPC, and WebSocket APIs for application integration.

Starting the Server

cargo run -p datasynth-server -- --port 3000 --worker-threads 4

Options:

OptionDefaultDescription
--port3000HTTP/WebSocket port
--grpc-port50051gRPC port
--worker-threadsCPU coresWorker thread count
--api-keyNoneRequired API key
--rate-limit100Max requests per minute

Authentication

When --api-key is set, include it in requests:

curl -H "X-API-Key: your-api-key" http://localhost:3000/api/config

REST API

Configuration Endpoints

GET /api/config

Retrieve current configuration.

curl http://localhost:3000/api/config

Response:

{
  "global": {
    "seed": 42,
    "industry": "manufacturing",
    "start_date": "2024-01-01",
    "period_months": 12
  },
  "transactions": {
    "target_count": 100000
  }
}

POST /api/config

Update configuration.

curl -X POST http://localhost:3000/api/config \
  -H "Content-Type: application/json" \
  -d '{"transactions": {"target_count": 50000}}'

POST /api/config/validate

Validate configuration without applying.

curl -X POST http://localhost:3000/api/config/validate \
  -H "Content-Type: application/json" \
  -d @config.json

Stream Control Endpoints

POST /api/stream/start

Start data generation.

curl -X POST http://localhost:3000/api/stream/start

Response:

{
  "status": "started",
  "stream_id": "abc123"
}

POST /api/stream/stop

Stop current generation.

curl -X POST http://localhost:3000/api/stream/stop

POST /api/stream/pause

Pause generation.

curl -X POST http://localhost:3000/api/stream/pause

POST /api/stream/resume

Resume paused generation.

curl -X POST http://localhost:3000/api/stream/resume

Pattern Trigger Endpoints

POST /api/stream/trigger/

Trigger special event patterns.

Available patterns:

  • month_end - Month-end close activities
  • quarter_end - Quarter-end activities
  • year_end - Year-end close activities
curl -X POST http://localhost:3000/api/stream/trigger/month_end

Health Check

GET /health

curl http://localhost:3000/health

Response:

{
  "status": "healthy",
  "uptime_seconds": 3600
}

WebSocket API

Connect to receive real-time events during generation.

Connection

const ws = new WebSocket('ws://localhost:3000/ws/events');

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log(data);
};

Event Types

Progress Event:

{
  "type": "progress",
  "current": 50000,
  "total": 100000,
  "percent": 50.0,
  "rate": 85000.5
}

Entry Event:

{
  "type": "entry",
  "data": {
    "document_id": "abc-123",
    "posting_date": "2024-03-15",
    "account": "1100",
    "debit": "1000.00",
    "credit": "0.00"
  }
}

Error Event:

{
  "type": "error",
  "message": "Memory limit exceeded"
}

Complete Event:

{
  "type": "complete",
  "total_entries": 100000,
  "duration_ms": 1200
}

gRPC API

Proto Definition

syntax = "proto3";

package synth;

service SynthService {
  rpc GetConfig(Empty) returns (Config);
  rpc SetConfig(Config) returns (Status);
  rpc StartGeneration(GenerationRequest) returns (stream Entry);
  rpc StopGeneration(Empty) returns (Status);
}

message Config {
  string yaml = 1;
}

message GenerationRequest {
  optional int64 count = 1;
}

message Entry {
  string document_id = 1;
  string posting_date = 2;
  string company_code = 3;
  repeated LineItem lines = 4;
}

message LineItem {
  string account = 1;
  string debit = 2;
  string credit = 3;
}

Client Example (Rust)

use synth::synth_client::SynthClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = SynthClient::connect("http://localhost:50051").await?;

    let request = tonic::Request::new(GenerationRequest { count: Some(1000) });
    let mut stream = client.start_generation(request).await?.into_inner();

    while let Some(entry) = stream.message().await? {
        println!("Entry: {:?}", entry.document_id);
    }

    Ok(())
}

Rate Limiting

The server implements sliding window rate limiting:

MetricDefault
Window1 minute
Max requests100

Exceeding the limit returns 429 Too Many Requests:

{
  "error": "rate_limit_exceeded",
  "retry_after": 30
}

Memory Management

The server enforces memory limits:

# Set memory limit (bytes)
cargo run -p datasynth-server -- --memory-limit 1073741824  # 1GB

When memory is low:

  • Generation pauses automatically
  • WebSocket sends warning event
  • New requests may be rejected

Error Responses

HTTP StatusMeaning
400Invalid request/configuration
401Missing or invalid API key
429Rate limit exceeded
500Internal server error
503Server overloaded

Error Response Format:

{
  "error": "error_code",
  "message": "Human readable description",
  "details": {}
}

Integration Examples

Python Client

import requests
import websocket
import json

BASE_URL = "http://localhost:3000"

# Set configuration
config = {
    "transactions": {"target_count": 10000}
}
requests.post(f"{BASE_URL}/api/config", json=config)

# Start generation
requests.post(f"{BASE_URL}/api/stream/start")

# Monitor via WebSocket
ws = websocket.create_connection(f"ws://localhost:3000/ws/events")
while True:
    event = json.loads(ws.recv())
    if event["type"] == "complete":
        break
    print(f"Progress: {event.get('percent', 0)}%")

Node.js Client

const axios = require('axios');
const WebSocket = require('ws');

const BASE_URL = 'http://localhost:3000';

async function generate() {
    // Configure
    await axios.post(`${BASE_URL}/api/config`, {
        transactions: { target_count: 10000 }
    });

    // Start
    await axios.post(`${BASE_URL}/api/stream/start`);

    // Monitor
    const ws = new WebSocket('ws://localhost:3000/ws/events');
    ws.on('message', (data) => {
        const event = JSON.parse(data);
        console.log(event);
    });
}

See Also