Skip to main content

Implement Recipes

Prerequisites

DoorDash has made an enhancement to the Open API contract to allow partners to provide default options or “recipes” for their menus.

Overview

A recipe includes the ingredients that automatically come with a particular menu item, and allow the restaurants to correctly charge / not charge for the included ingredients. It also helps streamline the kitchen operations by reducing the information that needs to be relayed to the crew to prepare a standard recipe based order.

E.g. a Merchant wants to specify the following ingredients as default included in the recipe definition for a Bacon Cheeseburger - Bacon, Cheese, Lettuce, Tomato, Mayo. Using the marketplace DoorDash app, we allow the customer to customize the order and remove some of the default ingredients such as Cheese. In this case the Merchant expects the order to be relayed to the KDS in the way that reduces complexity, as follows:

Menu defined using Recipes Expected OrderMenu defined without Recipes Current Order
Bacon CheeseburgerBacon Cheeseburger
Modifier: No CheeseModifiers: Bacon, Lettuce, Mayo, Tomato

By supporting Recipes, DoorDash will help merchants to reduce kitchen complexity and inaccuracy rate as a result of lower number of customizations communicated to the KDS. Recipes will also allow the Merchants to define pricing rules, that would include selected quantities of an ingredient to be included in the item price and additional quantity to incur an incremental charge to the order.

Get Started

How

DoorDash has amended the Menu API contract with a new field to indicate that items and options that need to be included as a recipe for the item.

The Order API is also amended to include removed options from the order for a recipe based menu item.

Menu API:

Specify sauce as an included recipe ingredient for the menu item, with a price of 20 cents, if the consumer selects above 3 quantity.

  • operation_context: indicates the mode for the item or an option. For recipe based item the context should be set as [“RECIPE”] for both the item and its included options as shown in the sample menu.
  • quantity_info: captures the option quantity related info.
    • default_quantity: default quantity for the recipe ingredient
    • charge_above: when consumer selected quantities are above charge_above quantity, each quantity will be charged with unit price
