API reference

Generate & push

Generate rows, push them into a database, and poll long-running jobs.

Three ways to run a generation, differing only in what happens to the output.

Endpoint Output Use when
POST /api/generate returned to you you want the data, not a write
POST /api/generate/push written to the target, synchronously small to medium volumes
POST /api/generate/push-async queued as a job large volumes, or CI that should not hold a connection

Request

{
  "connection": {
    "db_type": "postgresql",
    "connection_string": "postgresql://user:pass@host:5432/mydb",
    "schema_name": "public"
  },
  "tables": [
    { "table_name": "users", "row_count": 500, "enabled": true, "column_overrides": {} }
  ],
  "seed": 42
}

connection db_type is postgresql, mysql or sqlite (default postgresql). schema_name defaults to public.

tables

  • table_name, must exist in the introspected schema
  • row_count, 1 to 500,000 per table, subject to your tier
  • enabled, set false to skip without removing the entry
  • column_overrides, per-column generation hints, keyed by column name

seed Optional. The same seed with the same config reproduces the same rows exactly. Omit it and one is chosen for you and returned as seed, so any run can be replayed later. Log it in CI.

Push-only fields truncate_first empties the target tables before writing; truncate_cascade extends that through dependent tables. Both default to false.

Responses

POST /api/generate:

{
  "total_rows": 5500,
  "per_table": { "users": 500, "orders": 5000 },
  "elapsed_seconds": 0.42,
  "seed": 42
}

POST /api/generate/push:

{
  "tables_processed": 2,
  "total_rows": 5500,
  "requested_rows": 5500,
  "per_table": { "users": 500, "orders": 5000 },
  "pushed_to_db": true,
  "errors": [],
  "cascaded_tables": [],
  "cascaded_rows": 0
}

Read pushed_to_db, not the status code. It is derived from tables actually written. A run where every row hit a constraint returns 200 with pushed_to_db: false and the reasons in errors. An earlier version reported success there, which is the sort of thing that gets discovered at 6pm.

Compare total_rows with requested_rows to catch partial writes.

Async pushes

curl -s "$SEEDQL_API/api/generate/push-async" -X POST \
  -H "Authorization: Bearer $SEEDQL_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "connection": {...}, "tables": [...] }'

202 Accepted:

{
  "job_id": "9d2f…",
  "status": "queued",
  "rows_requested": 500000,
  "poll": "/api/jobs/9d2f…"
}

Poll it:

curl -s "$SEEDQL_API/api/jobs/$JOB_ID" -H "Authorization: Bearer $SEEDQL_KEY"

Status moves queued → running → completed, or failed / cancelled. Cancel with POST /api/jobs/{id}/cancel; the runner stops at the next safe checkpoint rather than mid-write.

Jobs are visible to their creator, and to org admins and owners.

Foreign keys

You never declare table order. SeedQL builds a dependency graph from the real foreign keys and runs a topological sort (Kahn's algorithm), generating parents before children so every child row references a parent that exists. Ties break alphabetically, which keeps a seeded run byte-identical across machines. Cycles are detected and broken explicitly rather than silently producing orphans.

Limits

Tier Rows per request Rows per month
Hobby 5,000 5,000
Pro 100,000 100,000
Business / Platinum 500,000 500,000
Enterprise 10,000,000 effectively unlimited

Exceeding a limit returns 402 with the tier and the cap in the body. Overage draws from your bonus-row balance first, if you have one.

Known gap: distributions

Generation is uniform. Foreign key values are chosen evenly across available parents, so no account ends up holding a disproportionate share of rows.

If a load test depends on that skew, one customer with 40,000 of 500,000 orders, SeedQL will not produce it today. Weighted distributions are on the roadmap and will be announced in the changelog, not quietly added. The practical workaround is to generate the bulk here and concentrate rows onto a chosen parent with an UPDATE, which is a few lines of SQL against a structurally valid database.