SynthForge SynthForge SynthForge IO

Docs · API

API keys & automation

Use a personal access token to call the SynthForge REST API from scripts, CI, or local tools without a browser session cookie.

1. Create a key

  1. Sign in at app.synthforge.io
  2. Open SettingsAPI keys
  3. Choose a short name (for example ci or laptop) and create the key
  4. Copy the secret immediately. It is shown only once. After that you only see a prefix like sfk_live_ab12…

Production secrets look like sfk_live_…. Dev-environment keys use sfk_dev_… against https://api-dev.synthforge.io.

2. Authenticate

Send the secret as a Bearer token on every request. Base URL for production:

text
https://api.synthforge.io
bash
export SF_API_KEY='sfk_live_…'   # paste your secret
export API_BASE='https://api.synthforge.io'

curl -sS -H "Authorization: Bearer $SF_API_KEY" \
  "$API_BASE/api/v1/users/me" | jq .

A successful response is your user profile JSON (email, quotas, etc.). A bad or revoked key returns 401.

3. curl: end-to-end generate

Minimal flow: create a schema → start a dataset job → poll status → download the ZIP (CSV, Parquet, SQL loaders, README, quality report).

bash
export SF_API_KEY='sfk_live_…'
export API_BASE='https://api.synthforge.io'

# 1) Create a minimal schema (or use an existing schema id from the app)
SCHEMA_JSON='{
  "name": "api-demo",
  "schema_data": {
    "tables": [
      {
        "name": "customers",
        "columns": [
          { "name": "id", "field_type": "integer_sequence", "primary_key": true },
          { "name": "email", "field_type": "email" },
          { "name": "full_name", "field_type": "full_name" }
        ]
      },
      {
        "name": "orders",
        "columns": [
          { "name": "id", "field_type": "integer_sequence", "primary_key": true },
          {
            "name": "customer_id",
            "field_type": "integer",
            "foreign_key": { "table": "customers", "column": "id" }
          },
          { "name": "amount", "field_type": "currency_amount" }
        ]
      }
    ]
  }
}'

SCHEMA_ID=$(curl -sS -X POST "$API_BASE/api/v1/schemas" \
  -H "Authorization: Bearer $SF_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$SCHEMA_JSON" | jq -r .id)

# 2) Start generation (flat formats stream out-of-core on the server)
DATASET_ID=$(curl -sS -X POST "$API_BASE/api/v1/datasets" \
  -H "Authorization: Bearer $SF_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"schema_id\": \"$SCHEMA_ID\",
    \"name\": \"api-demo-run\",
    \"row_counts\": { \"customers\": 100, \"orders\": 400 },
    \"formats\": [\"csv\", \"parquet\"],
    \"seed\": 42
  }" | jq -r .id)

# 3) Poll until completed / failed / cancelled
while true; do
  STATUS=$(curl -sS -H "Authorization: Bearer $SF_API_KEY" \
    "$API_BASE/api/v1/datasets/$DATASET_ID/status")
  S=$(echo "$STATUS" | jq -r .status)
  echo "status=$S"
  case "$S" in completed|failed|cancelled) break ;; esac
  sleep 2
done

# 4) Presigned download URL → ZIP bundle
URL=$(curl -sS -H "Authorization: Bearer $SF_API_KEY" \
  "$API_BASE/api/v1/datasets/$DATASET_ID/download" | jq -r .url)
curl -sS -L -o dataset.zip "$URL"
echo "wrote dataset.zip"

Prefer schemas you already built in the visual editor? Skip step 1 and pass that schema’s UUID as schema_id. List yours with GET /api/v1/schemas.

4. Python

Same flow with the standard library-friendly requests package (pip install requests):

python
import os
import time
import requests

API = os.environ.get("SF_API_BASE", "https://api.synthforge.io")
KEY = os.environ["SF_API_KEY"]  # sfk_live_… or sfk_dev_…
H = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}

# Who am I?
me = requests.get(f"{API}/api/v1/users/me", headers=H, timeout=30)
me.raise_for_status()
print(me.json()["email"])

# Create schema
schema = {
    "name": "py-demo",
    "schema_data": {
        "tables": [
            {
                "name": "events",
                "columns": [
                    {"name": "id", "field_type": "integer_sequence", "primary_key": True},
                    {"name": "label", "field_type": "word"},
                ],
            }
        ]
    },
}
r = requests.post(f"{API}/api/v1/schemas", headers=H, json=schema, timeout=60)
r.raise_for_status()
schema_id = r.json()["id"]

