{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://apiv2.blizzfull.com/schema/blizzfullMenuSchema.json",
    "title": "Blizzfull Menu",
    "description": "Standard interchange format for merchant syncronization.",
    "type": "object",
    "properties": {
        "enforceSyncCompatibility": {
            "description": "Prevents syncronizing if the Blizzfull syncronizer's compatibility index does not match the provided index. Current compatibility index is 1. Only use this if you want syncronizing to be prevented upon breaking changes to the syncronize functionality.",
            "type": "integer"
        },
        "categories": {
            "description": "Array of categories which are containers for menu items",
            "type": "array",
            "uniqueItems": true,
            "items": {
                "$ref": "#/$defs/category"
            }
        },
        "option_groups": {
            "description": "Array of globally defined option groups/option sets which are referenced within items using the option set id",
            "type": "array",
            "minItems": 0,
            "items": {
                "title": "Option group",
                "description": "Option groups are containers of option items. Their behavior changes based on the group type: \"TYPE_MULTI_SELECT\", \"TYPE_VARIABLE_AMOUNT\", \"TYPE_SINGLE_SELECT\", \"TYPE_UNIT_STEPPER\"",
                "type": "object",
                "properties": {
                    "id": {
                        "description": "The ID the option group on the source side (generally point-of-sale). Must be unique. Should not be 0.",
                        "type": [
                            "integer",
                            "string"
                        ]
                    },
                    "name": {
                        "type": "string"
                    },
                    "type": {
                        "description": "Blizzfull supports 4 different option types.",
                        "type": "string",
                        "enum": [
                            "TYPE_MULTI_SELECT",
                            "TYPE_VARIABLE_AMOUNT",
                            "TYPE_SINGLE_SELECT",
                            "TYPE_UNIT_STEPPER"
                        ]
                    },
                    "options": {
                        "description": "Array of option items that belong to an option group. For example: onions, lettuce, tomato would all be items belonging to the burger toppings option group",
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "description": "The ID the option item on the source side (generally point-of-sale). Must be unique. Should not be 0 or empty",
                                    "type": [
                                        "integer",
                                        "string"
                                    ]
                                },
                                "name": {
                                    "type": "string"
                                },
                                "inactiveEnds": {
                                    "type": "number",
                                    "description": "A unix timestamp for when the option item becomes active again. Do not include this field for active option items."
                                },
                                "price": {
                                    "type": "number"
                                },
                                "min_units": {
                                    "type": "integer",
                                    "description": "Minimum selection for the option. Only use for option groups of type TYPE_UNIT_STEPPER."
                                },
                                "max_units": {
                                    "type": "integer",
                                    "description": "Maximum selection for the option. Only use for option groups of type TYPE_UNIT_STEPPER."
                                },
                                "sort": {
                                    "type": "number",
                                    "description": "If sort is not included the position in the array will be used for the positions."
                                },
                                "sub_options": {
                                    "description": "Array of sub options which reference a top level option_group",
                                    "type": "array",
                                    "minItems": 1,
                                    "items": {
                                        "title": "Sub Option reference",
                                        "description": "",
                                        "type": "object",
                                        "properties": {
                                            "id": {
                                                "description": "The ID the option group (Option group must be included in top level option groups list).",
                                                "type": [
                                                    "integer",
                                                    "string"
                                                ]
                                            }
                                        },
                                        "required": [
                                            "id"
                                        ]
                                    }
                                }
                            }
                        },
                        "required": [
                            "id",
                            "name",
                            "price"
                        ]
                    }
                }
            },
            "required": [
                "id",
                "name",
                "type",
                "options"
            ]
        },
        "sizes": {
            "description": "Array of sizes to be imported into Blizzfull menu. Will be referenced within items using the id",
            "type": "array",
            "uniqueItems": true,
            "minItems": 0,
            "items": {
                "title": "Size",
                "description": "Only real property of a size is its name (besides the id). They exist to be referenced by menu items, at which time the pricing is set (on a per-menu item basis)",
                "type": "object",
                "properties": {
                    "id": {
                        "description": "The ID the size on the source side (generally point-of-sale). Must be unique. Should not be 0 or empty",
                        "type": [
                            "integer",
                            "string"
                        ]
                    },
                    "name": {
                        "type": "string"
                    }
                },
                "required": [
                    "id",
                    "name"
                ]
            }
        },
        "merchant": {
            "title": "Merchant settings",
            "description": "Merchant specific settings that do not relate to the menu categories",
            "type": "object",
            "properties": {
                "hours": {
                    "title": "Store Hours",
                    "description": "The store hours",
                    "type": "object",
                    "properties": {
                        "delivery": {
                            "$ref": "#/$defs/store_hours"
                        },
                        "pickup": {
                            "$ref": "#/$defs/store_hours"
                        }
                    },
                    "additionalProperties": false
                },
                "paused": {
                    "title": "Ordering Paused",
                    "description": "If this is set to true, ordering is disabled for the merchant.",
                    "type": "boolean"
                }
            }
        }
    },
    "required": [
        "categories",
        "option_groups",
        "sizes"
    ],
    "$defs": {
        "store_hours": {
            "description": "Hours entries for weekdays and specific dates",
            "type": "object",
            "patternProperties": {
                "sunday|monday|tuesday|wednesday|thursday|friday|saturday|\\d{2}\\/\\d{2}": {
                    "title": "Hours ranges array",
                    "type": "array",
                    "items": {
                        "title": "Hours range",
                        "description": "Each entry in the array is in military time in `HH:MM` format. For example `02:21`",
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "minItems": 2,
                        "maxItems": 2
                    }
                }
            },
            "additionalProperties": false
        },
        "images": {
            "description": "imageUrl can be a string for single images or an array of url strings. Urls must be absolute and publicly accessible.",
            "type": [
                "string",
                "array"
            ]
        },
        "item": {
            "title": "Menu item",
            "description": "Menu items can define a flat price or reference sizes for sized-based pricing. They can reference option groups for more fine-grained manipulation",
            "type": "object",
            "properties": {
                "id": {
                    "type": [
                        "integer",
                        "string"
                    ],
                    "description": "The ID the menu item on the source side (generally point-of-sale). Must be unique. Should not be 0 or empty"
                },
                "name": {
                    "type": "string"
                },
                "description": {
                    "type": "string"
                },
                "tags": {
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "description": "Tags are an array of strings indicating special characteristics of an item can be: 'spicy','specialty','vegan','gf' (for gluten free),'keto','alcoholic'"
                },
                "active": {
                    "type": [
                        "boolean",
                        "integer"
                    ],
                    "description": "Can be true for active false for inactive or a unix timestamp indicating when the item is inactive until."
                },
                "imageUrl": {
                    "$ref": "#/$defs/images"
                },
                "price": {
                    "type": "number",
                    "description": "The base price of the item."
                },
                "sizes": {
                    "type": "array",
                    "minItems": 0,
                    "items": {
                        "title": "Size linkage",
                        "description": "References a size from the sizes top-level array. Only ID and price are required. Size prices will be added to the `price`. For example if the base `price` field is set to 5 and a size price is set to 1, the size price will be set to 6.",
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": [
                                    "integer",
                                    "string"
                                ],
                                "description": "Reference to the ID in the top level sizes array"
                            },
                            "price": {
                                "type": "number"
                            }
                        },
                        "required": [
                            "id",
                            "price"
                        ]
                    }
                },
                "groups": {
                    "type": "array",
                    "minItems": 0,
                    "items": {
                        "$ref": "#/$defs/option_group_linkage"
                    }
                }
            },
            "required": [
                "id",
                "name",
                "active",
                "price",
                "groups"
            ]
        },
        "subcategory": {
            "title": "Sub Category",
            "description": "A Category is a container for menu items. Sub Categories cannot have their own subcategories.",
            "type": "object",
            "properties": {
                "id": {
                    "type": [
                        "integer",
                        "string"
                    ]
                },
                "name": {
                    "type": "string"
                },
                "description": {
                    "type": "string"
                },
                "active": {
                    "type": "boolean",
                    "description": "Whether the category is active or not. This will overrride any hours that are set."
                },
                "hours": {
                    "type": "object",
                    "description": "An object with weekday entries in this format. Time ranges are in military time. only single ranges are supported currently. Example for a category that is only available on sunday and monday from 9:30am to 5:30pm: {'sunday': [['9:30','17:30']], 'monday':[['9:30','17:30']]}. Valid entries: sunday monday tuesday wednesday thursday friday saturday"
                },
                "imageUrl": {
                    "$ref": "#/$defs/images"
                },
                "items": {
                    "type": "array",
                    "items": {
                        "$ref": "#/$defs/item"
                    }
                },
                "groups": {
                    "description": "Option groups in this list will be prepended to the option groups in every menu item in this category.",
                    "type": "array",
                    "minItems": 0,
                    "items": {
                        "$ref": "#/$defs/option_group_linkage"
                    }
                }
            },
            "required": [
                "id",
                "name",
                "items"
            ]
        },
        "category": {
            "title": "Category",
            "description": "A Category is a container for menu items. ",
            "type": "object",
            "properties": {
                "id": {
                    "type": [
                        "integer",
                        "string"
                    ]
                },
                "name": {
                    "type": "string"
                },
                "description": {
                    "type": "string"
                },
                "active": {
                    "type": "boolean",
                    "description": "Whether the category is active or not. This will overrride any hours that are set."
                },
                "hours": {
                    "type": "object",
                    "description": "An object with weekday entries in this format. Time ranges are in military time. only single ranges are supported currently. Example for a category that is only available on sunday and monday from 9:30am to 5:30pm: {'sunday': [['9:30','17:30']], 'monday':[['9:30','17:30']]}. Valid entries: sunday monday tuesday wednesday thursday friday saturday"
                },
                "imageUrl": {
                    "$ref": "#/$defs/images"
                },
                "items": {
                    "type": "array",
                    "items": {
                        "$ref": "#/$defs/item"
                    }
                },
                "groups": {
                    "description": "Option groups in this list will be prepended to the option groups in every menu item in this category.",
                    "type": "array",
                    "minItems": 0,
                    "items": {
                        "$ref": "#/$defs/option_group_linkage"
                    }
                },
                "children": {
                    "type": "array",
                    "items": {
                        "$ref": "#/$defs/subcategory"
                    },
                    "description": "A list of sub categories. These sub categories cannot have children categories."
                }
            },
            "required": [
                "id",
                "name",
                "items"
            ]
        },
        "option_group_linkage": {
            "title": "Option group linkage",
            "description": "References an option group defined in the option_groups top-level array. Only ID is required, everything else is for menu item-based overrides",
            "type": "object",
            "properties": {
                "id": {
                    "type": [
                        "integer",
                        "string"
                    ],
                    "description": "Reference to the ID in the top level option group."
                },
                "required": {
                    "type": "boolean"
                },
                "free_options": {
                    "type": "number",
                    "description": "How many options are included for free. Default selected options dop not count toward this value. Does not apply for single select options."
                },
                "force_min": {
                    "type": "number",
                    "description": "Not currently supported. Force a minumum number of selected options among all option selections."
                },
                "force_max": {
                    "type": "number",
                    "description": "Force a maximum number of selected options among all option selections."
                },
                "options": {
                    "type": "array",
                    "minItems": 0,
                    "items": {
                        "title": "Option item linkage",
                        "description": "References an *option item* defined in the option_groups->options top-level array. Only ID is required, everything else is for menu item-based overrides",
                        "properties": {
                            "id": {
                                "type": [
                                    "integer",
                                    "string"
                                ],
                                "description": "Reference to the ID in the top level option *item*"
                            },
                            "sizePriceOverrides": {
                                "description": "Size prices can be overriden for each option. Prices can be flat numeric prices or a percentage of the option item price.",
                                "type": "array",
                                "items": {
                                    "properties": {
                                        "id": {
                                            "type": "string",
                                            "description": "A size id that must match a size in your top level sizes data."
                                        },
                                        "price": {
                                            "type": [
                                                "integer",
                                                "string"
                                            ],
                                            "description": "Can be an integer or float indicating a price or a percentage or -9999 to disable the option for the size. Percentage example of 50% would be half of the price that is set on the option. -9999 would disable this option for the size."
                                        }
                                    }
                                }
                            },
                            "default": {
                                "type": "integer"
                            },
                            "name": {
                                "type": "string"
                            },
                            "sub_options": {
                                "type": "array",
                                "minItems": 0,
                                "items": {
                                    "required": [
                                        "id",
                                        "options"
                                    ],
                                    "properties": {
                                        "id": {
                                            "type": [
                                                "integer",
                                                "string"
                                            ],
                                            "description": "Reference to the ID in the top level option *group*"
                                        },
                                        "force_min": {
                                            "type": "number",
                                            "description": "Not currently supported. Force a minumum number of selected options among all option selections."
                                        },
                                        "force_max": {
                                            "type": "number",
                                            "description": "Force a maximum number of selected options among all option selections."
                                        },
                                        "options": {
                                            "type": "array",
                                            "minItems": 0,
                                            "required": [
                                                "id",
                                                "default"
                                            ],
                                            "items": {
                                                "properties": {
                                                    "id": {
                                                        "type": [
                                                            "integer",
                                                            "string"
                                                        ],
                                                        "description": "Reference to the ID in the top level option *item*"
                                                    },
                                                    "default": {
                                                        "type": "integer",
                                                        "description": ""
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "required": [
                            "id"
                        ]
                    }
                }
            },
            "required": [
                "id",
                "options"
            ]
        }
    }
}