How To Send Menu Items to Punchh

You send menu item data to Punchh on two occasions:

  • When redeeming offers
  • When finalizing a guest check-in

The menu item data allows Punchh to evaluate the validity of a redemption, determine how many points a guest should earn given the check details, and determine which items a Punchh offer applies to. This information is returned to you in the corresponding API response and is also supplied to the Punchh platform to power such things as loyalty program analytics, guest history, and support data.

Send Menu Item Data for Redemptions

You send menu item data to Punchh when creating redemption API calls through the POS and Online Ordering APIs:

The purpose of including the menu item data for the redemption calls is so that Punchh can determine whether the offer is valid given the current cart items, and if it is, which items qualify for the offer the guest is redeeming.

For example, your business might offer a BOGO (buy-one-get-one) offer on a specific burger. For the offer to be valid, there must be two burgers of a particular ID on the check. If you send menu item data listing one or no burgers that match the item ID, the redemption API calls will return that the offer cannot be honored. If you send menu item data listing two burgers with a matching ID, the redemption API calls will return that the offer can be honored and specify one of the burger items as a qualifying burger that can be discounted for the full amount.

Refer to the Redemption Examples for details.

Send Menu Item Data for Check-ins

You send menu item data to Punchh when creating check-in API calls through the POS and Online Ordering APIs:

The purpose of including the menu item data for the check-in calls is to determine how many points a guest should earn for a loyalty visit given the check details.

For example, your business might award 1 point for every dollar spent. However, your earning rules might exclude dollars spent on taxes, service charges, and particular item types like alcohol, from earning loyalty points. By sending Punchh the menu item data in a categorized format, which will include purchased items, discounts, service charges, taxes, and payment information, Punchh can maintain an accurate transactional history for your business and ensure that guests earn points according to your configured rules.

Refer to the check-in examples in POS Check Details for more information.

Other API Calls

You also send the menu items for the following API calls, which will work similarly to redemptions and check-ins:

Structure of Menu Item Data

The following code snippet shows a basic example of the menu item data structure.

"menu_items":[ 
  { 
"item_name":"White rice",
"item_qty":1,
"item_amount":2.86,
"menu_item_type":"M",
"menu_item_id":3419,
"menu_family":"800",
"menu_major_group":"152",
"serial_number":"1.0"
  }
]

The following table describes the fields that comprise the menu items object.

Field Description Type
menu_items The array that contains all the menu item objects. You send one of these arrays per API call. Array (required)
item_name The name of the item as it displays in your catalog. String (required)
item_qty The quantity of the item on the check. If you have more than one of the same item on the check, include the items in one menu item object and reflect the total quantity in this field. Integer (required)
item_amount The total price of the line item or the amount of the discount that you applied to an item. If you have three items with the same ID on the check, this amount should represent the total amount for the three items, not the unit price. Always represent this as a positive number, even when the item is a discount. Number (required)
menu_item_type The classification of the item. Choose from the following types based on the item: M - An item in your catalog, whether it is a base item or a modifier to a base item. D - A discount. S - A charge for service or fee, such as an employee’s service charge, delivery fees, tips, a purchase of a gift card, etc. T - A tax applied to the check. P - A payment collected on the check.

Note: We do not recommend sending any line items set to D in any Redemptions 1.0 requests. Instead, send them in the Create Loyalty Check-in and Receipt Details API calls. If any items with line item type D are sent in these requests, the business will require additional configuration for all offers to filter out the line item type D. Any non-loyalty discounts should be reflected in reduced totals of the line items of type M that the discounts apply to. For example, if a business offers a $2 discount on a $10 burger, send the burger as $8 ($10 - $2) in the API request.
String (required)
menu_item_id The unique identifier your system uses for the item. String (required)
menu_family The family that the item belongs to. The family is the subcategory for the item. You can leave this blank if the item does not belong to a family. String
menu_major_group The major group that the item belongs to. The major group is the parent category for the item. You can leave this blank if the item does not belong to a major group. String
serial_number A serialized number that differentiates distinct items on the check. The purpose of this field is to identify which items on the check are base items and which items are modifiers to the base items. For example, your check might contain a pizza and a salad. The pizza has an add-on topping modifier, but the salad does not have any modifiers. To represent this, you could assign the following serial numbers to the items: Pizza - 1.0; Add-on topping - 1.1; Salad - 2.0. The exact numbers do not matter as long as you are consistent with which items modify the others. If you have an item with serial number 3.0, any items with serial number 3.x will modify the 3.0 item. Note: Serialization is limited to one decimal point, so you can only modify the base item. You cannot modify a modifier with 1.x.x, and so on. String (required)

Redemption Examples