# Generate
r = requests.post(
    f"{API}/api/v1/datasets",
    headers=H,
    json={
        "schema_id": schema_id,
        "name": "py-demo-run",
        "row_counts": {"events": 500},
        "formats": ["csv"],
        "seed": 7,
    },
    timeout=60,
)
r.raise_for_status()
dataset_id = r.json()["id"]

# Poll
while True:
    st = requests.get(
        f"{API}/api/v1/datasets/{dataset_id}/status", headers=H, timeout=30
    ).json()
    print(st["status"], st.get("progress_pct"))
    if st["status"] in ("completed", "failed", "cancelled"):
        break
    time.sleep(2)

if st["status"] != "completed":
    raise SystemExit(st)

# Download ZIP
url = requests.get(
    f"{API}/api/v1/datasets/{dataset_id}/download", headers=H, timeout=30
).json()["url"]
zip_bytes = requests.get(url, timeout=120).content
open("dataset.zip", "wb").write(zip_bytes)
print("wrote dataset.zip", len(zip_bytes), "bytes")

5. CLI (synthforge)

The synthforge CLI (alias sf) wraps the same API. It is available for early use (not on public npm yet). You can always inject a Settings-minted key via SF_API_KEY without synthforge login.

bash
# CLI early access. Easiest path: set SF_API_KEY from Settings.

# Option A: login (mints a key named "cli" and stores it locally)
export SF_PASSWORD='your-password'
synthforge login --email you@example.com

# Option B: use a key you created in Settings
export SF_API_KEY='sfk_live_…'
export SF_API_BASE='https://api.synthforge.io'   # optional; production is the default

synthforge whoami
synthforge schemas list

# AI-forge a schema, then generate + download
SCHEMA_ID=$(synthforge schemas forge -d "customers and orders with FK" --name demo | tail -1)
synthforge generate --schema "$SCHEMA_ID" \
  --rows customers=50,orders=200 \
  --format csv --seed 42 -o demo.zip

6. TypeScript SDK

@synthforgeio/sdk is a thin typed client for schemas, AI schema jobs, and datasets. Early access only for now (not on public npm yet).

typescript
// Workspace package @synthforgeio/sdk (not published to npm in v1)
import { SynthForge, SynthForgeError } from '@synthforgeio/sdk';

const sf = new SynthForge({
  apiKey: process.env.SF_API_KEY!, // sfk_…
  // baseUrl: 'https://api-dev.synthforge.io',
});

const { items } = await sf.schemas.list({ limit: 20 });

const schema = await sf.schemas.create({
  name: 'orders',
  schema_data: {
    tables: [
      {
        name: 'orders',
        columns: [
          { name: 'id', field_type: 'uuid', primary_key: true },
          { name: 'label', field_type: 'word' },
        ],
      },
    ],
  },
});

const dataset = await sf.datasets.create({
  schema_id: schema.id,
  name: 'demo',
  row_counts: { orders: 100 },
  formats: ['csv'],
  seed: 42,
});

const status = await sf.datasets.wait(dataset.id);
if (status.status === 'completed') {
  const { url } = await sf.datasets.getDownloadUrl(dataset.id);
  // fetch(url) → ZIP
}

Useful endpoints

Method Path Notes
GET /api/v1/users/me Account + quota snapshot
GET / POST /api/v1/schemas List or create schemas
POST /api/v1/datasets Start generation (row_counts, formats, seed, locale…)
GET /api/v1/datasets/:id/status Poll until completed / failed / cancelled
GET /api/v1/datasets/:id/download JSON with presigned url for the ZIP
POST /api/v1/datasets/:id/cancel Cooperative cancel of an in-flight job
GET /openapi.json Full OpenAPI document (no auth)

Machine-readable catalog: https://api.synthforge.io/openapi.json

Security notes

FAQ

Where do I create an API key?
Sign in at app.synthforge.io, open Settings, and use the API keys panel. The full secret is shown once at creation; copy it immediately. The list view only shows a short prefix afterward.
What does a key look like?
Secrets start with sfk_live_ (production) or sfk_dev_ (dev). Pass them as Authorization: Bearer <secret> on every API request.
Can I create more keys from an existing API key?
No. Minting, listing, and revoking keys require a browser session. That prevents key-from-key sprawl if a secret leaks.
How do I revoke a key?
Settings → API keys → revoke. Scripts using that secret will start receiving 401. Re-run synthforge login (same key name) also rotates the server key used by the CLI.
Is the TypeScript SDK on npm?
Not yet on public npm. The curl and Python samples on this page work with only an API key. Ask us if you want early access to the TypeScript SDK or CLI.
Create an API key

All docs · Data generation