Free restaurant profit check, recipe costing, calculators, website check, deadlines, guides, blog.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Works out what a US restaurant's reservation app costs it, as the free booking fee check on restaurantdoctorai.com does: a month, a year, per guest who booked through it and as a share of the average spend, from the plan's published price (dated, sourced) or the owner's invoice, plus fees per guest and the percentage on deposits. Of the apps checked, only OpenTable charges per guest: for guests from its own app and website, possibly from Google and partners, and on Basic from the restaurant's own website. Returns a one-sentence headline first, the month line by line, what isn't counted, what the owner can do (book direct, mark no-shows, the contract's notice date), other apps' published prices as information, not a recommendation, the caveats and sources. It answers what OpenTable, Resy, Tock, Yelp, Toast Tables, SpotOn or SevenRooms costs a restaurant per reservation or per guest. It needs the app and plan (on the invoice) and, for OpenTable, last month's guests from its covers report by where they booked; the rest is optional. A figure that isn't sent is never counted as 0. Not affiliated with any app; it reads no account. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
The app and plan, on the invoice. tock_ = Tock, now sold by Resy; other = any app not listed, with monthlyFee.
Works out what a US restaurant's reservation app costs it, as the free booking fee check on restaurantdoctorai.com does: a month, a year, per guest who booked through it and as a share of the average spend, from the plan's published price (dated, sourced) or the owner's invoice, plus fees per guest and the percentage on deposits. Of the apps checked, only OpenTable charges per guest: for guests from its own app and website, possibly from Google and partners, and on Basic from the restaurant's own website. Returns a one-sentence headline first, the month line by line, what isn't counted, what the owner can do (book direct, mark no-shows, the contract's notice date), other apps' published prices as information, not a recommendation, the caveats and sources. It answers what OpenTable, Resy, Tock, Yelp, Toast Tables, SpotOn or SevenRooms costs a restaurant per reservation or per guest. It needs the app and plan (on the invoice) and, for OpenTable, last month's guests from its covers report by where they booked; the rest is optional. A figure that isn't sent is never counted as 0. Not affiliated with any app; it reads no account. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| platform* | string | The app and plan, on the invoice. tock_ = Tock, now sold by Resy; other = any app not listed, with monthlyFee. |
| firstMonth | any | |
| monthlyFee | any | |
| renewalDate | any | |
| averageSpend | any | |
| networkCovers | any | |
| partnerCovers | any | |
| prepaidAmount | any | |
| websiteCovers | any | |
| networkCoverFee | any | |
| partnerCoverFee | any | |
| websiteFlatAddOn | any | |
| prepaidFeePercent | any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"platform"
],
"properties": {
"platform": {
"enum": [
"opentable_basic",
"opentable_core",
"opentable_pro",
"resy_platform",
"resy_platform_360",
"tock_essential",
"tock_premium",
"yelp_basic",
"yelp_plus",
"toast_tables_plus",
"spoton_reserve",
"sevenrooms",
"other"
],
"type": "string",
"description": "The app and plan, on the invoice. tock_ = Tock, now sold by Resy; other = any app not listed, with monthlyFee."
},
"firstMonth": {
"anyOf": [
{
"type": "boolean",
"description": "OpenTable Basic only: true if last month was the first 30 days (network guests free)."
},
{
"type": "null"
}
]
},
"monthlyFee": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "The invoice's monthly fee: plan plus add-ons, before fees per guest. Left out: the published price. Needed for sevenrooms and other."
},
{
"type": "null"
}
]
},
"renewalDate": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Not on opentable_basic or spoton_reserve: the contract's renewal date, YYYY-MM-DD, from the contract; month-to-month plans have none."
},
{
"type": "null"
}
]
},
"averageSpend": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "The average spend per guest: net sales ÷ guests, from the POS."
},
{
"type": "null"
}
]
},
"networkCovers": {
"anyOf": [
{
"type": "integer",
"maximum": 1000000000,
"minimum": 0,
"description": "Guests seated last month who booked through the app itself (its own app or site). OpenTable: the Network line of its covers report; needed for OpenTable. Other apps: every guest booked through it, wherever they booked."
},
{
"type": "null"
}
]
},
"partnerCovers": {
"anyOf": [
{
"type": "integer",
"maximum": 1000000000,
"minimum": 0,
"description": "OpenTable only: guests who booked through Google and other partners, the report's Partner or Affiliate line. Left out: not counted."
},
{
"type": "null"
}
]
},
"prepaidAmount": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Money the app collected last month, from its statement: deposits, prepayments, no-show charges. tock_: prepayments only."
},
{
"type": "null"
}
]
},
"websiteCovers": {
"anyOf": [
{
"type": "integer",
"maximum": 1000000000,
"minimum": 0,
"description": "OpenTable only: guests who booked through the restaurant's own website (a fee each on Basic)."
},
{
"type": "null"
}
]
},
"networkCoverFee": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "OpenTable or other only: the fee per guest on the invoice, only if it isn't the published one."
},
{
"type": "null"
}
]
},
"partnerCoverFee": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "OpenTable only: the fee per partner guest, from its Billing History tab. Left out: a range."
},
{
"type": "null"
}
]
},
"websiteFlatAddOn": {
"anyOf": [
{
"type": "boolean",
"description": "OpenTable Basic only: true if the invoice shows the monthly flat fee for website bookings."
},
{
"type": "null"
}
]
},
"prepaidFeePercent": {
"anyOf": [
{
"type": "number",
"maximum": 100,
"minimum": 0,
"description": "The app's percentage of that money, as a percent (2 for 2%, not 0.02), only if it isn't the published one."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}Works out a restaurant's break-even sales from the owner's figures for one typical month, as the free break-even calculator on restaurantdoctorai.com does: the sales a month needs to pay every bill, also a week, a day open and guests a day; how far the month was above or short of it; what was left over after every bill; what a point of cost moves it by; with and without the owner's own pay; and if prices were 10% lower or higher (an illustration). Hourly pay can rise with sales or stay fixed, or both ways as a range. Takes the month's figures in any currency; a figure not sent is never counted as 0. Returns the result, the working and a link that opens the calculator with the figures in. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| goal | any | |
| sales | any | |
| hourly | any | |
| ownerPay | any | |
| hourlyPay | any | |
| purchases | any | |
| fixedBills | any | |
| daysPerWeek | any |
Checks a US restaurant's card processing fees for one month, as the free card fees check on restaurantdoctorai.com does: the cost per 100 dollars of card sales (the effective rate), against a dated fair range for that type of restaurant (an estimate of a competitive interchange-plus account from Visa's published restaurant interchange, network fees and a fair markup); how far above it the fees are, a month and a year; how they compare with Square's, Toast's, Clover's or Stripe's published rate; what's realistic for that processor, words to read out to it, the fees to question on the statement by name, and the caveats. It answers whether card fees are too high, what the effective rate is, and what to ask the processor. It needs the month's total card sales and total card fees from the processor's statement (every fee, monthly and annual ones included), who processes the cards and what kind of restaurant it is; the number of card sales or the average sale narrows it. A figure that isn't sent is never counted as 0. It doesn't read statements, contact a processor or take payment. Returns the result, how it was worked out, and a link that opens the same check with the figures filled in. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| format* | string | The type of restaurant, which sets the likely mix of debit and credit cards: quick_service = Quick service (Counter or kiosk, fast turnover); fast_casual = Fast casual (Order at the counter, food brought to the table); full_service = Full service / casual dining (Servers, moderate check); fine_dining = Fine dining (Chef-driven, higher check); bar_lounge = Bar, taproom or lounge (Drinks are about half of sales or more); cafe = Café or coffee shop (Drinks lead, with pastries and light food). |
| cardCount | any |
Works out a restaurant's nightly cash close for one drawer and one day or shift, as the free cash-out sheet on restaurantdoctorai.com does: expected cash (starting bank + cash sales - cash tips paid out - paid outs), over or short against the cash counted, the deposit (counted minus the starting bank), the card difference (processor batch minus POS card sales) when both are sent, and comps, voids and discounts as a share of net sales. Takes the starting bank, cash sales and cash counted, plus optional paid outs, card figures and sales totals, in any currency; a figure that isn't sent is never counted as 0. It sets no normal for over or short. Returns the result, how it was worked out, and a link to the free cash-out sheet. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| comps | any | |
| voids | any | |
| netSales | any | |
| paidOuts | any | |
| cardBatch | any | |
| cardSales | any | |
| cashSales | any | |
| discounts |
Checks a restaurant's own website as the online check on restaurantdoctorai.com does: secure (https), made for phones, a menu written as text that phones and Google can read, online orders on its own terms or only through delivery apps, tap to call, a title and description for Google, and Google's phone speed test (15 to 40 seconds; phoneSpeed: false skips it). Returns each check with what to fix, the three to fix first, and a link to the full online check, which adds the Google listing and places nearby, free on the website. Takes only the website address. The website isn't stored; only an anonymous daily count of checks is kept.
| Argument | Type | Description |
|---|---|---|
| website* | string | The restaurant's own website address, such as joesdiner.com or https://www.joesdiner.com. Not a DoorDash, Uber Eats or Google Maps page. |
| phoneSpeed | boolean | Whether to run Google's phone speed test too (the default). It takes 15 to 40 seconds; false skips it. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"website"
],
"properties": {
"website": {
"type": "string",
"maxLength": 300,
"minLength": 4,
"description": "The restaurant's own website address, such as joesdiner.com or https://www.joesdiner.com. Not a DoorDash, Uber Eats or Google Maps page."
},
"phoneSpeed": {
"type": "boolean",
"default": true,
"description": "Whether to run Google's phone speed test too (the default). It takes 15 to 40 seconds; false skips it."
}
},
"additionalProperties": false
}Reads a recipe's ingredient lines as written, weighs each one with USDA FoodData Central and USDA yields, and prices it with the owner's own prices when given, else dated US public prices (BLS and USDA ERS store averages, USDA wholesale prices, and USDA weekly store-ad sale prices, which run low). Returns a draft in US dollars: each line's grams, cost and price source, what each line still needs, the cost per plate as a range, and a link that opens the draft on restaurantdoctorai.com, where the owner checks each line and adds prices for one plate cost and a menu price. The draft never gives one plate cost or a menu price, and says nothing about allergens or nutrition. The recipe isn't stored; only an anonymous daily count of drafts is kept.
| Argument | Type | Description |
|---|---|---|
| prices | array | The owner's own prices, when they give them. Lines without one use US public prices: store averages (BLS, USDA ERS), wholesale prices (USDA) and, for items those don't cover, USDA weekly store-ad sale prices, which run low. None is the owner's cost. Tap water is costed at 0. |
| recipe* | string | The recipe as written: its name, its servings line ("Serves 6") and its ingredient lines, one a line, each amount and unit exactly as the recipe or the photo gives it. Method steps may follow under a heading such as "Instructions"; only ingredient lines are costed. The lines are read as sent, not converted, rounded or corrected: the owner checks them on the website. At most 8000 characters and 60 ingredient lines. |
| source | string | Where the recipe came from: text the owner typed or pasted (text), a photo or scan of a printed or typed page (typed-photo), a handwritten card (handwriting), or a PDF (pdf). It sets how many lines the owner confirms on the website: handwriting, every line. |
Lists a US restaurant's coming tax, payroll, license and permit deadlines, as the deadline calendar on restaurantdoctorai.com does: federal dates (payroll forms, tip reports, W-2s, 1099s, returns, estimated tax) and the state's (sales tax, unemployment reports, yearly reports, franchise taxes, minimum wage changes, liquor and health permit dates where one date applies to everyone), each moved for weekends and holidays by the agency's rule, with the rule, what a miss costs and the official source. A state date is given only where the state's own page confirms it; the rest come as what to check with the agency. Also the rules for each hire, and a link that opens the same calendar on the website, where the owner adds their own license and permit dates and gets free email reminders. Takes the state and yes/no answers, no names or emails; scope (federal or state) and withinDays (the next so many days) cut the list. Reminders, not legal or tax advice. The answers aren't stored; only an anonymous daily count of calendars is kept.
| Argument | Type | Description |
|---|---|---|
| city | string | A city with its own minimum wage, as an id like los-angeles or chicago; left out, the state's rate applies. |
| tips | boolean | Customers usually tip the staff. |
| scope | string | Optional, to cut the list: federal (the IRS's and other federal dates only), state (the state's and the city's only) or all (the default). The rules for each hire are listed either way. |
| staff* | boolean | Has anyone on payroll. |
Works out a dish's break-even price on a delivery app, the app price that leaves the owner the same money as selling it in their dining room, as the free delivery app price calculator on restaurantdoctorai.com does: the in-house price ÷ (1 − the app's real commission rate), the markup on the in-house price that takes (rounded up to a whole percent), and what the app keeps. Takes the dish's in-house price, in any currency, and one app's real commission rate from its payout statements; a figure that isn't sent is never counted as 0. Returns the calculator's result, how it was worked out, and a link that opens the calculator with the same figures filled in. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| rate | any | |
| price | any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"rate": {
"anyOf": [
{
"type": "number",
"maximum": 89,
"minimum": 0,
"description": "One delivery app's real commission rate, as a percent: 30 for 30%, not 0.30. From a month of that app's payout statements: (menu sales before tax and tips − the app's payout without tax and tips) ÷ those menu sales × 100, so marketing fees, promotions the owner funds and refunds are in it; the rate in the app's plan leaves them out. Each app is worked out on its own. Needed for a result: 0, or from 1 to 89; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"price": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "The dish's price on the owner's own menu, as a dining room guest pays it, in the owner's own currency (14 or 18.5). Needed for a result, and more than 0; if missing, the reply asks for it."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}Estimates a US restaurant's FICA tip credit (IRS Form 8846, the 45B credit) for a year like the one in its payroll figures, as the free FICA tip credit check on restaurantdoctorai.com does: the employer's 7.65% Social Security and Medicare tax on reported tips, less the tips needed to bring tipped staff's cash wage up to the 5.15 dollars an hour the law fixes for restaurants. Returns the reasons the real answer may be zero first (already claimed, no federal income tax owed, service charges aren't tips, only the business can claim it), then the credit as a range, its worth after the deduction it replaces, the years that may still be open, and sources. It answers questions about taxes on tips, Form 8846, the 45B credit or money the business may be missing on tips. It needs the state, a year's tips reported through payroll (never service charges) and, where the cash wage is under 5.15 dollars, tipped staff's hours that year; whether the return already includes Form 8846 comes first, if known. A figure that isn't sent is never counted as 0. It files nothing, isn't tax advice and takes no payment: the result is an estimate to take to the accountant, with a link that opens the same check with the figures filled in. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| state | any | |
| cashWage | any | |
| tippedHours | any | |
| businessType | any | |
| reportedTips | any |
Lists the 12 multiple-choice questions of the free restaurant profit check, with the answer values each one accepts. Money ranges, delivery apps and review sites follow the restaurant's country (default US).
| Argument | Type | Description |
|---|---|---|
| country | string | Where the restaurant is: a two-letter ISO 3166-1 code such as US, CA, AU or DE (GB for the United Kingdom). Sets the currency and local wording. Defaults to US. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"country": {
"type": "string",
"default": "US",
"pattern": "^[A-Za-z]{2}$",
"description": "Where the restaurant is: a two-letter ISO 3166-1 code such as US, CA, AU or DE (GB for the United Kingdom). Sets the currency and local wording. Defaults to US."
}
},
"additionalProperties": false
}Works out a restaurant's labor cost from the owner's own payroll figures for one week or month, as the free labor cost calculator on restaurantdoctorai.com does, in one of its three modes: share (labor as a % of net sales, against the range for its type of restaurant, with what the points over are worth), hours (next period's labor budget and the hourly staff hours it pays for once salaries are paid) or line (the cut line: the sales per labor hour below which the first person goes home). Takes net sales, hourly pay and hours worked, plus optional salaries, payroll taxes and benefits, expected sales, a target and more, in any currency; a figure that isn't sent is never counted as 0. Returns the calculator's result, how it was worked out, and a link that opens the calculator with the same figures filled in. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| mode* | string | What to work out, as the page's tabs. share: last period's labor cost, % of net sales, against the range (needs sales, hourlyWages). hours: the labor budget for next period's expected sales and the hourly staff hours it pays for (needs forecast, hourlyWages, hours). line: the cut line, the sales per labor hour below which the first person goes home (needs hourlyWages, hours, and sales or forecast). |
| hours | any | |
| sales | any | |
| format* | string | The type of restaurant, which sets the labor range and the starting target: quick_service = Quick service (Counter or kiosk, fast turnover); fast_casual = Fast casual (Order at the counter, food brought to the table); full_service = Full service / casual dining (Servers, moderate check); fine_dining = Fine dining (Chef-driven, higher check); bar_lounge = Bar, taproom or lounge (Drinks are about half of sales or more); cafe = Café or coffee shop (Drinks lead, with pastries and light food). |
Lists the entries of RestaurantDoctorAI's sourced library, all or one kind (guide, post, play, targets, fact or knowledge), up to 50 at a time: each with its id, kind, title, link and source, and for guides and blog posts the day it was published and last updated. It shows what the library has, such as every blog post and its date. Pages with offset and limit; nextOffset gives the next page. Nothing about the request is stored; only an anonymous daily count of searches (a list counts as one) is kept.
| Argument | Type | Description |
|---|---|---|
| kind | string | Which kind of entry to list: guide (the website's guides), post (blog posts), play (RestaurantDoctorAI's step-by-step fixes), targets (RestaurantDoctorAI's targets by type of restaurant), fact (sourced industry facts) or knowledge (sourced how-tos, rules and checklists); or all (the default). |
| limit | integer | How many entries to return, 1 to 50 (default 20). |
| offset | integer | How many entries to skip (default 0). The next page starts at the nextOffset the previous list returned. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"kind": {
"enum": [
"guide",
"post",
"play",
"targets",
"fact",
"knowledge",
"all"
],
"type": "string",
"default": "all",
"description": "Which kind of entry to list: guide (the website's guides), post (blog posts), play (RestaurantDoctorAI's step-by-step fixes), targets (RestaurantDoctorAI's targets by type of restaurant), fact (sourced industry facts) or knowledge (sourced how-tos, rules and checklists); or all (the default)."
},
"limit": {
"type": "integer",
"default": 20,
"maximum": 50,
"minimum": 1,
"description": "How many entries to return, 1 to 50 (default 20)."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 0,
"description": "How many entries to skip (default 0). The next page starts at the nextOffset the previous list returned."
}
},
"additionalProperties": false
}Works out a dish's calories from its recipe, as the free menu calorie counter on restaurantdoctorai.com does: each ingredient's calories from USDA FoodData Central (a list of 118 common foods) or its pack label, added up, shared by the plates it makes or by portion weight, and rounded once the way US, Ontario or UK and EU menus show calories. Ingredients are matched to that list, never guessed: words that fit several foods come back with the foods to pick from, and words that fit none with the nearest foods, or as not on the list. A pack label's kcal per 100 g comes from the owner's own label, never an estimate: without one, that ingredient can't be counted yet. Returns the menu figure, the exact one, how it was worked out with each food's FDC ID, what to check before printing, and a link that opens the counter with the same recipe filled in. It's an estimate, not a lab test. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| dish | any | |
| plates | any | |
| country* | string | Where the menu is: sets the energy figure and its rounding. us = US; ontario = Canada (Ontario); ukeu = UK, Ireland or EU (kcal, with the EU's energy factors). |
| portioning* | string | plates: one plate, or a batch shared into plates (12 pancakes). weight: portions weighed from a cooked batch (a ladle of soup). |
| ingredients |
Works out par levels and what to order for up to 50 kitchen or bar items, as the free prep and par sheet on restaurantdoctorai.com does. Par = use per day × days covered + safety stock (days covered: from the day of the count and the order until the next delivery after this one arrives); order = par minus what's on hand, never below 0, rounded up to whole packs when a pack size is sent. Takes each item's use per day (or per week and the days open a week), days covered, optional safety stock and pack size, and what's on hand, in the owner's own units; a figure that isn't sent is never counted as 0, and an item missing one is returned as incomplete. Returns each item's par and order, the items that need an order, and a link to the free prep and par sheet. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| items | any | |
| daysCovered | any | |
| daysOpenPerWeek | any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"items": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"anyOf": [
{
"type": "string",
"maxLength": 60,
"description": "Optional: the item."
},
{
"type": "null"
}
]
},
"unit": {
"anyOf": [
{
"type": "string",
"maxLength": 60,
"description": "Optional: the unit, such as lb or each."
},
{
"type": "null"
}
]
},
"onHand": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Units on hand when the order is placed. Needed."
},
{
"type": "null"
}
]
},
"safety": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: units kept on top for a busy day or a late truck. Left out, 0."
},
{
"type": "null"
}
]
},
"packSize": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"description": "Optional: units in one pack, to 3 decimals. With it, the order is whole packs.",
"exclusiveMinimum": 0
},
{
"type": "null"
}
]
},
"usePerDay": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Units used in a day open. Needed, or usePerWeek."
},
{
"type": "null"
}
]
},
"usePerWeek": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Units used in a week: divided by daysOpenPerWeek. Not used when usePerDay is sent."
},
{
"type": "null"
}
]
},
"daysCovered": {
"anyOf": [
{
"type": "number",
"maximum": 60,
"description": "This item's days covered. Left out, the list's daysCovered.",
"exclusiveMinimum": 0
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"maxItems": 50,
"description": "Needed: the items, up to 50."
},
{
"type": "null"
}
]
},
"daysCovered": {
"anyOf": [
{
"type": "number",
"maximum": 60,
"description": "Days each order covers, for items without their own: from the day of the count and the order to the day the next delivery after this one arrives.",
"exclusiveMinimum": 0
},
{
"type": "null"
}
]
},
"daysOpenPerWeek": {
"anyOf": [
{
"type": "integer",
"maximum": 7,
"minimum": 1,
"description": "Days open a week, 1 to 7. Needed only for items sent with usePerWeek."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}Works out what one plate of a dish costs and what to charge for it, as the free plate cost calculator on restaurantdoctorai.com does: from each ingredient's pack price and the amount used (with a usable % for trim), or from a plate cost the owner already knows; then the food cost at the menu price, what's left per plate, the price for their target food cost and the prices inside the range for their type of restaurant, with the tax taken out of a tax-inclusive menu. It works from the owner's own prices and amounts, in any currency; a figure that isn't sent is never counted as 0. Returns the calculator's result, how it was worked out, and a link that opens the calculator with the same figures filled in. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| mode* | string | ingredients: from each ingredient's pack price and the amount used. known: from a plate cost the owner already has. |
| sold | any | |
| extras | any | |
| format* | string | The type of restaurant, which sets the food cost range and the starting target: quick_service = Quick service (Counter or kiosk, fast turnover); fast_casual = Fast casual (Order at the counter, food brought to the table); full_service = Full service / casual dining (Servers, moderate check); fine_dining = Fine dining (Chef-driven, higher check); bar_lounge = Bar, taproom or lounge (Drinks are about half of sales or more); cafe = Café or coffee shop (Drinks lead, with pastries and light food). |
Works out a restaurant's prime cost from the owner's own figures for one week or month, as the free prime cost calculator on restaurantdoctorai.com does: food and drink used plus labor, as a share of net sales, against the target for its type of restaurant, with what the points over or under are worth, food and labor each against their own range, and which to look at first. Takes net sales, food and drink purchases and wages, plus optional payroll taxes and benefits, stock counts and the owner's unpaid hours, in any currency; a figure that isn't sent is never counted as 0. Returns the calculator's result, how it was worked out, and a link that opens the calculator with the same figures filled in. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| sales | any | |
| wages | any | |
| format* | string | The type of restaurant, which sets the targets: prime cost, and the ranges for food and drink and for labor: quick_service = Quick service (Counter or kiosk, fast turnover); fast_casual = Fast casual (Order at the counter, food brought to the table); full_service = Full service / casual dining (Servers, moderate check); fine_dining = Fine dining (Chef-driven, higher check); bar_lounge = Bar, taproom or lounge (Drinks are about half of sales or more); cafe = Café or coffee shop (Drinks lead, with pastries and light food). |
| period* | string | Whether every figure covers one week or one month, the same dates for all of them. Sets how a year is worked out (52 weeks or 12 months). |
Reads one entry of RestaurantDoctorAI's library in full (a guide, a blog post, a playbook fix, the targets, a fact or a knowledge entry), by its id (such as 'guide:restaurant-prime-cost'), with its title, link and source. A long entry comes 8,000 characters at a time, with its total length: the next part starts at the nextOffset it returns. The query isn't stored; only an anonymous daily count of searches and reads is kept.
| Argument | Type | Description |
|---|---|---|
| id* | string | An entry id, as the library's search and list give it, e.g. 'guide:restaurant-prime-cost' or 'post:restaurant-break-even-point'. |
| offset | integer | Where to start, in characters (default 0, the start). A long entry comes 8,000 characters at a time: the next part starts at the nextOffset the previous read returned. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"maxLength": 120,
"minLength": 3,
"description": "An entry id, as the library's search and list give it, e.g. 'guide:restaurant-prime-cost' or 'post:restaurant-break-even-point'."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 0,
"description": "Where to start, in characters (default 0, the start). A long entry comes 8,000 characters at a time: the next part starts at the nextOffset the previous read returned."
}
},
"additionalProperties": false
}Works out a restaurant's monthly budget from the owner's expected sales and type of restaurant, as the free restaurant budget calculator on restaurantdoctorai.com does: food and drink, labor, prime cost and rent with utilities as money ranges by RestaurantDoctorAI's targets for that type, other operating costs at the owner's share or a 20% working assumption, what's left after every bill, and break-even sales with labor counted both ways. Takes expected net sales and the type, plus optional rent, the owner's own pay and the other costs share, in any currency; a figure that isn't sent is never counted as 0. Returns the calculator's result, how it was worked out, and a link that opens the calculator with the same figures filled in. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| rent | any | |
| sales | any | |
| format* | string | The type of restaurant, which sets RestaurantDoctorAI's targets the budget is split by: quick_service = Quick service (Counter or kiosk, fast turnover); fast_casual = Fast casual (Order at the counter, food brought to the table); full_service = Full service / casual dining (Servers, moderate check); fine_dining = Fine dining (Chef-driven, higher check); bar_lounge = Bar, taproom or lounge (Drinks are about half of sales or more); cafe = Café or coffee shop (Drinks lead, with pastries and light food). |
| otherPct | any | |
| ownerPay |
Scores a restaurant's 12 answers against RestaurantDoctorAI's targets for its type of restaurant and returns the free result the website shows: an overall grade, grades by area, the estimated profit leak of all the leaks together a month and a year, the biggest leak or opportunity with its estimated money a month, what one point of prime cost is worth, and the first fix. Includes a link that opens the same result on restaurantdoctorai.com. Takes only the 12 answers and the country, each answer one of the values its question accepts. The answers aren't stored; only an anonymous daily count of checks is kept.
| Argument | Type | Description |
|---|---|---|
| country | string | Where the restaurant is: a two-letter ISO 3166-1 code such as US, CA, AU or DE (GB for the United Kingdom). Sets the currency and local wording. Defaults to US. |
| laborFlexing* | string | When a shift gets slow, what happens to staffing? realtime_cuts_splh = We cut staff based on sales per labor hour; fixed_shifts_regardless = Everyone works their scheduled shift anyway; overtime_above_8_percent = Overtime is common (More than 8% of hours); chronic_understaffing_owner_covers = We're short-staffed (The owner or GM works the line). |
| serviceModel* | string | What kind of restaurant do you run? quick_service = Quick service (Counter or kiosk, fast turnover); fast_casual = Fast casual (Order at the counter, food brought to the table); full_service = Full service / casual dining (Servers, moderate check); fine_dining = Fine dining (Chef-driven, higher check); bar_lounge = Bar, taproom or lounge (Drinks are about half of sales or more); cafe = Café or coffee shop (Drinks lead, with pastries and light food). |
Searches RestaurantDoctorAI's sourced library: the website's guides and blog posts, RestaurantDoctorAI's step-by-step fixes, RestaurantDoctorAI's targets by type of restaurant, sourced industry facts, and an expert knowledge base of sourced how-tos, rules and checklists (costs, labor, money, growth, compliance, operations). Keyword search: "break-even", "breakeven" and "break even" are one term, and plurals match. Returns the best passages, each with its id, kind, title, link and source; kind narrows the search to one kind of entry. RestaurantDoctorAI's targets are its own, not industry benchmarks. The query isn't stored; only an anonymous daily count of searches and reads is kept.
| Argument | Type | Description |
|---|---|---|
| kind | string | Only this kind of entry: guide (the website's guides), post (blog posts), play (RestaurantDoctorAI's step-by-step fixes), targets (RestaurantDoctorAI's targets by type of restaurant), fact (sourced industry facts) or knowledge (sourced how-tos, rules and checklists). Left out, every kind. |
| limit | integer | How many passages to return, 1 to 8 (default 5). |
| query* | string | What to look up, in plain words, e.g. 'how to lower food cost', 'tip pool rules' or 'delivery app commission'. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"query"
],
"properties": {
"kind": {
"enum": [
"guide",
"post",
"play",
"targets",
"fact",
"knowledge"
],
"type": "string",
"description": "Only this kind of entry: guide (the website's guides), post (blog posts), play (RestaurantDoctorAI's step-by-step fixes), targets (RestaurantDoctorAI's targets by type of restaurant), fact (sourced industry facts) or knowledge (sourced how-tos, rules and checklists). Left out, every kind."
},
"limit": {
"type": "integer",
"default": 5,
"maximum": 8,
"minimum": 1,
"description": "How many passages to return, 1 to 8 (default 5)."
},
"query": {
"type": "string",
"maxLength": 300,
"minLength": 1,
"description": "What to look up, in plain words, e.g. 'how to lower food cost', 'tip pool rules' or 'delivery app commission'."
}
},
"additionalProperties": false
}Works out how a restaurant shares tips, two ways, as the free tip-out sheet on restaurantdoctorai.com does. method percent: a server's tip-out to support roles, each a percentage of the server's net sales or tips, with the total tip-out, what the server keeps from their tips, and an error-level check when the tip-out is more than the tips. method pool: a tip pool shared by hours, with optional points for each role, rounded to the cent with the rounding remainder placed on the largest share. Takes the figures in any currency; a figure that isn't sent is never counted as 0. Returns the split, how it was worked out, the Department of Labor's published points on tips with their sources, and a link to the free tip-out sheet. It only works out a split from the numbers sent; it doesn't say whether a tip-out or a tip pool is allowed. The figures aren't stored; only an anonymous daily count of calculator runs is kept.
| Argument | Type | Description |
|---|---|---|
| base | any | |
| pool | any | |
| tips | any | |
| roles | any | |
| method* | string | percent: one server's tip-out to support roles, each a % of the base. pool: a tip pool shared by hours, with optional points. |
| members | any | |
| averageSpend | any |
| closingStock | any |
| openingStock | any |
| otherVariable | any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"goal": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: what the owner would like left over a month after every bill, before income tax. Adds the sales for it."
},
{
"type": "null"
}
]
},
"sales": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Net sales for one typical month, in the owner's own currency: the POS sales summary, before tax and tips, app orders at menu price. Not a holiday rush: every figure is for that month. Needed, more than 0; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"hourly": {
"anyOf": [
{
"enum": [
"yes",
"no",
"unsure"
],
"type": "string",
"description": "Whether hourly staff time goes up and down with sales: yes, shifts are added and cut as it gets busy or quiet; no, about the same team every shift (a bill that stays the same); unsure (the default): both ways, as a range."
},
{
"type": "null"
}
],
"default": "unsure"
},
"ownerPay": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: the owner's own pay a month, if not on payroll. Counted as a bill; break-even is also given without it."
},
{
"type": "null"
}
]
},
"hourlyPay": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "That month's hourly wages from payroll, plus the employer's payroll taxes and benefits; no tips. Paid every two weeks: one pay run × 26 ÷ 12. Needed (0 with no hourly staff); if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"purchases": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "That month's food and drink supplier invoices, by delivery date. Needed; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"fixedBills": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "A month of the bills that stay the same: rent and utilities, salaries with their payroll taxes and benefits, insurance, software, marketing, loan and lease payments in full. No depreciation. Yearly bills ÷ 12. Not the owner's pay. Needed; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"daysPerWeek": {
"anyOf": [
{
"type": "integer",
"maximum": 7,
"minimum": 1,
"description": "Optional: days open a week, a whole number from 1 to 7. Turns the month into a day open (and guests a day, with averageSpend)."
},
{
"type": "null"
}
]
},
"averageSpend": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: average spend per guest, the POS average check or net sales ÷ guests. Turns sales into guests."
},
{
"type": "null"
}
]
},
"closingStock": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: stock at cost at the end of the month. Used only with openingStock."
},
{
"type": "null"
}
]
},
"openingStock": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: stock at cost at the start of the month. Used only with closingStock: food and drink is then opening + purchases - closing. Skip both if stock stayed steady."
},
{
"type": "null"
}
]
},
"otherVariable": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "That month's other costs that rise with every sale: card fees, app commissions (app sales minus payouts, without tax and tips), packaging, percentage rent, royalties, ad fund fees; nothing in the food and drink invoices. Needed (0 if none); if missing, the reply asks for it."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}| cardSales | any |
| processor* | string | Who processes the cards (the name at the top of the statement): bank = a bank or independent processor; other = another processor, or not sure. |
| totalFees | any |
| pricingModel | any |
| averageTicket | any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"processor",
"format"
],
"properties": {
"format": {
"enum": [
"quick_service",
"fast_casual",
"full_service",
"fine_dining",
"bar_lounge",
"cafe"
],
"type": "string",
"description": "The type of restaurant, which sets the likely mix of debit and credit cards: quick_service = Quick service (Counter or kiosk, fast turnover); fast_casual = Fast casual (Order at the counter, food brought to the table); full_service = Full service / casual dining (Servers, moderate check); fine_dining = Fine dining (Chef-driven, higher check); bar_lounge = Bar, taproom or lounge (Drinks are about half of sales or more); cafe = Café or coffee shop (Drinks lead, with pastries and light food)."
},
"cardCount": {
"anyOf": [
{
"type": "integer",
"maximum": 1000000000,
"minimum": 1,
"description": "Optional: the month's number of card sales (transactions), from the same statement. It narrows the fair range to the owner's own sale size."
},
{
"type": "null"
}
]
},
"cardSales": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "A month's card sales in US dollars, from the processor's statement or the POS card report: everything charged to cards, tips included, before fees, without delivery app orders. Needed for a result; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"processor": {
"enum": [
"square",
"toast",
"clover",
"stripe",
"bank",
"other"
],
"type": "string",
"description": "Who processes the cards (the name at the top of the statement): bank = a bank or independent processor; other = another processor, or not sure."
},
"totalFees": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "The same month's total card fees in US dollars, from the same statement: every fee the processor took (percentage, per-sale, monthly, annual, PCI and statement fees), not one line. Needed for a result; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"pricingModel": {
"anyOf": [
{
"enum": [
"flat",
"interchange_plus",
"tiered",
"not_sure"
],
"type": "string",
"description": "Optional, if the owner knows it: flat = Flat rate: one rate for every card; interchange_plus = Interchange-plus: interchange at cost plus a stated markup; tiered = Tiered: qualified, mid-qualified and non-qualified rates; not_sure = Not sure. It changes the advice, not the fair range."
},
{
"type": "null"
}
]
},
"averageTicket": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: the average card sale in US dollars, when cardCount isn't known. It narrows the fair range too."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}| any |
| cashCounted | any |
| startingBank | any |
| cashTipsPaidOut | any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"comps": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: the day's comps total from the POS. Needs netSales for its share."
},
{
"type": "null"
}
]
},
"voids": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: the day's voids total from the POS. Needs netSales for its share."
},
{
"type": "null"
}
]
},
"netSales": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: that day's net sales from the POS, before tax and tips. Turns comps, voids and discounts into shares."
},
{
"type": "null"
}
]
},
"paidOuts": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: cash taken out of the drawer for supplies and the like. Taken off expected cash."
},
{
"type": "null"
}
]
},
"cardBatch": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: what the card processor settled for the same day. With cardSales."
},
{
"type": "null"
}
]
},
"cardSales": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: that day's card sales from the POS. With cardBatch, gives the card difference."
},
{
"type": "null"
}
]
},
"cashSales": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "That day's cash payments, from the POS end-of-day (Z) report. Needed; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"discounts": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: the day's discounts total from the POS. Needs netSales for its share."
},
{
"type": "null"
}
]
},
"cashCounted": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "The cash counted at close, bank included. Needed; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"startingBank": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "The cash in the drawer at open: one drawer, one day or shift, in the owner's own currency like every figure here. Needed; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"cashTipsPaidOut": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: card tips paid to staff in cash from this drawer. Taken off expected cash."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}| servings | number | How many plates the recipe makes, when its text doesn't say. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"recipe"
],
"properties": {
"prices": {
"type": "array",
"items": {
"type": "object",
"required": [
"ingredient",
"paid",
"packSize",
"packUnit"
],
"properties": {
"paid": {
"type": "number",
"maximum": 1000000,
"minimum": 0,
"description": "What the owner pays for one pack, in US dollars."
},
"countOf": {
"enum": [
"each",
"clove",
"slice",
"stick",
"bunch",
"sprig",
"leaf",
"can",
"package"
],
"type": "string",
"description": "With packUnit each: what one item is, when it isn't a whole one, such as clove or bunch."
},
"packSize": {
"type": "number",
"maximum": 1000000,
"description": "How much one pack holds: 10 for a 10 lb case.",
"exclusiveMinimum": 0
},
"packUnit": {
"enum": [
"g",
"kg",
"oz",
"lb",
"ml",
"l",
"floz",
"gal",
"each"
],
"type": "string",
"description": "The pack's unit: g, kg, oz, lb, ml, l, floz (US fluid ounces), gal (US gallons) or each."
},
"ingredient": {
"type": "string",
"maxLength": 100,
"minLength": 1,
"description": "The ingredient as the recipe names it, such as \"ground beef\"."
}
},
"additionalProperties": false
},
"maxItems": 60,
"description": "The owner's own prices, when they give them. Lines without one use US public prices: store averages (BLS, USDA ERS), wholesale prices (USDA) and, for items those don't cover, USDA weekly store-ad sale prices, which run low. None is the owner's cost. Tap water is costed at 0."
},
"recipe": {
"type": "string",
"maxLength": 8000,
"minLength": 1,
"description": "The recipe as written: its name, its servings line (\"Serves 6\") and its ingredient lines, one a line, each amount and unit exactly as the recipe or the photo gives it. Method steps may follow under a heading such as \"Instructions\"; only ingredient lines are costed. The lines are read as sent, not converted, rounded or corrected: the owner checks them on the website. At most 8000 characters and 60 ingredient lines."
},
"source": {
"enum": [
"text",
"typed-photo",
"handwriting",
"pdf"
],
"type": "string",
"default": "text",
"description": "Where the recipe came from: text the owner typed or pasted (text), a photo or scan of a printed or typed page (typed-photo), a handwritten card (handwriting), or a PDF (pdf). It sets how many lines the owner confirms on the website: handwriting, every line."
},
"servings": {
"type": "number",
"maximum": 100000,
"description": "How many plates the recipe makes, when its text doesn't say.",
"exclusiveMinimum": 0
}
},
"additionalProperties": false
}| state* |
| string |
| The restaurant's US state, two letters (DC for Washington DC). |
| formed | string | The month the LLC or corporation was formed with the state, YYYY-MM. Some states set the yearly report by it. |
| months | integer | How many months ahead to list, 1 to 15 (default 3). The calendar runs to the end of 2027. withinDays, when sent, sets the window instead. |
| alcohol* | boolean | Sells alcohol. |
| caterer | boolean | Mainly catering or a food truck, not a restaurant or bar (OSHA's injury log). |
| business | string | How the business is set up: sole (sole owner, no LLC), llc_single, llc_multi, partnership (no LLC), s_corp or c_corp. Decides the tax return and the state's yearly report. Left out, both return dates come with an "If". |
| deposits | string | Who pays the payroll taxes to the IRS: provider (a payroll company), monthly (the owner, by the 15th), semiweekly (the owner, after each payday). |
| salesTax | string | How often the state has the restaurant file sales tax (on its permit letter or state account). |
| bigTipped | boolean | Tipped, and staff worked more than 80 hours in total on a typical day last year, all locations together (Form 8027). |
| estimated | boolean | The owner pays quarterly estimated tax on the business's profit. |
| fullTime50 | boolean | 50 or more full-time staff on average, counting part-timers' hours, related businesses together (ACA forms). |
| withinDays | integer | Optional: only the dates in the next so many days, 1 to 460, from today in the state (7 for the coming week). Sent, it replaces months. |
| contractors | boolean | Pays a contractor, or rent to a landlord that isn't a corporation, $2,000 or more a year (1099 forms). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"state",
"staff",
"alcohol"
],
"properties": {
"city": {
"type": "string",
"pattern": "^[a-z0-9-]{1,40}$",
"description": "A city with its own minimum wage, as an id like los-angeles or chicago; left out, the state's rate applies."
},
"tips": {
"type": "boolean",
"default": false,
"description": "Customers usually tip the staff."
},
"scope": {
"enum": [
"all",
"federal",
"state"
],
"type": "string",
"description": "Optional, to cut the list: federal (the IRS's and other federal dates only), state (the state's and the city's only) or all (the default). The rules for each hire are listed either way."
},
"staff": {
"type": "boolean",
"description": "Has anyone on payroll."
},
"state": {
"enum": [
"AL",
"AK",
"AZ",
"AR",
"CA",
"CO",
"CT",
"DE",
"DC",
"FL",
"GA",
"HI",
"ID",
"IL",
"IN",
"IA",
"KS",
"KY",
"LA",
"ME",
"MD",
"MA",
"MI",
"MN",
"MS",
"MO",
"MT",
"NE",
"NV",
"NH",
"NJ",
"NM",
"NY",
"NC",
"ND",
"OH",
"OK",
"OR",
"PA",
"RI",
"SC",
"SD",
"TN",
"TX",
"UT",
"VT",
"VA",
"WA",
"WV",
"WI",
"WY"
],
"type": "string",
"description": "The restaurant's US state, two letters (DC for Washington DC)."
},
"formed": {
"type": "string",
"pattern": "^\\d{4}-(0[1-9]|1[0-2])$",
"description": "The month the LLC or corporation was formed with the state, YYYY-MM. Some states set the yearly report by it."
},
"months": {
"type": "integer",
"default": 3,
"maximum": 15,
"minimum": 1,
"description": "How many months ahead to list, 1 to 15 (default 3). The calendar runs to the end of 2027. withinDays, when sent, sets the window instead."
},
"alcohol": {
"type": "boolean",
"description": "Sells alcohol."
},
"caterer": {
"type": "boolean",
"description": "Mainly catering or a food truck, not a restaurant or bar (OSHA's injury log)."
},
"business": {
"enum": [
"sole",
"llc_single",
"llc_multi",
"partnership",
"s_corp",
"c_corp"
],
"type": "string",
"description": "How the business is set up: sole (sole owner, no LLC), llc_single, llc_multi, partnership (no LLC), s_corp or c_corp. Decides the tax return and the state's yearly report. Left out, both return dates come with an \"If\"."
},
"deposits": {
"enum": [
"provider",
"monthly",
"semiweekly"
],
"type": "string",
"description": "Who pays the payroll taxes to the IRS: provider (a payroll company), monthly (the owner, by the 15th), semiweekly (the owner, after each payday)."
},
"salesTax": {
"enum": [
"monthly",
"quarterly",
"yearly"
],
"type": "string",
"description": "How often the state has the restaurant file sales tax (on its permit letter or state account)."
},
"bigTipped": {
"type": "boolean",
"description": "Tipped, and staff worked more than 80 hours in total on a typical day last year, all locations together (Form 8027)."
},
"estimated": {
"type": "boolean",
"description": "The owner pays quarterly estimated tax on the business's profit."
},
"fullTime50": {
"type": "boolean",
"description": "50 or more full-time staff on average, counting part-timers' hours, related businesses together (ACA forms)."
},
"withinDays": {
"type": "integer",
"maximum": 460,
"minimum": 1,
"description": "Optional: only the dates in the next so many days, 1 to 460, from today in the state (7 for the coming week). Sent, it replaces months."
},
"contractors": {
"type": "boolean",
"description": "Pays a contractor, or rent to a landlord that isn't a corporation, $2,000 or more a year (1099 forms)."
}
},
"additionalProperties": false
}| owesIncomeTax | any |
| alreadyClaimed | any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"state": {
"anyOf": [
{
"type": "string",
"description": "The US state the restaurant is in: a two-letter code (TX) or its name. It sets tipped staff's cash wage from the US Department of Labor's table. Needed for a result unless cashWage is sent; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"cashWage": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: the hourly cash wage tipped staff were paid before tips that year, in US dollars (2.13), if it wasn't the state's tipped wage; the lowest if it changed. Used instead of the state's."
},
{
"type": "null"
}
]
},
"tippedHours": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "The hours tipped staff worked that year, all together, from the payroll hours report. Needed for a result only when the cash wage is under $5.15 an hour (Texas: $2.13); then, if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"businessType": {
"anyOf": [
{
"enum": [
"c_corp",
"s_corp",
"partnership",
"sole_owner",
"unsure"
],
"type": "string",
"description": "Optional: how the business files its taxes, which sets what the credit is worth after tax: c_corp = C corporation; s_corp = S corporation (or an LLC taxed as one); partnership = Partnership (or an LLC taxed as one); sole_owner = Sole owner (or a one-owner LLC); unsure = Not sure (left out: unsure)."
},
{
"type": "null"
}
]
},
"reportedTips": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "A year's tips reported through payroll for one business, in US dollars: line 5b of the year's four Forms 941 added up, W-2 box 7 totals, or the year's total from the payroll tips report (Toast, Gusto). Service charges, automatic gratuities and delivery fees don't count: they're wages. Needed for a result; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"owesIncomeTax": {
"anyOf": [
{
"enum": [
"yes",
"no",
"unsure"
],
"type": "string",
"description": "Optional: whether the business (for a pass-through, its owners) usually owes federal income tax: yes, no or unsure (left out: unsure)."
},
{
"type": "null"
}
]
},
"alreadyClaimed": {
"anyOf": [
{
"enum": [
"yes",
"no",
"unsure"
],
"type": "string",
"description": "Optional, asked first: whether the business's return already includes Form 8846 (Form 3800, Part III, line 4f, or the credit on a K-1 from the business): yes, no or unsure (left out: unsure). Yes means there may be nothing left to find."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}| period* | string | Whether the figures are a week's or a month's: last period's, all for the same dates, and forecast for the next. Sets how a year is worked out (52 weeks or 12 months). |
| target | any |
| forecast | any |
| ownerPay | any |
| salaries | any |
| hourSales | any |
| hourlyWages | any |
| payrollCosts | any |
| overtimeHours | any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"mode",
"format",
"period"
],
"properties": {
"mode": {
"enum": [
"share",
"hours",
"line"
],
"type": "string",
"description": "What to work out, as the page's tabs. share: last period's labor cost, % of net sales, against the range (needs sales, hourlyWages). hours: the labor budget for next period's expected sales and the hourly staff hours it pays for (needs forecast, hourlyWages, hours). line: the cut line, the sales per labor hour below which the first person goes home (needs hourlyWages, hours, and sales or forecast)."
},
"hours": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Hours those staff worked last period, from the time clock: overtime in, salaried managers out. Needed for hours and line."
},
{
"type": "null"
}
]
},
"sales": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Last period's net sales, in the owner's own currency like every amount here, from the POS: after discounts and comps, before tax and tips, plus any service charge paid out to staff. Needed for share, and for line without forecast."
},
{
"type": "null"
}
]
},
"format": {
"enum": [
"quick_service",
"fast_casual",
"full_service",
"fine_dining",
"bar_lounge",
"cafe"
],
"type": "string",
"description": "The type of restaurant, which sets the labor range and the starting target: quick_service = Quick service (Counter or kiosk, fast turnover); fast_casual = Fast casual (Order at the counter, food brought to the table); full_service = Full service / casual dining (Servers, moderate check); fine_dining = Fine dining (Chef-driven, higher check); bar_lounge = Bar, taproom or lounge (Drinks are about half of sales or more); cafe = Café or coffee shop (Drinks lead, with pastries and light food)."
},
"period": {
"enum": [
"week",
"month"
],
"type": "string",
"description": "Whether the figures are a week's or a month's: last period's, all for the same dates, and forecast for the next. Sets how a year is worked out (52 weeks or 12 months)."
},
"target": {
"anyOf": [
{
"type": "number",
"maximum": 99,
"minimum": 1,
"description": "Optional, for hours and line: the owner's labor target, % of net sales (1 to 99). Left out: the top of the range, where the page starts."
},
{
"type": "null"
}
]
},
"forecast": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Net sales expected next period, more than 0: the last 4 weeks' (or 3 months') average, adjusted for events and holidays. Needed for hours; for line, the line is then for these sales."
},
{
"type": "null"
}
]
},
"ownerPay": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional, for share: if the owner works without a salary, what someone doing their hours would cost, payroll taxes in. Shown as a second figure."
},
{
"type": "null"
}
]
},
"salaries": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: salaried pay for the period (a yearly salary ÷ 52, or ÷ 12 for a month)."
},
{
"type": "null"
}
]
},
"hourSales": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional, for line: net sales in the last hour of a shift, for how many hourly staff it pays for."
},
{
"type": "null"
}
]
},
"hourlyWages": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Last period's gross pay for everyone paid by the hour, from payroll: by the days worked, overtime in, tips out. 0 if all are salaried (share only). Needed in every mode."
},
{
"type": "null"
}
]
},
"payrollCosts": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: the employer's payroll taxes and benefits on that pay, such as health insurance. Left out, labor reads lower, unless the pay already includes them."
},
{
"type": "null"
}
]
},
"overtimeHours": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional, for share: how many of the hours worked were overtime."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}| any |
| cookedWeight | any |
| portionWeight | any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"country",
"portioning"
],
"properties": {
"dish": {
"anyOf": [
{
"type": "string",
"maxLength": 100,
"minLength": 0,
"description": "Optional: the dish's name, for the record."
},
{
"type": "null"
}
]
},
"plates": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0.001,
"description": "With plates: how many plates it makes, 1 for a single plate. Needed then; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"country": {
"enum": [
"us",
"ontario",
"ukeu"
],
"type": "string",
"description": "Where the menu is: sets the energy figure and its rounding. us = US; ontario = Canada (Ontario); ukeu = UK, Ireland or EU (kcal, with the EU's energy factors)."
},
"portioning": {
"enum": [
"plates",
"weight"
],
"type": "string",
"description": "plates: one plate, or a batch shared into plates (12 pancakes). weight: portions weighed from a cooked batch (a ladle of soup)."
},
"ingredients": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"required": [
"unit"
],
"properties": {
"food": {
"anyOf": [
{
"type": "string",
"maxLength": 100,
"minLength": 1,
"description": "The food: its name on the counter's list of USDA foods, as an earlier answer gave it, or the owner's words for it, matched to that list. Words that fit several foods, or none, come back as a tool error naming the foods to pick from, or saying it isn't on the list. With kcalPer100g, just its name."
},
{
"type": "null"
}
]
},
"unit": {
"enum": [
"g",
"kg",
"oz",
"lb",
"ml",
"l",
"floz",
"cup",
"tbsp",
"tsp",
"each"
],
"type": "string",
"description": "g, kg, oz or lb for any food. ml, l, floz, cup, tbsp or tsp (US measures) for liquids and fats only; each for foods counted by the piece."
},
"amount": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "How much goes in, after trimming, in unit. Weighed if possible. Needed for a result; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"kcalPer100g": {
"anyOf": [
{
"type": "number",
"maximum": 900,
"minimum": 0,
"description": "For a food not on the list: kcal per 100 g from the nutrition panel on the owner's own pack, as the owner reads it (a US label gives a serving: its calories ÷ its grams × 100). It's the label's figure, not an estimate by the assistant: without the owner's label, the ingredient can't be counted yet. Weighed only."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"maxItems": 30,
"description": "What goes into the dish or batch, one entry each. Needed for a result; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"cookedWeight": {
"anyOf": [
{
"type": "object",
"required": [
"amount",
"unit"
],
"properties": {
"unit": {
"enum": [
"g",
"kg",
"oz",
"lb"
],
"type": "string"
},
"amount": {
"type": "number",
"maximum": 1000000000,
"minimum": 0.001
}
},
"description": "With weight: the whole batch, weighed after cooking. Needed then; if missing, the reply asks for it.",
"additionalProperties": false
},
{
"type": "null"
}
]
},
"portionWeight": {
"anyOf": [
{
"type": "object",
"required": [
"amount",
"unit"
],
"properties": {
"unit": {
"enum": [
"g",
"kg",
"oz",
"lb"
],
"type": "string"
},
"amount": {
"type": "number",
"maximum": 1000000000,
"minimum": 0.001
}
},
"description": "With weight: one portion. Needed then; if missing, the reply asks for it.",
"additionalProperties": false
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}| target | any |
| taxRate | any |
| portions | any |
| menuPrice | any |
| plateCost | any |
| ingredients | any |
| taxIncluded | any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"mode",
"format"
],
"properties": {
"mode": {
"enum": [
"ingredients",
"known"
],
"type": "string",
"description": "ingredients: from each ingredient's pack price and the amount used. known: from a plate cost the owner already has."
},
"sold": {
"anyOf": [
{
"type": "integer",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: how many of this dish sold last month (POS item sales), for the figures a month."
},
{
"type": "null"
}
]
},
"extras": {
"anyOf": [
{
"type": "number",
"maximum": 100,
"minimum": 0,
"description": "Optional, mode ingredients: small extras without a line of their own (salt, oil, garnish), % of the ingredients; often 5 to 10."
},
{
"type": "null"
}
]
},
"format": {
"enum": [
"quick_service",
"fast_casual",
"full_service",
"fine_dining",
"bar_lounge",
"cafe"
],
"type": "string",
"description": "The type of restaurant, which sets the food cost range and the starting target: quick_service = Quick service (Counter or kiosk, fast turnover); fast_casual = Fast casual (Order at the counter, food brought to the table); full_service = Full service / casual dining (Servers, moderate check); fine_dining = Fine dining (Chef-driven, higher check); bar_lounge = Bar, taproom or lounge (Drinks are about half of sales or more); cafe = Café or coffee shop (Drinks lead, with pastries and light food)."
},
"target": {
"anyOf": [
{
"type": "number",
"maximum": 99,
"minimum": 1,
"description": "Optional: the owner's target food cost, %. Left out, the middle of the format's range (32 for full service); none for a bar."
},
{
"type": "null"
}
]
},
"taxRate": {
"anyOf": [
{
"type": "number",
"maximum": 50,
"minimum": 0,
"description": "With taxIncluded, needed: the tax rate in this dish's price, %. Food and drinks can have different rates."
},
{
"type": "null"
}
]
},
"portions": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"description": "With mode ingredients, needed: how many plates the amounts make, 1 for a single plate.",
"exclusiveMinimum": 0
},
{
"type": "null"
}
]
},
"menuPrice": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"description": "Optional: the dish's price on the menu. Left out, the result gives the prices to charge, as for a new dish.",
"exclusiveMinimum": 0
},
{
"type": "null"
}
]
},
"plateCost": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "With mode known, needed: what the ingredients on one plate cost, from a recipe card or costing sheet, in the owner's own currency like every money figure here."
},
{
"type": "null"
}
]
},
"ingredients": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"required": [
"packUnit",
"usedUnit"
],
"properties": {
"name": {
"anyOf": [
{
"type": "string",
"maxLength": 100,
"description": "Optional: what it is, as the owner calls it."
},
{
"type": "null"
}
]
},
"paid": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "What the owner paid for one pack, from their latest invoice, before any VAT or GST they claim back."
},
{
"type": "null"
}
]
},
"used": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "The amount that goes in the pot or on the plate, after trimming, for the plates in portions. Spoons or cups: weighed once."
},
{
"type": "null"
}
]
},
"usable": {
"anyOf": [
{
"type": "number",
"maximum": 100,
"minimum": 1,
"description": "Optional: of what's bought, the % left after trimming or cooking: 85 for 1 kg that trims to 850 g. Left out, 100."
},
{
"type": "null"
}
]
},
"packSize": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"description": "How much one pack holds, in packUnit: 5 for a 5 lb bag. A case of 6 cans is 6 each; a 4 × 5 lb case is 20 lb.",
"exclusiveMinimum": 0
},
{
"type": "null"
}
]
},
"packUnit": {
"enum": [
"g",
"kg",
"oz",
"lb",
"ml",
"l",
"floz",
"gal",
"each"
],
"type": "string",
"description": "The pack's unit: floz and gal are US fluid ounces and gallons."
},
"usedUnit": {
"enum": [
"g",
"kg",
"oz",
"lb",
"ml",
"l",
"floz",
"gal",
"each"
],
"type": "string",
"description": "The amount's unit, of the pack's kind: weight, volume and count don't convert into each other."
}
},
"additionalProperties": false
},
"maxItems": 30,
"description": "With mode ingredients: each ingredient. A sauce or side already costed is one: its cost for a pack of 1 each, 1 each used."
},
{
"type": "null"
}
]
},
"taxIncluded": {
"anyOf": [
{
"type": "boolean",
"description": "true when menu prices include VAT or GST (UK, EU, Australia, New Zealand); left out when tax is added at the till (US, Canada)."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}| ownerPay | any |
| purchases | any |
| closingStock | any |
| openingStock | any |
| payrollCosts | any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"format",
"period"
],
"properties": {
"sales": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Net sales for the period, in the owner's own currency like every figure here, from the POS sales summary: after discounts and comps, before tax and tips, with any service charge paid out to staff added back. Needed for a result, and more than 0; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"wages": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Every wage and salary for the same dates, from payroll, managers included (a salary counts as a 52nd of a year for a week, a 12th for a month). No tips, but a service charge paid to staff stays in. Needed for a result; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"format": {
"enum": [
"quick_service",
"fast_casual",
"full_service",
"fine_dining",
"bar_lounge",
"cafe"
],
"type": "string",
"description": "The type of restaurant, which sets the targets: prime cost, and the ranges for food and drink and for labor: quick_service = Quick service (Counter or kiosk, fast turnover); fast_casual = Fast casual (Order at the counter, food brought to the table); full_service = Full service / casual dining (Servers, moderate check); fine_dining = Fine dining (Chef-driven, higher check); bar_lounge = Bar, taproom or lounge (Drinks are about half of sales or more); cafe = Café or coffee shop (Drinks lead, with pastries and light food)."
},
"period": {
"enum": [
"week",
"month"
],
"type": "string",
"description": "Whether every figure covers one week or one month, the same dates for all of them. Sets how a year is worked out (52 weeks or 12 months)."
},
"ownerPay": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: when the owner works in the restaurant without a salary, what they'd pay someone to do their hours, plus the payroll taxes on it. It's a second figure; the main one stays as the books have it."
},
{
"type": "null"
}
]
},
"purchases": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Food and drink supplier invoices for the same dates, added up by delivery date, minus credits. No packaging. Needed for a result; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"closingStock": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: stock at cost at the end of the period, counted on the same items the invoices cover. Used only with openingStock."
},
{
"type": "null"
}
]
},
"openingStock": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: stock at cost at the start of the period. Used only with closingStock: food and drink then becomes what was used, opening + purchases - closing."
},
{
"type": "null"
}
]
},
"payrollCosts": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: the employer's payroll taxes and benefits for the period, such as health insurance or a pension, when the wages figure leaves them out."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}| any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"format"
],
"properties": {
"rent": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: the owner's own rent, property charges and utilities for a month, together, as the occupancy targets count them. Replaces the occupancy range."
},
{
"type": "null"
}
]
},
"sales": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Expected net sales for one month, in the owner's own currency like every figure here: before tax and tips. Needed for a result, and more than 0; if missing, the reply asks for it."
},
{
"type": "null"
}
]
},
"format": {
"enum": [
"quick_service",
"fast_casual",
"full_service",
"fine_dining",
"bar_lounge",
"cafe"
],
"type": "string",
"description": "The type of restaurant, which sets RestaurantDoctorAI's targets the budget is split by: quick_service = Quick service (Counter or kiosk, fast turnover); fast_casual = Fast casual (Order at the counter, food brought to the table); full_service = Full service / casual dining (Servers, moderate check); fine_dining = Fine dining (Chef-driven, higher check); bar_lounge = Bar, taproom or lounge (Drinks are about half of sales or more); cafe = Café or coffee shop (Drinks lead, with pastries and light food)."
},
"otherPct": {
"anyOf": [
{
"type": "number",
"maximum": 60,
"minimum": 0,
"description": "Optional: other operating costs as a % of sales (card fees, packaging, cleaning, repairs, marketing, insurance, software, accounting, loan payments). Left out, 20% is used: a working assumption, not a target or a published figure."
},
{
"type": "null"
}
]
},
"ownerPay": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Optional: the owner's own pay for a month, when it isn't on payroll. Comes off what's left, and counts as a bill that stays the same."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}| contactCapture* | string | How do you bring guests back? automated_pos_loyalty_50plus = Loyalty or email list with automatic campaigns (50+ new contacts a week); occasional_checkout_emails = We collect some emails but rarely use them; no_database_social_only = Social media and walk-ins only; paid_ads_no_list = Paid ads, but no guest list of our own. |
| monthlyRevenue* | string | About how much do you sell in a typical month? Amounts are in US dollars, or in the local currency where that's the euro, pound sterling, Swiss franc, or Canadian, Australian or New Zealand dollar. under_25k = Under $25,000 (Under $300K a year); 25k_60k = $25,000 – $60,000 ($300K – $720K a year); 60k_120k = $60,000 – $120,000 ($720K – $1.44M a year); 120k_200k = $120,000 – $200,000 ($1.44M – $2.4M a year); over_200k = Over $200,000 (Over $2.4M a year). |
| seatingDynamics* | string | How full is your dining room across the week? consistent_weekround = Steady all week; packed_weekends_dead_midweek = Packed on weekends, quiet midweek; strong_lunch_weak_dinner = Busy lunches, slow dinners; erratic_unpredictable = Hard to predict week to week. |
| reputationHealth* | string | What's your average rating on Google and Yelp? 4_5_to_5_0 = 4.5 – 5.0 stars; 4_0_to_4_4 = 4.0 – 4.4 stars; 3_5_to_3_9 = 3.5 – 3.9 stars; under_3_5 = Below 3.5 stars. |
| beverageMonitoring* | string | How do you control drink pours? no_alcohol = We don't serve alcohol; measured_pour_keg_audits = Measured pours, plus weekly pour-cost checks; occasional_spot_checks = Spot checks when bottles run out early; free_pour_no_audit = Free pours, no pour-cost checks. |
| deliveryDependency* | string | How much of your sales come through DoorDash, Uber Eats or similar apps? zero_direct_only = None (Dine-in and our own ordering only); under_15_with_markup = Under 15% (With higher app prices to cover fees); 15_to_35_standard_cut = 15% – 35% (At regular menu prices); over_35_heavy_drag = More than 35%. |
| occupancyCostRatio* | string | What share of sales goes to rent, property costs and utilities? under_8_percent = Under 8%; 8_to_12_percent = 8% – 12%; over_12_percent = More than 12%; unsure_ratio = I'm not sure. |
| primeCostAwareness* | string | What's your prime cost: food, drink and labor costs as a share of sales? under_58 = Under 58%; 58_to_64 = 58% – 64%; over_65 = 65% or more; not_tracked_weekly = I don't track it regularly. |
| wasteTrackingMethod* | string | How do you track kitchen waste and spoilage? daily_signed_log = A daily log the chef signs off; weekly_visual_estimate = A rough estimate during weekly inventory; bulk_loss_only = Only when a big batch or case goes bad; no_formal_logging = We don't track it. |
| plateCostingFrequency* | string | How often do you update recipe costs with current supplier prices? live_monthly_software = Monthly or live, with software (Synced to supplier invoices); 6_to_12m_manual = Once or twice a year (In a spreadsheet); new_menu_only = Only when the menu changes; rarely_gut_feeling = Rarely (Prices are set by feel or by competitors). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"serviceModel",
"monthlyRevenue",
"primeCostAwareness",
"plateCostingFrequency",
"wasteTrackingMethod",
"beverageMonitoring",
"laborFlexing",
"occupancyCostRatio",
"deliveryDependency",
"seatingDynamics",
"contactCapture",
"reputationHealth"
],
"properties": {
"country": {
"type": "string",
"default": "US",
"pattern": "^[A-Za-z]{2}$",
"description": "Where the restaurant is: a two-letter ISO 3166-1 code such as US, CA, AU or DE (GB for the United Kingdom). Sets the currency and local wording. Defaults to US."
},
"laborFlexing": {
"enum": [
"realtime_cuts_splh",
"fixed_shifts_regardless",
"overtime_above_8_percent",
"chronic_understaffing_owner_covers"
],
"type": "string",
"description": "When a shift gets slow, what happens to staffing? realtime_cuts_splh = We cut staff based on sales per labor hour; fixed_shifts_regardless = Everyone works their scheduled shift anyway; overtime_above_8_percent = Overtime is common (More than 8% of hours); chronic_understaffing_owner_covers = We're short-staffed (The owner or GM works the line)."
},
"serviceModel": {
"enum": [
"quick_service",
"fast_casual",
"full_service",
"fine_dining",
"bar_lounge",
"cafe"
],
"type": "string",
"description": "What kind of restaurant do you run? quick_service = Quick service (Counter or kiosk, fast turnover); fast_casual = Fast casual (Order at the counter, food brought to the table); full_service = Full service / casual dining (Servers, moderate check); fine_dining = Fine dining (Chef-driven, higher check); bar_lounge = Bar, taproom or lounge (Drinks are about half of sales or more); cafe = Café or coffee shop (Drinks lead, with pastries and light food)."
},
"contactCapture": {
"enum": [
"automated_pos_loyalty_50plus",
"occasional_checkout_emails",
"no_database_social_only",
"paid_ads_no_list"
],
"type": "string",
"description": "How do you bring guests back? automated_pos_loyalty_50plus = Loyalty or email list with automatic campaigns (50+ new contacts a week); occasional_checkout_emails = We collect some emails but rarely use them; no_database_social_only = Social media and walk-ins only; paid_ads_no_list = Paid ads, but no guest list of our own."
},
"monthlyRevenue": {
"enum": [
"under_25k",
"25k_60k",
"60k_120k",
"120k_200k",
"over_200k"
],
"type": "string",
"description": "About how much do you sell in a typical month? Amounts are in US dollars, or in the local currency where that's the euro, pound sterling, Swiss franc, or Canadian, Australian or New Zealand dollar. under_25k = Under $25,000 (Under $300K a year); 25k_60k = $25,000 – $60,000 ($300K – $720K a year); 60k_120k = $60,000 – $120,000 ($720K – $1.44M a year); 120k_200k = $120,000 – $200,000 ($1.44M – $2.4M a year); over_200k = Over $200,000 (Over $2.4M a year)."
},
"seatingDynamics": {
"enum": [
"consistent_weekround",
"packed_weekends_dead_midweek",
"strong_lunch_weak_dinner",
"erratic_unpredictable"
],
"type": "string",
"description": "How full is your dining room across the week? consistent_weekround = Steady all week; packed_weekends_dead_midweek = Packed on weekends, quiet midweek; strong_lunch_weak_dinner = Busy lunches, slow dinners; erratic_unpredictable = Hard to predict week to week."
},
"reputationHealth": {
"enum": [
"4_5_to_5_0",
"4_0_to_4_4",
"3_5_to_3_9",
"under_3_5"
],
"type": "string",
"description": "What's your average rating on Google and Yelp? 4_5_to_5_0 = 4.5 – 5.0 stars; 4_0_to_4_4 = 4.0 – 4.4 stars; 3_5_to_3_9 = 3.5 – 3.9 stars; under_3_5 = Below 3.5 stars."
},
"beverageMonitoring": {
"enum": [
"no_alcohol",
"measured_pour_keg_audits",
"occasional_spot_checks",
"free_pour_no_audit"
],
"type": "string",
"description": "How do you control drink pours? no_alcohol = We don't serve alcohol; measured_pour_keg_audits = Measured pours, plus weekly pour-cost checks; occasional_spot_checks = Spot checks when bottles run out early; free_pour_no_audit = Free pours, no pour-cost checks."
},
"deliveryDependency": {
"enum": [
"zero_direct_only",
"under_15_with_markup",
"15_to_35_standard_cut",
"over_35_heavy_drag"
],
"type": "string",
"description": "How much of your sales come through DoorDash, Uber Eats or similar apps? zero_direct_only = None (Dine-in and our own ordering only); under_15_with_markup = Under 15% (With higher app prices to cover fees); 15_to_35_standard_cut = 15% – 35% (At regular menu prices); over_35_heavy_drag = More than 35%."
},
"occupancyCostRatio": {
"enum": [
"under_8_percent",
"8_to_12_percent",
"over_12_percent",
"unsure_ratio"
],
"type": "string",
"description": "What share of sales goes to rent, property costs and utilities? under_8_percent = Under 8%; 8_to_12_percent = 8% – 12%; over_12_percent = More than 12%; unsure_ratio = I'm not sure."
},
"primeCostAwareness": {
"enum": [
"under_58",
"58_to_64",
"over_65",
"not_tracked_weekly"
],
"type": "string",
"description": "What's your prime cost: food, drink and labor costs as a share of sales? under_58 = Under 58%; 58_to_64 = 58% – 64%; over_65 = 65% or more; not_tracked_weekly = I don't track it regularly."
},
"wasteTrackingMethod": {
"enum": [
"daily_signed_log",
"weekly_visual_estimate",
"bulk_loss_only",
"no_formal_logging"
],
"type": "string",
"description": "How do you track kitchen waste and spoilage? daily_signed_log = A daily log the chef signs off; weekly_visual_estimate = A rough estimate during weekly inventory; bulk_loss_only = Only when a big batch or case goes bad; no_formal_logging = We don't track it."
},
"plateCostingFrequency": {
"enum": [
"live_monthly_software",
"6_to_12m_manual",
"new_menu_only",
"rarely_gut_feeling"
],
"type": "string",
"description": "How often do you update recipe costs with current supplier prices? live_monthly_software = Monthly or live, with software (Synced to supplier invoices); 6_to_12m_manual = Once or twice a year (In a spreadsheet); new_menu_only = Only when the menu changes; rarely_gut_feeling = Rarely (Prices are set by feel or by competitors)."
}
},
"additionalProperties": false
}| baseKind |
| any |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"method"
],
"properties": {
"base": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "With percent, needed: the server's net sales for the shift (before tax and tips), or their tips, as baseKind says. In the owner's own currency."
},
{
"type": "null"
}
]
},
"pool": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "With pool, needed: the tips in the pool for the period."
},
{
"type": "null"
}
]
},
"tips": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "With percent: the server's tips for the shift, to work out what they keep. Not used when baseKind is tips."
},
{
"type": "null"
}
]
},
"roles": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"anyOf": [
{
"type": "string",
"maxLength": 60,
"description": "Optional: the role, such as Bartender or Busser."
},
{
"type": "null"
}
]
},
"percent": {
"anyOf": [
{
"type": "number",
"maximum": 100,
"minimum": 0,
"description": "The role's % of the base, 0 to 100. Needed for each role."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"maxItems": 50,
"description": "With percent, needed: the support roles tipped out."
},
{
"type": "null"
}
]
},
"method": {
"enum": [
"percent",
"pool"
],
"type": "string",
"description": "percent: one server's tip-out to support roles, each a % of the base. pool: a tip pool shared by hours, with optional points."
},
"members": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"anyOf": [
{
"type": "string",
"maxLength": 60,
"description": "Optional: the person or role."
},
{
"type": "null"
}
]
},
"hours": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"minimum": 0,
"description": "Hours worked in the pool's period. Needed for each person."
},
{
"type": "null"
}
]
},
"points": {
"anyOf": [
{
"type": "number",
"maximum": 1000000000,
"description": "Optional: the role's weight, such as 1.5, to one decimal. Left out, 1.",
"exclusiveMinimum": 0
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"maxItems": 50,
"description": "With pool, needed: the people or roles sharing the pool."
},
{
"type": "null"
}
]
},
"baseKind": {
"anyOf": [
{
"enum": [
"netSales",
"tips"
],
"type": "string",
"description": "With percent, needed: netSales or tips, what the roles' percentages are taken of."
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}