The reason to send menu item data for redemption calls is to check whether the redemption can be honored. Given this, you only need to send menu item data related to:

  • Purchased items
  • Discounts that have already been applied to the check prior to the current redemption call

You do not need to send menu item data related to service charges, taxes, or payment for redemption calls.

Note: The Punchh platform is designed to support the redemption of one applicable offer on a check at a time. Discounting the same item on a check with multiple offers is not supported.

Redemption Without Prior Discounts on the Check

The following example shows how you would represent menu item data for a redemption API call when no prior discounts have been applied to the check. This example shows a sandwich, a modifier to the sandwich, a side, and two alcoholic beverages. Note how the serial numbers determine which items modify the others. The two alcoholic beverages share the same ID and thus are grouped in one line item, with a quantity of 2, and an item amount that reflects the total cost of both beverages.

"menu_items":[ 
  { 
"item_name":"Muffuletta",
"item_qty":1,
"item_amount":10.00,
"menu_item_type":"M",
"menu_item_id": "3419",
"menu_family":"Sandwiches",
"menu_major_group":"Entrees",
"serial_number":"1.0"
  },
{ 
"item_name":"Beef Cotto Salame",
"item_qty":1,
"item_amount":1.00,
"menu_item_type":"M",
"menu_item_id": "7657",
"menu_family":"",
"menu_major_group":"Add-ons",
"serial_number":"1.1"
  },
{ 
"item_name":"Potato Salad",
"item_qty":1,
"item_amount":3.00,
"menu_item_type":"M",
"menu_item_id": "5487",
"menu_family":"",
"menu_major_group":"Sides",
"serial_number":"2.0"
  },
{ 
"item_name":"Mezcal Negroni",
"item_qty":2,
"item_amount":14.00,
"menu_item_type":"M",
"menu_item_id": "6547",
"menu_family":"Cocktails",
"menu_major_group":"Alcohol",
"serial_number":"3.0"
  }
]

If the redemption is valid, the response from the redemption API call will return the menu items the offer applies to in a qualified_menu_items object, alongside the discount amount. This could be one or more items and will depend on how the offer is set up. For example, if the offer you were redeeming applied to the potato salad but not the other menu items, you would see the following object in the response:

"qualified_menu_items":[ 
{ 
"item_name":"Potato Salad",
"item_qty":1,
"item_amount":3.00,
"menu_item_type":"M",
"menu_item_id": "5487",
"menu_family":"",
"menu_major_group":"Sides",
"serial_number":"2.0"
  }
]

Redemption With a Prior Discount on the Check That Applies to a Single Item

Note: We do not recommend sending D (discount), T (tax), and P (payment) menu item types in Create Online Redemption 1.0 API calls. Instead, send them in check-in API calls, such as Create Loyalty Check-in and Receipt Details. See the note in the description of the menu_item_type in the Structure of Menu Item Data section.

If you must send D, T, and P menu item types, you must configure an exclusion qualification criterion (QC) for the offer in the Punchh platform. Create an exclusion filter using item types D, T, and P to ensure they are properly excluded. See the Qualification Criteria article on the Support Portal.

Note: To view the Punchh product documentation on the Punchh Support Portal, you must log in to a Punchh platform production environment. If you already have access to a production environment, follow the instructions here to access the Punchh Support Portal.

The following example shows how you would represent menu item data for a redemption API call with a prior discount already applied to the check. This example shows a sandwich, a modifier to the sandwich, a side, a discount applied to the side, and two alcoholic beverages. Note how the serial numbers determine which items modify the others.

"menu_items":[ 
  { 
"item_name":"Muffuletta",
"item_qty":1,
"item_amount":10.00,
"menu_item_type":"M",
"menu_item_id": "3419",
"menu_family":"Sandwiches",
"menu_major_group":"Entrees",
"serial_number":"1.0"
  },
{ 
"item_name":"Beef Cotto Salame",
"item_qty":1,
"item_amount":1.00,
"menu_item_type":"M",
"menu_item_id": "7657",
"menu_family":"",
"menu_major_group":"Add-ons",
"serial_number":"1.1"
  },
{ 
"item_name":"Potato Salad",
"item_qty":1,
"item_amount":3.00,
"menu_item_type":"M",
"menu_item_id": "5487",
"menu_family":"",
"menu_major_group":"Sides",
"serial_number":"2.0"
  },
{ 
"item_name":"Free Potato Salad w/ Sandwich",
"item_qty":1,
"item_amount":3.00,
"menu_item_type":"D",
"menu_item_id": "3548",
"menu_family":"",
"menu_major_group":"",
"serial_number":"2.1"
  },
{ 
"item_name":"Mezcal Negroni",
"item_qty":2,
"item_amount":14.00,
"menu_item_type":"M",
"menu_item_id": "6547",
"menu_family":"Cocktails",
"menu_major_group":"Alcohol",
"serial_number":"3.0"
  }
]

