Distributions
Weighted custom values, date sequences, and reproducible generation.
Use Custom fields to choose from a weighted value pool. The current shape is an options.distribution object mapping each value to a weight:
{
"name": "country",
"type": "Custom",
"options": {
"distribution": {"DE": 10, "AT": 2, "CH": 1, "FR": 1},
"stringify": true
}
}Weights are normalized. Here the expected shares are about 71.4% DE, 14.3% AT and 7.1% each CH and FR. A small random sample will not necessarily match those proportions exactly.
Custom values are strings by default. With stringify: false, JSON scalar spellings such as true or 42 can become booleans or numbers; this does not turn arbitrary object text into a nested object.
Numeric ranges
{"name":"age","type":"Number","options":{"min":18,"max":80}}Use the options exposed by your installation's field catalogue. There is no generic documented gaussian, pareto or recent_bias option across all field types. For a particular statistical distribution, implement and validate the sampling in a scenario.
Sequences and relationships
These options have no controls in the field editor. Set them in the template JSON through the API or a saved template, then inspect a sample containing several related records. Re-picking a field's data type in the editor rewrites its options with the catalogue defaults, which discards a hand-written block, so make these edits last or keep them in the API payload.
sequence makes a Date or Datetime field generate its whole column together, in order:
{
"name": "posted_at",
"type": "Datetime",
"options": {
"range": {"start": "2026-01-01", "end": "2026-03-31"},
"format": "dd/MM/yyyy HH:mm",
"sequence": {"mode": "interval", "minGapMinutes": 5, "maxGapMinutes": 120}
}
}mode is monotonic (random values sorted ascending), spread (evenly spaced, the first on range.start and the last on range.end) or interval (starts at range.start and advances by a random gap per row, clamped at range.end rather than overshooting). minGapMinutes and maxGapMinutes apply to interval only; they default to 1 and to ten times the minimum. That clamping has a consequence worth planning for: a walk that reaches range.end early leaves every remaining row holding range.end exactly, so widen the range or narrow the gaps if you need distinct values throughout. Without a range the window is roughly the preceding year, ending at a recent instant rather than exactly now.
Two failure modes are quiet rather than loud. A mode outside those three throws while the column is generated, and the request still answers 200 with every cell of that column set to <<{{ERROR}}>>. A mode that is not a string at all is not recognised as a sequence, so the field silently generates ordinary unordered dates. Read the column back either way.
parentWindow constrains a child record's dates to the enclosing record's window. It takes the place of range, and composes with sequence:
{
"name": "shipped_at",
"type": "Date",
"options": {
"parentWindow": {"startField": "order_date", "endField": "closed_date", "parseFormat": "dd/MM/yyyy"}
}
}startField is required; omit endField for an open-ended window. Parent rows carry formatted strings, so set parseFormat to the parent field's date format unless its values parse as ISO.
A parent window needs a parent row to read, and generation only supplies one to the child fields of a Template reference. On a top-level field, or inside a Nested object, parentWindow is ignored without comment and the field falls back to an unbounded random date - so the example above behaves as described only in a template reached through Template.
progression is a Custom option, not a date one. It walks ordered stages down the column, which is why it pairs with a sequence date on the same template: the row index carries both.
{
"name": "status",
"type": "Custom",
"options": {
"progression": {"stages": ["created", "approved", "completed"], "mode": "steps"}
}
}steps, the default, gives row i stage i and holds the final stage for any further rows, so each row is one event of the chain. distribute partitions the batch into contiguous ordered blocks instead, for a population sitting at different lifecycle points.
For reusable weighted lists, save a custom data type or install a value library from the Hub.
Reproducibility
Pass an integer seed to POST /datamaker and retain the same fields, quantity and locale to reproduce internal generation. Save the request definition alongside test code. A seed does not freeze AI output, database contents, API responses or Python Script execution, and it is not a promise that outputs remain identical across generator upgrades.