Specification

Menu Interchange Format 2.0

A vendor-neutral JSON format for exchanging restaurant and cafe menus between systems — points of sale, ordering apps, delivery platforms, and websites. The normative definition is menu.schema.json (JSON Schema draft 2020-12); this page explains the structure and states the conformance rules that JSON Schema alone cannot express.

The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be interpreted as described in RFC 2119. A producer is any system that authors or emits documents; a consumer is any system that parses them.

Machine-readable & LLM-friendly

Point a tool or an LLM straight at the raw files — the schema and example are served live from the source of truth, so they never drift.

1. Document structure

One document describes one venue and any number of menus (Breakfast, Lunch, Drinks…). Menus contain sections, which hold items and may nest sub-sections to any depth.

document
├── schemaVersion         "2.0.0"
├── venue                 name, logo, timezone, contact info, openingHours
├── defaults              currency + language inherited by everything below
├── modifierGroups[]      reusable option sets, referenced by id
└── menus[]
    ├── available         86' the whole menu on/off (also on sections, items, variants, options)
    ├── availability      day/time schedule, optional date range
    └── sections[]        nestable
        └── items[]
            ├── price | variants[]     one base price, or sizes/forms
            ├── modifierGroupIds[]     references to shared groups
            ├── modifierGroups[]       or inline, item-specific groups
            ├── dietaryLabels[] / allergens[] / spiceLevel
            ├── nutrition, media, tags, sku
            └── available / availability

Core types

TypePurposeKey rules
LocalizedTextAny display stringPlain string (in defaults.language) or a map of BCP-47 tags to strings.
PriceMoneyInteger minor units: {"amount": 450, "currency": "USD"} is $4.50. currency falls back to defaults.currency.
PriceDeltaModifier adjustmentSame as Price but the amount may be negative (“no cheese −0.50”).
VariantPurchasable formMutually exclusive sizes/forms with full prices. When present, they replace the item’s base price.
ModifierGroupOption setminSelections > 0 makes it required; maxSelections: 1 makes it single-choice; omitted maxSelections means unlimited.
AvailabilityScheduleDay-of-week windows in venue.timezone, plus optional startDate/endDate bounds. Omitted means “always”.
allergens / dietaryLabelsFilterable factsClosed enums (EU 14 + US FDA superset). Free-form labels go in tags instead.
extensionsVendor dataMap whose keys must start with x-. The only place arbitrary properties are allowed.

2. Conformance: authoring (producers)

3. Conformance: parsing (consumers)

4. Versioning

schemaVersion is semver. Within a major version, new releases only add optional fields or enum values — a valid 2.0 document is a valid 2.x document. A major bump may add or tighten requirements: 2.0 makes venue.timezone and venue.openingHours required, so a 1.x document is not a valid 2.0 document. Consumers MUST reject documents whose major version they do not support, and SHOULD validate against the newest schema available for the major version they support, since a validator built from an older minor may reject fields added in a newer one. Producers MUST declare the version whose features they actually use.

Unknown values of open-ended strings (tags, cuisine) carry no interoperability burden. New enum values (allergens, dietary labels) only appear with a minor version bump, so a consumer validating against the matching schema never sees a value it cannot list.

5. Validating

npm install          # ajv + ajv-formats
node validate.mjs    # checks examples/cafe-menu.json against menu.schema.json

Note that ajv’s optional strictRequired lint flag false-positives on the schema’s “at least one of items / sections” idiom; leave it at its default (off).

6. Change log

Every published version of the format, newest first. Each version's normative schema and example are served at a stable URL.

2.0.0Breaking2026-07-28

venue.timezone and venue.openingHours become required.

  • BREAKING: venue.timezone and venue.openingHours are now required — every venue must declare its IANA timezone and at least one opening window. A 1.x document that omits them is not a valid 2.0 document.
1.2.02026-07-28

Adds optional venue opening hours.

  • Added the optional venue.openingHours field — a list of time windows, interpreted in venue.timezone, declaring when the venue is open.
1.1.02026-07-18

Availability toggles across every level.

  • Extended the available on/off toggle to sections, variants, and options (menus and items already had it), so any level of the menu tree can be 86'd while staying in the document.
  • Extended the availability day/time schedule to sections.
1.0.02026-07-06

Initial format.

  • First schema: one venue with any number of menus, nestable sections, items, variants, and shared or inline modifier groups.
  • Prices as integer minor units, localizable text, dietary labels, allergens, spice level, nutrition, media, and tags.
  • Availability model: available on/off flags and availability day/time schedules on menus and items.

Check a file against this spec — open a file and see every problem with its line number, explained in plain language.