"extras":[
{
"name":"sauce",
"merchant_supplied_id":"sauce",
"active":true,
"sort_id":2,
"min_option_choice_quantity":0,
"max_option_choice_quantity":9,
"min_aggregate_options_quantity":0,
"max_aggregate_options_quantity":99,
"options":[
{
"name":"mocha sauce",
"merchant_supplied_id":"mochasauce",
"active":true,
"price":20,
"default":true,
"operation_context":[
"RECIPE"
],
"quantity_info":{
"default_quantity":3,
"charge_above":3
},
"extras":[

]
}

Order API:

Indicate on the order, that the customer removed the mocha sauce from the recipe based item. If its parent item is a recipe item defined in the menu:

  • options: will reflect what is included in the order but different from the recipe.
    • Any option selected by customer but different quantity from the default recipe ingredient, will result in an entry in options with its new quantity, as shown in the order sample below.
    • Any option selected by consumer but not on the recipe will result in an entry in options
  • removed_options: will reflect what is excluded from the recipe
    • No quantity will be passed
   "name": "sauce",
"merchant_supplied_id": "sauce",
"removed_options": [
{
"name": "Mocha Sauce",
"merchant_supplied_id": "mochasauce"
}
]
}

Example

Menu

{
"menu": {
"name": "Breakfast",
"subtitle": "",
"active": true,
"categories": [
{
"name": "Coffee",
"subtitle": "",
"merchant_supplied_id": "coffee",
"active": true,
"sort_id": 0,
"items": [
{
"name": "Mocha Frappuccino",
"description": "",
"merchant_supplied_id": "MFrapp",
"active": true,
"price": 500,
"operation_context": [
"RECIPE"
],
"extras": [
{
"name": "sauce",
"merchant_supplied_id": "sauce",
"active": true,
"sort_id": 2,
"min_option_choice_quantity": 0,
"max_option_choice_quantity": 9,
"min_aggregate_options_quantity": 0,
"max_aggregate_options_quantity": 99,
"options": [
{
"name": "mocha sauce",
"merchant_supplied_id": "mochasauce",
"active": true,
"price": 20,
"default": true,
"operation_context": [
"RECIPE"
],
"quantity_info": {
"default_quantity": 3,
"charge_above": 3
},
"extras": []
},
{
"name": "vanilla sauce",
"merchant_supplied_id": "vanilla",
"active": true,
"price": 20,
"default": false,
"extras": []
}
]
},
{
"name": "shots",
"merchant_supplied_id": "shots",
"active": true,
"sort_id": 1,
"min_option_choice_quantity": 1,
"max_option_choice_quantity": 9,
"options": [
{
"name": "roast coffee",
"merchant_supplied_id": "roastcoffee",
"active": true,
"price": 60,
"default": true,
"operation_context": [
"RECIPE"
],
"quantity_info": {
"default_quantity": 1,
"charge_above": 1
},
"extras": []
}
]
}
]
}
]
}
]
}
}

Order

{
"id": "744de2d4-39ae-44e8-b7c8-6799add0cb9a",
"consumer": {
"id": 123,
"email": "[email protected]",
"first_name": "Jane",
"last_name": "D",
"phone": "123456"
},
"store": {
"merchant_supplied_id": "111",
"provider_type": "mock"
},
"subtotal": 560,
"tax": 40,
"estimated_pickup_time": "2021-05-11T22:40:43Z",
"is_pickup": false,
"categories": [
{
"name": "Coffee",
"merchant_supplied_id": "coffee",
"items": [
{
"name": "Mocha Frappuccino",
"merchant_supplied_id": "MFrapp",
"price": 500,
"quantity": 1,
"operation_conext": [
"RECIPE"
],
"extras": [
{
"name": "shots",
"merchant_supplied_id": "shots",
"options": [
{
"name": "roast coffee",
"merchant_supplied_id": "roastcoffee", // Roast Coffee is adjusted to increase the quantity to 2 instead of the default 1 shot
"price": 60,
"quantity": 2,
“chargeable_quantity”: 1
}
]
},
{
"name": "sauce",
"merchant_supplied_id": "sauce",
"removed_options": [
{
"name": "Mocha Sauce",
"merchant_supplied_id": "mochasauce" // Mocha Sauce was completely removed from the order
}
]
}
],
"consumer_name": "Jane",
"special_instructions": ""
}
]
}
],
"is_tax_remitted_by_doordash": false,
"commission_type": "regular",
"delivery_short_code": "abc"
}

FAQ

In what cases will a modifier appear in the “removed_options” list?

For an option to appear as a removed_options within the order payload:

  • It must be specified with an operation_context of “RECIPE” (quantity_info does not have to be specified)
  • AND be fully removed (either substituted for another option or just removed) from the item being added to the cart

Example Order:

Scenario: Customer Orders “Caramel Macchiato”, an item that has only one recipe component: Milk Temperature > Steamed Hot.

In this order, the customer has opted to change (unselect default and select new option) the Milk Temperature to Extra Hot

{
"id": "5e87ace4-c87a-403f-9134-be4d3eef0055",
"store_order_cart_id": "3000000340445079",
"tax": 28,
"subtotal": 595,
"estimated_pickup_time": "2022-03-09T05:05:02+00:00",
"is_pickup": false,
"order_special_instructions": "",
"delivery_address": {},
"consumer": {
"id": 46527989,
"first_name": "User",
"last_name": "T",
"email": "[email protected]",
"phone": "8559731040"
},
"store": {
"merchant_supplied_id": "sample_location",
"provider_type": "sample_provider",
"timezone": "US/Hawaii",
"id": "2701653"
},
"categories": [
{
"merchant_supplied_id": "Hot Coffees",
"name": "sample_menu",
"items": [
{
"name": "Caramel Macchiato",
"quantity": 1,
"price": 595,
"merchant_supplied_id": "126196",
"consumer_name": "DO",
"extras": [
{
"merchant_supplied_id": "413-Hot-size-Grande-Short-Tall-Venti",
"name": "Size",
"options": [
{
"name": "Grande Caramel Macchiato",
"quantity": 1,
"price": 60,
"merchant_supplied_id": "126198",
"extras": [
{
"merchant_supplied_id": "413-Hot-Grande-recipe-240",
"name": "Milk Temperature",
"options": [
{
"name": "Extra Hot",
"quantity": 1,
"price": 0,
"merchant_supplied_id": "109889",
"extras": []
}
],
"removed_options": [
{
"name": "Steamed Hot",
"merchant_supplied_id": "109890"
}
]
}
]
}
],
"removed_options": []
}
],
"special_instructions": "",
"item_context": [
"RECIPE"
]
}
]
}
],
"delivery_short_code": "915784",
"tax_transaction_id": "",
"is_demand_gen": false,
"commission_type": "regular",
"is_tax_remitted_by_doordash": false,
"tax_amount_remitted_by_doordash": 0,
"fulfillment_type": "dx_delivery",
"merchant_tip_amount": 0,
"experience": "DOORDASH"
}

In what cases will a modifier specified as a part of the recipe via “operation_context” still be specified in the order payload?

A recipe modifier will be recognized in the order payload as a recipe variation in the following circumstances

  • The selected modifier quantity is greater than the default_quantity specified via quantity_info in the menu payload
    • In this case, chargeable_quantity will also be specified in the order payload:
    • chargeable_quantity = selected_qty - charge_above
  • The selected modifier quantity is less than the default_quantity specified via quantity_info in the menu payload
    • In this case, chargeable_quantity will also be specified in the order payload:
    • chargeable_quantity = selected_qty - charge_above
    • In these cases, if charge_above = default_quantity, then chargeable_quantity = 0

If the modifier is fully removed, it will appear in the order payload, but specifically within the removed_options list

Example Order:

Customer Orders “Caffe Americano”, an item that has only one recipe component: Expresso Shots with default_quantity: 2 specified within quantity_info.

In this order, the customer has opted to change add an additional Expresso shot, bringing the total to 3

{
"id":"e9b54601-4c31-4f5f-aba1-fdc9f2ddfdb5",
"store_order_cart_id":"3000000296721092",
"tax":31,
"subtotal":445,
"estimated_pickup_time":"2022-03-01T22:02:36+00:00",
"is_pickup":false,
"order_special_instructions":"",
"consumer":{
"id":46527989,
"first_name":"DO NOT MAKE - National Testing",
"last_name":"T",
"email":"[email protected]",
"phone":"8559731040"
},
"store":{
"merchant_supplied_id":"sample_location",
"provider_type":"sample_provider",
"timezone":"US/Eastern",
"store_business":{
"auto_release_enabled":false
},
"id":"2243679"
},
"categories":[
{
"merchant_supplied_id":"Hot Coffees",
"name":"Hot Coffees",
"items":[
{
"name":"Caffe Americano",
"quantity":1,
"price":445,
"merchant_supplied_id":"93",
"consumer_name":"DO",
"extras":[
{
"merchant_supplied_id":"406-Hot-size-Grande-Short-Tall-Venti",
"name":"Size",
"options":[
{
"name":"Tall Caffe Americano",
"quantity":1,
"price":60,
"merchant_supplied_id":"94",
"extras":[
{
"merchant_supplied_id":"406-Hot-Tall-recipe-485",
"name":"Shots",
"options":[
{
"name":"Expresso Shots",
"quantity":3,
"chargeable_quantity":1,
"price":100,
"merchant_supplied_id":"55",
"extras":[

]
}
],
"removed_options":[

]
}
]
}
],
"removed_options":[

]
}
],
"special_instructions":"",
"item_context":[
"RECIPE"
]
}
]
}
],
"delivery_short_code":"4c5d308b",
"tax_transaction_id":"",
"is_demand_gen":false,
"commission_type":"regular",
"is_tax_remitted_by_doordash":false,
"tax_amount_remitted_by_doordash":0,
"fulfillment_type":"dx_delivery",
"merchant_tip_amount":0,
"experience":"DOORDASH"
}

Modified: 5/01/2023