If the redemption is valid, the response from the redemption API call will return the menu items the offer applies to in a qualified_menu_items object, alongside the discount amount. This could be one or more items and will depend on how the offer is set up. If the offer you were redeeming applied to the potato salad, it would not be valid because that item is already discounted. However, if it applied to the sandwich and its modifiers, you would see the following qualified menu items in the response:

"qualified_menu_items":[ 
{ 
"item_name":"Muffuletta",
"item_qty":1,
"item_amount":10.00,
"menu_item_type":"M",
"menu_item_id": "3419",
"menu_family":"Sandwiches",
"menu_major_group":"Entrees",
"serial_number":"1.0"
  },
{ 
"item_name":"Beef Cotto Salame",
"item_qty":1,
"item_amount":1.00,
"menu_item_type":"M",
"menu_item_id": "7657",
"menu_family":"",
"menu_major_group":"Add-ons",
"serial_number":"1.1"
  }
]

Redemption With a Prior Discount on the Check That Applies to Multiple Items

Note: We do not recommend sending D (discount), T (tax), and P (payment) menu item types in Create Online Redemption 1.0 API calls. Instead, send them in check-in API calls, such as Create Loyalty Check-in and Receipt Details. See the note in the description of the menu_item_type in the Structure of Menu Item Data section.

If you must send D, T, and P menu item types, you must configure an exclusion qualification criterion (QC) for the offer in the Punchh platform. Create an exclusion filter using item types D, T, and P to ensure they are properly excluded. See the Qualification Criteria article on the Support Portal.

Note: To view the Punchh product documentation on the Punchh Support Portal, you must log in to a Punchh platform production environment. If you already have access to a production environment, follow the instructions here to access the Punchh Support Portal.

The following example shows how you would represent menu item data for a redemption API call with a prior discount already applied to multiple items on the check. This example shows a sandwich, a modifier to the sandwich, a side, a discount applied to all the food items, and two alcoholic beverages. Note how the serial numbers determine which items modify the others.

It is important to split the already processed discounts out for each item the discounts apply to. Otherwise, Punchh does not know an item has been discounted, which may lead to the guest receiving a larger discount than intended.

"menu_items":[ 
  { 
"item_name":"Muffuletta",
"item_qty":1,
"item_amount":10.00,
"menu_item_type":"M",
"menu_item_id": "3419",
"menu_family":"Sandwiches",
"menu_major_group":"Entrees",
"serial_number":"1.0"
  },
{ 
"item_name":"Beef Cotto Salame",
"item_qty":1,
"item_amount":1.00,
"menu_item_type":"M",
"menu_item_id": "7657",
"menu_family":"",
"menu_major_group":"Add-ons",
"serial_number":"1.1"
  },
{ 
"Item_name":"2 Off Sand",
"item_qty":1,
"item_amount":2.00,
"menu_item_type":"D",
"menu_item_id": "3419",
"menu_family":"Sandwiches",
"menu_major_group":"Entrees",
"serial_number":"1.2"
  },
{ 
"item_name":"Potato Salad",
"item_qty":1,
"item_amount":3.00,
"menu_item_type":"M",
"menu_item_id": "5487",
"menu_family":"",
"menu_major_group":"Sides",
"serial_number":"2.0"
  },
{ 
"item_name":"Free Potato Salad w/ Sandwich",
"item_qty":1,
"item_amount":3.00,
"menu_item_type":"D",
"menu_item_id": "3548",
"menu_family":"",
"menu_major_group":"",
"serial_number":"2.1"
  },
{ 
"item_name":"Mezcal Negroni",
"item_qty":2,
"item_amount":14.00,
"menu_item_type":"M",
"menu_item_id": "6547",
"menu_family":"Cocktails",
"menu_major_group":"Alcohol",
"serial_number":"3.0"
  }
]

If the redemption is valid, the response from the redemption API call will return the menu items the offer applies to in a qualified_menu_items object, alongside the discount amount. In this case, if the offer excluded alcoholic beverages, it would likely return as invalid because each food item is already discounted.

Multiple Redemptions Example

This example scenario only applies to the Create Online Redemption 1.0 API calls. If a guest wants to apply multiple offers to the order, you must send the applicable offers applied in the previous redemption calls as separate line items with menu_item_type set to D for the item the loyalty offer was applied to. For example, if a guest's loyalty account has two offers that can be applied to the order, and if the guest wants to redeem both offers:

  • In the first Create Redemption 1.0 processing requests, do not send any line items with menu_item_type set to D. Any non-loyalty discounts should be reflected in reduced totals of the line items of type M that the discounts apply to.
  • Once the first applicable offer is successfully applied/processed, include it in subsequent Create Redemption 1.0 requests as a separate line item with menu_item_type set to D for the item the loyalty offer was applied to. This discount amount must be subtracted from the receipt total. Repeat this for all subsequent redemptions.

