Skip to content

Recipe examples

Thirteen worked recipe documents, one per source shape, each complete enough to copy, edit and register.

Each page carries one whole recipe document in a single fence, the commands that register and run it, and the mistakes that shape makes easy. Each document validates against the v4 recipe schema as printed.

Read Write a recipe first if you have not written one before, and Recipe document for the field-by-field reference.

Source shape Page Connector and Reader What it shows
One published CSV response One CSV file public.https, direct CSV the smallest complete document: one source, one step, three checks
A daily series from two stations Daily city temperatures public.https, direct CSV a union, an aggregation, and a request window that refreshes a few days
A JSON API JSON API public.https + json.tabular@1.1.0 a records pointer, nested column pointers, and two ways to paginate
Many HTML pages behind one index Many HTML pages public.https.collection@2.0.0 + html.web_extract@1.1.0 page discovery, fetch budgets, and the seven provenance columns
A table inside a PDF Documents and PDFs document.projection@1.0.0 the document lane, and why mr-data cannot reach it yet
A weather model file Weather GRIB2 public.https + weather.grib2@3.0.0 exact message selection, named places, and a closed source
A wss:// venue WebSocket stream stream.wss@1.0.0 recording before building, and the fixed eight-column frame relation
A changing stream roster from a live table Table-driven stream discovery table_members series + stream.wss@1.0.0 member selection, typed context, freshness, limits and segment replay
Two feeds joined Two sources joined public.https + json.tabular@1.1.0, twice a left join, and the check that catches a join that fanned out
Two prediction venues on one event Two venues, one question public.https + json.tabular@1.1.0, one per venue a key the recipe builds itself, and the rights basis each publisher needs
A forecast and what happened Forecast against observation public.https + weather.grib2@3.0.0 a model file joined to the station it predicted, and the error columns
A listing that keeps no history Snapshot windows public.https + json.tabular@1.0.0 window.snapshot, and why an explicit full resync can replace live material
Twenty stations of one kind Twenty stations, one hourly table public.https, twenty times a twenty-way union, per-source byte ceilings, and a learned cadence
A recorded stream reduced A stream aggregated into bars stream.wss@1.0.0 + json.tabular@1.1.0 one-minute bars, and the two headers a recorder seals

The dataset page exists before the recipe does. mr-data dataset create --name "…" --json prints a dataset_id for the document’s dataset.id. Without it, registration resolves a container from the name and creates a second page that is not connected to your existing dataset. These examples print dataset.name and leave dataset.id out, so add your own before you register.

You do not compute a digest by hand. Submit the document as written. The backend canonicalizes the bytes, takes the digest of that, and returns recipe_id, recipe_digest, dataset_id, table_id and source_ids. Registering identical bytes twice registers one recipe.

Every run needs both identifiers: mr-data run --recipe RECIPE_ID --digest RECIPE_DIGEST. The digest is the bare lowercase hex the registration printed, with no sha256: prefix. The CLI refuses mr-data run RECIPE_ID.

A sample comes before a full run, and exercises every column, every cast and every declared check. --max-rows is a ceiling on each source separately, so a recipe with four sources can deliver four times the number you passed.

The first succeeded run goes live. There is no promote click. mr-data promote records cadence for an eligible incremental table; it does not make the table readable. A snapshot or other unwindowed source refuses ordinary refresh before acquisition and needs an explicit full resync instead.

No fractional number appears anywhere. Every number is a count, a byte ceiling, a parts-per-million bound or a number of seconds. A check bound that is not a whole number travels as a decimal string: "min_value": "-2".

Every acquired source reaches the SQL as text. The engine binds each source as all-text CSV, so every declared type becomes an explicit cast in the statement. A column declared decimal must come back as DECIMAL(p,s), and a column declared timestamp as TIMESTAMP WITH TIME ZONE.

A Reader pin lives on connector.parameters, under three reserved names: reader.family_id, reader.family_version and reader.decode_options. Write all three or none. The options value is the canonical JSON text of what the family itself admits, with every defaulted setting written out. A stated subset is refused.

Datasets of every shape here run on this platform:

  • Kalshi fifteen-minute order-book stream tables
  • a Kalshi and Polymarket settlement comparison
  • NOAA GEFS forecasts
  • a twenty-city weather dataset
  • corpora built from HTML collections
  • a Y Combinator company snapshot

Browse them at Datasets. Copy these documents and edit them. They do not reproduce those datasets byte for byte.