Skip to main content

Relational Seed Data API with Working Foreign Keys

MOCK DATA

A multi-table seed dataset where every foreign key resolves — JSON tables plus topologically ordered SQL that applies with FK checks left on.

Generated test data for fixtures and development

Base URL
/api/relational-seed
Capabilities
2 routes Seedable 8 locales
Last updated
July 29, 2026

GET /api/relational-seed

Returns the tables of one schema in topological order. Every non-null foreign-key value in tables is the primary key of a row in the referenced table of this same response.

Live requestRuns against the public API
No key required
GET/api/relational-seed

Request parameters

Which hand-designed fixture schema to generate: ecommerce (categories → products → customers → orders → order_items), saas (plans → accounts → users → invoices → invoice_items) or blog (tags → authors → posts → comments + post_tags).

Number of parent rows: customers (ecommerce), accounts (saas) or authors (blog). Growing this never changes the rows that were already there.

Child rows per parent: orders, invoices or posts. 0 leaves every dependent table empty instead of inventing rows — two tables for ecommerce and saas, three for blog, and the warning names them.

Grandchild rows per child row: order_items, invoice_items or comments. Ignored when ordersPerCustomer is 0.

Primary/foreign key format: int (1..N per table), uuid (seeded RFC 9562 version-4 layout) or prefixed (cus_4f2a91c0d7b3). Only the identifier columns change.

Active ISO 4217 code, case-insensitive. It fills the currency columns and scales every minor-unit amount by that currency's ISO minor-unit digits. XDR is refused (ISO defines no minor unit for it); no effect on schema=blog.

Determinism anchor. The same seed, parameters and asOf always return byte-identical rows and SQL.

Timestamp anchor: every generated row is dated at or before it (up to 900 days back). Defaults to the current time, so pin it to replay a bundle exactly.

Advanced response options5 options

Locale for the generated data (names, addresses, …).

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/relational-seed"
const res = await fetch("https://randomapi.dev/api/relational-seed");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/relational-seed").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/relational-seed"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 8
schema enum

Which hand-designed fixture schema to generate: ecommerce (categories → products → customers → orders → order_items), saas (plans → accounts → users → invoices → invoice_items) or blog (tags → authors → posts → comments + post_tags).

default: ecommerce
allowed: ecommerce | saas | blog
example: schema=saas
customers int

Number of parent rows: customers (ecommerce), accounts (saas) or authors (blog). Growing this never changes the rows that were already there.

default: 10
allowed: 1 – 50
example: customers=25
ordersPerCustomer int

Child rows per parent: orders, invoices or posts. 0 leaves every dependent table empty instead of inventing rows — two tables for ecommerce and saas, three for blog, and the warning names them.

default: 2
allowed: 0 – 5
example: ordersPerCustomer=3
itemsPerOrder int

Grandchild rows per child row: order_items, invoice_items or comments. Ignored when ordersPerCustomer is 0.

default: 3
allowed: 1 – 6
example: itemsPerOrder=5
idStyle enum

Primary/foreign key format: int (1..N per table), uuid (seeded RFC 9562 version-4 layout) or prefixed (cus_4f2a91c0d7b3). Only the identifier columns change.

default: int
allowed: int | uuid | prefixed
example: idStyle=uuid
currency string

Active ISO 4217 code, case-insensitive. It fills the currency columns and scales every minor-unit amount by that currency's ISO minor-unit digits. XDR is refused (ISO defines no minor unit for it); no effect on schema=blog.

default: USD
allowed: 3 – 3
example: currency=JPY
seed int

Determinism anchor. The same seed, parameters and asOf always return byte-identical rows and SQL.

default: 1
allowed: 0 – 4294967295
example: seed=42
asOf date

Timestamp anchor: every generated row is dated at or before it (up to 900 days back). Defaults to the current time, so pin it to replay a bundle exactly.

example: asOf=2026-01-15T09:00:00Z
Universal parameters Shared response and formatting options 5
locale enum

Locale for the generated data (names, addresses, …).

default: en
allowed: en | da | de | fr | es | it | pt | ja
example: locale=da
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=schema,asOf
exclude list

Return all fields except these (comma-separated).

example: exclude=tables
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 8
schema string

Resolved schema: ecommerce, saas or blog.

example: ecommerce

asOf string (ISO 8601)

Resolved timestamp anchor; no generated row is dated after it.

example: 2026-01-15T09:00:00Z

currency string nullable

ISO 4217 code used for the money columns; null for schema=blog, which has none.

example: USD

idStyle string

Identifier format used for every primary and foreign key.

example: int

rowCount integer

Total rows across all tables (capped at 400).

example: 118

tableOrder string[]

Table names in topological insertion order — parents before the rows that reference them.

example: ["categories","products","customers","orders","order_items"]

foreignKeys object[]

Every foreign key in the schema: table, column, whether it is nullable, and the referenced table/column.

example: [{"table":"products","column":"category_id","nullable":false,"references":{"table":"categories","column":"id"}}]

tables object

The rows themselves, keyed by table name in tableOrder. Every non-null foreign-key value appears as a primary key in the referenced table of this same response.

example: {"categories":[{"id":1,"slug":"home-kitchen","name":"Home & Kitchen"}],"customers":[{"id":1,"email":"emily.carter1@example.com","full_name":"Emily Carter","city":"Portland","country_code":"US","is_active":true,"created_at":"2025-04-18T07:31:44Z"}]}

Documented examples

