Changelog
Our product is growing for You
A curated, month-by-month history of what shipped — new generators, capabilities added across the whole catalogue, and the platform milestones that made them possible.
- Milestone
Seed a database — a whole dataset in one request
Every other endpoint returns one field. **`POST /v1/compose`** returns your whole database: not a value at a time, but the entire nested shape your app expects — users with their orders, orders with their line items, foreign keys that line up — ready to load into Postgres, a `db.json`, or a mock server. You send a JSON skeleton and mark each slot with a `$`-source (`$generator.pl.person`, `$generator.any.uuid`, a literal, a nested object); everything else passes through. `$count` turns any node into an array (a fixed number, or a random `[2, 5]` that rolls per parent, so 100 orders each get their own 2–5 items). Declaring an entity once under `$generators` or top-level `shared` keeps several fields describing the **same** person — a buyer whose name, PESEL, and email agree — where `shared` is drawn once for the whole response (the one admin who created every row) and a local entity is drawn fresh per record. Dates relate to each other: `$date` computes an offset or a random range from an anchor, and `$anchor` / `$parent.createdAt` measure a child from its own parent, so every order lands after the customer who placed it and every shipment after its order. The whole dataset is reproducible from one `seed`, and the output format is pluggable — JSON today, with SQL and CSV designed for. Requires the Pro plan. See the “Seed a database” guide under the Data menu for the full grammar; reachable from the `/docs` playground, the MCP server, and the Playwright addon (`compose()`).
- New generator
Weighted enum and object pickers — bring your own distribution
Two new locale-agnostic generators for the categorical fields no registry issues but every dataset needs — status, tier, plan, a skewed cohort. `/v1/enum` draws a member from a weighted map you supply (`choices={"gold":1,"silver":4,"bronze":15}` → drawn 1/20, 4/20, 15/20), and `/v1/object` does the same over whole JSON objects (`choices=[{"object":{"tier":"gold"},"weight":3},…]`), returning the chosen object verbatim. Weights are **relative** — they need not sum to 1, so probabilities and integer counts are the same thing — and the response echoes the drawn value’s normalized `probability`. Pass the `choices` as URL-encoded JSON (capped at 16 KB). Output is reproducible from the `seed`, and all three testing modes apply: `edge` **inverts** the distribution (the rarest member becomes the most likely, a zero-weight member rises to the top), `extreme` wraps the value in a hostile encoding, and `invalid` returns a value that is *not* in your set. Live in the `/docs` playground and the MCP server.
- New generator
Product & service offerings for all 27 EU countries
A whole new data type: the **offering** — a realistic product or service a business sells, with a name, a price, and the industry it belongs to. Every EU country gets a `/v1/<cc>/offering` endpoint, and `/v1/offering` draws across the union — pass `countries=pl,de,it` to mix, omit for all 27, and each record reports its `country`. The name is localised into that country’s language (multilingual states blend theirs — Belgium across Dutch/French/German, Luxembourg across French/German/Luxembourgish, Finland Finnish/Swedish, Ireland English/Irish, Malta Maltese/English), and the industry label comes back localised too. Draw the whole catalogue or narrow it: pin an `industry` by NACE code, restrict to `type=product` or `type=service`, or full-text filter by `offeringName` or `industryName` (`?offeringName=fibre`). Prices are the real touch — each is a single plausible amount snapped onto a sensible grid for its size (a €25 haircut, a €1,499.99 fibre install, a €209,500 construction job), never raw machine noise. As everywhere, output is reproducible from the `seed`, and `edge` (the price/format corners), `extreme` (a hostile-encoded name), and `invalid` (a deliberately broken record) all apply. Live in the `/docs` playground and the MCP server.
- New generator
Synthetic ID generators — UUID, ULID, Nano ID, ObjectId, and sequences
Five new locale-agnostic generators for the technical identifiers every record needs but no national registry issues — the primary keys. `/v1/uuid` produces a UUID, random (`version=4`, the default) or time-ordered (`version=7`, RFC 9562); `/v1/ulid` a 26-character Crockford-Base32 ULID; `/v1/nanoid` a compact URL-safe Nano ID, with `size` and a custom `alphabet`; `/v1/object-id` a well-formed 24-character MongoDB ObjectId; and `/v1/sequence` an auto-increment integer — the classic SQL primary key — where a single call returns `start` (default 1) and a batch (`count`) returns the run `start, start + step, …`. Like everything else they are deterministic from the `seed`, so a seeded UUID is *reproducible* — better than a real random one for fixtures. Any embedded timestamp (UUID v7, ULID, ObjectId) is derived from the seed, not the wall clock, keeping output stable. They fill the gap when you seed a whole record and need an `id` column to sit beside the name, address, and national number.
- New generator
IBANs for all 27 EU countries
The IBAN generator went pan-European: every EU country now has its own `/v1/<cc>/iban` endpoint producing a bank account number in that country’s exact ISO 13616 format — Germany’s 22-character `DE…`, France’s 27-character `FR…`, Italy’s `IT…` with its leading CIN letter, Spain’s `ES…` with the two dígitos de control, and so on. Every IBAN carries correct mod-97 check digits **and**, where the national account number embeds its own internal check digit, that too is computed the real way (Belgium’s mod-97 suffix, France’s clé RIB, Italy’s CIN, Spain’s DC, Portugal’s and Slovenia’s ISO 7064 checks, Finland’s Luhn, Estonia’s 7-3-1, Hungary’s two check digits, Croatia’s per-field MOD 11-10, and the Czech/Slovak self-checking account) — so the numbers pass strict per-country validators, not just the outer checksum. The embedded bank identifier is drawn from a **real** registry per country (Germany’s Bankleitzahl, France’s code banque, the Netherlands’ four-letter BIC prefix, …), so you can pin the issuing bank by `bankCode` or `bankName`, or let it be chosen at random. As before, `invalid=true` deliberately breaks the checksum for testing validators, and `edge` and `extreme` both apply.
- New generator
Vehicle registration plates for all 27 EU countries
The vehicle-registration generator went pan-European: every EU country now has its own `/v1/<cc>/vehicle-registration` endpoint producing realistic plates in that country’s exact current format — Germany’s district-coded `M-AB 1234`, France’s `AB-965-KL`, Italy’s `AK 514 RH`, Ireland’s year-and-county `262-D-12345`, the Netherlands’ sidecode `PDA-01-D`, and so on. Where a country encodes a region in the plate, the code is drawn from the **real** registry (Germany’s Unterscheidungszeichen, Slovakia’s district codes, Romania’s 42 counties, Ireland’s counties, Poland’s wyróżniki, …), so the regional part is genuine and filterable. Each country offers the plate classes whose format actually differs — standard plus, where they exist, custom/vanity, military, diplomatic, police, temporary/dealer/export, motorcycle, historic, taxi, and electric — and, where the old format still on the road looks different, an `era` switch (`current` / `legacy` / `both`) that reaches back to it (Spain’s province plates, France’s FNI, Hungary’s 3-letter series, Ireland’s two-digit-year plates, …). Bulgaria and Greece can render in their native Cyrillic/Greek glyphs on request. Poland additionally gained motorcycle and reduced-size (US/JP-import) variants. Plates carry no checksum, so there is no “invalid” mode — but `edge` and `extreme` both apply.
- Across generators Enhancement
New `extreme` trigger — correct data in a deliberately hostile encoding
Every generator that already took `edge` now also accepts `extreme=true`: it returns **correct** data presented in the most disturbing way a real system ever sees it. The value is wrapped with one class per record — untrimmed whitespace (including non-breaking spaces and a trailing newline), invisible and zero-width characters with a leading byte-order mark, homoglyph letters (Cyrillic/Greek/fullwidth lookalikes that read as Latin), or a right-to-left override / stacked combining marks — so a batch (`count`) rotates across all four. It’s built to answer “how *should* my system behave here?”: does your pipeline trim, normalise (NFKC), and compare values safely, or does a zero-width space break an equality check and a homoglyph slip past a filter? Only the human-facing string is mangled and it stays recoverable: identifiers (PESEL, NIP, IBAN, CPR, codice fiscale, BSN, …) keep their digits ASCII — homoglyphs are excluded — so they still parse and checksum after normalisation; names, companies, emails, and whole people/companies mangle the name (or assembled value) only, leaving `initials`, `legalForm`, birth dates, and national identifiers clean. The `lorem` and custom-regex endpoints don’t take it (it would break their length and pattern-match contracts). Output stays reproducible from the `seed`; the flag is live in the `/docs` playground, the MCP server, and the Playwright addon.
Read the full story →
- New generator Enhancement
Localised email generators for all 27 EU countries
Email generation goes country-aware: every member state gets a `/v1/<country>/email` endpoint, and `/v1/email` now draws across the EU — pass `countries=pl,de,it` to mix, omit for all 27, and each record reports its `country`. Names come from each country’s real first-name and surname banks, romanised to ASCII for non-Latin scripts so Bulgarian and Greek names become deliverable local parts. A new `corporate` domain category builds the address on a company-derived domain (`anna.schmidt@mueller-bau.de`), drawing the brand from that country’s company-name generator and the suffix from its ccTLDs; two new local-part patterns weave a company token in (`first.company`, `company.first`), alongside regional providers (`wp.pl`, `web.de`, …) and global webmail. Output stays reproducible from the `seed`; the new endpoints are live in the `/docs` playground and the MCP server.
- New generator
Full-company generators for all 27 EU countries
The one-call “whole company” idea behind `/v1/pl/company` now spans the EU: every member state gets a `/v1/<country>/company` endpoint that returns a consistent synthetic company — a full trading name with its legal form, plus the matching national identifiers — in a single request. Each bundles that country’s real registers: Denmark’s CVR, France’s SIREN, Sweden’s organisationsnummer, Italy’s partita IVA, the Netherlands’ KvK + RSIN + btw-id, Germany’s Handelsregister + USt-IdNr + Wirtschafts-IdNr, Austria’s Firmenbuchnummer + UID + Steuernummer, and so on — one to three numbers depending on what the country issues. The name and identifiers are drawn from one seeded sequence, so a given `seed` always yields the same company; `strategy` and `legalForm` shape the name exactly as on `/v1/<country>/company-name`, `invalid=true` corrupts every checksummed identifier while leaving the name (and any checksum-less number) intact, and `edge=true` sweeps the rare corners. Each costs a single token regardless of the sub-draws inside. The new endpoints are live in the `/docs` playground and the MCP server.
- New generator
Custom-regex generator — random data matching your own pattern
A new `/v1/custom-regex` endpoint inverts a regular expression you supply into a random string that matches it — for seeding data whose format the catalogue doesn’t model: in-house serial numbers, SKUs, ticket ids, order references. Pass `pattern` (the regex in source form, e.g. `[A-Z]{2}-\d{6}`) and get back a conforming value; `maxRepetition` caps how far unbounded quantifiers (`*`, `+`, `{n,}`) expand. Patterns are validated up front — back-references and look-around assertions are rejected (they can’t be honoured when generating a match), as is any pattern whose worst-case expansion is too large. Reserved characters must be percent-encoded in the query (`+` as `%2B`). Output stays reproducible from the `seed`. Available on the Pro plan and above.
- New generator
Full-person generators for all 27 EU countries
The one-call “whole person” idea behind `/v1/pl/person` now spans the EU: every member state gets a `/v1/<country>/person` endpoint that returns a mutually consistent synthetic person — given name(s), surname, initials, birth date, and the matching national number — in a single request, so the name, sex, and identity always agree. Each is wired to that country’s real identifier: Denmark’s CPR, France’s NIR, Italy’s Codice Fiscale, Sweden’s personnummer, Germany’s Steuer-ID, Spain’s DNI, the Netherlands’ BSN, and so on. Where the number encodes a birth date and sex (CPR, EGN, isikukood, CNP, EMŠO, …) it is minted first and those facts flow into the name — so a female record always carries the matching parity and birth date. Italy’s Codice Fiscale, which encodes the *name itself*, is built the other way round: the name is generated first and the code derived from it, letters and all. Where the number is non-semantic (BSN, DNI, Steuer-ID, PPSN, TIC, Maltese ID, Cartão de Cidadão, personas kods) the birth date is drawn independently within the same age/birth-date filters and `sex` shapes the name. Every endpoint takes the familiar `sex` and age/birth-date filters, `invalid=true` (a deliberately wrong checksum, name and date intact), `edge=true`, and `caseStrict=false` to mangle the name casing for testing; each costs a single token regardless of the sub-draws inside and stays reproducible from the `seed`. The new endpoints are live in the `/docs` playground and the MCP server.
- Enhancement
Mix both standards in one call for the time-versioned ID generators
The national-ID generators that run two coexisting standards now take `standard=both` alongside the existing single-standard choices: Ireland’s PPSN (`/v1/ie/ppsn`) and VAT (`/v1/ie/vat`) — `pre-2013` vs `modern`; the Netherlands’ btw-id (`/v1/nl/btw-id`) — `legacy` vs `modern`; Latvia’s personas kods (`/v1/lv/personas-kods`) — `legacy` vs `modern`; and Hungary’s személyi azonosító (`/v1/hu/szemelyi-azonosito`) — `pre-1997` vs `modern`. With `both`, each record independently draws one of the two standards, so a single batch realistically mixes the old and new forms instead of being uniform. The drawn standard is resolved before generation and reported back where the generator already returns it, so values are never ambiguous. Output stays reproducible from the `seed`.
- Enhancement
Historic (vintage) plates for the Polish vehicle-registration generator
The `/v1/pl/vehicle-registration` generator gains a fifth plate kind: `type=historic` mints a *tablica zabytkowa* — the black-on-yellow plate carried by registered vintage vehicles. Its right-hand historic-vehicle symbol shortens the number to five characters, so behind a genuine area code (wyróżnik, drawn from the official registry exactly like a standard plate) sits a short individual part of digits, optionally with one letter — `BSI 12A`, `DJ 15M`, `IM 62C`. Like standard plates it honours `voivodeship` and `county`, reports the real region back, and joins the `edge=true` corner set. Output stays reproducible from the `seed`.
- New generator
National ID and tax numbers for all 27 EU countries
Real Fake Data now mints the national identification and tax numbers of every EU member state — 66 new generators, the PESEL/NIP idea taken Europe-wide. Personal numbers (`/v1/de/steuer-id`, `/v1/fr/nir`, `/v1/it/codice-fiscale`, `/v1/se/personnummer`, `/v1/es/dni`, …) and company/VAT numbers (`/v1/fr/siren`, `/v1/de/ust-idnr`, `/v1/nl/btw-id`, `/v1/it/partita-iva`, …) for all 27 countries, each carrying a **correct, country-specific checksum** — Luhn, mod-11, ISO 7064, Verhoeff, mod-97, the lot — so they pass real validators. Date-encoded personal numbers accept the familiar `sex` and age/birth-date filters and report the encoded birth date back; company and VAT numbers take `format` (national vs the EU `vat` form, e.g. `HR…` → `HR…`, Greece’s `EL` prefix); every generator supports `invalid=true` (a deliberately wrong checksum, for testing your validators) and `edge=true` (rare-but-valid corners). Where a country runs two standards the generator lets you pick: Denmark’s pre/post-2007 CPR checksum, the Netherlands’ 2020 btw-id, Latvia’s 2017 personal-code format, Ireland’s 2013 PPSN. Croatia’s single OIB serves both people and companies; legacy numbers (Croatian JMBG) are available too. Everything stays reproducible from the `seed`, and the new endpoints are live in the `/docs` playground and the MCP server.
- New generator
Company-name generators for all 27 EU countries
Company-name generation now spans the EU: new `company-name` endpoints for every member state at `/v1/<country>/company-name`, plus a multi-country `/v1/company-name?countries=de,fr,it` that blends them in one call (each record reports its `country`). Every country produces names across four naming families — coined portmanteaus (`Polbud`, `Eurosysteme`), owner-surname firms with the local partnership form (`Kowalski i Syn`, `Müller & Söhne`, `Rossi & Figli`, `García e Hijos`), descriptive trading names, and modern tech brands — each closed with that country’s **real legal form** in its authentic local script: German `GmbH` / `AG`, French `SARL` / `SAS`, Italian `S.r.l.` / `S.p.A.`, Spanish `S.L.`, Greek `Α.Ε.` / `Ε.Π.Ε.` in Greek letters, Bulgarian `ООД` / `АД` in Cyrillic, and so on. The `/docs` playground enumerates each country’s actual legal forms, so requesting one that doesn’t exist there is rejected. `strategy`, `legalForm`, and `edge` controls work everywhere, founder surnames are shared with the person-name generators, and output stays reproducible from the `seed`.
- New generator
Mixed-country person-name generator
A new `/v1/person-name` endpoint returns names drawn from a mix of EU countries in one call. Pass `countries` as a comma-separated list of ISO codes — `?countries=pl,sk,it` — and each record is generated by one of them, picked at random, so a single batch can blend Polish, Slovak, and Italian names, each in its own local form (script, surname inflection, ordering). Every record reports the `country` it came from. Omit `countries` to draw from all 27 EU countries at once. The same `sex`, `edge`, and `caseStrict` controls apply, and output stays reproducible from the `seed` — handy for seeding a realistic, pan-European set of test users in one request.
- New generator
Person-name generators for 26 EU countries
Person-name generation now spans the whole EU: new `person-name` endpoints for all 26 other member states — Austria, Belgium, Bulgaria, Croatia, Cyprus, Czechia, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Ireland, Italy, Latvia, Lithuania, Luxembourg, Malta, Netherlands, Portugal, Romania, Slovakia, Slovenia, Spain, and Sweden — each at `/v1/<country>/person-name`. Every one uses authentic local given names and surnames in the country’s own script and diacritics: Greek and Cypriot names in Greek letters, Bulgarian in Cyrillic, German umlauts, Polish and Czech diacritics. The local conventions are built in, not bolted on — surnames inflect to the chosen `sex` where the language does (Czech/Slovak `-ová`, Lithuanian `-aitė`, Latvian `-a`, Greek genitive, Bulgarian `-ова`, Irish `Ní`/`Nic`); Spain and Portugal carry two surnames; Hungary writes the surname first; France hyphenates compound given names (`Jean-Pierre`); Denmark leans on double given names (`Hans Christian`); and Dutch/German/Italian nobiliary particles (`van der`, `von`, `De`) are handled correctly, including in the initials. The same `sex`, `edge`, and `caseStrict` controls work everywhere, and every result is reproducible from its `seed`.
- New generator
Standalone Polish person-name generator
A new `pl/person-name` endpoint generates just a realistic Polish name — given name(s), surname, and initials — without minting an identity around it. Often you only need a believable name to label a row, seed a UI, or fill a form, and pulling a full PESEL and birth date for it is overkill; now you can ask for the name alone. It carries the same realism as the full person: the surname is inflected to the chosen `sex` (`Kowalski` / `Kowalska`), names can run to a second given name (`Anna Maria`) or a double-barrelled surname (`Kowalska-Nowak`), `edge=true` pushes those rarer shapes plus very short names (`Jan Lis`), and `caseStrict=false` mangles the casing for testing case-insensitive matching. The full `pl/person` generator is now built on top of it — same names, same seeds — and still returns the name together with the birth date and a matching, checksum-valid PESEL.
- Enhancement
Richer Polish names and casing control
The Polish person generator now produces realistic name variety — second given names (`Anna Maria`), double-barrelled surnames (`Kowalska-Nowak`), and very short names (`Jan Lis`), all far more likely under `edge`. A new `caseStrict=false` switch deliberately mangles the casing of name and surname (all-lower, all-upper, or random like `kArOl nOwAkOwSki`) for testing case-insensitive matching and storage.
- Milestone
Public website and live playground
Launched the marketing site with a spec-driven live Playground, an API reference generated straight from the OpenAPI spec, pricing, and self-contained GDPR cookie consent. The product now has a public face people can try before they buy.
- Across generators
Edge-case mode for every generator
Rolled an `edge` parameter across all fifteen generators in one sweep: boundary values, unusual-but-valid records, and deliberately awkward inputs on demand. Customers can now test how their systems handle the hard cases, not just the happy path.
Read the full story → - New generator
Five Polish identity and registry generators
Added Polish ID card, passport, KRS, land-register, and driving-licence number generators in one batch — five new document types, each valid by format.
- New generator
Lorem Ipsum generator
A locale-agnostic Lorem Ipsum generator for filler text, exposed over REST and as a Playwright fixture.
- Across generators
KRS numbers and the P.S.A. legal form for companies
The Polish company generator now emits KRS registration numbers and can produce the P.S.A. (simple joint-stock) legal form.
- Milestone
Seeded test suites across every generator
Added seeded invariant test suites covering every generator, so each one is checked for valid output and deterministic, reproducible results on every change.
- Across generators
Bulk generation with count
Every endpoint can now return many records in a single call. Seed a whole table or fixture set in one request instead of looping over the API.
- New generator
Email addresses
A locale-agnostic email generator, exposed over REST and as a Playwright fixture.
- New generator
Composite Polish company generator
A full Polish company generator that assembles a coherent record — name, NIP, REGON, and address — available over REST and as a Playwright fixture.
- New generator
Polish person and company-name generators
New Polish person and company-name generators — coherent people and believable Polish business names.
- Milestone
Playwright addon launched
Shipped the @przeslijmi/real-fake-data-playwright addon — seeded, valid fixtures pulled straight into Playwright tests, one line per record. No HTTP glue required.
- New generator
Polish REGON and vehicle-registration generators
New Polish REGON numbers (with correct checksums) and Polish vehicle registration plates.
- Milestone
Self-service API docs
Interactive OpenAPI docs went live at /docs, generated from the same Zod schemas that validate every request — so the docs can never drift from the API.
- Across generators
Invalid-data testing
An `invalid` parameter across the API returns deliberately invalid records — wrong checksums, malformed fields — so customers can test their rejection paths, not just the happy path.
- New generator
Polish tax and banking identifiers
Polish NIP, IBAN (with bank selection by code or name), and PESEL generators — every one with correct checksums, so they pass real validation just like production data.
Read the full story →
- Milestone
Polish addresses at national scale
Moved the Polish address generator onto the PRG dataset — 8.57 million real Polish address points with valid postal codes — behind a memory-bounded cache so it runs comfortably on modest hosting.
- Milestone New generator
Platform launch and first generator
The hexagonal core, deterministic PRNG, generator registry, and REST API went live, shipping with the first generator: Polish addresses built from real TERYT cities and streets.