The following example shows how you would represent menu item data for multiple redemptions. In this example, we will make two Create Redemption API calls to apply two offers of type reward on two different menu items for the same order. The first redemption call shows a burger, a side, a beverage, and a reward applied to the order. The original price of fries was $5 and was reduced to $3 by an internal non-loyalty discount. After adding the price of menu line items and subtracting the internal discount, the receipt total is $19.86.

{
  "discount_type": "reward",
  "reward_id": 327380,
  "receipt_amount": 19.86,
  "cc_last4": 4387,
  "employee_id": "7",
  "employee_name": "EMPLOYEE_NAME_GOES_HERE",
  "store_number": "58",
  "menu_items": [
    {
      "item_name": "Burger",
      "item_qty": 1,
      "item_amount": 6.86,
      "menu_item_type": "M",
      "menu_item_id": 3418,
      "menu_family": "Burgers",
      "menu_major_group": "Entrees",
      "serial_number": "1.0"
    },
    {
      "item_name": "Fries",
      "item_qty": 1,
      "item_amount": 3.00,
      "menu_item_type": "M",
      "menu_item_id": 3419,
      "menu_family": "Sides",
      "menu_major_group": "Add-ons",
      "serial_number": "2.0"
    },
    {
      "item_name": "Soda",
      "item_qty": 1,
      "item_amount": 10.00,
      "menu_item_type": "M",
      "menu_item_id": 3420,
      "menu_family": "Beverages",
      "menu_major_group": "Drinks",
      "serial_number": "3.0"
    }
  ],
  "subtotal_amount": 19.86,
  "receipt_datetime": "2025-04-03T18:05:01+05:30",
  "transaction_no": 5678,
  "client": "CLIENT_KEY_GOES_HERE"
}

If the redemption is valid, the response from the redemption API call will return the menu items the offer applies to in a qualified_menu_items object alongside the discount amount. The example response shows that the reward is successfully redeemed, and Punchh applies a $2 discount to the Burger.

{
  "status": "Redeemed at April 03, 2025 10:49 by FIRST_NAME_GOES_HERE LAST_NAME_GOES_HERE at Naperville. Please HONOR it.",
  "redemption_amount": 2.00,
  "category": "redeemable",
  "qualified_menu_items": [
    {
      "item_name": "Burger",
      "item_qty": 1,
      "item_amount": 6.86,
      "menu_item_type": "M",
      "menu_item_id": 3418,
      "menu_family": "Burgers",
      "menu_major_group": "Entrees",
      "serial_number": "1.0"
    }
  ],
  "redemption_id": 12345678,
  "redemption_code": "REDEMPTION_CODE_GOES_HERE"
}

The second redemption API call shows the same menu item data as was sent in the first redemption API call. However, it also includes the loyalty offer on the burger applied in the previous redemption API call as a separate line item with menu_item_type set to D. The serial_number of the discount (1.1) indicates that it modifies the burger.

{
  "discount_type": "reward",
  "reward_id": 327381,
  "receipt_amount": 17.86,
  "cc_last4": 4387,
  "employee_id": "7",
  "employee_name": "EMPLOYEE_NAME_GOES_HERE",
  "store_number": "58",
  "menu_items": [
    {
      "item_name": "Burger",
      "item_qty": 1,
      "item_amount": 6.86,
      "menu_item_type": "M",
      "menu_item_id": 3418,
      "menu_family": "Burgers",
      "menu_major_group": "Entrees",
      "serial_number": "1.0"
    },
    {
      "item_name": "Punchh Discount 1 on Burger (Already Applied)",
      "item_qty": 1,
      "item_amount": 2.00,
      "menu_item_type": "D",
      "menu_item_id": 3418,
      "menu_family": "Burgers",
      "menu_major_group": "Entrees",
      "serial_number": "1.1"
    },
    {
      "item_name": "Fries",
      "item_qty": 1,
      "item_amount": 3.00,
      "menu_item_type": "M",
      "menu_item_id": 3419,
      "menu_family": "Sides",
      "menu_major_group": "Add-ons",
      "serial_number": "2.0"
    },
    {
      "item_name": "Soda",
      "item_qty": 1,
      "item_amount": 10.00,
      "menu_item_type": "M",
      "menu_item_id": 3420,
      "menu_family": "Beverages",
      "menu_major_group": "Drinks",
      "serial_number": "3.0"
    }
  ],
  "subtotal_amount": 17.86,
  "receipt_datetime": "2025-04-03T18:05:01+05:30",
  "transaction_no": 5679,
  "client": "CLIENT_KEY_GOES_HERE"
}