Build-generated requests and complete responses
5
Ten customers, orders and line items
GET /api/relational-seed
{
  "data": {
    "schema": "ecommerce",
    "asOf": "2026-07-29T08:13:22Z",
    "currency": "USD",
    "idStyle": "int",
    "rowCount": 118,
    "tableOrder": [
      "categories",
      "products",
      "customers",
      "orders",
      "order_items"
    ],
    "foreignKeys": [
      {
        "table": "products",
        "column": "category_id",
        "nullable": false,
        "references": {
          "table": "categories",
          "column": "id"
        }
      },
      {
        "table": "orders",
        "column": "customer_id",
        "nullable": false,
        "references": {
          "table": "customers",
          "column": "id"
        }
      },
      {
        "table": "order_items",
        "column": "order_id",
        "nullable": false,
        "references": {
          "table": "orders",
          "column": "id""generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Reproducible SaaS accounts and invoices
GET /api/relational-seed?schema=saas&customers=6&ordersPerCustomer=3&itemsPerOrder=2&seed=42
{
  "data": {
    "schema": "saas",
    "asOf": "2026-07-29T08:13:22Z",
    "currency": "USD",
    "idStyle": "int",
    "rowCount": 70,
    "tableOrder": [
      "plans",
      "accounts",
      "users",
      "invoices",
      "invoice_items"
    ],
    "foreignKeys": [
      {
        "table": "accounts",
        "column": "plan_id",
        "nullable": false,
        "references": {
          "table": "plans",
          "column": "id"
        }
      },
      {
        "table": "users",
        "column": "account_id",
        "nullable": false,
        "references": {
          "table": "accounts",
          "column": "id"
        }
      },
      {
        "table": "invoices",
        "column": "account_id",
        "nullable": false,
        "references": {
          "table": "accounts",
          "column": "id""generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Blog posts, comments and tag links with UUID keys
GET /api/relational-seed?schema=blog&customers=8&idStyle=uuid&seed=7
{
  "data": {
    "schema": "blog",
    "asOf": "2026-07-29T08:13:22Z",
    "currency": null,
    "idStyle": "uuid",
    "rowCount": 110,
    "tableOrder": [
      "tags",
      "authors",
      "posts",
      "comments",
      "post_tags"
    ],
    "foreignKeys": [
      {
        "table": "posts",
        "column": "author_id",
        "nullable": false,
        "references": {
          "table": "authors",
          "column": "id"
        }
      },
      {
        "table": "comments",
        "column": "post_id",
        "nullable": false,
        "references": {
          "table": "posts",
          "column": "id"
        }
      },
      {
        "table": "comments",
        "column": "author_id",
        "nullable": true,
        "references": {
          "table": "authors",
          "column": "id"
    …
    ]
  }
}
Yen orders with prefixed string keys
GET /api/relational-seed?customers=12&currency=JPY&idStyle=prefixed&ordersPerCustomer=1&itemsPerOrder=4&seed=3
{
  "data": {
    "schema": "ecommerce",
    "asOf": "2026-07-29T08:13:22Z",
    "currency": "JPY",
    "idStyle": "prefixed",
    "rowCount": 100,
    "tableOrder": [
      "categories",
      "products",
      "customers",
      "orders",
      "order_items"
    ],
    "foreignKeys": [
      {
        "table": "products",
        "column": "category_id",
        "nullable": false,
        "references": {
          "table": "categories",
          "column": "id"
        }
      },
      {
        "table": "orders",
        "column": "customer_id",
        "nullable": false,
        "references": {
          "table": "customers",
          "column": "id"
        }
      },
      {
        "table": "order_items",
        "column": "order_id",
        "nullable": false,
        "references": {
          "table": "orders",
          "column": "id""generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Replayable bundle pinned to a fixed anchor
GET /api/relational-seed?asOf=2026-01-15T09:00:00Z&customers=5&seed=99
{
  "data": {
    "schema": "ecommerce",
    "asOf": "2026-01-15T09:00:00Z",
    "currency": "USD",
    "idStyle": "int",
    "rowCount": 73,
    "tableOrder": [
      "categories",
      "products",
      "customers",
      "orders",
      "order_items"
    ],
    "foreignKeys": [
      {
        "table": "products",
        "column": "category_id",
        "nullable": false,
        "references": {
          "table": "categories",
          "column": "id"
        }
      },
      {
        "table": "orders",
        "column": "customer_id",
        "nullable": false,
        "references": {
          "table": "customers",
          "column": "id"
        }
      },
      {
        "table": "order_items",
        "column": "order_id",
        "nullable": false,
        "references": {
          "table": "orders",
          "column": "id""generatedAt": "2026-07-29T08:13:22.000Z"
  }
}

GET /api/relational-seed/sql

CREATE TABLE plus INSERT statements, parents first, for postgres, mysql or sqlite. The script is returned in the sql field — add fields=sql&unwrap=true to pipe it straight into a client.

Live requestRuns against the public API
No key required
GET/api/relational-seed/sql?seed=42

Request parameters

Which hand-designed fixture schema to generate: ecommerce (categories → products → customers → orders → order_items), saas (plans → accounts → users → invoices → invoice_items) or blog (tags → authors → posts → comments + post_tags).

SQL dialect to emit. Each one has its own identifier quoting, column types and literal syntax; nothing outside this list is supported.

Emit CREATE TABLE statements before the INSERTs. Set false to get inserts only, for tables you already created.

Number of parent rows: customers (ecommerce), accounts (saas) or authors (blog). Growing this never changes the rows that were already there.

Child rows per parent: orders, invoices or posts. 0 leaves every dependent table empty instead of inventing rows — two tables for ecommerce and saas, three for blog, and the warning names them.

Grandchild rows per child row: order_items, invoice_items or comments. Ignored when ordersPerCustomer is 0.

Primary/foreign key format: int (1..N per table), uuid (seeded RFC 9562 version-4 layout) or prefixed (cus_4f2a91c0d7b3). Only the identifier columns change.

Active ISO 4217 code, case-insensitive. It fills the currency columns and scales every minor-unit amount by that currency's ISO minor-unit digits. XDR is refused (ISO defines no minor unit for it); no effect on schema=blog.

Determinism anchor. The same seed, parameters and asOf always return byte-identical rows and SQL.

Timestamp anchor: every generated row is dated at or before it (up to 900 days back). Defaults to the current time, so pin it to replay a bundle exactly.

Advanced response options5 options

Locale for the generated data (names, addresses, …).

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/relational-seed/sql?seed=42"
const res = await fetch("https://randomapi.dev/api/relational-seed/sql?seed=42");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/relational-seed/sql?seed=42").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/relational-seed/sql?seed=42"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 10
schema enum

Which hand-designed fixture schema to generate: ecommerce (categories → products → customers → orders → order_items), saas (plans → accounts → users → invoices → invoice_items) or blog (tags → authors → posts → comments + post_tags).

default: ecommerce
allowed: ecommerce | saas | blog
example: schema=saas
dialect enum

SQL dialect to emit. Each one has its own identifier quoting, column types and literal syntax; nothing outside this list is supported.

default: postgres
allowed: postgres | mysql | sqlite
example: dialect=sqlite
includeDdl boolean

Emit CREATE TABLE statements before the INSERTs. Set false to get inserts only, for tables you already created.

default: true
example: includeDdl=false
customers int

Number of parent rows: customers (ecommerce), accounts (saas) or authors (blog). Growing this never changes the rows that were already there.

default: 10
allowed: 1 – 50
example: customers=25
ordersPerCustomer int

Child rows per parent: orders, invoices or posts. 0 leaves every dependent table empty instead of inventing rows — two tables for ecommerce and saas, three for blog, and the warning names them.

default: 2
allowed: 0 – 5
example: ordersPerCustomer=3
itemsPerOrder int

Grandchild rows per child row: order_items, invoice_items or comments. Ignored when ordersPerCustomer is 0.

default: 3
allowed: 1 – 6
example: itemsPerOrder=5
idStyle enum

Primary/foreign key format: int (1..N per table), uuid (seeded RFC 9562 version-4 layout) or prefixed (cus_4f2a91c0d7b3). Only the identifier columns change.

default: int
allowed: int | uuid | prefixed
example: idStyle=uuid
currency string

Active ISO 4217 code, case-insensitive. It fills the currency columns and scales every minor-unit amount by that currency's ISO minor-unit digits. XDR is refused (ISO defines no minor unit for it); no effect on schema=blog.

default: USD
allowed: 3 – 3
example: currency=JPY
seed int

Determinism anchor. The same seed, parameters and asOf always return byte-identical rows and SQL.

default: 1
allowed: 0 – 4294967295
example: seed=42
asOf date

Timestamp anchor: every generated row is dated at or before it (up to 900 days back). Defaults to the current time, so pin it to replay a bundle exactly.

example: asOf=2026-01-15T09:00:00Z
Universal parameters Shared response and formatting options 5
locale enum

Locale for the generated data (names, addresses, …).

default: en
allowed: en | da | de | fr | es | it | pt | ja
example: locale=da
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=schema,dialect
exclude list

Return all fields except these (comma-separated).

example: exclude=sql
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 9
schema string

Resolved schema: ecommerce, saas or blog.

example: ecommerce

dialect string

Dialect the script was rendered for.

example: postgres

idStyle string

Identifier format used for every key column.

example: int

includeDdl boolean

Whether CREATE TABLE statements were included.

example: true

tableOrder string[]

Insertion order of the statements — parents before the rows that reference them.

example: ["categories","products","customers","orders","order_items"]

rowCount integer

Total rows inserted by the script.

example: 118

statementCount integer

Number of executable statements (pragma + CREATE TABLEs + INSERTs).

example: 10

byteLength integer

UTF-8 byte length of the sql field.

example: 14820

sql string

The complete script: header comments, optional DDL, then one multi-row INSERT per non-empty table.

example: CREATE TABLE "categories" ( "id" BIGINT NOT NULL, "slug" TEXT NOT NULL, "name" TEXT NOT NULL, PRIMARY KEY ("id") ); INSERT INTO "categories" ("id", "slug", "name") VALUES (1, 'home-kitchen', 'Home & Kitchen');

Documented examples

Build-generated requests and complete responses
4
PostgreSQL script for the ecommerce schema
GET /api/relational-seed/sql?seed=42
{
  "data": {
    "schema": "ecommerce",
    "dialect": "postgres",
    "idStyle": "int",
    "includeDdl": true,
    "tableOrder": [
      "categories",
      "products",
      "customers",
      "orders",
      "order_items"
    ],
    "rowCount": 118,
    "statementCount": 10,
    "byteLength": 10079,
    "sql": "-- randomapi.dev · relational-seed · schema=ecommerce dialect=postgres idStyle=int\n-- seed=42 asOf=2026-07-29T08:13:22Z · 118 rows across 5 tables\n-- Fixture data for development, demos and CI. Never load it into a production database.\n-- Tables are emitted parents-first, so the script applies with foreign key checks enabled.\n-- No DROP statements: create the target schema (or an empty database) first.\n\nCREATE TABLE \"categories\" (\n  \"id\" BIGINT NOT NULL,\n  \"slug\" TEXT NOT NULL,\n  \"name\" TEXT NOT NULL,\n  PRIMARY KEY (\"id\")\n);\n\nCREATE TABLE \"products\" (\n  \"id\" BIGINT NOT NULL,\n  \"category_id\" BIGINT NOT NULL,\n  \"sku\" TEXT NOT NULL,\n  \"name\" TEXT NOT NULL,\n  \"price_minor\" BIGINT NOT NULL,\n  \"currency\" TEXT NOT NULL,\n  \"in_stock\" BOOLEAN NOT NULL,\n  \"created_at\" TIMESTAMPTZ NOT NULL,\n  PRIMARY KEY (\"id\"),\n  CONSTRAINT \"fk_products_category_id\" FOREIGN KEY (\"category_id\") REFERENCES \"categories\" (\"id\")\n);\n\nCREATE TABLE \"customers\" (\n  \"id\" BIGINT NOT NULL,\n  \"email\" TEXT NOT NULL,\n  \"full_name\" TEXT NOT NULL,\n  \"city\" TEXT NOT NULL,\n  \"country_code\" TEXT NOT NULL,\n  \"is_active\" BOOLEAN NOT NULL,\n  \"created_at\" TIMESTAMPTZ NOT NULL,\n  PRIMARY KEY (\"id\")\n);\n\nCREATE TABLE \"orders\" (\n  \"id\" BIGINT NOT NULL,\n  \"customer_id\" BIGINT NOT NULL,\n  \"order_number\" TEXT NOT NULL,\n  \"status\" TEXT NOT NULL,\n  \"currency\" TEXT NOT NULL,\n  \"total_minor\" BIGINT NOT NULL,\n  \"placed_at\" TIMESTAMPTZ NOT NULL,\n  \"shipped_at\" TIMESTAMPTZ,\n  PRIMARY KEY (\"id\"),\n  CONSTRAINT \"fk_orders_customer_id\" FOREIGN KEY (\"customer_id\") REFERENCES \"customers\" (\"id\")\n);\n\nCREATE TABLE \"order_items\" (\n  \"id\" BIGINT NOT NULL,\n  \"order_id\" BIGINT NOT NULL,\n  \"product_id\" BIGINT NOT NULL,\n  \"quantity\" INTEGER NOT NULL,\n  \"unit_price_minor\" BIGINT NOT NULL,\n  \"line_total_minor\" BIGINT NOT NULL,\n  PRIMARY KEY (\"id\"),\n  CONSTRAINT \"fk_order_items_order_id\" FOREIGN KEY (\"order_id\") REFERENCES \"orders\" (\"id\"),\n  CONSTRAINT \"fk_order_items_product_id\" FOREIGN KEY (\"product_id\") REFERENCES \"products\" (\"id\")\n);\n\nINSERT INTO \"categories\" (\"id\", \"slug\", \"name\") VALUES\n  (1, 'home-kitchen', 'Home & Kitchen'),\n  (2, 'childrens-toys', 'Children''s Toys'),\n  (3, 'outdoor-garden', 'Outdoor & Garden'),\n  (4, 'office-supplies', 'Office Supplies');\n\nINSERT INTO \"products\" (\"id\", \"category_id\", \"sku\", \"name\", \"price_minor\", \"currency\", \"in_stock\", \"created_at\") VALUES\n  (1, 2, 'SKU-5AJ9Y3GU', 'Handmade Steel Cheese', 18900, 'USD', TRUE, '2024-08-31 04:18:50+00:00'),\n  (2, 4, 'SKU-NECVGX4L', 'Luxurious Concrete Table', 46400, 'USD', TRUE, '2024-07-01 23:21:16+00:00'),\n  (3, 1, 'SKU-PAWG246G', 'Generic Concrete Mouse', 17800, 'USD', TRUE, '2024-12-21 08:57:01+00:00'),\n  (4, 1, 'SKU-C4S6YHD7', 'Refined Cotton Shirt', 28400, 'USD', TRUE, '2025-02-11 09:09:49+00:00'),\n  (5, 2, 'SKU-FTSGPUWW', 'Fresh Concrete Hat', 13100, 'USD', TRUE, '2024-11-06 05:23:57+00:00'),\n  (6, 3, 'SKU-WFGRDNHH', 'Frozen Silk Gloves', 17300, 'USD', TRUE, '2024-07-06 10:09:42+00:00'),\n  (7, 1, 'SKU-B6XHGHZQ', 'Fresh Metal Salad', 28500, 'USD', TRUE, '2025-04-30 19:25:11+00:00'),\n  (8, 2, 'SKU-72R8UKLU', 'Oriental Gold Tuna', 8400, 'USD', TRUE, '2024-12-09 16:01:49+00:00'),\n  (9, 4, 'SKU-QDX4ANC3', 'Fantastic Silk Chicken', 42500, 'USD', TRUE, '2024-05-08 20:32:03+00:00'),\n  (10, 2, 'SKU-FV8JSSVT', 'Gorgeous Cotton Bike', 49800, 'USD', FALSE, '2024-03-28 15:20:35+00:00'),\n  (11, 3, 'SKU-PRNMKKA7', 'Ergonomic Ceramic Bike', 7300, 'USD', TRUE, '2025-04-15 00:44:59+00:00'),\n  (12, 4, 'SKU-UWC98TG4', 'Soft Gold Fish', 1300, 'USD', FALSE, '2024-06-24 09:22:11+00:00'),\n  (13, 2, 'SKU-JHVVXZZE', 'Tasty Marble Chair', 19600, 'USD', TRUE, '2025-07-29 20:23:51+00:00'),\n  (14, 2, 'SKU-6MXCQYEF', 'Gorgeous Silk Bike', 37400, 'USD', FALSE, '2025-06-04 00:14:36+00:00'),\n  (15, 1, 'SKU-TNNXDGYF', 'Fantastic Bronze Tuna', 36200, 'USD', TRUE, '2024-06-05 06:25:25+00:00'),\n  (16, 2, 'SKU-2MGT55A7', 'Fresh Cotton Sausages', 38300, 'USD', TRUE, '2024-12-31 02:38:56+00:00'),\n  (17, 3, 'SKU-48TUXME6', 'Soft Bamboo Mouse', 45700, 'USD', TRUE, '2024-07-13 01:15:09+00:00'),\n  (18, 1, 'SKU-A4T68A8R', 'Luxurious Steel Towels', 38500, 'USD', TRUE, '2024-11-30 00:56:47+00:00'),\n  (19, 4, 'SKU-9QVWGFWJ', 'Electronic Bronze Soap', 39800, 'USD', TRUE, '2024-10-18 20:06:44+00:00'),\n  (20, 1, 'SKU-68F7SP3C', 'Frozen Aluminum Bacon', 43600, 'USD', TRUE, '2025-02-10 04:10:10+00:00'),\n  (21, 1, 'SKU-BT3PNLQ3', 'Licensed Aluminum Car', 30600, 'USD', TRUE, '2025-12-28 09:47:43+00:00'),\n  (22, 3, 'SKU-UV655HG5', 'Fantastic Silk Pants', 17200, 'USD', TRUE, '2025-10-17 13:08:02+00:00'),\n  (23, 3, 'SKU-4PE6ZVV2', 'Fantastic Marble Bike', 46700, 'USD', TRUE, '2024-11-05 22:17:50+00:00'),\n  (24, 1, 'SKU-2EA7MNDR', 'Gorgeous Concrete Mouse', 37500, 'USD', TRUE, '2025-04-23 12:54:12+00:00');\n\nINSERT INTO \"customers\" (\"id\", \"email\", \"full_name\", \"city\", \"country_code\", \"is_active\", \"created_at\") VALUES\n  (1, 'kristie.heaneykutch1@example.com', 'Kristie Heaney-Kutch', 'Natalietown', 'US', TRUE, '2025-07-10 22:35:48+00:00'),\n  (2, 'vaughn.hackett2@example.com', 'Vaughn Hackett', 'West Wilson', 'US', TRUE, '2024-05-05 19:54:14+00:00'),\n  (3, 'marvin.cassin3@example.com', 'Marvin Cassin', 'Fort Joy', 'US', TRUE, '2025-07-09 10:56:17+00:00'),\n  (4, 'dwight.mohr4@example.com', 'Dwight Mohr', 'Aspen Hill', 'US', TRUE, '2025-07-09 00:41:26+00:00'),\n  (5, 'arlene.wisozk5@example.com', 'Arlene Wisozk', 'Fort Garnettfurt', 'US', TRUE, '2025-01-02 02:50:17+00:00'),\n  (6, 'catherine.kutch6@example.com', 'Catherine Kutch', 'North Blakeside', 'US', TRUE, '2026-06-22 21:52:46+00:00'),\n  (7, 'ryan.gerhold7@example.com', 'Ryan Gerhold', 'Lucieborough', 'US', TRUE, '2025-02-07 07:11:34+00:00'),\n  (8, 'domenick.funk8@example.com', 'Domenick Funk', 'West Liana', 'US', TRUE, '2026-02-12 16:45:17+00:00'),\n  (9, 'webster.walter9@example.com', 'Webster Walter', 'Torrance', 'US', TRUE, '2025-05-22 16:52:07+00:00'),\n  (10, 'beaulah.walter10@example.com', 'Beaulah Walter', 'Joycebury', 'US', TRUE, '2025-11-23 06:56:32+00:00');\n\nINSERT INTO \"orders\" (\"id\", \"customer_id\", \"order_number\", \"status\", \"currency\", \"total_minor\", \"placed_at\", \"shipped_at\") VALUES\n  (1, 1, 'ORD-2026-00001', 'paid', 'USD', 177500, '2026-05-21 02:04:54+00:00', NULL),\n  (2, 1, 'ORD-2025-00002', 'shipped', 'USD', 377600, '2025-09-11 18:53:25+00:00', '2025-09-15 18:53:25+00:00'),\n  (3, 2, 'ORD-2026-00003', 'paid', 'USD', 315000, '2026-04-03 01:16:28+00:00', NULL),\n  (4, 2, 'ORD-2025-00004', 'paid', 'USD', 217300, '2025-07-18 17:23:44+00:00', NULL),\n  (5, 3, 'ORD-2026-00005', 'paid', 'USD', 329000, '2026-07-10 22:45:52+00:00', NULL),\n  (6, 3, 'ORD-2026-00006', 'paid', 'USD', 524500, '2026-06-27 16:40:02+00:00', NULL),\n  (7, 4, 'ORD-2026-00007', 'paid', 'USD', 400300, '2026-07-28 14:37:32+00:00', NULL),\n  (8, 4, 'ORD-2026-00008', 'shipped', 'USD', 269300, '2026-06-03 06:41:34+00:00', '2026-06-05 06:41:34+00:00'),\n  (9, 5, 'ORD-2025-00009', 'cancelled', 'USD', 164300, '2025-05-11 01:15:28+00:00', NULL),\n  (10, 5, 'ORD-2025-00010', 'paid', 'USD', 418100, '2025-02-22 14:49:58+00:00', NULL),\n  (11, 6, 'ORD-2026-00011', 'paid', 'USD', 217100, '2026-07-09 08:39:43+00:00', NULL),\n  (12, 6, 'ORD-2026-00012', 'cancelled', 'USD', 485700, '2026-06-27 20:25:37+00:00', NULL),\n  (13, 7, 'ORD-2026-00013', 'shipped', 'USD', 243600, '2026-04-18 19:13:20+00:00', '2026-04-22 19:13:20+00:00'),\n  (14, 7, 'ORD-2026-00014', 'pending', 'USD', 231200, '2026-03-15 00:05:24+00:00', NULL),\n  (15, 8, 'ORD-2026-00015', 'shipped', 'USD', 532300, '2026-03-15 10:25:33+00:00', '2026-03-18 10:25:33+00:00'),\n  (16, 8, 'ORD-2026-00016', 'paid', 'USD', 344200, '2026-07-06 13:45:28+00:00', NULL),\n  (17, 9, 'ORD-2025-00017', 'pending', 'USD', 394600, '2025-06-16 03:21:09+00:00', NULL),\n  (18, 9, 'ORD-2025-00018', 'shipped', 'USD', 209400, '2025-11-25 10:24:22+00:00', '2025-11-27 10:24:22+00:00'),\n  (19, 10, 'ORD-2026-00019', 'pending', 'USD', 162100, '2026-06-03 15:00:48+00:00', NULL),\n  (20, 10, 'ORD-2025-00020', 'shipped', 'USD', 311900, '2025-12-17 05:17:13+00:00', '2025-12-22 05:17:13+00:00');\n\nINSERT INTO \"order_items\" (\"id\", \"order_id\", \"product_id\", \"quantity\", \"unit_price_minor\", \"line_total_minor\") VALUES\n  (1, 1, 21, 4, 30600, 122400),\n  (2, 1, 1, 1, 18900, 18900),\n  (3, 1, 15, 1, 36200, 36200),\n  (4, 2, 15, 2, 36200, 72400),\n  (5, 2, 17, 4, 45700, 182800),\n  (6, 2, 21, 4, 30600, 122400),\n  (7, 3, 19, 3, 39800, 119400),\n  (8, 3, 11, 2, 7300, 14600),\n  (9, 3, 15, 5, 36200, 181000),\n  (10, 4, 4, 4, 28400, 113600),\n  (11, 4, 23, 1, 46700, 46700),\n  (12, 4, 7, 2, 28500, 57000),\n  (13, 5, 19, 5, 39800, 199000),\n  (14, 5, 13, 4, 19600, 78400),\n  (15, 5, 22, 3, 17200, 51600),\n  (16, 6, 10, 4, 49800, 199200),\n  (17, 6, 17, 4, 45700, 182800),\n  (18, 6, 7, 5, 28500, 142500),\n  (19, 7, 9, 4, 42500, 170000),\n  (20, 7, 7, 3, 28500, 85500),\n  (21, 7, 15, 4, 36200, 144800),\n  (22, 8, 1, 1, 18900, 18900),\n  (23, 8, 17, 5, 45700, 228500),\n  (24, 8, 11, 3, 7300, 21900),\n  (25, 9, 5, 2, 13100, 26200),\n  (26, 9, 17, 2, 45700, 91400),\n  (27, 9, 23, 1, 46700, 46700),\n  (28, 10, 10, 5, 49800, 249000),\n  (29, 10, 20, 3, 43600, 130800),\n  (30, 10, 16, 1, 38300, 38300),\n  (31, 11, 12, 4, 1300, 5200),\n  (32, 11, 24, 1, 37500, 37500),\n  (33, 11, 20, 4, 43600, 174400),\n  (34, 12, 2, 5, 46400, 232000),\n  (35, 12, 21, 2, 30600, 61200),\n  (36, 12, 18, 5, 38500, 192500),\n  (37, 13, 3, 5, 17800, 89000),\n  (38, 13, 19, 2, 39800, 79600),\n  (39, 13, 24, 2, 37500, 75000),\n  (40, 14, 15, 5, 36200, 181000),\n  (41, 14, 13, 1, 19600, 19600),\n  (42, 14, 21, 1, 30600, 30600),\n  (43, 15, 23, 5, 46700, 233500),\n  (44, 15, 18, 4, 38500, 154000),\n  (45, 15, 15, 4, 36200, 144800),\n  (46, 16, 18, 2, 38500, 77000),\n  (47, 16, 15, 4, 36200, 144800),\n  (48, 16, 21, 4, 30600, 122400),\n  (49, 17, 23, 1, 46700, 46700),\n  (50, 17, 17, 5, 45700, 228500),\n  (51, 17, 19, 3, 39800, 119400),\n  (52, 18, 2, 4, 46400, 185600),\n  (53, 18, 6, 1, 17300, 17300),\n  (54, 18, 12, 5, 1300, 6500),\n  (55, 19, 19, 3, 39800, 119400),\n  (56, 19, 24, 1, 37500, 37500),\n  (57, 19, 12, 4, 1300, 5200),\n  (58, 20, 8, 4, 8400, 33600),\n  (59, 20, 10, 1, 49800, 49800),\n  (60, 20, 17, 5, 45700, 228500);\n"
  },
  "meta": {
    "endpoint": "relational-seed",
    "route": "/sql",
    "locale": "en",
    "params": {
      "schema": "ecommerce",
      "dialect": "postgres",
      "includeDdl": true,
      "customers": 10,
      "ordersPerCustomer": 2,
      "itemsPerOrder": 3,
      "idStyle": "int",
      "currency": "USD",
      "seed": 42,
      "asOf": "2026-07-29T08:13:22.000Z"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
SQLite script for a small blog
GET /api/relational-seed/sql?dialect=sqlite&schema=blog&customers=5&seed=7
{
  "data": {
    "schema": "blog",
    "dialect": "sqlite",
    "idStyle": "int",
    "includeDdl": true,
    "tableOrder": [
      "tags",
      "authors",
      "posts",
      "comments",
      "post_tags"
    ],
    "rowCount": 71,
    "statementCount": 11,
    "byteLength": 7786,
    "sql": "-- randomapi.dev · relational-seed · schema=blog dialect=sqlite idStyle=int\n-- seed=7 asOf=2026-07-29T08:13:22Z · 71 rows across 5 tables\n-- Fixture data for development, demos and CI. Never load it into a production database.\n-- Tables are emitted parents-first, so the script applies with foreign key checks enabled.\n-- No DROP statements: create the target schema (or an empty database) first.\n\nPRAGMA foreign_keys = ON;\n\nCREATE TABLE \"tags\" (\n  \"id\" INTEGER NOT NULL,\n  \"slug\" TEXT NOT NULL,\n  \"name\" TEXT NOT NULL,\n  \"description\" TEXT NOT NULL,\n  PRIMARY KEY (\"id\")\n);\n\nCREATE TABLE \"authors\" (\n  \"id\" INTEGER NOT NULL,\n  \"email\" TEXT NOT NULL,\n  \"display_name\" TEXT NOT NULL,\n  \"country_code\" TEXT NOT NULL,\n  \"is_staff\" INTEGER NOT NULL,\n  \"joined_at\" TEXT NOT NULL,\n  PRIMARY KEY (\"id\")\n);\n\nCREATE TABLE \"posts\" (\n  \"id\" INTEGER NOT NULL,\n  \"author_id\" INTEGER NOT NULL,\n  \"slug\" TEXT NOT NULL,\n  \"title\" TEXT NOT NULL,\n  \"status\" TEXT NOT NULL,\n  \"word_count\" INTEGER NOT NULL,\n  \"comment_count\" INTEGER NOT NULL,\n  \"published_at\" TEXT NOT NULL,\n  \"updated_at\" TEXT,\n  PRIMARY KEY (\"id\"),\n  CONSTRAINT \"fk_posts_author_id\" FOREIGN KEY (\"author_id\") REFERENCES \"authors\" (\"id\")\n);\n\nCREATE TABLE \"comments\" (\n  \"id\" INTEGER NOT NULL,\n  \"post_id\" INTEGER NOT NULL,\n  \"author_id\" INTEGER,\n  \"guest_name\" TEXT,\n  \"body\" TEXT NOT NULL,\n  \"is_approved\" INTEGER NOT NULL,\n  \"created_at\" TEXT NOT NULL,\n  PRIMARY KEY (\"id\"),\n  CONSTRAINT \"fk_comments_post_id\" FOREIGN KEY (\"post_id\") REFERENCES \"posts\" (\"id\"),\n  CONSTRAINT \"fk_comments_author_id\" FOREIGN KEY (\"author_id\") REFERENCES \"authors\" (\"id\")\n);\n\nCREATE TABLE \"post_tags\" (\n  \"post_id\" INTEGER NOT NULL,\n  \"tag_id\" INTEGER NOT NULL,\n  PRIMARY KEY (\"post_id\", \"tag_id\"),\n  CONSTRAINT \"fk_post_tags_post_id\" FOREIGN KEY (\"post_id\") REFERENCES \"posts\" (\"id\"),\n  CONSTRAINT \"fk_post_tags_tag_id\" FOREIGN KEY (\"tag_id\") REFERENCES \"tags\" (\"id\")\n);\n\nINSERT INTO \"tags\" (\"id\", \"slug\", \"name\", \"description\") VALUES\n  (1, 'engineering', 'Engineering', 'How the team builds and ships.'),\n  (2, 'product', 'Product', 'What we''re shipping, and why.'),\n  (3, 'design', 'Design', 'Interface, typography and motion notes.'),\n  (4, 'operations', 'Operations', 'Runbooks, on-call and incident reviews.'),\n  (5, 'research', 'Research', 'Interviews, benchmarks and prototypes.'),\n  (6, 'changelog', 'Changelog', 'Release notes for every shipped change.');\n\nINSERT INTO \"authors\" (\"id\", \"email\", \"display_name\", \"country_code\", \"is_staff\", \"joined_at\") VALUES\n  (1, 'judge.schmitt1@example.com', 'Judge Schmitt', 'US', 0, '2024-08-29T22:44:29Z'),\n  (2, 'alberta.nienow2@example.com', 'Alberta Nienow', 'US', 1, '2025-09-30T07:40:02Z'),\n  (3, 'tyson.jerde3@example.com', 'Tyson Jerde', 'US', 0, '2024-08-28T16:21:41Z'),\n  (4, 'cleveland.wiza4@example.com', 'Cleveland Wiza', 'US', 1, '2025-02-15T12:57:50Z'),\n  (5, 'merl.kohler5@example.com', 'Merl Kohler', 'US', 0, '2024-07-01T08:36:59Z');\n\nINSERT INTO \"posts\" (\"id\", \"author_id\", \"slug\", \"title\", \"status\", \"word_count\", \"comment_count\", \"published_at\", \"updated_at\") VALUES\n  (1, 1, 'why-our-p99-didn-t-move-after-caching-1', 'Why our p99 didn''t move after caching', 'published', 2200, 3, '2026-06-25T04:42:16Z', NULL),\n  (2, 1, 'reading-the-flame-graph-before-the-code-2', 'Reading the flame graph before the code', 'published', 1066, 3, '2026-01-07T16:14:49Z', '2026-03-31T16:14:49Z'),\n  (3, 2, 'why-our-p99-didn-t-move-after-caching-3', 'Why our p99 didn''t move after caching', 'archived', 466, 3, '2026-06-07T00:06:53Z', NULL),\n  (4, 2, 'what-we-learned-migrating-to-a-queue-4', 'What we learned migrating to a queue', 'published', 2016, 3, '2026-06-06T03:47:48Z', NULL),\n  (5, 3, 'reading-the-flame-graph-before-the-code-5', 'Reading the flame graph before the code', 'published', 2055, 3, '2026-05-24T10:09:07Z', NULL),\n  (6, 3, 'retry-budgets-and-where-they-leak-6', 'Retry budgets, and where they leak', 'published', 2355, 3, '2025-05-28T03:19:45Z', '2025-08-09T03:19:45Z'),\n  (7, 4, 'our-incident-review-template-7', 'Our incident review template', 'published', 1894, 3, '2025-09-02T16:41:40Z', '2025-09-05T16:41:40Z'),\n  (8, 4, 'how-we-size-a-database-index-8', 'How we size a database index', 'published', 2040, 3, '2026-07-13T00:07:33Z', NULL),\n  (9, 5, 'our-incident-review-template-9', 'Our incident review template', 'published', 2051, 3, '2025-06-24T01:25:41Z', '2025-07-17T01:25:41Z'),\n  (10, 5, 'reading-the-flame-graph-before-the-code-10', 'Reading the flame graph before the code', 'published', 1077, 3, '2024-08-21T06:44:31Z', '2024-10-05T06:44:31Z');\n\nINSERT INTO \"comments\" (\"id\", \"post_id\", \"author_id\", \"guest_name\", \"body\", \"is_approved\", \"created_at\") VALUES\n  (1, 1, 1, NULL, 'We hit the same thing last quarter.', 1, '2026-07-08T19:20:04Z'),\n  (2, 1, 1, NULL, 'Any numbers on the memory overhead?', 1, '2026-07-12T23:00:42Z'),\n  (3, 1, NULL, 'Modesto Vandervort', 'Great write-up — the diagram made it click.', 1, '2026-07-23T11:54:00Z'),\n  (4, 2, 1, NULL, 'We hit the same thing last quarter.', 0, '2026-06-21T15:22:08Z'),\n  (5, 2, 1, NULL, 'Doesn''t this break when the queue is empty?', 1, '2026-03-15T11:02:27Z'),\n  (6, 2, 1, NULL, 'Great write-up — the diagram made it click.', 1, '2026-07-15T12:08:59Z'),\n  (7, 3, 1, NULL, 'Would love a follow-up on the rollback path.', 1, '2026-06-14T01:47:17Z'),\n  (8, 3, 1, NULL, 'We hit the same thing last quarter.', 0, '2026-07-13T07:38:49Z'),\n  (9, 3, NULL, 'Michele Murray', 'The second example has a typo, I think.', 1, '2026-07-02T11:10:15Z'),\n  (10, 4, 2, NULL, 'Would love a follow-up on the rollback path.', 1, '2026-07-26T01:42:11Z'),\n  (11, 4, 1, NULL, 'Bookmarking this for the next migration.', 1, '2026-06-29T21:42:28Z'),\n  (12, 4, 1, NULL, 'Bookmarking this for the next migration.', 1, '2026-06-16T22:37:12Z'),\n  (13, 5, 3, NULL, 'Great write-up — the diagram made it click.', 1, '2026-07-21T04:17:31Z'),\n  (14, 5, NULL, 'Leticia Rippin', 'The second example has a typo, I think.', 1, '2026-07-19T04:28:59Z'),\n  (15, 5, 2, NULL, 'This saved me an afternoon, thank you.', 1, '2026-06-27T09:45:46Z'),\n  (16, 6, 1, NULL, 'This saved me an afternoon, thank you.', 1, '2025-06-21T09:23:23Z'),\n  (17, 6, 2, NULL, 'We hit the same thing last quarter.', 1, '2025-08-05T03:10:40Z'),\n  (18, 6, 1, NULL, 'This saved me an afternoon, thank you.', 1, '2025-12-24T05:50:05Z'),\n  (19, 7, 2, NULL, 'Would love a follow-up on the rollback path.', 1, '2026-03-16T20:21:49Z'),\n  (20, 7, 4, NULL, 'This saved me an afternoon, thank you.', 1, '2026-05-15T22:46:27Z'),\n  (21, 7, 4, NULL, 'The second example has a typo, I think.', 1, '2025-10-18T20:54:20Z'),\n  (22, 8, 2, NULL, 'Would love a follow-up on the rollback path.', 1, '2026-07-25T07:00:25Z'),\n  (23, 8, NULL, 'Kristie Armstrong', 'Doesn''t this break when the queue is empty?', 1, '2026-07-27T10:52:22Z'),\n  (24, 8, 3, NULL, 'Great write-up — the diagram made it click.', 1, '2026-07-18T16:58:51Z'),\n  (25, 9, 4, NULL, 'Great write-up — the diagram made it click.', 1, '2026-07-22T22:42:25Z'),\n  (26, 9, NULL, 'Sheri Boyer', 'Bookmarking this for the next migration.', 1, '2026-05-07T12:06:49Z'),\n  (27, 9, 5, NULL, 'Doesn''t this break when the queue is empty?', 1, '2026-02-02T14:13:38Z'),\n  (28, 10, 5, NULL, 'Great write-up — the diagram made it click.', 1, '2025-12-12T02:19:21Z'),\n  (29, 10, 4, NULL, 'The second example has a typo, I think.', 1, '2025-07-09T11:21:16Z'),\n  (30, 10, NULL, 'Dwight Weissnat', 'Doesn''t this break when the queue is empty?', 1, '2025-07-01T07:39:49Z');\n\nINSERT INTO \"post_tags\" (\"post_id\", \"tag_id\") VALUES\n  (1, 4),\n  (1, 6),\n  (2, 6),\n  (2, 1),\n  (3, 6),\n  (3, 5),\n  (4, 3),\n  (4, 5),\n  (5, 3),\n  (5, 6),\n  (6, 3),\n  (6, 4),\n  (7, 2),\n  (7, 3),\n  (8, 4),\n  (8, 3),\n  (9, 1),\n  (9, 2),\n  (10, 3),\n  (10, 6);\n"
  },
  "meta": {
    "endpoint": "relational-seed",
    "route": "/sql",
    "locale": "en",
    "params": {
      "schema": "blog",
      "dialect": "sqlite",
      "includeDdl": true,
      "customers": 5,
      "ordersPerCustomer": 2,
      "itemsPerOrder": 3,
      "idStyle": "int",
      "currency": "USD",
      "seed": 7,
      "asOf": "2026-07-29T08:13:22.000Z"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z",
    "warnings": [
      "Schema 'blog' has no money columns, so the resolved 'currency' (USD) is not applied to any column and the response reports \"currency\": null."
    ]
  }
}
MySQL inserts only, tables already exist
GET /api/relational-seed/sql?dialect=mysql&includeDdl=false&customers=4&seed=11
{
  "data": {
    "schema": "ecommerce",
    "dialect": "mysql",
    "idStyle": "int",
    "includeDdl": false,
    "tableOrder": [
      "categories",
      "products",
      "customers",
      "orders",
      "order_items"
    ],
    "rowCount": 64,
    "statementCount": 5,
    "byteLength": 5203,
    "sql": "-- randomapi.dev · relational-seed · schema=ecommerce dialect=mysql idStyle=int\n-- seed=11 asOf=2026-07-29T08:13:22Z · 64 rows across 5 tables\n-- Fixture data for development, demos and CI. Never load it into a production database.\n-- Tables are emitted parents-first, so the script applies with foreign key checks enabled.\n-- No DROP statements: create the target schema (or an empty database) first.\n\nINSERT INTO `categories` (`id`, `slug`, `name`) VALUES\n  (1, 'home-kitchen', 'Home & Kitchen'),\n  (2, 'childrens-toys', 'Children''s Toys'),\n  (3, 'outdoor-garden', 'Outdoor & Garden'),\n  (4, 'office-supplies', 'Office Supplies');\n\nINSERT INTO `products` (`id`, `category_id`, `sku`, `name`, `price_minor`, `currency`, `in_stock`, `created_at`) VALUES\n  (1, 3, 'SKU-CSR2Q7K3', 'Recycled Wooden Hat', 46900, 'USD', 0, '2025-02-24 11:55:31'),\n  (2, 2, 'SKU-L372DK5Y', 'Rustic Bamboo Computer', 21400, 'USD', 0, '2024-07-09 20:45:27'),\n  (3, 1, 'SKU-DUQXXPH9', 'Modern Steel Ball', 9000, 'USD', 1, '2025-09-02 01:56:53'),\n  (4, 3, 'SKU-M3P7ZYLY', 'Awesome Bamboo Ball', 40800, 'USD', 1, '2025-03-10 21:01:24'),\n  (5, 3, 'SKU-BRLUJ5Y6', 'Small Aluminum Towels', 4500, 'USD', 1, '2025-11-08 15:59:40'),\n  (6, 4, 'SKU-PHQ5BWQM', 'Tasty Silk Salad', 46600, 'USD', 1, '2024-05-05 15:11:18'),\n  (7, 2, 'SKU-8JHQZH6N', 'Tasty Marble Towels', 1600, 'USD', 1, '2024-02-17 04:01:40'),\n  (8, 2, 'SKU-DT8D4CNT', 'Handcrafted Bamboo Keyboard', 18900, 'USD', 1, '2025-08-27 01:59:42'),\n  (9, 3, 'SKU-YSEUVKCD', 'Ergonomic Concrete Fish', 9800, 'USD', 1, '2025-05-28 13:07:06'),\n  (10, 2, 'SKU-XJKLYD8K', 'Intelligent Marble Cheese', 20500, 'USD', 1, '2024-09-02 12:24:12'),\n  (11, 3, 'SKU-ZKH9SXQA', 'Bespoke Gold Sausages', 36200, 'USD', 1, '2024-08-01 15:01:44'),\n  (12, 4, 'SKU-Q4K8J6GU', 'Oriental Gold Tuna', 38700, 'USD', 0, '2024-12-08 05:36:03'),\n  (13, 4, 'SKU-JX2PJXVS', 'Intelligent Gold Hat', 15500, 'USD', 1, '2025-08-07 14:44:42'),\n  (14, 3, 'SKU-9Y7WBHJN', 'Oriental Metal Shirt', 24500, 'USD', 1, '2025-08-18 02:22:38'),\n  (15, 2, 'SKU-2SB7YFBU', 'Sleek Aluminum Bacon', 12200, 'USD', 1, '2025-08-24 21:03:18'),\n  (16, 1, 'SKU-5JVK3GCB', 'Handmade Gold Soap', 20900, 'USD', 1, '2025-03-21 02:58:17'),\n  (17, 1, 'SKU-A6RUHUMW', 'Frozen Ceramic Table', 9000, 'USD', 1, '2024-11-13 15:51:54'),\n  (18, 4, 'SKU-GBVYZ5B5', 'Ergonomic Bronze Bacon', 8900, 'USD', 1, '2025-10-12 09:33:10'),\n  (19, 1, 'SKU-UEDYHLWP', 'Modern Aluminum Towels', 16300, 'USD', 0, '2025-06-29 14:06:46'),\n  (20, 4, 'SKU-UBQBA42W', 'Luxurious Plastic Gloves', 22400, 'USD', 1, '2025-08-31 05:24:12'),\n  (21, 4, 'SKU-CS95GG5E', 'Fresh Concrete Sausages', 45700, 'USD', 1, '2024-06-14 08:30:18'),\n  (22, 4, 'SKU-7EUVKG4U', 'Oriental Cotton Computer', 33200, 'USD', 0, '2025-06-14 06:53:48'),\n  (23, 2, 'SKU-XE5QE279', 'Handcrafted Gold Hat', 10900, 'USD', 1, '2025-06-03 16:17:07'),\n  (24, 2, 'SKU-VFGNBCAX', 'Rustic Steel Keyboard', 6300, 'USD', 0, '2024-08-23 23:17:56');\n\nINSERT INTO `customers` (`id`, `email`, `full_name`, `city`, `country_code`, `is_active`, `created_at`) VALUES\n  (1, 'doug.jaskolski1@example.com', 'Doug Jaskolski', 'South Sheliaborough', 'US', 1, '2025-12-09 06:38:35'),\n  (2, 'tomas.durgan2@example.com', 'Tomas Durgan', 'Wildermanstead', 'US', 1, '2025-04-01 08:22:22'),\n  (3, 'chaim.hamill3@example.com', 'Chaim Hamill', 'Nilsborough', 'US', 1, '2024-07-11 07:37:17'),\n  (4, 'mack.schroeder4@example.com', 'Mack Schroeder', 'Bennyfield', 'US', 1, '2024-04-24 22:36:33');\n\nINSERT INTO `orders` (`id`, `customer_id`, `order_number`, `status`, `currency`, `total_minor`, `placed_at`, `shipped_at`) VALUES\n  (1, 1, 'ORD-2026-00001', 'cancelled', 'USD', 133800, '2026-03-13 11:31:24', NULL),\n  (2, 1, 'ORD-2025-00002', 'pending', 'USD', 315800, '2025-12-10 19:51:46', NULL),\n  (3, 2, 'ORD-2026-00003', 'shipped', 'USD', 115800, '2026-03-17 11:21:16', '2026-03-19 11:21:16'),\n  (4, 2, 'ORD-2025-00004', 'paid', 'USD', 336200, '2025-06-20 07:49:11', NULL),\n  (5, 3, 'ORD-2024-00005', 'cancelled', 'USD', 62400, '2024-10-26 22:18:18', NULL),\n  (6, 3, 'ORD-2025-00006', 'shipped', 'USD', 239800, '2025-06-17 05:38:49', '2025-06-19 05:38:49'),\n  (7, 4, 'ORD-2024-00007', 'shipped', 'USD', 210300, '2024-07-27 16:32:43', '2024-07-29 16:32:43'),\n  (8, 4, 'ORD-2026-00008', 'shipped', 'USD', 131600, '2026-05-01 21:29:47', '2026-05-05 21:29:47');\n\nINSERT INTO `order_items` (`id`, `order_id`, `product_id`, `quantity`, `unit_price_minor`, `line_total_minor`) VALUES\n  (1, 1, 2, 2, 21400, 42800),\n  (2, 1, 10, 4, 20500, 82000),\n  (3, 1, 3, 1, 9000, 9000),\n  (4, 2, 18, 2, 8900, 17800),\n  (5, 2, 12, 5, 38700, 193500),\n  (6, 2, 16, 5, 20900, 104500),\n  (7, 3, 3, 5, 9000, 45000),\n  (8, 3, 9, 5, 9800, 49000),\n  (9, 3, 23, 2, 10900, 21800),\n  (10, 4, 13, 2, 15500, 31000),\n  (11, 4, 21, 4, 45700, 182800),\n  (12, 4, 4, 3, 40800, 122400),\n  (13, 5, 12, 1, 38700, 38700),\n  (14, 5, 8, 1, 18900, 18900),\n  (15, 5, 7, 3, 1600, 4800),\n  (16, 6, 22, 3, 33200, 99600),\n  (17, 6, 21, 2, 45700, 91400),\n  (18, 6, 15, 4, 12200, 48800),\n  (19, 7, 11, 2, 36200, 72400),\n  (20, 7, 23, 2, 10900, 21800),\n  (21, 7, 12, 3, 38700, 116100),\n  (22, 8, 5, 3, 4500, 13500),\n  (23, 8, 19, 5, 16300, 81500),\n  (24, 8, 15, 3, 12200, 36600);\n"
  },
  "meta": {
    "endpoint": "relational-seed",
    "route": "/sql",
    "locale": "en",
    "params": {
      "schema": "ecommerce",
      "dialect": "mysql",
      "includeDdl": false,
      "customers": 4,
      "ordersPerCustomer": 2,
      "itemsPerOrder": 3,
      "idStyle": "int",
      "currency": "USD",
      "seed": 11,
      "asOf": "2026-07-29T08:13:22.000Z"
    },
    "generatedAt": "2026-07-29T08:13:22.000Z"
  }
}
Just the script, ready to pipe into psql
GET /api/relational-seed/sql?fields=sql&unwrap=true&customers=3&seed=5
{
  "sql": "-- randomapi.dev · relational-seed · schema=ecommerce dialect=postgres idStyle=int\n-- seed=5 asOf=2026-07-29T08:13:22Z · 55 rows across 5 tables\n-- Fixture data for development, demos and CI. Never load it into a production database.\n-- Tables are emitted parents-first, so the script applies with foreign key checks enabled.\n-- No DROP statements: create the target schema (or an empty database) first.\n\nCREATE TABLE \"categories\" (\n  \"id\" BIGINT NOT NULL,\n  \"slug\" TEXT NOT NULL,\n  \"name\" TEXT NOT NULL,\n  PRIMARY KEY (\"id\")\n);\n\nCREATE TABLE \"products\" (\n  \"id\" BIGINT NOT NULL,\n  \"category_id\" BIGINT NOT NULL,\n  \"sku\" TEXT NOT NULL,\n  \"name\" TEXT NOT NULL,\n  \"price_minor\" BIGINT NOT NULL,\n  \"currency\" TEXT NOT NULL,\n  \"in_stock\" BOOLEAN NOT NULL,\n  \"created_at\" TIMESTAMPTZ NOT NULL,\n  PRIMARY KEY (\"id\"),\n  CONSTRAINT \"fk_products_category_id\" FOREIGN KEY (\"category_id\") REFERENCES \"categories\" (\"id\")\n);\n\nCREATE TABLE \"customers\" (\n  \"id\" BIGINT NOT NULL,\n  \"email\" TEXT NOT NULL,\n  \"full_name\" TEXT NOT NULL,\n  \"city\" TEXT NOT NULL,\n  \"country_code\" TEXT NOT NULL,\n  \"is_active\" BOOLEAN NOT NULL,\n  \"created_at\" TIMESTAMPTZ NOT NULL,\n  PRIMARY KEY (\"id\")\n);\n\nCREATE TABLE \"orders\" (\n  \"id\" BIGINT NOT NULL,\n  \"customer_id\" BIGINT NOT NULL,\n  \"order_number\" TEXT NOT NULL,\n  \"status\" TEXT NOT NULL,\n  \"currency\" TEXT NOT NULL,\n  \"total_minor\" BIGINT NOT NULL,\n  \"placed_at\" TIMESTAMPTZ NOT NULL,\n  \"shipped_at\" TIMESTAMPTZ,\n  PRIMARY KEY (\"id\"),\n  CONSTRAINT \"fk_orders_customer_id\" FOREIGN KEY (\"customer_id\") REFERENCES \"customers\" (\"id\")\n);\n\nCREATE TABLE \"order_items\" (\n  \"id\" BIGINT NOT NULL,\n  \"order_id\" BIGINT NOT NULL,\n  \"product_id\" BIGINT NOT NULL,\n  \"quantity\" INTEGER NOT NULL,\n  \"unit_price_minor\" BIGINT NOT NULL,\n  \"line_total_minor\" BIGINT NOT NULL,\n  PRIMARY KEY (\"id\"),\n  CONSTRAINT \"fk_order_items_order_id\" FOREIGN KEY (\"order_id\") REFERENCES \"orders\" (\"id\"),\n  CONSTRAINT \"fk_order_items_product_id\" FOREIGN KEY (\"product_id\") REFERENCES \"products\" (\"id\")\n);\n\nINSERT INTO \"categories\" (\"id\", \"slug\", \"name\") VALUES\n  (1, 'home-kitchen', 'Home & Kitchen'),\n  (2, 'childrens-toys', 'Children''s Toys'),\n  (3, 'outdoor-garden', 'Outdoor & Garden'),\n  (4, 'office-supplies', 'Office Supplies');\n\nINSERT INTO \"products\" (\"id\", \"category_id\", \"sku\", \"name\", \"price_minor\", \"currency\", \"in_stock\", \"created_at\") VALUES\n  (1, 1, 'SKU-D6B854VE', 'Awesome Bronze Chips', 45500, 'USD', TRUE, '2025-04-06 22:08:22+00:00'),\n  (2, 2, 'SKU-V4KNGGYJ', 'Fantastic Steel Chicken', 6200, 'USD', FALSE, '2024-08-11 19:42:13+00:00'),\n  (3, 1, 'SKU-P9FG2TVY', 'Sleek Steel Salad', 29900, 'USD', TRUE, '2025-07-13 17:52:34+00:00'),\n  (4, 3, 'SKU-DBT3AQW3', 'Handmade Plastic Shirt', 28300, 'USD', TRUE, '2024-12-30 13:27:28+00:00'),\n  (5, 3, 'SKU-59SVQKQ6', 'Ergonomic Silk Shoes', 3300, 'USD', TRUE, '2025-11-08 16:59:40+00:00'),\n  (6, 2, 'SKU-6U9LKLFS', 'Modern Rubber Pizza', 18700, 'USD', FALSE, '2024-04-08 08:51:17+00:00'),\n  (7, 4, 'SKU-PHALXATN', 'Practical Ceramic Towels', 3900, 'USD', TRUE, '2024-11-26 21:52:43+00:00'),\n  (8, 4, 'SKU-PRR7CCWP', 'Elegant Gold Car', 35700, 'USD', FALSE, '2024-11-22 16:06:49+00:00'),\n  (9, 4, 'SKU-M5YEGG7F', 'Fresh Bronze Computer', 15100, 'USD', FALSE, '2024-11-05 11:35:18+00:00'),\n  (10, 4, 'SKU-66P33NSA', 'Sleek Granite Salad', 5500, 'USD', TRUE, '2024-12-26 14:19:53+00:00'),\n  (11, 2, 'SKU-4M744JK2', 'Frozen Bronze Towels', 11100, 'USD', TRUE, '2025-04-17 12:02:36+00:00'),\n  (12, 3, 'SKU-JC729FNP', 'Oriental Concrete Shirt', 2200, 'USD', TRUE, '2025-10-01 21:56:36+00:00'),\n  (13, 2, 'SKU-WJP3AJ65', 'Licensed Bronze Soap', 37100, 'USD', TRUE, '2025-11-11 16:22:44+00:00'),\n  (14, 3, 'SKU-79ZP4RF6', 'Frozen Cotton Ball', 3200, 'USD', FALSE, '2024-07-21 22:21:27+00:00'),\n  (15, 4, 'SKU-HMHMWH2Z', 'Electronic Bronze Chicken', 33100, 'USD', TRUE, '2024-10-01 14:39:47+00:00'),\n  (16, 4, 'SKU-79F7NWYU', 'Handmade Rubber Sausages', 8900, 'USD', TRUE, '2024-06-27 14:04:04+00:00'),\n  (17, 3, 'SKU-B8ZR54XX', 'Tasty Bronze Shirt', 36500, 'USD', TRUE, '2024-02-17 21:00:10+00:00'),\n  (18, 1, 'SKU-SL23PFWR', 'Handcrafted Wooden Towels', 17400, 'USD', FALSE, '2024-05-20 05:23:46+00:00'),\n  (19, 4, 'SKU-RL67SQXE', 'Generic Cotton Keyboard', 1100, 'USD', TRUE, '2025-07-21 23:02:15+00:00'),\n  (20, 2, 'SKU-84QY88A4', 'Sleek Granite Gloves', 5800, 'USD', TRUE, '2024-05-24 16:38:31+00:00'),\n  (21, 2, 'SKU-HBBSAU3V', 'Rustic Granite Shoes', 2400, 'USD', TRUE, '2024-09-30 12:49:23+00:00'),\n  (22, 1, 'SKU-QHWSFQV4', 'Electronic Metal Car', 10800, 'USD', TRUE, '2025-04-26 18:08:40+00:00'),\n  (23, 4, 'SKU-74TH73SP', 'Sleek Bamboo Pants', 8100, 'USD', TRUE, '2026-01-06 17:39:08+00:00'),\n  (24, 4, 'SKU-FZ77AR6S', 'Frozen Bronze Shoes', 4900, 'USD', FALSE, '2024-04-11 18:06:38+00:00');\n\nINSERT INTO \"customers\" (\"id\", \"email\", \"full_name\", \"city\", \"country_code\", \"is_active\", \"created_at\") VALUES\n  (1, 'raymundo.lebsack1@example.com', 'Raymundo Lebsack', 'Rancho Palos Verdes', 'US', TRUE, '2026-01-16 04:26:00+00:00'),\n  (2, 'aniya.grimes2@example.com', 'Aniya Grimes', 'Mariestad', 'US', TRUE, '2025-06-15 12:47:10+00:00'),\n  (3, 'alexander.jast3@example.com', 'Alexander Jast', 'Pfannerstill-Walterburgh', 'US', TRUE, '2025-12-30 21:11:04+00:00');\n\nINSERT INTO \"orders\" (\"id\", \"customer_id\", \"order_number\", \"status\", \"currency\", \"total_minor\", \"placed_at\", \"shipped_at\") VALUES\n  (1, 1, 'ORD-2026-00001', 'paid', 'USD', 160700, '2026-02-18 13:58:22+00:00', NULL),\n  (2, 1, 'ORD-2026-00002', 'paid', 'USD', 93400, '2026-07-12 08:09:59+00:00', NULL),\n  (3, 2, 'ORD-2026-00003', 'paid', 'USD', 181900, '2026-04-20 11:43:49+00:00', NULL),\n  (4, 2, 'ORD-2025-00004', 'paid', 'USD', 259600, '2025-06-29 11:35:46+00:00', NULL),\n  (5, 3, 'ORD-2026-00005', 'paid', 'USD', 142700, '2026-04-21 22:09:58+00:00', NULL),\n  (6, 3, 'ORD-2026-00006', 'shipped', 'USD', 66100, '2026-03-26 22:42:42+00:00', '2026-03-28 22:42:42+00:00');\n\nINSERT INTO \"order_items\" (\"id\", \"order_id\", \"product_id\", \"quantity\", \"unit_price_minor\", \"line_total_minor\") VALUES\n  (1, 1, 19, 5, 1100, 5500),\n  (2, 1, 8, 4, 35700, 142800),\n  (3, 1, 2, 2, 6200, 12400),\n  (4, 2, 12, 2, 2200, 4400),\n  (5, 2, 4, 2, 28300, 56600),\n  (6, 2, 23, 4, 8100, 32400),\n  (7, 3, 1, 3, 45500, 136500),\n  (8, 3, 16, 3, 8900, 26700),\n  (9, 3, 6, 1, 18700, 18700),\n  (10, 4, 17, 2, 36500, 73000),\n  (11, 4, 13, 5, 37100, 185500),\n  (12, 4, 19, 1, 1100, 1100),\n  (13, 5, 3, 4, 29900, 119600),\n  (14, 5, 5, 5, 3300, 16500),\n  (15, 5, 12, 3, 2200, 6600),\n  (16, 6, 22, 5, 10800, 54000),\n  (17, 6, 5, 2, 3300, 6600),\n  (18, 6, 19, 5, 1100, 5500);\n"
}

About this API

Coverage & behavior

Most fake-data APIs hand you one flat list. This one returns a whole relational fixture: five tables per schema, with parent, child, grandchild and join rows whose foreign keys all resolve inside the same response. Every customer_id, product_id, order_id, account_id, post_id and tag_id is the primary key of a row you were just handed.

Three hand-designed schemas. ecommerce: categories → products → customers → orders → order_items. saas: plans → accounts → users → invoices → invoice_items (invoices reference two different parents). blog: tags → authors → posts → comments → post_tags, including a nullable foreign key (guest comments have no author) and a composite-key join table. These schemas are ours — small, deliberate teaching models. They are not a copy of any real product's data model and they implement no standard.

Guarantees this endpoint actually keeps

  • Arithmetic is exact. line_total_minor = quantity × unit_price_minor, and an order's or invoice's total_minor is the exact integer sum of its line items. All money is in ISO 4217 minor units (integers), so nothing rounds. In ecommerce a line item's unit price is the referenced product's price_minor.
  • Timestamps are causal. An order is placed strictly after its customer was created, a comment lands after its post was published, and nothing is dated after asOf.
  • Growing the dataset is append-only. With every other parameter fixed, a row depends only on (seed, table, row position), so raising customers from 10 to 50 leaves the first 10 parents — and every row that hangs off them — byte-identical. customers is the only knob with that property: ordersPerCustomer and itemsPerOrder re-shape the child tables, so the same row position means something different afterwards.
  • Denormalized counters agree. posts.comment_count equals the number of comment rows that reference the post.
  • Status and its date never disagree. A row is shipped exactly when it has a shipped_at, and an invoice is paid exactly when it has a paid_at. When the derived date would fall after asOf the status is downgraded (shippedpaid, paidopen) rather than the date being dropped, so you never get a paid invoice with no payment date.

/sql renders the same bundle as a seed script. Tables are emitted parents-first, so the script applies with foreign key checks on — no SET FOREIGN_KEY_CHECKS=0, no deferred constraints. postgres, mysql and sqlite are each genuinely generated: identifier quoting (double quotes for PostgreSQL and SQLite, backticks for MySQL), column types (TIMESTAMPTZ / DATETIME / TEXT, BOOLEAN / TINYINT(1) / INTEGER), boolean literals (TRUE vs 1), timestamp literals and ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 for MySQL all differ per dialect. The SQLite script starts with PRAGMA foreign_keys = ON; because SQLite disables enforcement by default. Apostrophes are escaped by doubling ('Children''s Toys'), which is portable across all three; MySQL additionally escapes backslashes, matching its default sql_mode. Pipe it straight in: curl -s '.../api/relational-seed/sql?fields=sql&unwrap=true' | jq -r .sql | psql mydb.

Scope limits, stated plainly

  • This is fixture data for development, demos and CI — never load it into a production database. Names, emails (@example.com), companies and SKUs are synthetic.
  • /sql is a seed script, not a migration: the DDL has primary and foreign keys and nothing else — no indexes, unique constraints, checks, triggers, defaults or sequences — and it never drops or truncates anything.
  • Only postgres, mysql and sqlite are supported. No portability beyond those three is claimed, and no other dialect is offered.
  • idStyle=uuid produces the RFC 9562 version-4 layout from the seeded PRNG. The values are reproducible, and therefore not cryptographically random — do not treat them as secrets.
  • locale only reaches the values faker generates for a bundle: person names, city, company.name and the derived country_code. The fixed catalog text — category, plan, tag, post-title, comment-body and invoice-line strings — is English in every locale, and faker itself falls back to English where a locale carries no data (locale=ja still returns English product names). Slugs are ASCII-only, so accounts.slug degrades to account-1account-N when the generated company name has no ASCII letters.
  • In blog, a comment's author is drawn from the authors that already existed when the post was written — never a later one, because that is precisely what keeps a comment row byte-identical as customers grows. The price is a lopsided fixture: the first author writes many times as many comments as the last, and the post's own author writes a noticeable share of its member comments (≈28 % at customers=10, ≈9 % at customers=50). That is the cost of the append-only guarantee, not a defect: the newest author can only ever comment on its own posts, so evening out the totals and suppressing self-replies are one dial pulled in opposite directions.
  • One bundle is capped at 400 rows across all tables; over that the request fails with a 400 that states the computed row count.
  • These rows are not the ones /api/users, /api/products or /api/orders return for the same seed. This endpoint has its own generators; its promise is consistency within the bundle it returns.

Use it for

  • Seed a local Postgres, MySQL or SQLite database with rows whose foreign keys already line up
  • Demo a customer → order → line-item graph instead of three unrelated flat lists
  • Reproduce the identical multi-table fixture in every CI run from one seed
  • Exercise ORM relation mapping and JOIN queries against constraint-satisfying data

Frequently asked questions

Do the foreign keys in the generated data actually resolve?

Yes. Every non-null foreign-key value is the primary key of a parent row in the same response — across all three schemas, every id style and the whole parameter grid. The one deliberately nullable key, comments.author_id on guest comments, is either NULL or a real author.

Can I run the SQL script with foreign key checks enabled?

Yes — that is the point. Tables are emitted parents-first, so no INSERT references a row that has not been inserted yet, and the SQLite script begins with PRAGMA foreign_keys = ON; because SQLite disables enforcement by default.

Which SQL dialects can the .sql output target?

postgres, mysql and sqlite. Each is genuinely generated — its own identifier quoting, column types, boolean and timestamp literals, and ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 for MySQL. No other dialect is offered or implied.

How do I pipe the seed script straight into psql?

curl -s 'https://randomapi.dev/api/relational-seed/sql?seed=42&fields=sql&unwrap=true' | jq -r .sql | psql mydbfields=sql&unwrap=true reduces the JSON envelope to the script itself.

How many rows can one seed bundle contain?

Up to 400 across all tables. Beyond that the request returns 400 and tells you the exact computed row count, so you can lower 'customers', 'ordersPerCustomer' or 'itemsPerOrder'.

Are these the same rows as /api/users and /api/orders?

No, and we won't pretend otherwise: this endpoint has its own generators, so the same seed gives different values there. Its guarantee is that the bundle it returns is internally consistent.

Standards & references