{
  "openapi": "3.1.0",
  "info": {
    "title": "ChaosData API",
    "version": "1.0.0",
    "description": "Turn a relational database schema into production-realistic, fuzzed test data. Send a SQL DDL schema and receive ordered INSERT statements (text/sql) or a structured payload (application/json) with hidden anomalies such as emoji, unicode overflows, boundary numbers and malformed strings. No signup required.",
    "contact": {
      "name": "ChaosData",
      "url": "https://chaosdata.net",
      "email": "hello@chaosdata.net"
    },
    "license": {
      "name": "MIT"
    }
  },
  "servers": [
    {
      "url": "https://api.chaosdata.net",
      "description": "Production"
    },
    {
      "url": "http://api.chaosdata.localhost",
      "description": "Local development"
    }
  ],
  "tags": [
    {
      "name": "generate",
      "description": "Generate fuzzed data from a schema"
    },
    {
      "name": "anomalies",
      "description": "Discover semantic types and anomaly categories"
    },
    {
      "name": "meta",
      "description": "Service metadata"
    },
    {
      "name": "waitlist",
      "description": "Join the launch waitlist"
    }
  ],
  "paths": {
    "/api/v1/quick-generate": {
      "post": {
        "tags": [
          "generate"
        ],
        "summary": "Generate fuzzed data from a schema",
        "description": "Parses the SQL DDL in the request body as a stream and returns generated rows. The schema is validated incrementally; on the first syntax error the request is aborted and the connection is closed. Dialect is auto-detected unless `dialect` is given.\n\nThis is the endpoint used by the one-line pipe: `mysqldump --no-data db | curl ... | mysql db_test`.",
        "operationId": "quickGenerate",
        "parameters": [
          {
            "name": "rows",
            "in": "query",
            "description": "Rows generated per table.",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "chaos",
            "in": "query",
            "description": "Percent chance that any eligible value becomes an anomaly. 0 is clean, realistic data.",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100,
              "default": 0
            }
          },
          {
            "name": "seed",
            "in": "query",
            "description": "Seed for reproducible output. The same seed produces byte-for-byte identical data.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "dialect",
            "in": "query",
            "description": "Override dialect detection.",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "postgres",
                "mysql",
                "sqlite",
                "auto"
              ],
              "default": "auto"
            }
          },
          {
            "name": "validate_only",
            "in": "query",
            "description": "Parse and validate the schema, returning a summary (including the resolved semantic type of each column) without generating data. No Accept header is required.",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "Accept",
            "in": "header",
            "description": "Negotiated response format. `text/sql` returns ordered INSERT statements; `application/json` returns a structured payload with metadata. An unsupported value returns 406.",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "text/sql",
                "application/json"
              ]
            }
          },
          {
            "name": "X-Chaos-Hints",
            "in": "header",
            "description": "Override the inferred semantic type of specific columns. Semicolon-separated `[schema.]table.column=type` pairs; the header may be repeated. Unknown types, types incompatible with the column's SQL kind, and hints that match no column are rejected with 400.",
            "required": false,
            "style": "simple",
            "explode": false,
            "schema": {
              "type": "string",
              "example": "users.user_id=identifier; users.email=email"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "SQL DDL (CREATE TABLE statements). Dumps containing SET/GRANT/CREATE INDEX etc. are tolerated and skipped.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              },
              "examples": {
                "schema": {
                  "summary": "A small schema",
                  "value": "CREATE TABLE users (\n  id SERIAL PRIMARY KEY,\n  email VARCHAR(255) NOT NULL UNIQUE,\n  age INT CHECK (age >= 0)\n);"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated data in the negotiated representation, or (with `validate_only=true`) a JSON validation summary.",
            "content": {
              "text/sql": {
                "schema": {
                  "type": "string"
                },
                "example": "-- ChaosData | seed=42 rows=5 chaos=15 anomalies=2\nSET client_encoding TO 'UTF8';\nBEGIN;\nINSERT INTO \"users\" (\"id\", \"email\", \"age\") VALUES\n  (1, 'alex\ud83d\ude80@example.com', 0);\nCOMMIT;"
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeneratedPayload"
                }
              }
            }
          },
          "400": {
            "description": "Invalid schema or invalid hints. For a schema parse error the connection is closed after the response.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "406": {
            "description": "The Accept header does not match a supported representation.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The schema exceeds the configured body limit.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The schema is understood but cannot be generated: it contains no tables, or a generation constraint could not be satisfied.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this client. The Retry-After header says how long to wait before retrying.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "Generation is not configured on this server.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/anomalies": {
      "get": {
        "tags": [
          "anomalies"
        ],
        "summary": "List anomalies and the datatypes they apply to",
        "operationId": "listAnomalies",
        "responses": {
          "200": {
            "description": "The datatype vocabulary and the anomaly catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnomalyCatalog"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/datatypes": {
      "get": {
        "tags": [
          "anomalies"
        ],
        "summary": "List supported datatypes",
        "description": "Every semantic content type (datatype) with its category, accepted aliases, an example value and the anomalies that can apply to it. These are the values accepted by the `X-Chaos-Hints` header.",
        "operationId": "listDataTypes",
        "responses": {
          "200": {
            "description": "The datatype catalog.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DataTypeCatalog"
                }
              }
            }
          }
        }
      }
    },
    "/api": {
      "get": {
        "tags": [
          "meta"
        ],
        "summary": "Service descriptor",
        "operationId": "serviceDescriptor",
        "responses": {
          "200": {
            "description": "Service name and endpoint list.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "service": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "homepage": {
                      "type": "string"
                    },
                    "docs": {
                      "type": "string"
                    },
                    "openapi": {
                      "type": "string"
                    },
                    "endpoints": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/healthz": {
      "get": {
        "tags": [
          "meta"
        ],
        "summary": "Health check",
        "operationId": "health",
        "responses": {
          "200": {
            "description": "The service is up.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "const": "ok"
                    }
                  },
                  "required": [
                    "status"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/waitlist": {
      "post": {
        "tags": [
          "waitlist"
        ],
        "summary": "Join the launch waitlist",
        "description": "Neutral: returns 202 for any valid address, whether or not it was already present, and sends a double opt-in confirmation email. Requires a configured database and the waitlist enabled.",
        "operationId": "joinWaitlist",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WaitlistSignup"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Confirmation email sent if one was needed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "Invalid email address.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "The waitlist is not configured.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/waitlist/confirm": {
      "post": {
        "tags": [
          "waitlist"
        ],
        "summary": "Confirm a waitlist signup",
        "description": "Consumes the token from the confirmation email. Tokens are single use and expire after 7 days.",
        "operationId": "confirmWaitlist",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Confirmed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          },
          "400": {
            "description": "Invalid or expired token.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "The waitlist is not configured.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details.",
        "properties": {
          "type": {
            "type": "string",
            "default": "about:blank"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "instance": {
            "type": "string"
          }
        },
        "required": [
          "title",
          "status"
        ]
      },
      "GeneratedPayload": {
        "type": "object",
        "properties": {
          "metadata": {
            "$ref": "#/components/schemas/GeneratedMetadata"
          },
          "data": {
            "type": "object",
            "description": "Table name to array of row objects, keyed by column name in declaration order.",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "required": [
          "metadata",
          "data"
        ]
      },
      "GeneratedMetadata": {
        "type": "object",
        "properties": {
          "seed": {
            "type": "integer",
            "format": "int64"
          },
          "rows_per_table": {
            "type": "integer"
          },
          "chaos": {
            "type": "integer"
          },
          "anomalies_injected": {
            "type": "integer"
          },
          "duration_ms": {
            "type": "integer"
          },
          "tables": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "rows": {
                  "type": "integer"
                },
                "anomalies": {
                  "type": "integer"
                },
                "order": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "AnomalyCatalog": {
        "type": "object",
        "properties": {
          "datatypes": {
            "type": "array",
            "description": "Every datatype name (also valid as an X-Chaos-Hints value).",
            "items": {
              "type": "string"
            }
          },
          "anomalies": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Anomaly"
            }
          }
        }
      },
      "Anomaly": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "email_plus"
          },
          "unique_safe": {
            "type": "boolean",
            "description": "True when the anomaly transforms the base value and is therefore safe for UNIQUE columns."
          },
          "datatypes": {
            "type": "array",
            "description": "Datatypes this anomaly can apply to.",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "name",
          "unique_safe",
          "datatypes"
        ]
      },
      "DataTypeCatalog": {
        "type": "object",
        "properties": {
          "datatypes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Datatype"
            }
          }
        }
      },
      "Datatype": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "email"
          },
          "category": {
            "type": "string",
            "enum": [
              "string",
              "integer",
              "float",
              "temporal",
              "boolean",
              "json",
              "binary",
              "bit",
              "array",
              "set",
              "enum",
              "network",
              "uuid"
            ]
          },
          "aliases": {
            "type": "array",
            "description": "Alternative X-Chaos-Hints values that resolve to this datatype.",
            "items": {
              "type": "string"
            }
          },
          "example": {
            "description": "A representative value."
          },
          "anomalies": {
            "type": "array",
            "description": "Anomalies that can apply to this datatype (including shared and kind-based ones).",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "name",
          "category",
          "aliases",
          "example",
          "anomalies"
        ]
      },
      "Accepted": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          }
        },
        "required": [
          "status"
        ]
      },
      "WaitlistSignup": {
        "type": "object",
        "required": [
          "email"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "source": {
            "type": "string"
          }
        }
      }
    }
  }
}
