API Reference

Version 1 · Base URL https://api.chaosdata.net

Overview

ChaosData turns a relational schema into production-realistic test data, then hides edge cases inside it: emoji, unicode overflows, boundary numbers, malformed strings and more. Post a SQL schema, get back ordered INSERT statements or a structured JSON payload.

  • Deterministic. Pass a seed for byte-for-byte reproducible output.
  • Dialect auto-detection. PostgreSQL, MySQL and SQLite dumps are recognized from a small prefix.
  • Constraint-aware. Keys, foreign keys, NOT NULL, UNIQUE, lengths, unsigned ranges and simple CHECKs are respected.
The machine-readable contract is available at /openapi.json (OpenAPI 3.1).

Quickstart

Send a schema and receive SQL:

curl -X POST "https://api.chaosdata.net/api/v1/quick-generate?rows=50&chaos=15" \
  -H "Accept: text/sql" \
  --data-binary @schema.sql

Or structured JSON:

curl -X POST "https://api.chaosdata.net/api/v1/quick-generate?rows=50&chaos=15" \
  -H "Accept: application/json" \
  --data-binary @schema.sql

A typical schema.sql:

CREATE TABLE users (
  id       SERIAL PRIMARY KEY,
  email    VARCHAR(255) NOT NULL UNIQUE,
  age      INT CHECK (age >= 0)
);

Waitlist

No key is required: quick-generate is public and anonymous. Join the waitlist at /waitlist and we will email you (once you confirm) when ChaosData opens up.

  • POST /api/v1/waitlist records interest and sends a double opt-in link. It answers the same way whether or not the address was already present.
  • POST /api/v1/waitlist/confirm consumes the emailed token.

Generate data

POST/api/v1/quick-generate

Query parameters

NameTypeDefaultDescription
rowsinteger25Rows generated per table (1–100).
chaosinteger0Percent chance that any eligible value becomes an anomaly (0–100).
seedint64randomReproducible output; the same seed yields identical bytes.
dialectstringautopostgres, mysql, sqlite or auto.
validate_onlybooleanfalseValidate and summarize the schema without generating data.

Request headers

HeaderDescription
Accepttext/sql or application/json. Anything else returns 406.
X-Chaos-HintsOverride per-column semantic types. See Column hints.

Request body

The raw SQL DDL (CREATE TABLE statements). It is parsed as a stream, so the server validates incrementally and, on the first syntax error, stops reading and closes the connection after returning 400. Non-DDL statements (SET, GRANT, CREATE INDEX, MySQL table options, SQLite STRICT, PRAGMA, …) are tolerated and skipped.

Sending a schema that is larger than the body cap (CHAOSDATA_MAX_BODY_BYTES, 2 MiB by default) returns 413. The dialect is detected from a 64 KiB prefix, so a dump can be piped in without extra flags.

Responses

Accept: text/sql: a metadata header, a transaction and parent-first multi-row inserts:

-- ChaosData | seed=42 rows=5 chaos=15 anomalies=2
SET client_encoding TO 'UTF8';
BEGIN;
INSERT INTO "users" ("id", "email", "age") VALUES
  (1, 'alex🚀@example.com', 0);
COMMIT;

Accept: application/json: a metadata block plus a table-keyed data object:

{
  "metadata": {
    "seed": 42,
    "rows_per_table": 5,
    "chaos": 15,
    "anomalies_injected": 2,
    "duration_ms": 4,
    "tables": [ { "name": "users", "rows": 5, "anomalies": 2, "order": 0 } ]
  },
  "data": {
    "users": [ { "id": 1, "email": "alex🚀@example.com", "age": 0 } ]
  }
}
validate_only=true returns a summary instead, including the resolved semantic type of every column:
{
  "valid": true,
  "input_dialect": "postgres",
  "tables": [ { "name": "users", "foreign_keys": 0,
    "columns": [ { "name": "email", "semantic": "email" } ] } ]
}

Column hints

ChaosData infers each column's semantic type from its name and SQL type (email → email, user_id → identifier, created_at → timestamp). When the name is ambiguous, tell us with X-Chaos-Hints. It affects both the realistic base values and which anomalies apply.

curl -X POST "https://api.chaosdata.net/api/v1/quick-generate?rows=100&chaos=20" \
  -H "X-Chaos-Hints: users.user_id=identifier; users.email=email; orders.total=money" \
  -H "Accept: application/json" \
  --data-binary @schema.sql
  • Pairs are [schema.]table.column=type or a bare column=type, semicolon-separated; the header may be repeated.
  • Keys are case-insensitive; a bare column name applies to every table that has it.
  • Validation is strict: an unknown type, a type incompatible with the column's SQL kind, or a hint that matches no column returns 400.
  • A hint overrides name inference. Use text/unknown to disable it.

Datatypes

Live from GET /api/v1/datatypes. A datatype is the semantic content of a column; these are the values accepted by X-Chaos-Hints, along with their aliases and the anomalies that can apply. unknown, none and opaque are aliases of text.

Loading…
DatatypeCategoryAliasesExampleAnomalies
Loading datatypes…

Anomaly catalog

Live from GET /api/v1/anomalies. Each anomaly lists the datatypes it can apply to. Only unique-safe anomalies are used on UNIQUE columns.

Loading…
AnomalyDatatypesUnique-safe
Loading catalog…

Other endpoints

GET/api/v1/datatypes

Returns every datatype with its category, aliases, an example and the anomalies that apply to it.

GET/api/v1/anomalies

Returns the datatype names (datatypes) and the anomaly catalog (anomalies).

GET/api

Service descriptor: name, description, homepage and the endpoint list.

GET/healthz

Returns {"status":"ok"}. Useful for load balancers and uptime checks.

Direct pipe

Dump a schema, pipe it through ChaosData, load it into a test database. One line, every time. The target tables must already exist.

# MySQL
mysqldump --no-data mydb | curl -s -X POST \
  "https://api.chaosdata.net/api/v1/quick-generate?rows=50&chaos=10" \
  -H "Accept: text/sql" --data-binary @- | mysql mydb_test

# PostgreSQL
pg_dump --schema-only mydb | curl -s -X POST \
  "https://api.chaosdata.net/api/v1/quick-generate?rows=50&chaos=10" \
  -H "Accept: text/sql" --data-binary @- | psql mydb_test

# SQLite
sqlite3 mydb .schema | curl -s -X POST \
  "https://api.chaosdata.net/api/v1/quick-generate?rows=50&chaos=10" \
  -H "Accept: text/sql" --data-binary @- | sqlite3 mydb_test

Errors

Errors use RFC 9457 application/problem+json. This is an example error response:

{
  "type": "about:blank",
  "title": "Bad Request",
  "status": 400,
  "detail": "line 1, column 26: unexpected character \"@\"",
  "instance": "/api/v1/quick-generate"
}

Rate limits

Anonymous requests are limited per client address.

ScopeLimit
Per client60 requests per minute
Rows per table100

Limits are token buckets, so short bursts are allowed on top. Larger rows cost more than one request. Over-limit requests return 429 with a Retry-After header, and IPv6 clients are counted by network prefix.

Need something else? Email hello@chaosdata.net.