
[title] Orders API
[path] API for Restaurant Partners/

# Overview

This document describes new features (mutations and event notifications) that will be available in the ezCater API, and is strictly additional to the existing Introduction to the ezCater API. All previously documented features (Event Notifications and GraphQL Endpoints) remain unchanged.

To accept or reject orders as an existing user of the ezCater API, you will need to be familiar with the following processes:

1. Creating subscriptions to event notifications for the new order submitted event, for one or more caterers (locations).
2. Querying for order details (using the existing `orderById` query) based on the `entity_id` returned by the order submitted event.
3. Calling either the `acceptOrder` or `rejectOrder` mutations with the order id to accept or reject it, based on the order data or whatever other criteria you have.
4. Subscribing to a new `rejected` event notification if that will provide useful confirmation.


[title] Subscription API
[path] API for Restaurant Partners/


[title] Troubleshooting
[path] API for Restaurant Partners/Overview/

If your IT Department runs into issues that need troubleshooting when using the API, remember that you can always reach out to ezCater's API support team at [integrations@ezcater.com](mailto\:integrations@ezcater.com).

In general, any errors in a request will be passed back in the response with a non- empty `errors` key.&#x20;

```graphql
{
    "data": { ... },
    "errors": [ ... ]
}
```

The contents of the errors key will provide information on what is wrong. The format will follow the GraphQL specification.&#x20;

[title] Acquiring Your API Token
[path] API for Restaurant Partners/Overview/

In order to access API, the integrator will need an API User created with Integrations permissions. Please reach out to [integrations@ezcater.com](mailto\:integrations@ezcater.com) to assist with this setup.&#x20;

***

Once the API User has been created, you'll receive an invitation email, at the address used, to set up the password and complete the first login, which will allow you to generate the authorization token.

1. Sign into the API User account that was created.
2. Go to Integrations within the Settings tab of Partner Portal.
3. Click “Generate” to receive your unique authorization token.

![](https://archbee-image-uploads.s3.amazonaws.com/Q23r_bOWYj6H-GcUXhvXG-C-mF7S-uxHIAZuHLtrb_m-20241009-132242.jpg)

:::hint{type="warning"}
**Make sure to save this token!&#x20;**&#x54;he token can only be granted once, and if lost cannot be recovered. This token will be used as you set up the integration on our API.
:::




[title] Courier Event Create
[path] API for Restaurant Partners/Delivery API/

# Creating Courier Events

Throughout the course of the delivery fulfillment lifecycle, there are a variety of events that can happen to a delivery to help us understand where it is at in the fulfillment process. Capturing these events is important to the ezCater fulfillment process as they can be tied to other side-effects, like communicating to our customers that their food is on the way or has arrived.

:::hint{type="info"}
If you already had a courier assigned to a delivery and are now assigning a new courier, we automatically take care of un-assigning the previous courier.
:::

## Mutation

:::CodeblockTabs
Mutation

```graphql
mutation CourierEventCreate($input: CourierEventCreateInput!) {
  courierEventCreate(input: $input) {
    clientMutationId
    delivery {
      id
    }
    userErrors {
      ... on DeliveryValidationError {
        message
        path
      }
    }
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables

```graphql
{
  "input": {
    "clientMutationId": "your-mutation-id",
    "coordinates": {
      "latitude": 42.360081,
      "longitude": -71.058884
    },
    "courier": {
      "id": "your-courier-id",
      "firstName": "Test",
      "lastName": "Courier",
      "phone": "+15555555555",
      "vehicle": {
        "make": "Your Vehicle Make",
        "model": "Your Vehicle Model",
        "color": "Your Vehicle Color"
      }
    },
    "deliveryId": "ezcater-delivery-id",
    "eventType": "EN_ROUTE_TO_PICKUP",
    "occurredAt": "2024-02-05T17:27:55+0000"
  }
}
```
:::

### Arguments

| Argument Name                                                     | Description                               |
| ----------------------------------------------------------------- | ----------------------------------------- |
| `input`: [CourierEventCreateInput!](docId\:K2qRzk03w9Db66ZorcAqT) | The Input object for creating a new menu. |

### Return Type

Returns a [CourierEventCreatePayload](docId:7gV344RnWmuokNj9u4rW7).

## Success Responses

When the `courierEventCreate` mutation succeeds you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "courierEventCreate": {
      "clientMutationId": "your-mutation-id",
      "delivery": {
        "id": "ezcater-delivery-id"
      },
      "userErrors": []
    }
  }
}
```
:::

## Failure Responses

### User Errors

When the `courierEventCreate` mutation fails because it is too early to add courier events you can expect the response payload to look like:

:::CodeblockTabs
Response - Too Early

```graphql
{
  "data": {
    "courierEventCreate": {
      "clientMutationId": "your-mutation-id",
      "delivery": null,
      "userErrors": [
        {
          "message": "It's too early to add the event for courier en route to pickup",
          "path": [
            "input",
            "occurredAt"
          ]
        }
      ]
    }
  }
}
```

Response - Too Late

```graphql
{
  "data": {
    "courierEventCreate": {
      "clientMutationId": "your-mutation-id",
      "delivery": null,
      "userErrors": [
        {
          "message": "Delivery cannot receive updates 2 hours past its event time",
          "path": [
            "input",
            "deliveryId"
          ]
        }
      ]
    }
  }
}
```
:::

### 400 Bad Request

When the `courierEventCreate` mutation fails due to bad user input, such as a invalid `eventType` enum or invalid field, you can expect a HTTP 400 Bad Request and the response payload to look like:

:::CodeblockTabs
Response - Invalid Enum

```graphql
{
  "errors": [
    {
      "message": "Variable \"$input\" got invalid value \"PICKEDUP\" at \"input.eventType\"; Value \"PICKEDUP\" does not exist in \"CourierEventCreateInputEventType\" enum.",
      "extensions": {
        "code": "BAD_USER_INPUT"
      }
    }
  ]
}
```

Response - Invalid Field

```graphql
{
  "errors": [
    {
      "message": "Variable \"$input\" got invalid value { clientMutationId: \"your-mutation-id\", coordinates: { latitude: 42.360081, longitude: -71.058884 }, courier: { id: \"your-courier-id\", firstName: \"Test\", lastName: \"Courier\", phone: \"+15555555555\", vehicle: [Object] }, deliveryId: \"your-ezcater-delivery-id\", eventType: \"PICKED_UP\", occurredAt: \"2025-05-07T19:52:32.841Z\" }; Field \"eventType\" is not defined by type \"CourierTrackingEventCreateInput\".",
      "extensions": {
        "code": "BAD_USER_INPUT"
      }
    }
  ]
}
```
:::




[title] SSO for Marketplace & Meal Program
[path] Enterprise Account Integrations/

# Single Sign-On for ezCater Marketplace & Meal Program&#x20;

**Single Sign-On (SSO)** enables users to access ezCater and/or Meal Program from any device with a single entry of their Identity Provider (IdP) user credentials.

## SSO Use Cases

- **Enhanced Security:&#x20;**&#x53;SO ensures that only authorized users can log in.
- **Simplified User Management:** If auto-provisioning is enabled, user accounts will automatically be created when a user logs in via SSO for the first time. If SSO is required, when an employee leaves the company, their access to ezCater/Meal Program can be revoked immediately through the identity provider, reducing the risk of unauthorized access.
- **Improved User Experience:&#x20;**&#x45;liminates the need for users to remember separate passwords for ezCater/Meal Program . 

## SSO Integration Availability

- Meal Program and Enterprise Account customers who use an identity provider (IdP) at their company.
- Integrates with any identity provider (IdP) that supports a SAML protocol.

## Supported SSO Functionality

- **Desktop & Mobile:&#x20;**&#x53;SO is supported on mobile and desktop devices.
- **Multiple Domains:** SSO configurations can support multiple domains. 
- **Auto-provisioning/Just-In-Time provisioning:&#x20;**&#x4F;ptional setting that automatically creates a user Marketplace or Meal Program account when they log in without a pre-existing account.
- **Require SSO/Force authentication:** Optional setting that requires users with matching domains to sign in SSO, meaning they cannot use username/password to log in.

## SSO Configuration Process

- The [ezCater Meal Program  SSO Form](https://ezcaterforms.formstack.com/forms/ezcater_sso) provides the ability to set up and update SAML and SCIM configurations. The form is intended to be completed by an IT contact. Once filled out, ezCater’s Integrations & Implementations team will email with confirmation that the SSO setup is ready to be tested on or before the date submitted with steps to test the SSO setup.

## SSO User Experience

- For users assigned to the app, Meal Program and/or ezCater marketplace are found within their company’s identity provider (IdP) dashboard/bookmarks.
- Users login with their company’s identity provider credentials, which eliminates the need for users to remember separate passwords for ezCater and/or Meal Program .
- For companies with the setting to require SSO enabled, if a user tries to login with username and password the page will redirect them to the SSO sign in page and state “Your company requires you to use Single Sign On”.
- For companies with the setting to autoprovision new users enabled:
  - Meal Program : Users are prompted to create their account when logging in for the first time and select their drop location.
  - ezCater Marketplace: Users are prompted to create their account when logging in for the first time and add a phone number. Admin individually adds users to groups, non-company wide spending policies, and adjusts roles. Admin does not need to verify users in the Admin Portal.&#x20;


[title] Order Modifications
[path] API for Restaurant Partners/Orders API/

In the event of an order modification, if the order had already been accepted via the API, the modification cannot be accepted/rejected using the API. Accepting/Rejecting the modification must be done in Partner Portal and/or your exisitng workflows, like phone, sms, or email.

Once the modication has been accepted, a new Accepted webhook is sent to the subscriber with the same ezCater `orderId`. This follows the same order flows mentioned in [Subscribing to Order Notifications](https://api.ezcater.io/subscribing-to-order-notifications).&#x20;

At this time, there is not a dedicated Modification webhook, though we plan to add this functionality in future versions.&#x20;

[title] Subscription Delete
[path] API for Restaurant Partners/Subscription API/

# Deleting Subscriptions

**Subscriptions** are how the **Subscriber** determines what events it needs to send out notifications for. Once you’ve created your **Subscriber**, you can customize the sorts of information that you may want to pull into your integrated system(s).

To delete your **Subscriptions** you will need to know the `UUID` of the caterer locations for which you want to sever the integration. These can be retrieved by making a [Caterer List](docId\:laoMLO-PM8Bz0WzIZ99hV) query. For each location, you will need to delete a **Subscription** for every event you want to sever.&#x20;

:::CodeblockTabs
Mutation

```graphql
mutation deleteSubscription {
    deleteSubscriptions(subscriptionsParams: {
      parentEntity: Caterer,
      parentId: "{{StoreUUID}}"
    }) {
      success
    }
  }
```
:::


[title] Caterers API
[path] API for Restaurant Partners/

'

[title] Subscribing to Order Notifications
[path] API for Restaurant Partners/Orders API/

# Subscribing to Order Notifications

Subscribing to **Order** notifications works in the same way as for other event subscriptions documented in the [Subscription API](docId\:vMKCbjsFOUH_t4Dt406_k) section. Please refer to this section for detailed information, including what input fields and enums are available.

:::hint{type="info"}
When subscribing to `Order` notifications please use:

- `EventEntity` enum of `Order`.
- `EventKey` enums of `submitted`, `accepted`, `rejected`, `cancelled`, `uncancelled` , `relish_finalized`
- `ParentEntity` enum should be `Caterer`.
:::

### Variables

Below is a example of the variables that would be used with [Subscription Create](docId\:YWDS1a-gxebJWknE8V90S) to subscribe to `Order` notifications.

:::CodeblockTabs
Variables

```graphql
{
  "subscriptionParams": {
    "eventEntity": "Order",
    "eventKey": "accepted",
    "parentEntity": "Caterer",
    "parentId": "ezcater-caterer-id",
    "subscriberId": "your-subscriber-id"
  }
}
```
:::

### Notifications

:::CodeblockTabs
Notification - Submitted

```graphql
{
  "id": "notification-id",
  "parent_type": "Caterer",
  "parent_id": "ezcater-caterer-id",
  "entity_type": "Order",
  "entity_id": "your-ezcater-order-id",
  "key": "submitted",
  "created_at": "2025-04-15 23:48:23 UTC",
  "occurred_at": "2025-04-15 23:48:21 UTC",
  "updated_at": "2025-04-15 23:48:23 UTC",
  "payload":null
}
```

Notification - Accepted

```graphql
{
  "id": "notification-id",
  "parent_type": "Caterer",
  "parent_id": "ezcater-caterer-id",
  "entity_type": "Order",
  "entity_id": "your-ezcater-order-id",
  "key": "accepted",
  "created_at": "2025-04-15 23:48:23 UTC",
  "occurred_at": "2025-04-15 23:48:21 UTC",
  "updated_at": "2025-04-15 23:48:23 UTC",
  "payload":null
}
```

Notification - Failed

```graphql
{
  "id": "notification-id",
  "parent_type": "Caterer",
  "parent_id": "ezcater-caterer-id",
  "entity_type": "Order",
  "entity_id": "your-ezcater-order-id",
  "key": "rejected",
  "created_at": "2025-04-15 23:48:23 UTC",
  "occurred_at": "2025-04-15 23:48:21 UTC",
  "updated_at": "2025-04-15 23:48:23 UTC",
  "payload":null
}
```

Example - Cancelled

```graphql
{
  "id": "notification-id",
  "parent_type": "Caterer",
  "parent_id": "ezcater-caterer-id",
  "entity_type": "Order",
  "entity_id": "your-ezcater-order-id",
  "key": "rejected",
  "created_at": "2025-04-15 23:48:23 UTC",
  "occurred_at": "2025-04-15 23:48:21 UTC",
  "updated_at": "2025-04-15 23:48:23 UTC",
  "payload":null
}
```
:::

:::ExpandableHeading
## Order Event Notification Flows

After initial Order `submitted` and `accepted` or `rejected` notifications, the only  notifications for an order are `accepted`, `rejected`, and `cancelled`. Below are some example order notification flows.&#x20;

### Order Submitted

Subscription notifications will be received for: 

- `submitted`

### Order Submitted -> Accepted

Subscription notifications will be received for: 

- `submitted`, `accepted`

### Order Submitted -> Rejected

Subscription notifications will be received for: 

- `submitted`, `rejected`, `cancelled`

### Order Submitted -> Rejected -> Uncancelled

Subscription notifications will be received for: 

- `submitted`, `rejected`
- **Note:&#x20;**&#x6E;o `uncancelled` notification will be received, however once it is re-\`accepted\` or `rejected` other webhooks will be received

### Order Submitted -> Rejected -> Uncancelled -> Accepted

Subscription notifications will be received for: 

- `submitted`, `rejected`, `accepted`
- **Note:&#x20;**&#x6E;o `uncancelled` notification will be received

### Order Submitted -> Accepted -> Cancelled -> Uncancelled

Subscription notifications will be received for: 

- `submitted`, `accepted`, `cancelled`
- **Note:&#x20;**&#x6E;o uncancelled notification will be received, however once it is reaccepted or rejected other notifications will be received

### Order Submitted -> Accepted -> Cancelled -> Uncancelled -> Accepted

Subscription notifications will be received for: 

- `submitted`, `accepted`, `cancelled`, `accepted`
- **Note:&#x20;**&#x6E;o uncancelled notification will be received

### Order Submitted -> Accepted -> Modified -> Accepted

Subscription notifications will be received for: 

- `submitted`, `accepted`, `accepted`
- **Note:&#x20;**&#x6E;o modified notification will be received

### Order Submitted -> Accepted -> Modified -> Accepted > Cancelled

Subscription notifications will be received for: 

- `submitted`, `accepted`, `accepted`, `cancelled`
- **Note:&#x20;**&#x6E;o `modified` notification will be received

### Order Submitted -> Accepted -> Modified > Rejected

Subscription notifications will be received for: 

- `submitted`, `accepted`, `rejected`
- **Note:&#x20;**&#x6E;o modified notification will be received
- **Note:&#x20;**`rejected` order modifications will not result in a `canceled` notification, ezCater is working behind the scenes to save the order

### Order Submitted > Accepted > Modified > Rejected > Cancelled

Subscription notifications will be received for: 

- `submitted`, `accepted`, `rejected`, `cancelled`
- **Note:&#x20;**&#x6E;o `modified` notification will be received

### Order Submitted -> Accepted -> Modified > Rejected -> Cancelled -> Uncancelled

Subscription notifications will be received for: 

- `submitted`, `accepted`, `rejected`, `cancelled`
- **Note:&#x20;**&#x6E;o `modified` notification will be received
- **Note:&#x20;**&#x6E;o `uncancelled` notification will be received, however once it is again `accepted` or `rejected` other notifications will be received

### Order Submitted -> Accepted -> Modified -> Cancelled -> Uncancelled -> Accepted

Subscription notifications will be received for: 

- `submitted`, `accepted`, `rejected`, `cancelled`, `accepted`
- **Note:&#x20;**&#x6E;o `modified` notification will be received
- **Note:&#x20;**&#x6E;o `uncancelled` notification will be received

### Order Submitted -> Accepted -> Store Changed

Subscription notifications will be received for: 

- `submitted`, `accepted`
- **Note:** agents are trained to cancel and replace orders, but if this does not happen

### Order Submitted -> Accepted -> Modified -> Cancelled for Replacement

Subscription notifications will be received for: 

- `submitted`, `accepted`
- **Note:** no `modified`, `cancelled` or `rejected` notification will be received for original order

### Order Submitted -> Cancelled for Replacement

Subscription notifications will be received for: 

- `submitted`
- **Note:** no `cancelled` or `rejected` notification will be received for the original order

### Meal Program Order Finalized

Subscription notifications will be received for: 

- `relish_finalized`
- **Note:** `submitted` and `accepted` notifications will **not** be received for Meal Program orders, as Meal Program orders are submitted two weeks before delivery time as placeholders that contain no menu items. `relish_finalized` is transmitted shortly after the cut-off time for that order, and indicates that the order has been populated with all items to be delivered.
:::


[title] Procurement PunchOut
[path] Enterprise Account Integrations/

# Procurement Integrations (PunchOut, Purchase Order, Direct Invoice)

1. **What is it:** The ezCater Punchout connects your procurement platform directly to ezCater, allowing staff to order from a variety of restaurants —all within our procurement system. This integration eliminates the need to switch between systems and manually enter purchase order details.
2. **Once set up, your organization will able to use ezCater PunchOut Ordering to:**
   1. **PunchOut Order&#x20;**&#x74;o ezCater within your procurement system, even if the individual doesn’t have an existing ezCater account.
   2. **Authenticate orders**, via the TradeCentric API, checking the bearer token verification and IP whitelisting.
   3. **Submit orders for approval.&#x20;**&#x4F;nce the procurement system approver approves the order it will be confirmed.
   4. **Generates an invoice,&#x20;**&#x77;hich is sent directly to the procurement system and standard ezCater invoice flow.
3. **Video:&#x20;**[https://ezcater.wistia.com/medias/ge7fxg3s8r](https://ezcater.wistia.com/medias/ge7fxg3s8r)
4. **Procurement Systems:** We’re able to connect with systems like Coupa, SAP Ariba, and Jagger.&#x20;
   TradeCentric is able to work with most companies as long as your current system has PunchOut catalog capabilities and/or if you have cXML or PO capabilities.


[title] Menus API
[path] API for Restaurant Partners/

# Preparing For Menu Integration with ezCater

ezCater is excited to connect your content systems with ezCater’s menu catalog. These pages will help you prepare your menu content in order to make the project move quickly. Please review the following guidelines to prepare your menu to be integrated with ezCater

# Menu Structure

ezCater has a specific structure for modeling menus. Information is primarily organized into Categories, Items, Options, and Choices. Here is a bit more information about each element of the ezCater menu structure: 

1. **Categories**: Sections that group items, options and choices together. The category includes elements such as the name, description, and the order categories will be presented in. See [Appendix A: Category Names & Order](https://api.ezcater.io/menus-api#lSASt) for additional information.
2. **Items**: These are typically the items you sell. Item images are supported.
3. **Options**: A group of choices or item modifier selections.
4. **Choices**: The individual selections available for a given option.

*Please note*: Nested items or options are not supported at this time. Therefore, you may need to prepare an ezCater specific menu or make modifications to your existing menu to remove nesting.

# ezCater Specific Field Configurations

1. **"Serves (# of people)"**: A numeric field identified as being specific to catering. The field allows a customer to identify the number of people participating in an event. restaurant partners use this numeric value to describe how many people a large tray or bowl serves.
2. **Dietary Tags (FoodLabelingTags)**:*&#xA0;*&#x44;escribe qualities of an item or choice related to labeling. If an item qualifies under a specific tag (ex. “vegetarian”) only if certain option choices are selected, then the option choices that qualify should also be tagged accordingly. Values include: *AWARD*, *GLUTEN\_FREE*, *HALAL*, *HEALTHY*, *KOSHER*,*&#x20;POPULAR*, *SPICY*, *STAR*, *VEGAN*, *VEGETARIAN*.
3. **Packaging Tags (IndividualWrapStatus)**: Identifies whether the item is individually wrapped. Values include: POSSIBLE/WRAP
4. **Drinks & Dessert Tags (ItemTypeTags, ChoiceTypeTags)**: These values are specifically used for upsell opportunities.  Please ensure all beverage and dessert items are tagged accordingly. Values include: DESSERT, DRINKS
5. **Utensil Tags (ItemTypeTags, ChoiceTypeTags)**: For items and option choice representing utensils, please tag the entity as “UTENSILS”. See [Appendix B](https://api.ezcater.io/menus-api#8akRE) for additional information.
6. **Tax categories**: Values stored by menu items describing the Avalara tax classifications. The classification is used by ezCater to look up tax rates and charge taxes per order. Tags used to classify how a given item is taxed. Values include: *BAKERY\_ITEMS*, *CAKES\_AND\_PIES*, *CANDY*, *CHIPS\_AND\_SNACKS*, *COFFEE\_TEA\_MILK*, *DRESSINGS\_AND\_CONDIMENTS*, *ICE\_CREAM*, *MISCELLANEOUS*, *NON\_SODA\_DRINKS*, *PREPARED\_FOOD*, *SANDWICHES*, *SODA*, *WATER*.
7. **UOM**: A set of values used to describe the quantity required of a given item.  
8. **QuantityUnit**: A UOM for ordering items. Default to item if needed. Values include:  *BAR*, *BOTTLE*,*&#x20;BOWL*, *BOX*, *BUFFET*, *CAKE*, *CAN*, *CARAFE*, *DOZEN*, *FOOT*, *FULL\_PAN*, *GALLON*, *HALF\_GALLON*, *HALF\_PAN*, *ITEM*, *KIT*, *LITER*, *PACKAGE*, *PAN*, *PERSON*, *PIE*, *PIECE*, *PINT*, *PIZZA*, *PLATTER*, *POUND*, *QUART*, *ROLL*, *SIX\_PACK*, *SKEWER*, *SLIDER*, *TACO*, *TRAY*, *TWELVE\_PACK*, *TWO\_LITER*

# Menu Requirements 

1. Per ezCater’s [Equal Price Guarantee](https://catering.ezcater.com/en/help/what-are-the-pricing-requirements-for-my-menu), which is agreed to by all caterers in the Terms & Conditions of the platform (or signed MSA if applicable), you agree that the pricing you provide us for menu items, service and other fees to display on your ezCater pages for a given location will match the lowest prices and fees you charge customers through your or any other website or online channel for substantially similar offerings at that location. ezCater cannot sell items for higher than the lowest advertised price online.
2. ezCater requires all items to have a price greater than zero.
3. Please don’t forget the utensils! ezCater’s core customer base is people and groups at work who often need forks, napkins, and plates. You can add utensils for a fee as items or you can provide free utensils as Options/Choices. ezCater does require utensils to be added to menu items with limited exceptions. See [Appendix B: ezCater Integrated Plates / Napkins / Utensils](https://api.ezcater.io/menus-api#8akRE) for additional information and examples.

# Menu Create User Permissioning

Prior to requesting user create permissions, an API user must be created, and confirmation that all API documentation on this platform has been read and understood must be provided. Once those steps are completed, a request needs to be submitted to integrations\@ezCater.com.

This request **must** include the following required information to ensure the process can move forward:

- Brand Name
- Integrator Name
- API User Email (the integrator should know this if the brand does not)

It is also highly preferred that the request includes the number of locations that will be integrated and a rough estimate of when the go-live event(s) would begin, as this information is very helpful to the ezCater team. Please note that the ezCater Integrations team reserves the right to withhold permission assignment until all required information is completed to ensure data cleanliness and system security.

:::ExpandableHeading
# Appendix A: Category Names & Order

ezCater customers value uniformity across menus.  It helps to make selecting food for the workplace quick and efficient.  

The following category names and order are used by ezCater associates to build menus.  Standard Offering is generally used for most restaurants. ezCater also uses cuisine specific naming.

## Standard Offerings

1. **Breakfast:&#x20;**&#x41;ll breakfast items (except drinks) go in the breakfast category, regardless of where they would go on a regular menu. This includes things like breakfast sides, pastries, breakfast packages, and breakfast sandwiches. Brunch items are added to Breakfast.
2. **Boxed/Bagged Lunches:** Items that are in a box or bag with other items such as sides, drinks, and/or desserts. The item is not a boxed lunch if it is a singular item just so happens to be served in a box.
3. **Appetizers/Tapas**   
4. **Catering Packages:&#x20;**&#x47;enerally come with a drink and/or dessert. Buffets can be catering packages, but if they are a la carte make a Buffets category. Some CP’s will list an item as “Chicken Parmesan Package”, but if it only comes with Chicken Parmesan it would go in Hot Entrees. Items that come with multiple sides to feed a large group of people can be considered Catering Packages.
5. **Sandwiches/Pizza/Specialty Items/Burgers/Hot Dogs:&#x20;**&#x42;asically anything handheld.
6. **Bowls**   
7. **Hot Entrees:** Generally come with a side.
8. **Pasta** 
9. **A La Carte Meats:** Can include basic items like chicken & meats served by the pound or simply without sides, or meats with bulk pricing.
10. **Soups:** Can include stews. 
11. **Salads:**  Salads that are mayo-based go into sides. Salads that are vegetable-forward go into Salads.
12. **Sides:** Side salads generally go in the salads category, other side-sized items can be placed in the Sides category. This indicates the item is not an entree portion.
13. **Hors d'Oeuvres:** Must be labeled as Hors d'Oeuvres on the CP’s menu
14. **Desserts** 
15. **Beverages** 
16. **Miscellaneous:** Utensils/paper goods/extended service/bags of ice, etc.

## Cuisine Specific Category Names and Order

### Chinese Cuisine Menu Category Names & Order

1. Appetizers
2. Chicken Entrees
3. Beef Entrees
4. Pork Entrees
5. Seafood Entrees
6. Vegetarian Entrees
7. Rice & Noodles
8. Salads
9. Sides
10. Desserts
11. Beverages

### Indian Cuisine Menu Category Names & Order

1. Appetizers
2. Dosas (Rice & Lentil Crepes)
3. Chicken Entrees
4. Lamb Entrees
5. Seafood Entrees
6. Vegetarian Entrees
7. Curries
8. Rice & Biryani
9. Bread
10. Salads
11. Sides
12. Desserts
13. Beverages

### Italian (w/ Pizza) Cuisine Menu Category Names & Order

1. Appetizers
2. Pizza
3. Calzones
4. Sandwiches & Wraps
5. Hot Entrees
6. Salads
7. Sides
8. Desserts
9. Beverages

### Japanese/Sushi Cuisine Menu Category Names & Order

1. Appetizers
2. Bento Boxes
3. Sushi
4. Hot Entrees
5. Rice & Noodles
6. Salads
7. Sides
8. Desserts
9. Beverages

### Mediterranean Cuisine Menu Category Names & Order

1. Appetizers
2. Sandwiches & Wraps
3. Hot Entrees
4. A La Carte Kebabs, Meat, Entrees, etc: if applicable
5. Salads
6. Sides
7. Desserts
8. Beverages

### Mexican Cuisine Menu Category Names & Order

1. Appetizers
2. Tacos & Burritos
3. Sandwiches & Wraps
4. Hot Entrees
5. A La Carte Meat, Entrees, etc: if applicable
6. Salads
7. Sides
8. Desserts
9. Beverages

### Smoothie Cuisine Menu Category Names & Order

1. Breakfast
2. Sandwiches & Wraps
3. Salads
4. Sides
5. Desserts
6. Smoothies
7. Juices
8. Beverages

### Thai Cuisine Menu Category Names & Order

1. Appetizers
2. Hot Entrees
3. Curry
4. Rice & Noodles
5. Salads
6. Sides
7. Desserts
8. Beverages
:::

:::ExpandableHeading
# Appendix B: ezCater Integrated Plates / Napkins / Utensils

To service ezCater’s food for the workplace clientele, ezCater requires menus including utensils individually and serving utensils. 

## Paid for vs Free Utensil Configuration

- Paid for items tagged as “UTENSIL” and presented in the menu.  Customers can select these items and add them to the cart as they build their order. 
- Free items modeled as an Option/Choice are tagged as “UTENSIL”, hidden on the menu, and presented as part of the checkout experience.  ezCater expects a majority, if not all items using this approach will have a utensil configuration.

## Free Utensil Order Experience

ezCater provides consumers the ability to select or deselect their utensil requirements as the order forms in the cart.  The experience includes:

| *Feature 1:*<br />As items are added to the cart, tableware options appear in the cart in a dedicated section.                                                                  | ::Image[****]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd2N9hTTGxS0xnoHS22AMEIlIGtZqlYwb9EN8VzNvURyF9hHWwjDt8i1rXH4qMBSdalELDrnA9VdPzqHfXcbDPfckz4ZO7LLe8MOfboHdgtan47Gi6ok8lKLkiWCkix_cvPgIS_i4Ga1ktPldpOmqKPNYY?key=Nj4QZu-jfuI65bOfAb1D2A" size="20" width="317" height="546" position="center" darkWidth="317" darkHeight="546" showCaption="false"}  |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| *Feature 2:*<br />Upon edit the consumer can select or deselect “tableware” as needed.  The options available for selection change based on the item’s option/choices selected. | ::Image[****]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXciEd4ihNueLDk85nY_-t6tmcde9WZFaYtjMK-QIL7GbvvdbdiIXEqC1QeUCmCYCQ45HDmYJb-A7TXEreLcjtslRjnwR16c1P1hmmTjfMqativLXA1h-hxVUPNHTgoBAA2lkCvDS0pj7Fri6yawMIveKk8W?key=Nj4QZu-jfuI65bOfAb1D2A" size="30" width="561" height="365" position="center" darkWidth="561" darkHeight="365" showCaption="false"} |

## Utensil item and option/choice configuration examples

The following represents common language used by ezCater to describe different types of utensils.  

1. Standard Items 
   1. Utensils
   2. Plates
   3. Napkins
2. Soups:
   1. Plates
   2. Bowls
   3. Napkins
   4. Utensils
3. Drinks
   1. Cups
   2. Ice (Optional)
4. Coffee
   1. Plates
   2. Napkins
   3. Utensils
   4. Cups
   5. Stirrers
   6. Sugar
   7. Diet Sweeteners
   8. Creamer
5. Exceptions that would not require utensils:  Individual drinks.


:::


[title] Delivery API
[path] API for Restaurant Partners/

The ezCater Delivery API empowers restaurants that manage and augment their own in- house deliveries to send delivery event updates directly from their systems.The intent is to only pass through in-house tracking information through those avenues, as we move toward creating a consistent, verifiable delivery experience for all ezCater customers. Want to learn more about our other tracking options? [Read more here](https://catering.ezcater.com/en/help/delivery-tracking-solutions)

***

The Delivery API allows you to update courier information and track your deliveries.

:::hint{type="warning"}
At a minimum, you will need to execute a query on the Order to get the `deliveryId`, which is required for calling any of the Delivery API mutations. You also must have permission within Partner Portal to access the store associated with the Order's UUID to be able to pull information about it.
:::

To pull information about an order, including the necessary `deliveryId`, when executing the  [Order Details](docId\:NY_Zz5d1X1mdgnQzFTwd9) query.

Each time courier information is provided through this API, we will perform an upsert based on the information you have provided us about the courier. The key piece of information that will help us distinguish this courier from other couriers in your system (and whether we’re creating a new courier record or updating an existing courier record) is the `deliveryId` value that you pass along in the mutation.

Once you have created a delivery in your Delivery Management System based on the order query information you've gathered, you’re ready to start providing ezCater with information on the delivery as it changes throughout its lifecycle.

To accommodate these changes to your delivery order, ezCater has developed a number of API mutations for you to use.

:::hint{type="info"}
The goal in building these delivery API mutations is to keep information as flexible as possible. We try to understand that different Delivery Management Systems will have different pieces of information through the delivery lifecycle. Feel empowered to provide as much information as you have about the delivery for each step of the lifecycle.
:::


[title] Meal Program with Olo Integration FAQ
[path] Restaurant Partner Integrations/Olo Rails Integration/

# What is the Meal Program?

- Formally known as Relish! Our product received a brand new name! 
- The ezCater Meal Program  is a corporate subsidy program that enables employees to place individual meal orders that are delivered together.
- These orders include items that are served on an individual basis, rather than larger catering items that may have a larger serving size. 

# What makes a Meal Program order different from a Marketplace order?

- Fast Cutoff: Order cutoff is approximately 90 minutes prior to fulfillment, creating significantly shorter lead times than typical catering lead times. 
- Recurring & Sizing: Orders are often recurring and scheduled, with a maximum of 30 individually packaged and labeled meals.
- Fulfillment:  Individual packaging and labeling creates unique needs, so all fulfillment should continue to be completed through the ezCater Partner Portal. The ezCater Partner Portal remains the source of truth for reporting and review of ezCater orders as a whole. 

# How does this impact the Olo Rails Integration implementation?

- This will impact any new brand that is integrating through the Olo Menu API or converting from Orders to Menu API. If there is even one location participating in the Meal Program for the brand, these steps are required.
- Currently, there is no method to uncouple the standard Marketplace menu from the Meal Program menus in ezCater, hence the need for tagging in Olo.
- If menu tagging is not complete for the Meal Program items, there will be no available Meal Program menu for the location. The import process will create a blank Meal Program menu, as the import pulls what is configured inside of the Olo Menu Admin.

# Best Practices and Considerations

- Meal Program orders are also subject to the $0.40 per order fees associated with successfully integrated orders. 
- A separate Olo menu category will be needed for the Meal Program specifically, which includes any item that is offered on their Meal Program menu.  This may be different from standard Marketplace catering items, and may not currently exist in the Olo Catering Channel. 
- Lead times for Meal Program categories should be set to \~60 minutes in Olo to avoid any order failures.

# Meal Program Menu Setup and Considerations

- Tagging must be completed on the Meal Program category just as done for Marketplace. Additional tags are necessary to ensure this category flows to the Meal Program menu and not the Marketplace menu.
- *Considerations:&#x20;*&#xA0;The Menu Sync resource outlines that a brand *could technically* use the same catering item for both catering Marketplace and Meal Program with special tagging. However, this set up will force order failures due to the lead time discrepancy and is not best practice.
- *Standardization:*  Internal brand alignment may be required, as the Meal Program menu setup may differ with Franchisee involvement and prior setup. 
- *Menu Tagging Requirements*:
  - Required Tags:
    - QuantityUnit
    - CateringServeSize ***(must always be "1")***
    - TaxCategory
    - “RelishChannel” = “T”
  - If the RP has individually packaged sides, they should also have: Key: INDIVIDUALLY\_PACKAGED\_RELISH\_SIDE  and the Value: T
  - Where applicable, FoodLabelingTags, ItemTypeTags, and ChoiceTypeTags will still be required and reviewed during a menu consultation.
  - Utensils are only required if the items are shared between the Marketplace and Meal Program. 
- *Testing*:
  - At this time, while ezCater can validate and provide Menu Requirement Consults for the menu build, there is no testing environment for the Meal Program, as this will be independent of the standard POS testing environment. 


**For any questions on the process, please reach out to the ezCater Integrations team at integrations\@ezcater.com.**

[title] Integration Setup - SAP Concur Enterprise
[path] Enterprise Account Integrations/SAP Concur Enterprise/

*This page contains instructions for enabling the SAP Concur Enterprise integration with ezCater. Roster sync can be enabled in the ezCater Admin Portal once automatic receipt forwarding is set up.&#x20;*

### Automatic Receipt Forwarding

- Access SAP Concur ([https://www.concursolutions.com/](https://www.concursolutions.com/)) as an admin with one of the following permissions:
  - Program Administrator
  - Authorized Support Contact
  - Web Services Administrator
- Navigate to the App Center and search for **ezCater Enterprise**
- Click **Connect&#x20;**&#x6F;n the ezCater Enterprise SAP Concur App listing

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/q-0_LRt0LAJQYWEqzEQaB_image-141.png" size="40" width="382" height="252" position="center" darkWidth="382" darkHeight="252" showCaption="false"}

- Read and **agree** to the terms and conditions

![](https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/ct9y3yNmBsCrxGEvnUnbM_image-20251218-150956.png)

- **Sign in&#x20;**&#x74;o your ezCater account with your **admin credentials**

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/as2YjN2B0pV7xuZinw4EU_image-142.png" size="48" width="785" height="648" position="center" darkWidth="785" darkHeight="648" showCaption="false"}

- Click **Connect**

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/kQhup6vw746HnOmBB8ven_image-143.png" size="50" width="798" height="649" position="center" darkWidth="798" darkHeight="649" showCaption="false"}

- You will see a success message you can close. Navigate to your ezCater Admin Portal ([http://enterpriseportal.ezcater.com](http://enterpriseportal.ezcater.com)) if you want to enable Roster Sync and follow the directions below.&#x20;

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/Pz1JS2edJGO5PycqVRa32_image-144.png" size="62" width="798" height="648" position="center" darkWidth="798" darkHeight="648" showCaption="false"}

### Roster Sync

- After enabling automatic receipt forwarding, navigate to your ezCater Admin Portal *http\://enterpriseportal.ezcater.com*
- In the Integrations tab, click **Manage** on the Concur Enterprise tile

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/tkwI8OGdljM66WqnncLWR_image-145.png" size="84" width="1531" height="866" position="center" darkWidth="1531" darkHeight="866" showCaption="false"}

- Select the checkbox **Automatically update account members from Concur roster (Optional)**

![](https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/YGmmJ9jyqiqclHfgMVw01_image-146.png)

- Click **Turn on**

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/A0mtMnGsBqzalosDrZJCw_image-147.png" size="82" width="1531" height="864" position="center" darkWidth="1531" darkHeight="864" showCaption="false"}

- Click and **save changes**

![](https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/xTVVJj9kNfUS9ncEjYIKE_image-148.png)

- Roster sync is now enabled.

![](https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/d4sw1fFpGtipBkOhqmpQv_image-149.png)


[title] Slack with Meal Program
[path] Enterprise Account Integrations/Slack Integration/

## Slack Admin Guide - Slack Business / Pro / Free

**Please install the app at the Workspace-specific level.**

**(Slack Business / Pro / Free) level&#xA0;**

1. Click on the [Installation Link](https://slack-connector-bot.ezcater.com/slack/install).
2. Go to the top right dropdown menu and **select the Workspace** you are an admin of and want to install the app to.
3. Review the permissions that the app will have access to within your Org and select "**Allow**".
4. Now, go to your Workspace settings dashboard and click on **Configure apps&#x20;**&#x77;ithin the left-side menu.
5. You will see the app listed within the **Installed apps** list. It’s now ready to use by everyone within your workspace.


**ezCater Slack Application Scopes**
The application can access the following permission scopes within your Slack environment:
**Users\:read:** View people in a workspace
**App\_mentions\:read:** View messages that directly mention @ezCater in conversations that the app is in
**Team\:read:** View the name, email domain, and icon for workspaces ezCater is connected to
**Chat\:write:** Send messages as @ezCater

That’s it, you’re done! You will get a message from Slackbot confirming that the app has been added to the workspaces and is ready to use.

## Slack Admin Guide - Slack Enterprise Grid&#x20;

**Please install the app at the organization level.**

1. Click on the [Installation Link](https://slack-connector-bot.ezcater.com/slack/install).
2. Go to the top right dropdown menu and **select the Organization** you are an admin of and want to install the app to.
3. Review the **permissions** that the app will have access to within your Org and select "**Allow"**.
4. Now, go to your Org settings dashboard and click on **Integrations**, then **Installed Apps**. You’ll see the ezCater app within the list.
5. Select the ... next to the app and **Add to more workspaces**. Add the app to all workspaces, or the few you want to limit it to.
6. Review the app’s **requested permissions** and select Next. Make sure you ✅ “I’m ready to add this app” and select **Add app**.

**ezCater Slack Application Scopes**
The application can access the following permission scopes within your Slack environment:
**Users\:read:** View people in a workspace
**App\_mentions\:read:** View messages that directly mention @ezCater in conversations that the app is in
**Team\:read:** View the name, email domain, and icon for workspaces ezCater is connected to
**Chat\:write:** Send messages as @ezCater

That’s it, you’re done! You will get a message from Slackbot confirming that the app has been added to the workspaces and is ready to use.

## Invite Users

Once you have successfully set up the Slack app, Admins will now be able to invite users to use the integration. *The user who set up the integration will be the primary admin and will need to add additional admins to invite team members.&#x20;*

To invite users, navigate to the ezCater app in Slack. Click on the "**Home**" tab, and then "**Invite Users**".&#x20;
There is a preloaded message for ease of inviting your team! The message will be sent to all users who have not connected to ezCater in Slack.&#x20;
The message can also be copied and pasted to be sent directly in specific channels.&#x20;

[title] Subscriber List
[path] API for Restaurant Partners/Subscription API/

# Listing Subscribers And Subscriptions

The **Subscriber** query returns information about the **Subscriber** and **Subscriptions** for the integration. This query can be useful in determining if you have successfully created a **Subscriber** or **Subscriptions**.&#x20;

:::hint{type="warning"}
At this time we only allow one Subscriber per API user.
:::

## Query

:::CodeblockTabs
Query

```graphql
query Subscribers {
  subscribers {
    id
    name
    subscriptions {
      eventEntity
      eventKey
      parentEntity
      parentId
      subscriberId
    }
    webhookUrl
  }
}
```
:::

### Return Type

Returns a [\[Subscriber!\]](docId:_6fu5DGR5rPbWAT27Pcxz).

## Successful Responses

When the `subscribers` query succeeds you can expect the response payload to look in one of three different ways:

1. If you have not yet created a **Subscriber** the `subscribers` field value will empty.&#x20;
2. If you have created a **Subscriber** but have not yet created any **Subscriptions** the `subscriptions` field value will empty.&#x20;
3. If you have created `subscriptions` all of them for the **Subscriber** will be returned.

:::CodeblockTabs
Response - Without Subscribers

```graphql
{
  "data": {
    "subscribers": []
  }
}
```

Response - Without Subscriptions

```graphql
{
  "data": {
    "subscribers": [
      {
        "id": "your-subscriber-id",
        "name": "Example Provider Updated - Example Brand",
        "subscriptions": [],
        "webhookUrl": "https://example.net/subscriptions"
      }
    ]
  }
}
```

Response - With Subscriptions

```graphql
{
  "data": {
    "subscribers": [
      {
        "id": "your-subscriber-id",
        "name": "Example Provider Updated - Example Brand",
        "subscriptions": [
          {
            "eventEntity": "Menu",
            "eventKey": "updated",
            "parentEntity": "Caterer",
            "parentId": "ezcater-caterer-id",
            "subscriberId": "your-subscriber-id"
          },
          {
            "eventEntity": "MenuCreationRequest",
            "eventKey": "failed",
            "parentEntity": "Caterer",
            "parentId": "ezcater-caterer-id",
            "subscriberId": "your-subscriber-id"
          },
          {
            "eventEntity": "MenuCreationRequest",
            "eventKey": "succeeded",
            "parentEntity": "Caterer",
            "parentId": "ezcater-caterer-id",
            "subscriberId": "your-subscriber-id"
          },
          {
            "eventEntity": "MenuCreationRequest",
            "eventKey": "succeeded_with_warnings",
            "parentEntity": "Caterer",
            "parentId": "ezcater-caterer-id",
            "subscriberId": "your-subscriber-id"
          },
          {
            "eventEntity": "Order",
            "eventKey": "accepted",
            "parentEntity": "Caterer",
            "parentId": "ezcater-caterer-id",
            "subscriberId": "your-subscriber-id"
          },
          {
            "eventEntity": "Order",
            "eventKey": "cancelled",
            "parentEntity": "Caterer",
            "parentId": "ezcater-caterer-id",
            "subscriberId": "your-subscriber-id"
          },
          {
            "eventEntity": "Order",
            "eventKey": "rejected",
            "parentEntity": "Caterer",
            "parentId": "ezcater-caterer-id",
            "subscriberId": "your-subscriber-id"
          },
          {
            "eventEntity": "Order",
            "eventKey": "submitted",
            "parentEntity": "Caterer",
            "parentId": "ezcater-caterer-id",
            "subscriberId": "your-subscriber-id"
          },
          {
            "eventEntity": "Order",
            "eventKey": "uncancelled",
            "parentEntity": "Caterer",
            "parentId": "ezcater-caterer-id",
            "subscriberId": "your-subscriber-id"
          }
        ],
        "webhookUrl": "https://example.net/subscriptions"
      }
    ]
  }
}
```
:::

## Failure Responses

When the `subscribers` query fails you can expect the response payload to look like:

:::CodeblockTabs
Response - Without Subscribers

```graphql
{
  "data": {
    "subscribers": []
  }
}
```
:::



##


[title] Utensils
[path] Restaurant Partner Integrations/General Menu Guidance/

Utensils is a general term used to describe the varying utensil items a customer will need. Utensils can include utensils, forks, knives, spoons, plates, bowls, and/or napkins. We can accommodate free or paid utensils. Utensils selections from customers can be found in Partner Portal.&#x20;

1. ezCater requires **all menus** to have a utensil configuration.
2. ezCater provides consumers the ability to select or deselect their utensil requirements as the order forms in the cart. The experience includes:
   - As items are added to the cart, tableware options appear in the cart in a dedicated section.
   - Upon edit the consumer can select or deselect “tableware” as needed. The options available for selection change based on the item’s option/choices selected.

# Free Utensils

Free utensils are modeled as an Option/Choice, are tagged as “*UTENSIL*”, while hidden on the ezCater menu, they are presented as part of the checkout experience. ezCater expects a majority, if not all items using this approach will have a utensil configuration. If utensils are free, all items will need to have a utensil configuration with the exception of individual drinks. 

The table below highlights the possible configurations for utensils depending on the menu items offered. Utensils must be applied to all food items.

| Item                  | Modifier Group  | Configuration                                         |
| --------------------- | --------------- | ----------------------------------------------------- |
| Standard Items        | Utensils        | - Utensils
- Plates
- Napkins                         |
| Soups                 | Soup Utensils   | * Bowls
* Napkins
* Spoons                            |
| Non-Individual Drinks | Cups& Ice       | - Cups
- Ice                                          |
| Coffee                | Coffee Utensils | * Cups
* Stirrers
* Sugar
* Diet Sweeteners
* Creamer |

:::hint{type="info"}
Exceptions that would not require utensils: Individual drinks.
:::

# Paid Utensils

Paid for items are tagged as “*UTENSIL*” and presented in the menu as an item. Customers can select these items and add them to the cart as they build their order. The table below highlights the possible configurations for paid utensils depending on the menu items offered.&#x20;

| Item          | Choices                       |
| ------------- | ----------------------------- |
| Utensils      | - Utensils
- Plates
- Napkins |
| Soup Utensils | * Bowls
* Napkins
* Spoons    |
| Cups          | - Cups                        |
| Ice           | * Ice                         |


[title] Menu Creation Request
[path] API for Restaurant Partners/Menus API/

# Viewing Menu Creation Request Status

The `MenuCreationRequest` query provides detailed information about a specific menu creation request, including the creation status, warning message and error messages to explain why a menu was not successfully created.

To use the query a valid `menuCreationRequestId` is required. This UUID is returned with the [Menu Create](docId\:iGAczTGMSnoYf0fe3zage) mutation as well as within the payload of `MenuCreationRequest` subscription notifications, which are sent after a Menu Creation Request is completed processing. Since menu creation is an asynchronous process we recommend [Subscribing to Menu Notifications](docId\:gJAIaYwOUbUgVFI8lfy6E) to be informed when the process is complete instead of continuously retrying the query.

## Query

:::CodeblockTabs
Query

```graphql
query MenuCreationRequest($menuCreationRequestId: UUID!) {
  menuCreationRequest(id: $menuCreationRequestId) {
    errors {
      details
      message
    }
    menuUuid
    outcome
    status
    warnings {
      details
      message
    }
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables

```graphql
{
  "menuCreationRequestId": "your-ezcater-menu-creation-request-id"
}
```
:::

### Arguments

| Argument Name                                 | Description                                                                                                                       |
| --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `id`: [UUID! ](docId\:IbvUQPK0mwpAa9DSKEujY)  | The `menuCreationRequestId` that was returned by the `MenuCreate` mutation or received from a menu creation request notification. |

### Return Type

Returns a [MenuCreationRequest](docId\:IbvUQPK0mwpAa9DSKEujY).

## Success Responses

When the `menuCreationRequest` query succeeds you can expect the response payload to look in one of two different ways:

1. If the menu was created with the outcome of `success`, the `warnings` and `errors` field values will empty.&#x20;
2. If the menu was created with the outcome of `success_with_warnings`, the `warnings` will be provided and the the `errors` field value will empty.&#x20;

:::CodeblockTabs
Response - Success

```graphql
{
  "data": {
    "menuCreationRequest": {
      "errors": [],
      "menuUuid": "ezcater-menu-version-id",
      "outcome": "success",
      "status": "complete",
      "warnings": []
    }
  }
}
```

Response - Success With Warnings

```graphql
{
  "data": {
    "menuCreationRequest": {
      "errors": [],
      "menuUuid": "your-ezcater-menu-version-id",
      "outcome": "success_with_warnings",
      "status": "completed",
      "warnings": [
        {
          "details": {},
          "message": "Item with pos_id assorted-sodas-item-selection-id has a price of $0.00.  It will not be displayed."
        }
      ]
    }
  }
}
```
:::

## Failure Responses

### Not authenticated

When an the user is unable to be authenticated.

:::CodeblockTabs
Response

```graphql
{
  "errors": [
    {
      "message": "Not authenticated.",
      "extensions": {
        "code": "ERR_UNAUTHENTICATED"
      }
    }
  ]
}
```
:::

### Invaild menuCreationRequestId

When an invalid `menuCreationRequestId` is provided, no `menuCreationRequest` data is returned in the response payload.

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "menuCreationRequest": null
  }
}
```
:::

### Internal Error

When an internal error occurs, we are unable to provide additional `details`.

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "menuCreationRequest": {
      "errors": [
        {
          "details": {},
          "message": "Internal error"
        }
      ],
      "menuUuid": null,
      "outcome": "failure",
      "status": "completed",
      "warnings": []
    }
  }
}
```
:::

### Referenced Entity Is Not Defined

When a menu entity references a child menu entity, but it is not properly defined you can expect an outcome of `failure` and the response payload to include a `message` with `details`.

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "menuCreationRequest": {
      "errors": [
        {
          "details": {
            "source": "categories",
            "source_name": "Drinks",
            "source_pos_id": "drinks-category-id",
            "reference_type": "items",
            "referenced_pos_id": "drinks-item-id"
          },
          "message": "Referenced entity is not defined"
        }
      ],
      "menuUuid": null,
      "outcome": "failure",
      "status": "completed",
      "warnings": []
    }
  }
}
```
:::

### Number Of Choice Selections

When the minimum number of choice selections is greater than the number of available choices you can expect an outcome of `failure` and the response payload to include a  `message` with `details`.

:::CodeblockTabs
Response - Min Choice Selections

```graphql
{
  "data": {
    "menuCreationRequest": {
      "errors": [
        {
          "details": {
            "minchoices": 10,
            "entity_name": "Cheese Addon",
            "entity_pos_id": "cheese-addon-options-id",
            "choices_present": 7
          },
          "message": "minChoiceSelections must be less than or equal to count of Choices""
        }
      ],
      "menuUuid": null,
      "outcome": "failure",
      "status": "completed",
      "warnings": []
    }
  }
}
```

Response - Max Choice Selections

```graphql
{
  "data": {
    "menuCreationRequest": {
      "errors": [
        {
          "details": {
            "maxchoices": 1,
            "minchoices": 2,
            "entity_name": "Cheese Addon",
            "entity_pos_id": "cheese-addon-options-id"
          },
          "message": "maxChoiceSelections must be greater than or equal to minChoiceSelections"
        }
      ],
      "menuUuid": null,
      "outcome": "failure",
      "status": "completed",
      "warnings": []
    }
  }
}
```
:::

### Invalid Images

When there is a problem finding the item image you can expect the response payload to include a `message` with `details`.

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "menuCreationRequest": {
      "errors": [
        {
          "details": {
            "image_url": "https://your-domain.com/menu-item-images/margherita-pizza.jpg",
            "item_pos_id": "margherita-pizza-item-id"
          },
          "message": "Problem with item image - could not find image"
        }
      ],
      "menuUuid": "ezcater-menu-id",
      "outcome": null,
      "status": "completed",
      "warnings": []
    }
  }
}
```
:::


[title] Microsoft SSO Instructions - ezCater Marketplace Only
[path] Enterprise Account Integrations/SSO for Marketplace & Relish/

- In the Microsoft Entra Admin Center, navigate to **Identity > Applications > Enterprise applications&#x20;**&#x61;nd click on **Create your own application**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcSaPzNY5aVi6D0DYKTl6hYveySHTrFtZtJEkvNu-B3QzrXiF6PLeQOg1ZFCCWD63IjdsEuYyQa4xoy0I7VW-bScyZYaUTy3sPiyauDp24XyMjsXwaS9bISagSi9tttGWWc7LcE?key=AvWn09Y7CVz2HnQXem_NL67Q" size="68" width="964" height="490" position="center" darkWidth="964" darkHeight="490" showCaption="false"}

- Name the app **ezCater&#x20;**&#x61;nd select the “non-gallery” option for this application

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfPNILGHVtS4TheOt1FXWHAmrEXZdsr3Y93AhxZIURrJGdZFSDHdbYrubMo3C0kzKH6Euz9RbvMGZE-2JfU6I9NMrgTnR-dCbQwlwZZGL-tTuDhCNQqtppbIKnGWNz88oN_yuqPzg?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Once the app is created, click on the **Set up single sign on&#x20;**&#x74;ile

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXf0_v3Yi6Xd9rDnp8ARsxB_29osxLFO9o33_8CWa-Mli1RcstVQyIZ3ThIl3Nlas5WJV2YOSSCXXuTpp4gSlyQ5RWGJlUzhB9QLD0YsOGt_kI5GT6N3np9zOB5PPTQVof9lNJ2V3g?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Click on the **SAML&#x20;**&#x6F;ption for the SSO method

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfwPim_3UAvv0SHbcvSzSYSzSP-5Nd2yEO_qDSscgdp_mD6yV-nNsvyytHkqPCcuJ1HaXHcYYxBSPVNT8Q3bz79NXOQWM7Y5JR9eqdTywKjdShsLgHZuxnir78JBGsQJ7nlwek_?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Click on the **Edit&#x20;**&#x62;utton in the first section

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXcahCAFY88BuhHsNgCSUTxiES19gDNWkurAlTHqIIxLN2elpr78N6OcFhEb9QFfGapXzrTAeeTjX2PA9N5KD0aBzULaxZrrNRPozcsAwR8N5BM5xkNpQv8pzmDTDiYEHv4UIjTFLA?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Use the following values for the SAML configuration:
  - Identifier (Entity ID): **ezcater.com**
    - *Do NOT add https or www*
  - Reply URL (Assertion Consumer Service URL): [https://www.ezcater.com/saml/consume](https://www.ezcater.com/saml/consume)
  - Reply URL Index:**&#x20;0**
  - **Sign on URL:&#x20;**[https://www.ezcater.com/sso\_session/new](https://www.ezcater.com/sso_session/new)

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXf4naMREExMMt0bhicndqKh3en5Doccewv-4-IM30T_mGmihWUcozv6E7_95KK7Bwn3luVpZ9-uhDG67sN-XZG0YU_LJwL-0s1CX5O1o-_kgFYsUAAesJY00Tsf-VXDcNnZUgfG?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Once the settings are saved, scroll down the SAML Certificates and click on **Download&#x20;**&#x6E;ext to Certificate (Base64). &#x20;

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXc8a-ggwKzgv1QqlZaDjilbAZBWe6Fk6iR9vGObgSQEuX2JLhW_9WaAAyg6zwmq6Mf39s7wX4KgkeZnfmk_Yo4EJDrTFXo5bcPXzB-N4ONPBVJQW2dQ7b37NQ0NGTsFec6lVnUBLw?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Submit the **public certificate** in plaintext along with copied app settings (**Login URL** and **Microsoft Entra Identifier**) through the [ezCater/Meal Program SSO Form ](https://ezcaterforms.formstack.com/forms/ezcater_sso)

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXdKumzEGaFXSDXfn6rxT7wkPJDmpqU-BP9L7y6O_ZJrc9t5DJTiuanwIi_cBwbL6JSQBzjjaz2R0odN7OsWSCWMDuRSMAhmDmuHDyg-D2_UN_g_RTcqZ09DNtI41RAiXcXn9Xzs?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Navigate back to **App Registrations,** click on the Meal Program application. Then, navigate to **Branding & properties** to update the logo. 

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/8FS4B1MRyQAn4TLMhjSgh_ezcater-logo-bright-primary-symbol-300dpi.png" size="36" width="2084" height="1918" position="center" showCaption="false"}


[title] Home
[path] /

Welcome to ezCater's documentation portal, your comprehensive resource for building seamless integrations and unlocking new opportunities.&#x20;

Dive into our expertly crafted guides, whether you're a developer exploring technical API documentation, a new or existing partner seeking robust integration information, or a business looking to create effortless guest experiences.&#x20;

Our portal provides the essential resources and best practices you need to connect with ezCater efficiently and effectively, empowering you to streamline operations and deliver exceptional service.

::::LinkArray{contentSource="CUSTOM"}
:::LinkArrayItem{headerType="IMAGE" headerImage="https://archbee-image-uploads.s3.amazonaws.com/CnBnWfHDNa9lZK7nmY_mG-k2N8XOpOeeP3Q-t6VT6sG-20250611-193601.jpg"}
# [For Developers](https://api.ezcater.io/public-api-for-catering-partners)

[Resources for developers interested in writing towards ezCater's API for our restaurant partners.](https://api.ezcater.io/public-api-for-catering-partners)
:::

:::LinkArrayItem{headerType="IMAGE" headerImage="https://archbee-image-uploads.s3.amazonaws.com/CnBnWfHDNa9lZK7nmY_mG-JVXePj41oCAQh-7f3ZBL6-20250611-193616.jpg"}
# [For restaurant partners](https://api.ezcater.io/general-menu-guidance)

[Resources for restaurant partners interested in integrating with a 3rd Party and ezCater.](https://api.ezcater.io/general-menu-guidance)
:::

:::LinkArrayItem{headerType="IMAGE" headerImage="https://archbee-image-uploads.s3.amazonaws.com/CnBnWfHDNa9lZK7nmY_mG-KH6fiKVT0EBgO_wY12UZk-20250611-193627.jpg"}
# [For Enterprise Accounts](https://api.ezcater.io/overview)

[Resources for Enterprise Accounts interested in learning more about ezCater Integrations.](https://api.ezcater.io/T3Cl-overview)
:::
::::

***


[title] Subscription Schema Reference
[path] API for Restaurant Partners/Subscription API/

# Subscription Schema Reference

## Objects

### CreateSubscriberPayload

Return type of `CreateSubscriber`.

| Field Name                                                     | Description                                       |
| -------------------------------------------------------------- | ------------------------------------------------- |
|   `subscriber`: [NewSubscriber!](docId:_6fu5DGR5rPbWAT27Pcxz)  | The information about a newly created subscriber. |

:::CodeblockTabs
Example

```graphql
{
  "subscriber": NewSubscriber!
}
```
:::

### CreateSubscriptionPayload

Return type of `CreateSubscription`.

| Field Name                                                          | Description                                               |
| ------------------------------------------------------------------- | --------------------------------------------------------- |
|  `subscription`: [EventSubscription!](docId:_6fu5DGR5rPbWAT27Pcxz)  | The information about a newly created event subscription. |

:::CodeblockTabs
Example

```graphql
{
  "subscription": EventSubscription!
}
```
:::

### UpdateSubscriberPayload

Return type of `UpdateSubscriber`.

| Field Name                                                  | Description                                  |
| ----------------------------------------------------------- | -------------------------------------------- |
|   `subscriber`: [Subscriber!](docId:_6fu5DGR5rPbWAT27Pcxz)  | The information about an updated subscriber. |

:::CodeblockTabs
Example

```graphql
{
  "subscriber": Subscriber!
}
```
:::

## InputObjects

### CreateSubscriberFields

Input object for making new subscribers.

| Field Name                                            | Description                                                                                                           |
| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `name`: [String!](docId:_6fu5DGR5rPbWAT27Pcxz)        | The entity subscribing to event notifications. Naming convention is `<provider_using_integration>-<affiliated_brand>` |
| `webhookUrl`: [String!](docId:_6fu5DGR5rPbWAT27Pcxz)  | An URL where subscription notification events will be sent to.                                                        |

:::CodeblockTabs
Example

```graphql
{
  "name": "Example Provider - Example Brand",
  "webhookUrl": "https://example.net/subscriptions"
}
```
:::

### CreateSubscriptionFields

Input object for making new subscriptions.

| Field Name                                                    | Description                                                                                                                                                                         |
| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `eventEntity`: [EventEntity!](docId:_6fu5DGR5rPbWAT27Pcxz)    | A `EventEntity` enum of the entity to receive notifications about (e.g. for notifications each time an order event occurs, this would be `Order`).                                  |
| `eventKey`: [EventKey!](docId:_6fu5DGR5rPbWAT27Pcxz)          | A `EventKey` enum of the particular event to notify on (e.g. for notifications when an Order is accepted, this would be an `accepted` event).                                       |
| `parentEntity`: [ParentEntity!](docId:_6fu5DGR5rPbWAT27Pcxz)  | A `ParentEntity` enum indicating the owner of the entity to receive notifications about (e.g. the specific Catering location to receive order `accepted` notifications for, etc.).  |
| `parentId`: [UUID!](docId:_6fu5DGR5rPbWAT27Pcxz)              | An ID for the owner of the entity to receive notifications about. For the Menu API the `ParentId` value should be a Caterer `UUID`.                                                 |
| `subscriberId`: [ID!](docId:_6fu5DGR5rPbWAT27Pcxz)            | An `ID` for the subscriber wanting to receive these events.                                                                                                                         |

:::CodeblockTabs
Example

```graphql
{
  "eventEntity": "Order",
  "eventKey": "accepted",
  "parentEntity": "Caterer",
  "parentId": "ezcater-caterer-id",
  "subscriberId": "your-subscriber-id"
}
```
:::

### EventSubscription

A subscription allows a subscriber to enable notifications for a particular event (e.g. when an order is accepted at a particular catering location). When a subscription is created, all event notifications will be received at the subscriber’s webhook URL.

| Field Name                                                    | Description                                                                                                                                                                         |
| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `eventEntity`: [EventEntity!](docId:_6fu5DGR5rPbWAT27Pcxz)    | A `EventEntity` enum of the entity to receive notifications about (e.g. for notifications each time an order event occurs, this would be `Order`).                                  |
| `eventKey`: [EventKey!](docId:_6fu5DGR5rPbWAT27Pcxz)          | A `EventKey` enum of the particular event to notify on (e.g. for notifications when an Order is accepted, this would be an `accepted` event).                                       |
| `parentEntity`: [ParentEntity!](docId:_6fu5DGR5rPbWAT27Pcxz)  | A `ParentEntity` enum indicating the owner of the entity to receive notifications about (e.g. the specific Catering location to receive order `accepted` notifications for, etc.).  |
| `parentId`: [UUID!](docId:_6fu5DGR5rPbWAT27Pcxz)              | An ID for the owner of the entity to receive notifications about. For the Menu API the `ParentId` value should be a Caterer `UUID`.                                                 |
| `subscriberId`: [ID!](docId:_6fu5DGR5rPbWAT27Pcxz)            | An `ID` for the subscriber wanting to receive these events.                                                                                                                         |

:::CodeblockTabs
Example

```graphql
{
  "eventEntity": "Order",
  "eventKey": "accepted",
  "parentEntity": "Caterer",
  "parentId": "ezcater-caterer-id",
  "subscriberId": "your-subscriber-id"
}
```
:::

### NewSubscriber

This object represents a URL to receive all subscription notifications. One
subscriber can be created per access token. A subscriber can have many subscriptions.

| Field Name                                                               | Description                                                                                                           |
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `id`: [ID!](docId:_6fu5DGR5rPbWAT27Pcxz)                                 | The ID for the subscriber                                                                                             |
| `name`: [String!](docId:_6fu5DGR5rPbWAT27Pcxz)                           | The entity subscribing to event notifications. Naming convention is `<provider_using_integration>-<affiliated_brand>` |
| `subscriptions`: [\[EventSubscription!\]!](docId:_6fu5DGR5rPbWAT27Pcxz)  | Active Event Subscriptions for the Subscriber                                                                         |
| `webhookSecret`: [String!](docId:_6fu5DGR5rPbWAT27Pcxz)                  | The token provided when POSTing events to the webhook to ensure the notification was sent by ezCater.                 |
| `webhookUrl`: [String!](docId:_6fu5DGR5rPbWAT27Pcxz)                     | An URL where subscription notification events will be sent to.                                                        |

:::CodeblockTabs
Example

```graphql
{
  "id": "your-subscriber-id",
  "name": "Example Provider - Example Brand",
  "subscriptions": [EventSubscription!]!,
  "webhookSecret": "be6efd0f8e88fec0d51364559ca9a258e70031f7f38448ea2e9705928a929a8d",
  "webhookUrl": "https://example.net/subscriptions"
}
```
:::

### Subscriber

This object represents a URL to receive all subscription notifications. One
subscriber can be created per access token. A subscriber can have many subscriptions.

| Field Name                                                               | Description                                                                                                           |
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `id`: [ID!](docId:_6fu5DGR5rPbWAT27Pcxz)                                 | The ID for the subscriber                                                                                             |
| `name`: [String!](docId:_6fu5DGR5rPbWAT27Pcxz)                           | The entity subscribing to event notifications. Naming convention is `<provider_using_integration>-<affiliated_brand>` |
| `subscriptions`: [\[EventSubscription!\]!](docId:_6fu5DGR5rPbWAT27Pcxz)  | Active Event Subscriptions for the Subscriber                                                                         |
| `webhookUrl`: [String!](docId:_6fu5DGR5rPbWAT27Pcxz)                     | An URL where subscription notification events will be sent to.                                                        |

:::CodeblockTabs
Example

```graphql
{
  "id": "your-subscriber-id",
  "name": "Example Provider - Example Brand",
  "subscriptions": [EventSubscription!]!,
  "webhookUrl": "https://example.net/subscriptions"
}
```
:::

### UpdateSubscriberFields

Input object for updating subscribers.

| Field Name                                           | Description                                                                                                           |
| ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `name`: [String](docId:_6fu5DGR5rPbWAT27Pcxz)        | The entity subscribing to event notifications. Naming convention is `<provider_using_integration>-<affiliated_brand>` |
| `webhookUrl`: [String](docId:_6fu5DGR5rPbWAT27Pcxz)  | An URL where subscription notification events will be sent to.                                                        |

:::CodeblockTabs
Example

```graphql
{
  "name": "Example Provider - Example Brand",
  "webhookUrl": "https://example.net/subscriptions"
}
```
:::

## Enums

### EventEntity

The name of the entity to receive subscription notifications about. Applied to the `eventEntity` type as the field's return type.

| Enum Name             | Description                                                                                                            |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `Menu`                | The `Menu` event entity is used to receive subscription notifications for menu events.                                 |
| `MenuCreationRequest` | The `MenuCreationRequest` event entity is used to receive subscription notifications for menu creation request events. |
| `Order`               | The `Order` event entity is used to receive subscription notifications for order events.                               |

### EventKey

The particular event to notify on. Applied to the `eventKey` type as the field's return type.

:::hint{type="info"}
&#x20;As the integration functionality expands, there may be additional event subscription options as well.&#x20;
:::

| Enum Name                 | Description                                                                                                                                                                                    |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `submitted`               | An `Order` entity event indicating an order has been placed by the ordering customer.                                                                                                          |
| `accepted`                | An `Order` entity event indicating an order has been accepted or an order has been updated & that update is accepted by there caterer or on behalf of a caterer through a partner integration. |
| `rejected`                | An `Order` entity event indicating an order has been rejected by a caterer or on behalf of a caterer through a partner integration.                                                            |
| `cancelled`               | An `Order` entity event indicating an order has been cancelled by the ordering customer, or ezCater on behalf of the caterer.                                                                  |
| `uncancelled`             | An `Order` entity event indicating an order has been uncancelled by the ordering customer, or ezCater on behalf of the caterer.                                                                |
| `relish_finalized`        | An `Order` entity event indicating that a Meal Program order has been finalized post-cutoff, and that the order now contains all the items to be delivered that day.                           |
| `updated`                 | A `Menu` entity event indicating that a menu has been changed.                                                                                                                                 |
| `succeeded`               | A `MenuCreationRequest` entity event indicating that a menu creation request has completed successfully.                                                                                       |
| `succeeded_with_warnings` | A `MenuCreationRequest` entity event indicating that a menu creation request has completed successfully but with warnings that may require review.                                             |
| `failed`                  | A `MenuCreationRequest` entity event indicating a menu creation request has failed with errors that require review.                                                                            |

### ParentEntity

The owner of the entity to receive notifications about. Applied to the `parentEntity` type as the field's return type.

| Enum Name | Description                                       |
| --------- | ------------------------------------------------- |
| `Caterer` | The `Caterer` is they only owner available today. |

## Scalars

### ID

The ID scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as "4") or integer (such as 4) input value will be accepted as an ID.

### String

The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.

### UUID

Universally unique identifier as defined by RFC 4122.


[title] Courier Assign (Legacy)
[path] API for Restaurant Partners/Delivery API/

# Assigning a Courier

`courierAssign` is a legacy mutation that assigns a single courier. New integrations should use [`couriersAssign`](https://api.ezcater.io/couriers-assign) instead.

The `courierAssign` mutation tells us about the individual who has been assigned to fulfill the ezCater delivery.

:::hint{type="info"}
If you already had a courier assigned to a delivery and are now assigning a new courier, we automatically take care of un-assigning the previous courier.
:::

:::hint{type="success"}
If you have dispatched the delivery to another 3rd party (e.g. DoorDash, Uber Direct, etc.) it is important for you to fill in the `deliveryServiceProvider` with the name of that delivery provider. Otherwise, you may populate the value of this field with the name of your company.
:::

## Mutation

:::CodeblockTabs
Mutation

```graphql
mutation CourierAssign($input: CourierAssignInput!) {
  courierAssign(input: $input) {
    clientMutationId
    delivery {
      id
    }
    userErrors {
      ... on DeliveryValidationError {
        message
        path
      }
    }
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables

```graphql
{
  "input": {
    "clientMutationId": "your-mutation-id",
    "courier": {
      "id": "your-courier-id",
      "firstName": "Test",
      "lastName": "Courier",
      "phone": "+15555555555",
      "vehicle": {
        "make": "Your Vehicle Make",
        "model": "Your Vehicle Model",
        "color": "Your Vehicle Color"
      }
    },
    "deliveryId": "ezcater-delivery-id",
    "deliveryServiceProvider": "Your Delivery Service Provider"
  }
}
```
:::

### Arguments

| Argument Name                                                | Description                               |
| ------------------------------------------------------------ | ----------------------------------------- |
| `input`: [CourierAssignInput!](docId:7gV344RnWmuokNj9u4rW7)  | The Input object for assigning a courier. |

### Return Type

Returns a [CourierAssignPayload](docId:7gV344RnWmuokNj9u4rW7).

## Success Response

When the `courierAssign` mutation succeeds you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "courierAssign": {
      "clientMutationId": "your-mutation-id",
      "delivery": {
        "id": "ezcater-delivery-id"
      },
      "userErrors": []
    }
  }
}
```
:::

## Failure Response

### User Errors

When the `courierAssign` mutation fails due to user errors you can expect a HTTP 200  and the response payload to look like:

:::CodeblockTabs
Response - Invalid Phone Number

```graphql
{
  "data": {
    "courierAssign": {
      "clientMutationId": "4cbc6b56-3636-4692-b3d8-9b9a6a4b92a1",
      "delivery": null,
      "userErrors": [
        {
          "message": "Phone 55555555 is an invalid US phone number",
          "path": [
            "input",
            "courier",
            "phone"
          ]
        }
      ]
    }
  }
}
```

Response - Too Far Past Event Time

```graphql
{
  "data": {
    "courierAssign": {
      "clientMutationId": "c3c047d9-e8e4-4431-b485-60c67fab8763",
      "delivery": null,
      "userErrors": [
        {
          "message": "Delivery cannot receive updates 2 hours past its event time",
          "path": [
            "input",
            "deliveryId"
          ]
        }
      ]
    }
  }
}
```
:::

### 400 Bad Request

When the `courierAssign` mutation fails due to an invalid `deliveryId` you can expect a HTTP 200  and the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "errors": [
    {
      "message": "Delivery not found",
      "path": [
        "courierAssign"
      ],
      "extensions": {
        "type": "request",
        "statusCode": 404,
        "serviceName": "delivery-public",
        "code": "DOWNSTREAM_SERVICE_ERROR",
        "exception": {
          "message": "Delivery not found",
          "locations": [
            {
              "line": 1,
              "column": 72
            }
          ],
          "path": [
            "courierAssign"
          ]
        }
      }
    }
  ],
  "data": {
    "courierAssign": null
  }
}
```
:::


[title] Optimization
[path] Restaurant Partner Integrations/General Menu Guidance/

# Photos

**Set expectations - and drive orders - by adding photos to your menu**. Studies show that menus with photos convert up to 30% more than menus without photos.

# Bundles

**Include catering packages, trays, and bundles.** Catering packages are the most-ordered option on ezCater.

# Individual Items

**Include individual items and boxed lunches.** 25% of ezCater orders include an individually packaged item.

Customers use the **individual packaging filter** often in Search to find restaurants that offer items that come individually wrapped.

# Drinks and Desserts

**Increase margins with drinks and desserts.** Almost 50% of customers order beverages when they are included on the menu.

# Dietary Restrictions

**Accommodate for dietary restrictions**. Customers frequently filter on ezCater for dietary options. Including vegan, gluten-free, or vegetarian entrees and sides on your menu ensures they’ll be able to find you.

Ensure you provide **all dietary information&#x20;**&#x66;or the items on your menu.

# Utensils and Packaging

**Offer free utensils and invest in packaging.&#x20;**&#x4F;ver 80% of ezCater orders are placed with restaurants who offer free utensils.

# Quality

**Put your best food forward.&#x20;**&#x43;hoose quality over quantity - more is not always better. Feature menu items that deliver well and can handle different catering formats.

# Resources

**For a deeper dive into these tips**, check out our General Menu Tips & Best Practices resource.

::File{src="https://archbee-doc-uploads.s3.amazonaws.com/CnBnWfHDNa9lZK7nmY_mG-TuHQT6sy2GRkNeny-noht-20250213-190612.pdf" label="ezCater General Menu Tips and Best Practices.pdf"}

# Live Examples

**To see these tips in action**, check out these great menu examples: 

1. [Ike’s Love & Sandwiches](https://www.ezcater.com/catering/ikes-place-oakland?fcv=1)
2. [Velvet Taco](https://www.ezcater.com/catering/velvet-taco-8?fcv=1)
3. [Curry Up Now](https://www.ezcater.com/catering/curry-up-now-san-mateo-3?fcv=1)
4. [California Pizza Kitchen](https://www.ezcater.com/catering/california-pizza-kitchen-boston-boylston-st?fulfillmentDetailId=7fe1d17f-a6e1-4741-b7e8-ee724cf6197c)
5. [TGI Fridays](https://www.ezcater.com/catering/tgi-fridays-chicago-e-erie-st?fcv=1)


[title] Other IdPs SSO Instructions - ezCater Marketplace & Meal Program
[path] Enterprise Account Integrations/SSO for Marketplace & Relish/

## Overview

Create TWO separate SAML setups in your IdP. Note the setups are identical, but the Meal Program adds a configuration to direct the user to a user sign-in URL. Without a redirection, the Meal Program app will not support IdP-initiated logins.

## ezCater Marketplace App

- Configure the following **SAML settings** in your IdP:
  - **Metadata URL:** [https://www.ezcater.com/saml/metadata.xml](https://www.ezcater.com/saml/metadata.xml)  
  - **Reply URL (ACS URL):** [https://www.ezcater.com/saml/consume](https://www.ezcater.com/saml/consume)
  - **Audience URI/Issuer/Entity ID:&#x20;**[ezcater.com](http://ezcater.com/)
    - *Do NOT add https or www*
  - Release first name, last name, and email. 
  - Use email as Name ID.

![]()

::Image[Meal Program **App**]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/QIoxSRk_KZ355hlJqswVh_ezcater-logo-bright-primary-symbol-300dpi.png" size="26" width="2084" height="1918" position="center" showCaption="false"}

- Configure the following **SAML settings** in your IdP:
  - **Metadata URL:** [https://www.ezcater.com/saml/metadata.xml](https://www.ezcater.com/saml/metadata.xml)  
  - **Reply URL (ACS URL):&#x20;**[https://www.ezcater.com/saml/consume](https://www.ezcater.com/saml/consume)
  - **Audience URI (SP Entity ID)/Issuer/Entity ID:** [ezcater.com](http://ezcater.com/)
    - *Do NOT add https or www*
  - Release first name, last name, and email.
  - Use email as Name ID.
- **Redirect Meal Program app&#x20;**&#x75;ser sign-in: 
  - **User sign-in URL:&#x20;**[https://login.ezcater.com/relish/sso/domain\_redirect?domain=mycompany.com](https://login.ezcater.com/relish/sso/domain_redirect?domain=mycompany.com) (change this to your domain)
    - *Example:&#x20;*[https://login.ezcater.com/relish/sso/domain\_redirect?domain=example.com](https://login.ezcater.com/relish/sso/domain_redirect?domain=example.com)
  - Without redirection, IdP-initiated login will not be supported. 
- Update the app logo with the image below:&#x20;



::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/CmQkluZKLFQtQcTEk-eNi_ezcater-logo-dark-primary-symbol-300dpi.png" size="30" width="2084" height="1918" position="center" showCaption="false"}

- Submit your metadata through the [ezCater/Meal Program  SSO Form](https://ezcaterforms.formstack.com/forms/ezcater_sso). These fields include:
  - **Your Domain(s)&#x20;**- any top level domain where the users receive emai&#x6C;*&#x20;Example: company.com*
  - **IdP SSO URL** - URL that ezCater will use to redirect a user to in order to authenticate with the IdP. *Example:&#x20;*[https://idp.example.com/sso/saml](https://idp.example.com/sso/saml)
  - **IdP Entity ID** - Unique identifier that ensures proper routing of authentication requests and responses. Also called Issuer. *Example:&#x20;*[https://idp.example.com/entity](https://idp.example.com/entity)
  - **Public Certificate&#x20;**- Also known as a digital certificate or an SSL/TLS certificate.


[title] Subscription Create
[path] API for Restaurant Partners/Subscription API/

# Creating Subscriptions

**Subscriptions** are how the **Subscriber** determines what events it needs to send out notifications for. Once you’ve created your **Subscriber**, you can customize the sorts of information that you may want to pull into your integrated system(s).

To create your **Subscriptions** you will need to know the `UUID` of the caterer locations for which you want notifications to be sent across the integration. These can be retrieved by making a [Caterer List](docId\:laoMLO-PM8Bz0WzIZ99hV) query. For each location, you will need to create a **Subscription** for every event you want to receive notifications for. As the integration functionality expands, there may be additional subscription options as well!

We recommend exploring [EventEntity](docId:_6fu5DGR5rPbWAT27Pcxz) and [EventKey](docId:_6fu5DGR5rPbWAT27Pcxz) to determine which available values are going to be useful for meeting your needs. You can find examples of how these subscriptions might look below.

Once your subscriptions are set up, you should now receive Subscription Notifications at the `webhookUrl` that was specified during [Subscriber Create](docId\:WZ2JpT1M-xiN8K7F58eKb).

:::hint{type="info"}
If you need to change the `webhookUrl`, you can use the [Subscriber Update](docId\:FNKr2TOw6HWaYCRgw37BP)  mutation to change the `webhookUrl` and/or `name` of your Subscriber.
:::

## Mutation

:::CodeblockTabs
Mutation

```graphql
mutation CreateSubscription($subscriptionParams: CreateSubscriptionFields!) {
  createSubscription(subscriptionParams: $subscriptionParams) {
    subscription {
      eventEntity
      eventKey
      parentEntity
      parentId
      subscriberId
    }
  }
}
```
:::

### Variables

:::hint{type="info"}
If you need your `subscriberId` you can run the [Subscriber List](docId:9DzcbPmXX-vinLGLpRqhR)  query.
:::

:::CodeblockTabs
Variables - Order Accepted

```graphql
{
  "subscriptionParams": {
    "eventEntity": "Order",
    "eventKey": "accepted",
    "parentEntity": "Caterer",
    "parentId": "ezcater-caterer-id",
    "subscriberId": "your-subscriber-id"
  }
}
```

Variables - Menu Updated

```graphql
{
  "subscriptionParams": {
    "eventEntity": "Mennu",
    "eventKey": "updated",
    "parentEntity": "Caterer",
    "parentId": "ezcater-caterer-id",
    "subscriberId": "your-subscriber-id"
  }
}
```

Variables - MenuCreationRequest Succeeded

```graphql
{
  "subscriptionParams": {
    "eventEntity": "MenuCreationRequest",
    "eventKey": "succeeded",
    "parentEntity": "Caterer",
    "parentId": "ezcater-caterer-id",
    "subscriberId": "your-subscriber-id"
  }
}
```
:::

### Arguments

| Argument Name                                                                    | Description                                  |
| -------------------------------------------------------------------------------- | -------------------------------------------- |
| `subscriptionParams`: [CreateSubscriptionFields! ](docId:_6fu5DGR5rPbWAT27Pcxz)  | The input object for making new subscribers. |

### Return Type

Returns a [CreateSubscriptionPayload](docId:_6fu5DGR5rPbWAT27Pcxz).

## Successful Responses

When the `createSubscription` mutation succeeds you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "createSubscription": {
      "subscription": {
        "eventEntity": "Order",
        "eventKey": "accepted",
        "parentEntity": "Caterer",
        "parentId": "ezcater-caterer-id",
        "subscriberId": "your-subscriber-id"
      }
    }
  }
}
```
:::

## Failure Responses

When `createSubscription` mutation fails you can expect the response payload to look like:&#x20;

:::CodeblockTabs
Response

```graphql
{
  "errors": [
    {
      "message": "Subscription could not be created.",
      "path": [
        "createSubscription"
      ],
      "extensions": {
        "type": "summary",
        "serviceName": "external-events",
        "code": "DOWNSTREAM_SERVICE_ERROR",
        "exception": {
          "message": "Subscription could not be created.",
          "locations": [
            {
              "line": 1,
              "column": 96
            }
          ],
          "path": [
            "createSubscription"
          ]
        }
      }
    }
  ],
  "data": {
    "createSubscription": null
  }
}
```
:::

# Receiving Notifications

Once you have set up your integration, you will begin to receive **Event Subscription Notifications** for any **Subscriptions** you have set up. Notifications will be sent to the `webhookUrl` specified during **Subscriber** creation. The notifications will provide basic information about the event that occurred, but for detailed information, you can query the API.

:::CodeblockTabs
Notification

```graphql
{
  "id": "[uuid of the notification]",
  "parent_type": "Caterer",
  "parent_id": "[uuid of the caterer]",
  "entity_type": "[type of event]",
  "entity_id": "[uuid of the order]",
  "key": "[entity event key]",
  "created_at": "[time]",
  "occurred_at": "[time]",
  "updated_at": "[time]",
  "payload":null
}
```

Notification - Order Accepted

```graphql
{
  "id": "ezcater-notification-id",
  "parent_type": "Caterer",
  "parent_id": "ezcater-caterer-id",
  "entity_type": "Order",
  "entity_id": "your-ezcater-order-id",
  "key": "accepted",
  "created_at":  "2025-04-15 23:48:23 UTC",
  "occurred_at":  "2025-04-15 23:48:23 UTC",
  "updated_at":  "2025-04-15 23:48:23 UTC",
  "payload":null
}
```

Notification - Menu Updated

```graphql
{
  "id": "ezcater-notification-id",
  "parent_type": "Caterer",
  "parent_id": "ezcater-caterer-id",
  "entity_type": "Menu",
  "entity_id": "your-ezcater-menu-version-id",
  "key": "updated",
  "created_at":  "2025-04-15 23:48:23 UTC",
  "occurred_at":  "2025-04-15 23:48:23 UTC",
  "updated_at":  "2025-04-15 23:48:23 UTC",
  "payload":null
}
```

Notification - MenuCreationRequest Succeeded

```graphql
{
  "id": "ezcater-notification-id",
  "parent_type": "Caterer",
  "parent_id": "ezcater-caterer-id",
  "entity_type": "MenuCreationRequest",
  "entity_id": "your-ezcater-menu-creation-request-id",
  "key": "succeeded",
  "created_at":  "2025-04-15 23:48:23 UTC",
  "occurred_at":  "2025-04-15 23:48:23 UTC",
  "updated_at":  "2025-04-15 23:48:23 UTC",
  "payload":null
}
```
:::

## Validating Notifications

:::hint{type="info"}
It is recommended to validate that the webhook subscription notifications you received actually came from ezCater.
:::

The `X-Ezcater-Signature` header value consists of a `timestamp` and the `signature`, separated by a period. You can use the `timestamp` from this header, your `webhookSecret` value (from when you initially created the subscription), and the request `body` to verify this `signature`.

### Create a computed signature payload from the webhook request data

You need two pieces of information for this step:

- The `timestamp` from the `X-Ezcater-Signature` header, which is the first portion before the period
- The request `body`

Concatenate these two values using a period to obtain a computed signature payload. For example, in Ruby this would look something like:

```ruby
timestamp = x_ezcater_signature_header.split(“.”) [0]
computed_signature_payload = [timestamp.to_i, request.body].join(".")
```

### Compute an HMAC signature of the request data

You need two pieces of information for this step:

- The computed signature payload from Step 1
- The `webhookSecret` provided to you when you created your subscription

Compute an HMAC signature using your `webhookSecret` and the computed signature payload. For example, in Ruby this would look something like:

```ruby
signature = OpenSSL::HMAC.hexdigest("sha256", webhook_secret, computed_signature_payload)
```

### Compare the provided signature with the computed one

You need two pieces of information for this step:

- The computed HMAC signature from Step 2
- The provided signature from the webhook request

Compare the computed HMAC signature with the value after the period in the `X-Ezcater-Signature` header. If these two values match, the request is valid. If they do not match, the request may have been tampered with or originated from an unauthorized source.






[title] Menu Create
[path] API for Restaurant Partners/Menus API/

# Creating Menus

The `MenuCreate` mutation enables integrators to create market-ready location level menus. Due to the size of menu creation requests, when one is received we return a `menuCreationRequestId` and enqueue the menu to be processed asyncronously. The provided UUID can be used with the [Menu Creation Request](docId:75j30izdnOxMQTj6V1pfV) query to retrieve detailed information about the status of the specific menu creation request. To be automatically infromed when the request has completed and this information is available we recommend [Subscribing to Menu Notifications](docId\:gJAIaYwOUbUgVFI8lfy6E).

**Note:** Please make sure to validate the [Menu Schema Reference](https://api.ezcater.io/menu-schema-reference) before making your `MenuCreate` request.&#x20;

## Mutation

:::CodeblockTabs
Mutation

```graphql
mutation MenuCreate($menu: MenuInput!) {
  menuCreate(menu: $menu) {
    errors {
      details
      message
    }
    success
    menuCreationRequestId
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables

```graphql
{
  "menu": {
    "name": "Your Menu Name",
    "locationId": "ezcater-caterer-id",
    "posId": "your-menu-version-id",
    "startDate": "2025-05-01",
    "endDate": "2025-06-01",
    "categories": [
      {
        "name": "Pizzas",
        "posId": "pizzas-category-id",
        "sortOrder": 2,
        "description": "A selection of our famous pizzas",
        "itemPosIds": [
          "margherita-pizza-item-id"
        ]
      },
      {
        "name": "Desserts",
        "posId": "desserts-category-id",
        "sortOrder": 3,
        "description": "A selection of our amazing desserts",
        "itemPosIds": [
          "chocolate-cake-item-id"
        ]
      },
      {
        "name": "Drinks",
        "posId": "drinks-category-id",
        "sortOrder": 4,
        "description": null,
        "itemPosIds": [
          "assorted-sodas-item-id"
        ]
      }
    ],
    "items": [
      {
        "name": "Margherita Pizza",
        "posId": "margherita-pizza-item-id",
        "channels": ["MARKETPLACE"],
        "imageUrl": "https://your-domain.com/menu-item-images/margherita-pizza.jpg",
        "selections": [
          {
            "price": 16.75,
            "posId": "12-inch-pizza-item-selection-id",
            "size": "12\" Pizza",
            "serves": 2,
            "minCalories": 512,
            "maxCalories": 1024,
            "sortOrder": 1
          },
          {
            "price": 24.75,
            "posId": "16-inch-pizza-item-selection-id",
            "size": "16\" Pizza",
            "serves": 4,
            "minCalories": 512,
            "maxCalories": 1024,
            "sortOrder": 1
          },
          {
            "price": 32.75,
            "posId": "20-inch-pizza-item-selection-id",
            "size": "20\" Pizza",
            "serves": 8,
            "minCalories": 512,
            "maxCalories": 1024,
            "sortOrder": 1
          }
        ],
        "description": "Thin crust margherita pizza",
        "taxCategory": "PREPARED_FOOD",
        "quantityUnit": "PIZZA",
        "itemTypeTags": [],
        "optionPosIds": [
          "cheese-addon-options-id"
        ],
        "foodLabelingTags": ["POPULAR","VEGETARIAN"],
        "individualWrapStatus": "NEVER"
      },
      {
        "name": "Chocolate Cake",
        "posId": "chocolate-cake-item-id",
        "channels": ["MARKETPLACE"],
        "imageUrl": null,
        "selections": [
          {
            "price": 5.75,
            "posId": "chocolate-cake-item-selection-id",
            "size": "1",
            "serves": 5,
            "sortOrder": 1
          }
        ],
        "description": "Rich and creamy flourless dark chocolate cake",
        "taxCategory": "CAKES_AND_PIES",
        "quantityUnit": "CAKE",
        "itemTypeTags": ["DESSERT"],
        "optionPosIds": [],
        "foodLabelingTags": ["GLUTEN_FREE"]
      },
      {
        "name": "Assorted Sodas",
        "posId": "assorted-sodas-item-id",
        "channels": ["MARKETPLACE"],
        "imageUrl": null,
        "selections": [
          {
            "price": 2.75,
            "posId": "assorted-sodas-item-selection-id",
            "size": "2ltr Soda",
            "serves": 4,
            "sortOrder": 1
          }
        ],
        "description": "Assorted 2 liter soda bottles",
        "taxCategory": "SODA",
        "quantityUnit": "TWO_LITER",
        "itemTypeTags": ["DRINKS"],
        "optionPosIds": [
          "soda-options-id"
        ],
        "foodLabelingTags": ["GLUTEN_FREE", "VEGAN", "VEGETARIAN"]
      }
    ],
    "options": [
      {
        "name": "Cheese Addon",
        "posId": "cheese-addon-options-id",
        "catererLabel": "Cheese",
        "choicePosIds": [
          "feta-choice-id",
          "parmigiano-reggiano-choice-id",
          "parmesan-choice-id"
        ],
        "customerPrompt": "Add Additional Cheese?",
        "maxChoiceSelections": null,
        "minChoiceSelections": 2
      },
      {
        "name": "Soda",
        "posId": "soda-options-id",
        "catererLabel": "Soda",
        "choicePosIds": [
          "brand-name-soda-choice-id",
          "diet-brand-name-soda-choice-id"
        ],
        "customerPrompt": "Select Soda",
        "maxChoiceSelections": 1,
        "minChoiceSelections": 1
      }
    ],
    "choices": [
      {
        "name": "Feta",
        "posId": "feta-choice-id",
        "selections": [
          {
            "price": 1.75,
            "posId": "feta-choice-12-inch-selection-id",
            "sortOrder": 1
          },
          {
            "price": 3.75,
            "posId": "feta-choice-16-inch-selection-id",
            "sortOrder": 2
          },
          {
            "price": 5.75,
            "posId": "feta-choice-20-inch-selection-id",
            "sortOrder": 3
          }
        ],
        "description": "Feta cheese",
        "choiceTypeTags": [],
        "foodLabelingTags": ["VEGETARIAN"],
        "enableSubQuantities": false
      },
      {
        "name": "Parmigiano Reggiano",
        "posId": "parmigiano-reggiano-choice-id",
        "selections": [
          {
            "price": 1.75,
            "posId": "parmigiano-reggiano-choice-12-inch-selection-id",
            "sortOrder": 1
          },
          {
            "price": 3.75,
            "posId": "parmigiano-reggiano-choice-16-inch-selection-id",
            "sortOrder": 2
          },
          {
            "price": 5.75,
            "posId": "parmigiano-reggiano-choice-20-inch-selection-id",
            "sortOrder": 3
          }
        ],
        "description": "Parmigiano Reggiano cheese",
        "choiceTypeTags": [],
        "foodLabelingTags": ["VEGETARIAN"],
        "enableSubQuantities": false
      },
      {
        "name": "Parmesan",
        "posId": "parmesan-choice-id",
        "selections": [
          {
            "price": 1.75,
            "posId": "parmesan-choice-12-inch-selection-id",
            "sortOrder": 1
          },
          {
            "price": 3.75,
            "posId": "parmesan-choice-16-inch-selection-id",
            "sortOrder": 2
          },
          {
            "price": 5.75,
            "posId": "parmesan-choice-20-inch-selection-id",
            "sortOrder": 3
          }
        ],
        "description": "Parmesan cheese",
        "choiceTypeTags": [],
        "foodLabelingTags": ["VEGETARIAN"],
        "enableSubQuantities": false
      },
      {
        "name": "Brand Name Soda",
        "posId": "brand-name-soda-choice-id",
        "selections": [
          {
            "price": 0.0,
            "posId": "brand-name-soda-selection-id",
            "sortOrder": 1
          }
        ],
        "description": "Refreshing Brand Name Soda",
        "choiceTypeTags": ["DRINKS"],
        "foodLabelingTags": [],
        "enableSubQuantities": false
      },
      {
        "name": "Diet Brand Name Soda",
        "posId": "diet-brand-name-soda-choice-id",
        "selections": [
          {
            "price": 0.0,
            "posId": "diet-brand-name-soda-choice-selection-id",
            "sortOrder": 1
          }
        ],
        "description": "Refreshing Diet Brand Name Soda",
        "choiceTypeTags": ["DRINKS"],
        "foodLabelingTags": [],
        "enableSubQuantities": false
      }
    ]
  }
}
```

Variables - NULL

```graphql
{
  "menu": {
    "name": null,
    "locationId": null,
    "posId": null,
    "startDate": null,
    "endDate": null,
    "categories": [
      {
        "description": null,
        "itemPosIds": null,
        "name": null,
        "posId": null,
        "sortOrder": null
      }
    ],
    "items": [
      {
        "catererNote": null,
        "channels": null,
        "dayBeforeCutoffTime": null,
        "description": null,
        "description2": null,
        "foodLabelingTags": null,
        "imageUrl": null,
        "individualWrapStatus": null,
        "itemTypeTags": null,
        "leadTime": null,
        "name": null,
        "optionPosIds": null,
        "posId": null,
        "quantityOptions": null,
        "quantityUnit": null,
        "selections": [
          {
            "maxCalories": null,
            "minCalories": null,
            "posId": null,
            "price": null,
            "serves": null,
            "size": null,
            "sortOrder": null
          }
        ],
        "selectionPrompt": null,
        "sizeLabel": null,
        "sortOrder": null,
        "taxCategory": null,
        "vegetarianOption": null
      }
    ],
    "options": [
      {
        "catererLabel": null,
        "choicePosIds": null,
        "customerPrompt": null,
        "maxChoiceSelections": null,
        "minChoiceSelections": null,
        "name": null,
        "posId": null
      }
    ],
    "choices": [
      {
        "catererNote": null,
        "choiceTypeTags": null,
        "defaultChoice": null,
        "description": null,
        "enableSubQuantities": null,
        "foodLabelingTags": null,
        "name": null,
        "posId": null,
        "selections": [
          {
            "posId": null,
            "price": null,
            "sortOrder": null
          }
        ],
        "sortOrder": null
      }
    ]
  }
}
```
:::

### Arguments

| Argument Name                                        | Description                           |
| ---------------------------------------------------- | ------------------------------------- |
| `menu`: [MenuInput! ](docId\:IbvUQPK0mwpAa9DSKEujY)  | Input object for creating a new menu. |

### Return Type

Returns a [MenuCreatePayload](docId\:IbvUQPK0mwpAa9DSKEujY).&#x20;

## Success Response

When the `menuCreate` mutation succeeds you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "menuCreate": {
      "errors": [],
      "menuCreationRequestId": "your-ezcater-menu-creation-request-id",
      "success": true
    }
  }
}
```
:::

## Failure Response

### Not authenticated

When an the user is unable to be authenticated.

:::CodeblockTabs
Response

```graphql
{
  "errors": [
    {
      "message": "Not authenticated.",
      "extensions": {
        "code": "ERR_UNAUTHENTICATED"
      }
    }
  ]
}
```
:::

### 400 Bad Request

When the `menuCreate` mutation fails due to bad user input you can expect a HTTP 400 Bad Request and the response payload to look like:

:::CodeblockTabs
Response - Required Field

```graphql
{
  "errors": [
    {
      "message": "Variable \"$menu\" got invalid value { name: \"Your Menu Name\", locationId: \"ezcater-caterer-id\", posId: \"your-menu-version-id\", startDate: \"2025-04-16\", endDate: \"2025-04-26\", items: [[Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], ... 11 more items], options: [[Object], [Object], [Object], [Object], [Object], [Object], [Object]], choices: [[Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], ... 7 more items] }; Field \"categories\" of required type \"[CategoryInput!]!\" was not provided.",
      "extensions": {
        "code": "BAD_USER_INPUT"
      }
    }
  ]
}
```

Response - Invalid Field Value

```graphql
{
  "errors": [
    {
      "message": "Variable \"$menu\" got invalid value null at \"menu.items[1].selections[0].price\"; Expected non-nullable type \"Float!\" not to be null.",
      "extensions": {
        "code": "BAD_USER_INPUT"
      }
    }
  ]
}
```
:::


[title] Meal Program Menu Set Up
[path] Restaurant Partner Integrations/Olo Rails Integration/

# Meal Program Menu Set Up

We are able to support menu syncing with your Meal Program locations with some caveats:
Meal Program menus and items need to be tagged according to these guidelines.

Like Marketplace orders, Meal Program orders will need to be sent through the API, but may fail due to “Relish Finalized” status happening \~90 minutes prior to the customer’s requested event time. Usage of ezCater specific menu items in Olo can assist with a specific lead time for the Meal Program items.&#x20;

This timing is an estimate and dependent on:

- Brand’s set required “Relish Finalized” timing
- Customer’s distance from location
- Dispatch pick-up time if applicable

**Item level:**

- **RelishChannel**= T (required)
- **Marketplacechannel**=T (Required only if items will be shared between Marketplace & Meal Program, otherwise the item will only be available on Meal Program)
  - RelishChannel=T can be used by itself or in combination with Marketplacechannel=T.&#x20;
    - Marketplacechannel= T cannot be standalone.&#x20;
- **CateringServeSize** (required)
- **TaxCategory** (required) 
- **QuantityUnit** (required) 
- **FoodLabelingTags** (required when applicable)
- **ItemTypeTags** (required when applicable)

**Choice Level:**

- **FoodLabelingTags** (required when applicable)
- **ChoiceTypeTags** for Drinks, Desserts\* (required when applicable)
  - This is needed for tracking and upsell opportunities 
- Sides: **INDIVIDUALLY\_PACKAGED\_RELISH\_SIDE** = T. (required when applicable)
  - This is only for printing an additional label.

**Meal Program Tagging Logic**

- When there is an item that is not a part of the main item and will not come in or on the ordered item, we will require “INDIVIDUALLY\_PACKAGED\_RELISH\_SIDE = T”. 
  - For example, if there is a bowl being ordered and there is the ability to add mac and cheese as a side to the item at an additional cost, the mac and cheese would not come inside the bowl, so it will need to be tagged in order to generate another label. 
- ChoiceTypeTags will also generate another label for Drinks or Desserts that come with the package. 
- If you duplicate/ add menu items specifically for Meal Program, Utensils are NOT required for Meal Program items. 

[title] Menu Schema Reference
[path] API for Restaurant Partners/Menus API/

# Menu Schema Reference

## Objects

### MenuCreatePayload

Return type of MenuCreate.

| Field Name                                                              | Description                                                                       |
| ----------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| `errors`:  [\[MenuCreationException!\]!](docId\:IbvUQPK0mwpAa9DSKEujY)  | A collection of errors generated when trying to create a menu.                    |
| `menuCreationRequestId` : [UUID](docId\:IbvUQPK0mwpAa9DSKEujY)          | A unique identifier for the specific menu creation request.                       |
| `success`: [Boolean!](docId\:IbvUQPK0mwpAa9DSKEujY)                     | A boolean indicating whether the menu creation request was received successfully. |

### MenuCreationException

An exception that occurred when trying to create a menu.

| Field Name                                         | Description                                            |
| -------------------------------------------------- | ------------------------------------------------------ |
| `details`: [JSON](docId\:IbvUQPK0mwpAa9DSKEujY)    | A list of more details related to an error or warning. |
| `message`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)  | A warning or error message.                            |

:::CodeblockTabs
Example

```graphql
{
  "details": {
    "source": "categories",
    "source_name": "Pizzas",
    "source_pos_id": "pizzas-category-id",
    "reference_type": "items",
    "referenced_pos_id": "margherita-pizza-item-id"
  },
  "message": "Referenced entity is not defined"
}
```
:::

### MenuCreationRequest

An object to describe the status of a MenuCreationRequest.

| Field Name                                                              | Description                                                         |
| ----------------------------------------------------------------------- | ------------------------------------------------------------------- |
| `errors`: [\[MenuCreationException!\]](docId\:IbvUQPK0mwpAa9DSKEujY)    | The collection of errors generated by this `MenuCreationRequest`.   |
| `menuUuid`: [ID](docId\:IbvUQPK0mwpAa9DSKEujY)                          | The uuid of the created menu                                        |
| `outcome`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)                       | An evaluation of the aggregate outcomes of all the steps            |
| `status`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)                        | The present status of the MCR                                       |
| `warnings`: [\[MenuCreationException!\]](docId\:IbvUQPK0mwpAa9DSKEujY)  | The collection of warnings generated by this `MenuCreationRequest`. |

:::CodeblockTabs
Example

```graphql
{
  "errors": [MenuCreationException!],
  "menuUuid": "ezcater-menu-id",
  "outcome": "success",
  "status": "complete",
  "warnings": [MenuCreationException!]
}
```
:::

## Inputs

:::hint{type="info"}
When creating a menu, each instance of a menu entity - category, item, option and choice - must have a different external `posId` if they have different names, prices, option groups etc.
:::

### CategoryInput

A section of the menu

| Field Name                                                 | Description                                                             |
| ---------------------------------------------------------- | ----------------------------------------------------------------------- |
| `description`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)      | A description providing more info about this category for users.        |
| `itemPosIds`: [\[String!\]!](docId\:IbvUQPK0mwpAa9DSKEujY) | A list of `item.posId`'s to be included within this Category.           |
| `name`: [String!](docId\:IbvUQPK0mwpAa9DSKEujY)            | A human friendly name to be displayed for this category.                |
| `posId`: [String!](docId\:IbvUQPK0mwpAa9DSKEujY)           | A client supplied category id to easily match between systems.          |
| `sortOrder`: [Int!](docId\:IbvUQPK0mwpAa9DSKEujY)          | A number to determine where in the menu the category will be displayed. |

:::CodeblockTabs
Example

```graphql
{
  "name": "Pizzas",
  "posId": "margherita-pizza-item-id",
  "sortOrder": 2,
  "description": "A selection of our famous pizzas",
  "itemPosIds": [
    "margherita-pizza-item-selection-id"
  ]
}
```
:::

### ChoiceInput

The choices available for a given option.

| Field Name                                                                | Description                                                                         |
| ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `catererNote`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)                     | A label supplied by the caterer for internal use.                                   |
| `choiceTypeTags`: [\[EntityTypeTag!\]](docId\:IbvUQPK0mwpAa9DSKEujY)      | A list of `EntityTypeTag` enums that apply to this choice.                          |
| `defaultChoice`: [Boolean](docId\:IbvUQPK0mwpAa9DSKEujY)                  | Whether this choice should be selected if the customer makes no selections.         |
| `description`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)                     | A description providing information about this choice for users.                    |
| `enableSubQuantities`: [Boolean](docId\:IbvUQPK0mwpAa9DSKEujY) = false    | Enable the selection of what percentage of the order for which this choice applies. |
| `foodLabelingTags`: [\[FoodLabelingTag!\]](docId\:IbvUQPK0mwpAa9DSKEujY)  | A list of `FoodLabelingTag` enums that apply to this choice.                        |
| `name`: [String!](docId\:IbvUQPK0mwpAa9DSKEujY)                           | A human friendly name to be displayed for this choice                               |
| `posId`: [String!](docId\:IbvUQPK0mwpAa9DSKEujY)                          | A client supplied id to easily match between systems                                |
| `selections`: [\[ChoiceSelectionInput!\]!](docId\:IbvUQPK0mwpAa9DSKEujY)  | A collection of price selections to customize this item.                            |
| `sortOrder`: [Int](docId\:IbvUQPK0mwpAa9DSKEujY)                          | An integer to describe where in the option this choice should be displayed.         |

:::CodeblockTabs
Example

```graphql
{
  "name": "Parmigiano Reggiano",
  "posId": "parmigiano-reggiano-choice",
  "selections": [ChoiceSelectionInput!]!,
  "description": "Parmigiano Reggiano cheese",
  "choiceTypeTags": [],
  "foodLabelingTags": ["VEGETARIAN"],
  "enableSubQuantities": false
}
```
:::

### ChoiceSelectionInput

An object to describe the price increase for a choice depending on the Item selection modifier.

| Field Name                                        | Description                                                                 |
| ------------------------------------------------- | --------------------------------------------------------------------------- |
| `posId`: [String!](docId\:IbvUQPK0mwpAa9DSKEujY)  | A client supplied selection id to easily match between systems.             |
| `price`: [Float](docId\:IbvUQPK0mwpAa9DSKEujY)    | A price for this selection.                                                 |
| `sortOrder`: [Int!](docId\:IbvUQPK0mwpAa9DSKEujY) | An integer to describe where in the option this choice should be displayed. |

:::CodeblockTabs
Example

```graphql
{
  "price": 1.75,
  "posId": "parmigiano-reggiano-choice-12-inch-selection-id",
  "sortOrder": 1
},
{
  "price": 3.75,
  "posId": "parmigiano-reggiano-choice-16-inch-selection-id",
  "sortOrder": 2
},
{
  "price": 5.75,
  "posId": "parmigiano-reggiano-choice-20-inch-selection-id",
  "sortOrder": 3
}
```
:::

### ItemInput

An item on the menu

| Field Name                                                                    | Description                                                                                                                                                                                                                                                                                         |
| ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `catererNote`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)                         | An internal note providing additional information from the caterer about this item.                                                                                                                                                                                                                 |
| `channels`: [\[Channel!\]!](docId\:IbvUQPK0mwpAa9DSKEujY)                     | A list of ezCater ordering `Channel` enums for which this item is available.                                                                                                                                                                                                                        |
| `dayBeforeCutoffTime`: [Hour](docId\:IbvUQPK0mwpAa9DSKEujY)                   | A `Hour` enum indicating the day before cutoff time after which this item cannot be added to a next day order. Provide *either* `leadTime` or `dayBeforeCutoffTime`.                                                                                                                                |
| `description`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)                         | A description providing information about this item for users.                                                                                                                                                                                                                                      |
| `description2`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)                        | An additional description providing more information about this item for users.                                                                                                                                                                                                                     |
| `foodLabelingTags`: [\[FoodLabelingTag!\]](docId\:IbvUQPK0mwpAa9DSKEujY)      | A list of `FoodLabelingTag` enums that apply to this item.                                                                                                                                                                                                                                          |
| `imageUrl`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)                            | A link to an image to display for the item. Please make sure that the referenced file has one of the following extensions: `gif`, `jpg`, `jpeg`, `png`                                                                                                                                              |
| `individualWrapStatus`: [IndividualWrapStatus](docId\:IbvUQPK0mwpAa9DSKEujY)  | An `IndividualWrapStatus` enum indicating whether this item is individually.                                                                                                                                                                                                                        |
| `itemTypeTags`: [\[EntityTypeTag!\]](docId\:IbvUQPK0mwpAa9DSKEujY)            | A list of `EntityTypeTag` enums that apply to this item.                                                                                                                                                                                                                                            |
| `leadTime`: [Int](docId\:IbvUQPK0mwpAa9DSKEujY)                               | A number in minutes indicating the minimum amount of time required to prepare this item. Provide *either* `leadTime` or `dayBeforeCutoffTime` not both.                                                                                                                                             |
| `name`: [String!](docId\:IbvUQPK0mwpAa9DSKEujY)                               | A human friendly name to be displayed for this item.                                                                                                                                                                                                                                                |
| `optionPosIds`: [\[String!\]](docId\:IbvUQPK0mwpAa9DSKEujY)                   | A list of `option.posId`'s to be included within this item.                                                                                                                                                                                                                                         |
| `posId`: [String!](docId\:IbvUQPK0mwpAa9DSKEujY)                              | A client supplied item id to easily match between systems                                                                                                                                                                                                                                           |
| `quantityOptions`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)                     | A comma separated list of integers describing the quantities a customer can order. Some special codes are available:<br />* `>N` will generate a list of numbers from `N to 50`, then `55-95` in multiples of `5`.&#x20;
* `xN` will generate a list of numbers from `1 to 50` in multiples of `N`. |
| `quantityUnit`: [QuantityUnit](docId\:IbvUQPK0mwpAa9DSKEujY)                  | A `QuantityUnit` enum for a singular quantity of this item.                                                                                                                                                                                                                                         |
| `selectionPrompt`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)                     | An `ItemSelectionInput` type consisting of a collection of size and price selections to customize this item.                                                                                                                                                                                        |
| `selections`: [\[ItemSelectionInput!\]!](docId\:IbvUQPK0mwpAa9DSKEujY)        | An list of choices to customize an item. Usually used for size/price selection                                                                                                                                                                                                                      |
| `sizeLabel`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)                           | A size label for this item.                                                                                                                                                                                                                                                                         |
| `sortOrder`: [Int](docId\:IbvUQPK0mwpAa9DSKEujY)                              | A number to determine where in the category the item will be displayed.                                                                                                                                                                                                                             |
| `taxCategory`: [TaxCategory!](docId\:IbvUQPK0mwpAa9DSKEujY)                   | A `TaxCategory` enum that applies to this item.                                                                                                                                                                                                                                                     |
| `vegetarianOption`: [Boolean](docId\:IbvUQPK0mwpAa9DSKEujY)                   | An indicator to customers that they can expect some of the item selections will be vegetarian.                                                                                                                                                                                                      |

:::CodeblockTabs
Example

```graphql
{
  "name": "Margherita Pizza",
  "posId": "margherita-pizza-item-id",
  "channels": ["MARKETPLACE"],
  "imageUrl": "https://your-domain.com/menu-item-images/margherita-pizza.jpg",
  "selections": [ItemSelectionInput!],
  "description": "Thin crust margherita pizza",
  "taxCategory": "PREPARED_FOOD",
  "quantityUnit": "PIZZA",
  "itemTypeTags": [],
  "optionPosIds": [
    "cheese-addon-options-id"
  ],
  "foodLabelingTags": ["POPULAR","VEGETARIAN"],
  "individualWrapStatus": "NEVER"
}
```
:::

### ItemSelectionInput

An object to describe options for modifying an item selection

| Field Name                                         | Description                                                                  |
| -------------------------------------------------- | ---------------------------------------------------------------------------- |
| `maxCalories`: [Int](docId\:IbvUQPK0mwpAa9DSKEujY) | The maximum of a range to describe how many calories are in this selection.  |
| `minCalories`: [Int](docId\:IbvUQPK0mwpAa9DSKEujY) | The minimum of a range to describe how many calories are in this selection.  |
| `posId`: [String!](docId\:IbvUQPK0mwpAa9DSKEujY)   | A client supplied selection id to easily match between systems.              |
| `price`: [Float!](docId\:IbvUQPK0mwpAa9DSKEujY)    | A price for this selection.                                                  |
| `serves`: [Int](docId\:IbvUQPK0mwpAa9DSKEujY)      | An integer to describe how many people the selection serves.                 |
| `size`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)     | A human friendly string to describe the size of this selection.              |
| `sortOrder`: [Int!](docId\:IbvUQPK0mwpAa9DSKEujY)  | An integer to describe where in the list this selection should be displayed. |

:::CodeblockTabs
Example

```graphql
{
  "price": 16.75,
  "posId": "12-inch-pizza-item-selection-id",
  "size": "12\" Pizza",
  "serves": 2,
  "minCalories": 512,
  "maxCalories": 1024,
  "sortOrder": 1
},
{
  "price": 24.75,
  "posId": "16-inch-pizza-item-selection-id",
  "size": "16\" Pizza",
  "serves": 4,
  "minCalories": 512,
  "maxCalories": 1024,
  "sortOrder": 1
},
{
  "price": 32.75,
  "posId": "20-inch-pizza-item-selection-id",
  "size": "20\" Pizza",
  "serves": 8,
  "minCalories": 512,
  "maxCalories": 1024,
  "sortOrder": 1
}
```
:::

### MenuInput

Input object for creating a new menu

| Field Name                                                         | Description                                                                                                                                                                |
| ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `locationId`: [UUID!](docId\:IbvUQPK0mwpAa9DSKEujY)                | The ezCater caterer location UUID that this menu will be attached to. Caterer location UUID's can be retrieved using the [Caterer List](docId\:laoMLO-PM8Bz0WzIZ99hV) API. |
| `name`: [String!](docId\:IbvUQPK0mwpAa9DSKEujY)                    | A human friendly name for the menu.                                                                                                                                        |
| `posId`: [String!](docId\:IbvUQPK0mwpAa9DSKEujY)                   | A client supplied menu id to easily match between systems.                                                                                                                 |
| `startDate`: [Date!](docId\:IbvUQPK0mwpAa9DSKEujY)                 | A date when the menu will become active.                                                                                                                                   |
| `endDate`: [Date](docId\:IbvUQPK0mwpAa9DSKEujY)                    | A date when the menu will stop being active.                                                                                                                               |
| `categories`: [\[CategoryInput!\]!](docId\:IbvUQPK0mwpAa9DSKEujY)  | A `CategoryInput` type consisting of a collection of categories for the menu.                                                                                              |
| `items`: [\[ItemInput!\]!](docId\:IbvUQPK0mwpAa9DSKEujY)           | An `ItemInput` type consisting of a collection of items available within categories.                                                                                       |
| `options`: [\[OptionInput!\]](docId\:IbvUQPK0mwpAa9DSKEujY)        | An `OptionInput` type consisting of a collection of options available within items.                                                                                        |
| `choices`: [\[ChoiceInput!\]](docId\:IbvUQPK0mwpAa9DSKEujY)        | A `ChoiceInput` type consisting of a collection of choices available within options.                                                                                       |

:::CodeblockTabs
Example

```graphql
{
  "name": "Your Menu Name",
  "locationId": "ezcater-caterer-id",
  "posId": "your-menu-version-id",
  "startDate": "2024-01-01",
  "endDate": "2024-04-01",
  "categories": [CategoryInput!]!,
  "items": [ItemInput!]!,
  "options": [OptionInput!],
  "choices": [ChoiceInput!]
}
```
:::

### OptionInput

A choice to customize a menu item

| Field Name                                                   | Description                                                                        |
| ------------------------------------------------------------ | ---------------------------------------------------------------------------------- |
| `catererLabel`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)       | A label supplied by the caterer for internal use.                                  |
| `choicePosIds`: [\[String!\]!](docId\:IbvUQPK0mwpAa9DSKEujY) | A list of `choice.posId`'s to be included within this option.                      |
| `customerPrompt`: [String](docId\:IbvUQPK0mwpAa9DSKEujY)     | An alternative text to display to the customer.                                    |
| `maxChoiceSelections`: [Int](docId\:IbvUQPK0mwpAa9DSKEujY)   | The maximum number of selections a customer may choose. Leave `nil` for unlimited. |
| `minChoiceSelections`: [Int!](docId\:IbvUQPK0mwpAa9DSKEujY)  | The minimum number of selections a customer must choose.                           |
| `name`: [String!](docId\:IbvUQPK0mwpAa9DSKEujY)              | A human friendly name to be displayed for this option.                             |
| `posId`: [String!](docId\:IbvUQPK0mwpAa9DSKEujY)             | A client supplied option id to easily match between systems.                       |

:::CodeblockTabs
Example

```graphql
{
  "name": "Cheese Addon",
  "posId": "cheese-addon-options-id",
  "catererLabel": "Cheese",
  "choicePosIds": [
    "feta-choice-id",
    "parmigiano-reggiano-choice-id",
    "parmesan-choice-id"
  ],
  "customerPrompt": "Add Additional Cheese?",
  "maxChoiceSelections": 1,
  "minChoiceSelections": 1
}
```
:::

## Enums

### Channel

Ordering Channels in which certain menu items are available ezCater provides multiple channels to present menu data.  The standard entry is `MARKETPLACE` however restaurant partners participating in the Meal Program it may be appropriate to use `RELISH`. Applied to the `channels` type as the field's return type.

| Enum Name     | Description                                                      |
| ------------- | ---------------------------------------------------------------- |
| `MARKETPLACE` | Determines whether a menu item is available on the Marketplace.  |
| `RELISH`      | Determines whether a menu item is available on the Meal Program. |

### EntityTypeTag

Tags applied to either an item or a choice to further describe the menu entity. Applied to the `itemTypeTags` and `choiceTypeTags` types as the field's return type. Please ensure all beverage and dessert items are tagged accordingly, including items that include a drink or dessert.

| Enum Name                           | Description                                                                                                                                              |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DESSERT`                           | Identifies a menu entity as a dessert.                                                                                                                   |
| `DRINKS`                            | Identifies a menu entity as a drink.                                                                                                                     |
| `ICE`                               | Identifies a menu entity as ice.                                                                                                                         |
| `INDIVIDUALLY_PACKAGED_RELISH_SIDE` | Identifies a menu entity as a individually packaged side when participating in the Meal Program channel. This tag is only relevant for `choiceTypeTags`. |
| `UTENSILS`                          | Identifies a menu entity as a utensil.                                                                                                                   |

### FoodLabelingTag

Tags applied to either an item or a choice to classifying the menu entity. Applied to the  `foodLableingTags` type as the field's return type.

| Enum Name     | Description                                                                                                                                                                |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AWARD`       | This identifies that the food item has received some form of recognition or award for its quality or taste.                                                                |
| `GLUTEN_FREE` | This identifies food items that do not contain gluten, making them suitable for individuals with gluten intolerance or celiac disease.                                     |
| `HALAL`       | This identifies that the food item is prepared following Islamic dietary laws, making it permissible for consumption by individuals who follow halal dietary restrictions. |
| `HEALTHY`     | This identifies that the food item is recognized for its health benefits, which could include being low in fat, sugar, or sodium, and rich in essential nutrients.         |
| `KOSHER`      | This identifies that the food item conforms to the dietary laws of kashrut, which are applicable to individuals who follow Jewish dietary guidelines.                      |
| `POPULAR`     | This identifies that the food items that are frequently ordered and favored by customers, indicating their popularity.                                                     |
| `SPICY`       | This identifies food items that are hot and spicy, catering to customers who prefer a bit of heat in their meals.                                                          |
| `STAR`        | This identifies food items that are highly recommended or signature dishes, often highlighted for their exceptional taste or quality.                                      |
| `VEGAN`       | This identifies that the food item contains no animal products, making it suitable for vegan diets.                                                                        |
| `VEGETARIAN`  | This identifies that the food items that contain no meat, making them suitable for vegetarian diets, although they may still include animal products like dairy or eggs.   |

### Hour

Hours of the day. Applied to the `dayBeforeCutoffTime` type as the field's return type.

| Enum Name   | Description |
| ----------- | ----------- |
| `EIGHT_AM`  |             |
| `EIGHT_PM`  |             |
| `ELEVEN_AM` |             |
| `ELEVEN_PM` |             |
| `FIVE_AM`   |             |
| `FIVE_PM`   |             |
| `FOUR_AM`   |             |
| `FOUR_PM`   |             |
| `NINE_AM`   |             |
| `NINE_PM`   |             |
| `ONE_AM`    |             |
| `ONE_PM`    |             |
| `SEVEN_AM`  |             |
| `SEVEN_PM`  |             |
| `SIX_AM`    |             |
| `SIX_PM`    |             |
| `TEN_AM`    |             |
| `TEN_PM`    |             |
| `THREE_AM`  |             |
| `THREE_PM`  |             |
| `TWELVE_AM` |             |
| `TWELVE_PM` |             |
| `TWO_AM`    |             |
| `TWO_PM`    |             |

### IndividualWrapStatus

Describes whether food items are or could be individually wrapped. Applied to the `individualWrapStatus` type as the field's return type.

| Enum Name  | Description                                                                                           |
| ---------- | ----------------------------------------------------------------------------------------------------- |
| `NEVER`    | This status indicates that the individual wrap option is never be available for the food item.        |
| `POSSIBLE` | This status indicates that the individual wrap option is available for the food item but is optional. |
| `WRAP`     | This status indicates that the individual wrap option will be used for the food item.                 |

### &#x20;QuantityUnit

Describes the unit for a singular quantity of an item. Applied to the `quantityUnit` type as the field's return type.

| Enum Name     | Description |
| ------------- | ----------- |
| `BAR`         |             |
| `BOTTLE`      |             |
| `BOWL`        |             |
| `BOX`         |             |
| `BUFFET`      |             |
| `CAKE`        |             |
| `CAN`         |             |
| `CARAFE`      |             |
| `DOZEN`       |             |
| `FOOT`        |             |
| `FULL_PAN`    |             |
| `GALLON`      |             |
| `HALF_GALLON` |             |
| `HALF_PAN`    |             |
| `ITEM`        |             |
| `KIT`         |             |
| `LITER`       |             |
| `PACKAGE`     |             |
| `PAN`         |             |
| `PERSON`      |             |
| `PIE`         |             |
| `PIECE`       |             |
| `PINT`        |             |
| `PIZZA`       |             |
| `PLATTER`     |             |
| `POUND`       |             |
| `QUART`       |             |
| `ROLL`        |             |
| `SIX_PACK`    |             |
| `SKEWER`      |             |
| `SLIDER`      |             |
| `TACO`        |             |
| `TRAY`        |             |
| `TWELVE_PACK` |             |
| `TWO_LITER`   |             |

### TaxCategory

Categories used to determine how items should be taxed. Applied to the `taxCategory` type as the field's return type.

| Enum Name                  | Description                                                                                          |
| -------------------------- | ---------------------------------------------------------------------------------------------------- |
| `BAKERY_ITEMS`             | Items that primarily include baked goods such as bread, pastries, and other bakery products.         |
| `CAKES_AND_PIES`           | Desserts specifically categorized as cakes and pies.                                                 |
| `CANDY`                    | Items that include various types of confectionery and candy.                                         |
| `CHIPS_AND_SNACKS`         | Snack foods that primarily include chips and other similar snack items.                              |
| `COFFEE_TEA_MILK`          | Beverages classified under coffee, tea, and milk.                                                    |
| `DRESSINGS_AND_CONDIMENTS` | Various types of dressings and condiments used to accompany meals.                                   |
| `EXEMPT`                   | Items that are exempt from sales tax under the given regulations.                                    |
| `ICE_CREAM`                | Frozen desserts categorized specifically as ice cream.                                               |
| `MISCELLANEOUS`            | Items that do not fit into other specific categories and are grouped as miscellaneous.               |
| `NON_SODA_DRINKS`          | Beverages that are not classified as soda, including juices, water, and other non-carbonated drinks. |
| `PREPARED_FOOD`            | Food items that are prepared and ready for consumption, often part of catering and meal services.    |
| `SANDWICHES`               | Items specifically identified as sandwiches.                                                         |
| `SODA`                     | Carbonated soft drinks.                                                                              |
| `WATER`                    | Bottled or packaged water.                                                                           |

## Scalars

### Boolean

The Boolean scalar type represents true or false.

### Date

ISO-8601 Date-only string, e.g. 2017-12-14

### Float

The Float scalar type represents signed double-precision fractional values as specified by IEEE 754.

### ID

The ID scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as "4") or integer (such as 4) input value will be accepted as an ID.

### Int

The Int scalar type represents non-fractional signed whole numeric values. Int can represent values between `-(2^31)` and `2^31 - 1`.

### JSON

Represents untyped JSON

### String

The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.

### UUID

Universally unique identifier as defined by RFC 4122


[title] Migration Guide
[path] API for Restaurant Partners/Delivery API/

# Delivery API Migration

There have been notable changes to the Delivery API to support multiple couriers per delivery and a new requirement for specifying the delivery provider source. This guide outlines how to handle these changes.

## Deadline

:::hint{type="danger"}
**January 5th, 2026**
:::

To meet the January 5th, 2026 deadline, your integration **must** be updated to use the new [providerSource](docId:7gV344RnWmuokNj9u4rW7) and [providerName](docId:7gV344RnWmuokNj9u4rW7) arguments when assigning a courier through [courierAssign](docId:7gV344RnWmuokNj9u4rW7), [courierEventCreate](docId:7gV344RnWmuokNj9u4rW7), [courierImagesCreate](docId:7gV344RnWmuokNj9u4rW7), and [courierTrackingEventCreate](docId:7gV344RnWmuokNj9u4rW7).

Migrating to use `courierId` for mutations [courierEventCreate](docId:7gV344RnWmuokNj9u4rW7), [courierImagesCreate](docId:7gV344RnWmuokNj9u4rW7),  [courierTrackingEventCreate](docId:7gV344RnWmuokNj9u4rW7), and [courierUnassign](docId:7gV344RnWmuokNj9u4rW7) is **not** required for this deadline but is *highly* recommended as the next step in your integration upgrade.

## Action Required by Deadline

The `deliveryServiceProvider` argument on [courierAssign](docId:7gV344RnWmuokNj9u4rW7) is now deprecated. It has been replaced by two new fields that must be provided within the courier object itself:

- [providerSource](docId:7gV344RnWmuokNj9u4rW7): A required enum (`IN_HOUSE` or `THIRD_PARTY`) that specifies who is fulfilling the delivery.
- [providerName](docId:7gV344RnWmuokNj9u4rW7): The name of the service provider. This is only necessary/required if `providerSource` is `THIRD_PARTY` (e.g., "DoorDash", "Uber Direct").

You must send these new arguments when using [courierEventCreate](docId:7gV344RnWmuokNj9u4rW7), [courierImagesCreate](docId:7gV344RnWmuokNj9u4rW7),  [courierTrackingEventCreate](docId:7gV344RnWmuokNj9u4rW7), and [courierUnassign](docId:7gV344RnWmuokNj9u4rW7) .

## A Note on Changes

To assist with the January 5th, 2026 deadline, the new `providerSource` and `providerName` arguments have also been added to the [CourierInput](docId:7gV344RnWmuokNj9u4rW7) object.

This was done to support integrations that have not yet migrated away from the deprecated inline courier assignment (i.e., you are still passing the `courier` object to [courierEventCreate](docId:7gV344RnWmuokNj9u4rW7), [courierImagesCreate](docId:7gV344RnWmuokNj9u4rW7),  [courierTrackingEventCreate](docId:7gV344RnWmuokNj9u4rW7), and [courierUnassign](docId:7gV344RnWmuokNj9u4rW7).

This change allows you to pass the new required `providerSource` and `providerName` arguments through the *deprecated courier argument*, enabling you to meet the deadline without immediately refactoring for the [Recommended Next Steps](docId\:CTwun8ZlRtVDOkn0jEr8J).

# Examples

## Migrating a courierAssign Call

This example shows the specific change required to meet the deadline.

:::CodeblockTabs
Before

```json
{
  "input": {
    "courier": {
      "id": "your-courier-id",
      "firstName": "Jane",
      "lastName": "Doe",
      "phone": "+16175551234"
    },
    "deliveryId": "ezcater-delivery-id",
    "deliveryServiceProvider": "DoorDash"
  }
}
```

After

```json
{
  "input": {
    "courier": {
      "id": "your-courier-id",
      "firstName": "Jane",
      "lastName": "Doe",
      "phone": "+16175551234",
      "providerName": "DoorDash",
      "providerSource": "THIRD_PARTY",
    },
    "deliveryId": "ezcater-delivery-id"
  }
}
```
:::

:::hint{type="info"}
**Note:&#x20;**`deliverySericeProvider` is removed and `providerName` and `providerSource` is added inside the `courier` object.&#x20;
:::

## Meeting the Deadline with courierEventCreate (Deprecated Flow)

```json
{
  "input": {
    "courier": {
      "id": "your-courier-id",
      "firstName": "Jane",
      "lastName": "Doe",
      "phone": "+16175551234",
      "providerSource": "IN_HOUSE"
    },
    "deliveryId": "ezcater-delivery-id",
    "eventType": "PICKED_UP",
    "occurredAt": "2025-11-01T22:03:03Z"
  }
}
```

While this path provides a bridge to compliance, we **strongly recommend** prioritizing the migration to the two-step process (only assigning couriers through `courierAssign` or `couriersAssign`) as outlined in the [Recommended Next Steps](docId\:CTwun8ZlRtVDOkn0jEr8J).

# Recommended Next Steps

## Migrating to courierId

This migration is **not** required for the January 5th, 2026 deadline but is the next step to fully modernize your integration.

Passing the courier object to mutations  [courierEventCreate](docId:7gV344RnWmuokNj9u4rW7), [courierImagesCreate](docId:7gV344RnWmuokNj9u4rW7),  [courierTrackingEventCreate](docId:7gV344RnWmuokNj9u4rW7), and [courierUnassign](docId:7gV344RnWmuokNj9u4rW7) will not be allowed in the near future. This means a courier **must** be created and assigned to a delivery *before* you can reference them in other operations.

## New Two-Step Process

Your integration must eventually be updated to follow this two-step process:

1. **Assign Courier(s):** Use `courierAssign` or `couriersAssign` to create/update and assign the courier(s) to the delivery.
2. **Perform Action:** Use the `courierId` from the prior step to call other mutations.

All courier creation, updates, and assignments are being centralized to `courierAssign` and `couriersAssign`.

# couriersAssign (The New Standard)

The new `couriersAssign` mutation is the standard for managing assignments.

**Behavior:** It accepts a list of `CourierAssignmentInput` objects.

- **Use Case:** Use this to set or overwrite the complete list of couriers. To remove all couriers, pass an empty list.

## Assigning Two couriers With couriersAssign

```json
{
  "input": {
    "couriers": [
      {
        "id": "courier-id-1",
        "firstName": "Jane",
        "lastName": "Doe",
        "phone": "+16175551234",
        "providerSource": "IN_HOUSE"
      },
      {
        "id": "courier-id-2",
        "firstName": "John",
        "lastName": "Smith",
        "phone": "+16175555678",
        "providerSource": "THIRD_PARTY",
        "providerName": "DoorDash"
      }
    ],
    "deliveryId": "ezcater-delivery-id"
  }
}
```

# courierAssign (Transition Mutation)

The existing `courierAssign` mutation is being phased out but has been updated to help you transition.

We've added a new optional boolean argument, `allowMultipleCouriers`. This is an opt-in flag for new behavior.

- **Legacy Behavior (omitted or&#x20;**`false`**):** The mutation replaces all existing couriers with the single courier provided.
- **New Behavior (**`true`**):** The mutation adds the provided courier to the delivery's existing list of assignments without removing others.

Once your application is ready to support multiple couriers, you should always pass `true` for `allowMultipleCouriers`.

## Handling New Error Responses

Migrating to the `courierId` argument introduces stricter validation and new potential errors. These errors will **only** happen when using the new `courierId` argument.

# Error Cases&#x20;

## Courier Does Not Exist

If the courier for the provided `courierId` does not exist, the mutation will fail.

```json
{
  "errors": [
    {
      "message": "Courier not found",
      "path": [
        "courierEventCreate"
      ],
      "extensions": {
        "type": "request",
        "statusCode": 404,
        "serviceName": "delivery-public",
        "code": "DOWNSTREAM_SERVICE_ERROR",
        "exception": {
          "message": "Courier not found",
          "locations": [
            {
              "line": 1,
              "column": 72
            }
          ],
          "path": [
            "courierEventCreate"
          ]
        }
      }
    }
  ],
  "data": {
    "courierEventCreate": null
  }
}
```

## &#x20;Courier Is Not Assigned

If the courier exists but has not been assigned to the specified `deliveryId`, the mutation will fail.

```json
{
  "errors": [
    {
      "message": "Courier assignment not found",
      "path": [
        "courierEventCreate"
      ],
      "extensions": {
        "type": "request",
        "statusCode": 404,
        "serviceName": "delivery-public",
        "code": "DOWNSTREAM_SERVICE_ERROR",
        "exception": {
          "message": "Courier assignment not found",
          "locations": [
            {
              "line": 1,
              "column": 72
            }
          ],
          "path": [
            "courierEventCreate"
          ]
        }
      }
    }
  ],
  "data": {
    "courierEventCreate": null
  }
}
```


[title] Order Accept
[path] API for Restaurant Partners/Orders API/

# Accepting Orders

Accepting an **Order** is a simple mutation that requires only the `uuid`for the order that’s to be accepted. To be automatically be informed when an order has been `submitted` and can be `accepted` please see [Subscribing to Order Notifications](docId\:RwXIHCSBkoW9Wv238Z7mh) .

## Mutation

:::CodeblockTabs
Mutation

```graphql
mutation AcceptOrder($orderId: ID!, $acceptModification: Boolean) {
  acceptOrder(orderId: $orderId, acceptModification: $acceptModification) {
    order {
      uuid
      lifecycle {
        orderIsCurrently
      }
    }
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables - Initial Acceptance

```graphql
{
  "orderId": "your-ezcater-order-id",
  "acceptModification": false
}
```

Variables - Modification Acceptance

```graphql
{
  "orderId": "your-ezcater-order-id",
  "acceptModification": true
}
```
:::

### Arguments

| Argument Name                                                         | Description                                                                                                                                         |
| --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `orderId`: [ID!](docId\:U2UigsYO0gfPXj-5tuif0)                        | The ezCater order UUID that is provided within the payload of `Order` subscription notifications.                                                   |
| `acceptModification`: [Boolean](docId\:U2UigsYO0gfPXj-5tuif0) = false | A boolean representing whether a modification to an order is accepted. `acceptModification: true` is required when accepting an order modification. |

### Return Type

Returns an [AcceptOrderPayload](docId\:U2UigsYO0gfPXj-5tuif0).

## Successful Responses

When the `AcceptOrder` mutation succeeds you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "acceptOrder": {
      "order": {
	    "uuid": "your-ezcater-order-id",
        "lifecycle": {
          "orderIsCurrently": "accepted"
        }
      }
    }
  }
}
```
:::

:::hint{type="info"}
You will also receive the `accepted` order event notification shortly afterwards, if you choose to subscribe to it via [Subscription Create](docId\:YWDS1a-gxebJWknE8V90S).
:::

## Failure Responses

`AcceptOrder` calls may fail for a variety of reasons: the order not being found, or the feature not being enabled for your brand. In the event that an `AcceptOrder` call fails, one of the below errors may be returned.&#x20;

### 404 Couldn’t find Order

You will get a 404 error when the specified order couldn’t be found.

:::CodeblockTabs
Response

```graphql
{
  "errors": [
    {
      "message": "Couldn't find Order",
      "path": [
        "acceptOrder"
      ],
      "extensions": {
        "type": "request",
        "statusCode": 404,
        "serviceName": "orders-public",
        "code": "DOWNSTREAM_SERVICE_ERROR",
        "exception": {
          "message": "Couldn't find Order",
          "locations": [
            {
              "line": 1,
              "column": 54
            }
          ],
          "path": [
            "acceptOrder"
          ]
        }
      }
    }
  ],
  "data": {
    "acceptOrder": null
  }
}
```
:::

### 403 Unauthorized

You will get a 403 error when the API user account doesn’t have permission to perform this action for this caterer location.

:::CodeblockTabs
Response

```graphql
{
  "errors": [
    {
      "message": "You are not authorized to access this data",
      "path": [
        "acceptOrder"
      ],
      "extensions": {
        "type": "request",
        "statusCode": 403,
        "serviceName": "orders-public",
        "code": "DOWNSTREAM_SERVICE_ERROR",
        "exception": {
          "message": "You are not authorized to access this data",
          "locations": [
            {
              "line": 1,
              "column": 54
            }
          ],
          "path": [
            "acceptOrder"
          ]
        }
      }
    }
  ],
  "data": {
    "acceptOrder": null
  }
}
```
:::

### Feature Not Enabled (feature\_not\_enabled)

You will get this error if this API feature has not yet been enabled for your brand.

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "acceptOrder": null
  },
  "errors": [
    {
      "message": "Feature not enabled for the caterer associated with this order",
      "locations": [
        {
          "line": 4,
          "column": 3
        }
      ],
      "path": [
        "acceptOrder"
      ],
      "extensions": {
        "type": "summary",
        "code": "feature_not_enabled"
      }
    }
  ]
}
```
:::

### Invalid State Transition (invalid\_state\_transition)

You will get this error when the order is no longer in a valid state to be accepted (the order hasn’t been submitted yet; the customer may have canceled it; it may have already been accepted or rejected by API or one of the other channels for accepting/rejecting orders).

This error can also occur when attempting to accept an order modification without providing the argument `"acceptModification": true`.

:::CodeblockTabs
Response

```graphql
{
  "errors": [
    {
      "message": "Sorry, we were unable to accept this order.",
      "path": [
        "acceptOrder"
      ],
      "extensions": {
        "type": "summary",
        "code": "invalid_state_transition",
        "serviceName": "orders-public",
        "exception": {
          "message": "Sorry, we were unable to accept this order.",
          "locations": [
            {
              "line": 1,
              "column": 54
            }
          ],
          "path": [
            "acceptOrder"
          ]
        }
      }
    }
  ],
  "data": {
    "acceptOrder": null
  }
}
```
:::

##


[title] Subscribing to Menu Notifications
[path] API for Restaurant Partners/Menus API/

# Subscribing to Menu Notifications

Subscribing to **Menu** and **Menu Creation Request** notifications works in the same way as for other event subscriptions documented in the [Subscription API](docId\:vMKCbjsFOUH_t4Dt406_k) section. Please refer to this section for detailed information, including what input fields and enums are available.

## Menu Creation Request Notifications

:::hint{type="info"}
When subscribing to `MenuCreationRequest` notifications please use:

- `EventEntity` enum of `MenuCreationRequest`.
- `EventKey` enums of `succeeded`, `succeeded_with_warnings`, or `failed`.
- `ParentEntity` enum should be `Caterer`.
:::

### Variables

Below is a example of the variables that would be used with [Subscription Create](docId\:YWDS1a-gxebJWknE8V90S) to subscribe to `MenuCreationRequest` notifications.

:::CodeblockTabs
Variables

```graphql
{
  "subscriptionParams": {
    "eventEntity": "MenuCreationRequest",
    "eventKey": "succeeded",
    "parentEntity": "Caterer",
    "parentId": "ezcater-caterer-id",
    "subscriberId": "your-subscriber-id"
  }
}
```
:::

### Notifications

:::CodeblockTabs
Notification - Success

```graphql
{
  "id": "notification-id",
  "parent_type": "Caterer",
  "parent_id": "ezcater-caterer-id",
  "entity_type": "MenuCreationRequest",
  "entity_id": "your-menu-creation-request-id",
  "key": "succeeded",
  "created_at": "2025-04-15 23:48:23 UTC",
  "occurred_at": "2025-04-15 23:48:21 UTC",
  "updated_at": "2025-04-15 23:48:23 UTC",
  "payload":null
}
```

Notification - Success With Warning

```graphql
{
  "id": "notification-id",
  "parent_type": "Caterer",
  "parent_id": "ezcater-caterer-id",
  "entity_type": "MenuCreationRequest",
  "entity_id": "your-menu-creation-request-id",
  "key": "succeeded_with_warnings",
  "created_at": "2025-04-15 23:48:23 UTC",
  "occurred_at": "2025-04-15 23:48:21 UTC",
  "updated_at": "2025-04-15 23:48:23 UTC",
  "payload":null
}
```

Notification - Failed

```graphql
{
  "id": "notification-id",
  "parent_type": "Caterer",
  "parent_id": "ezcater-caterer-id",
  "entity_type": "MenuCreationRequest",
  "entity_id": "your-menu-creation-request-id",
  "key": "failed",
  "created_at": "2025-04-15 23:48:23 UTC",
  "occurred_at": "2025-04-15 23:48:21 UTC",
  "updated_at": "2025-04-15 23:48:23 UTC",
  "payload":null
}
```
:::

## Menu Notifications

:::hint{type="info"}
When subscribing to `Menu` notifications please use:

- `EventEntity` enum of `Menu`.
- `EventKey` enums of `updated`.
- `ParentEntity` enum should be `Caterer`.
:::

### Variables

Below is a example of the variables that would be used with [Subscription Create](docId\:YWDS1a-gxebJWknE8V90S) to subscribe to `Menu` notifications.

:::CodeblockTabs
Variables

```graphql
{
  "subscriptionParams": {
    "eventEntity": "Menu",
    "eventKey": "Updated",
    "parentEntity": "Caterer",
    "parentId": "ezcater-caterer-id",
    "subscriberId": "your-subscriber-id"
  }
}
```
:::

### Notifications

:::CodeblockTabs
Notification

```graphql
{
  "id": "notification-id",
  "parent_type": "Caterer",
  "parent_id": "ezcater-caterer-id",
  "entity_type": "Menu",
  "entity_id": "your-menu-creation-request-id",
  "key": "updated",
  "created_at": "2025-04-15 23:48:23 UTC",
  "occurred_at": "2025-04-15 23:48:21 UTC",
  "updated_at": "2025-04-15 23:48:23 UTC",
  "payload":null
}
```
:::


[title] Subscriber Update
[path] API for Restaurant Partners/Subscription API/

# Updating Subscribers

The `updateSubscriber` mutation provides the ability to need to change the `name` and `webhookUrl` of your **Subscriber**.

:::hint{type="warning"}
At present webhook Secrets are not able to be changed.
:::

## Mutation

:::CodeblockTabs
Mutation

```graphql
mutation UpdateSubscriber(
  $subscriberId: ID!
  $subscriberParams: UpdateSubscriberFields!
) {
  updateSubscriber(
    subscriberId: $subscriberId
    subscriberParams: $subscriberParams
  ) {
    subscriber {
      id
      name
      subscriptions {
        subscriberId
        parentId
        parentEntity
        eventEntity
        eventKey
      }
      webhookUrl
    }
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables

```graphql
{
  "subscriberId": "your-subscriber-id",
  "subscriberParams": {
    "name": "Example Provider Updated - Example Brand",
    "webhookUrl": "https://example.net/subscriptions-updated"
  }
}
```
:::

### Arguments

| Argument Name                                                                | Description                                |
| ---------------------------------------------------------------------------- | ------------------------------------------ |
| `subscriberId`: [ID!](docId:_6fu5DGR5rPbWAT27Pcxz)                           | The ID for the subscriber to be updated.   |
| `subscriberParams`: [UpdateSubscriberFields!](docId:_6fu5DGR5rPbWAT27Pcxz)   | The input object for updating a Subscriber |

### Return Type

Returns a [UpdateSubscriberPayload](docId:_6fu5DGR5rPbWAT27Pcxz).

## Successful Responses

When the `updateSubscriber` mutation succeeds you can expect the response payload to look in one of two different ways:

1. If you have created a **Subscriber** but have not yet created any **Subscriptions** the `subscriptions` field value will empty.&#x20;
2. If you have created `subscriptions` all of them for the **Subscriber** will be returned.

:::CodeblockTabs
Response - Without Subscriptions

```graphql
{
  "data": {
    "subscribers": [
      {
        "id": "your-subscriber-id",
        "name": "Example Provider Updated - Example Brand",
        "subscriptions": [],
        "webhookUrl": "https://example.net/subscriptions-updated"
      }
    ]
  }
}
```

Response - With Subscriptions

```graphql
{
  "data": {
    "subscribers": [
      {
        "id": "your-subscriber-id",
        "name": "Example Provider Updated - Example Brand",
        "subscriptions": [
          {
            "eventEntity": "Order",
            "eventKey": "accepted",
            "parentEntity": "Caterer",
            "parentId": "ezcater-caterer-id",
            "subscriberId": "your-subscriber-id"
          }
        ],
        "webhookUrl": "https://example.net/subscriptions-updated"
      }
    ]
  }
}
```
:::

## Failure Responses

When `updateSubscriber` mutation fails you can expect the response payload to look like:&#x20;

:::CodeblockTabs
Response

```graphql
{
  "errors": [
    {
      "message": "Subscriber could not be updated.",
      "path": [
        "updateSubscriber"
      ],
      "extensions": {
        "type": "summary",
        "serviceName": "external-events",
        "code": "DOWNSTREAM_SERVICE_ERROR",
        "exception": {
          "message": "Subscriber could not be updated.",
          "locations": [
            {
              "line": 1,
              "column": 107
            }
          ],
          "path": [
            "updateSubscriber"
          ]
        }
      }
    }
  ],
  "data": {
    "updateSubscriber": null
  }
}
```
:::


[title] Order Details
[path] API for Restaurant Partners/Orders API/

# Viewing Order Details

After using [Subscription Create](docId\:YWDS1a-gxebJWknE8V90S)  to create subscription notifications for the `eventEntity` of `Order`, you will begin to receive order notifications. The payload for these notifications will include the `uuid` of the order which can be used to retrieves the details of the order.&#x20;

:::hint{type="warning"}
Information will only be available for orders you have been granted access to from within Partner Portal, this may be limited by location, depending on your brand's structure.&#x20;
:::

:::hint{type="info"}
We recommend subscribing to all notification `eventKey` for the `eventEntity` of  `Order` to assist in keeping up-to-date with order information. Please see [Subscription Create](docId\:YWDS1a-gxebJWknE8V90S) for more details.
:::

## Query

:::CodeblockTabs
Query

```graphql
query Order(
  $orderId: ID!
  $types: [FeeOrDiscountType!]
) {
  order(id: $orderId) {
    deliveryId
    uuid
    caterer {
      address {
        city
        deliveryInstructions
        name
        state
        stateName
        street
        street2
        street3
        zip
      }
      live
      name
      storeNumber
      uuid
    }
    catererCart {
      feesAndDiscounts(types: $types) {
        cost {
          currency
          subunits
          subunitsV2
        }
        name
      }
      orderItems {
        customizations {
          customizationId
          customizationTypeId
          customizationTypeName
          name
          posCustomizationId
          quantity
        }
        labelFor
        menuItemSizeId
        menuItemSizeName
        name
        noteToCaterer
        posItemId
        quantity
        specialInstructions
        totalInSubunits {
          currency
          subunits
          subunitsV2
        }
        uuid
      }
      tableware {
        specialInstructions
        tablewareChoices {
          choiceUuid
          isIncluded
          itemCount
          name
        }
      }
      totals {
        catererTotalDue
      }
    }
    event {
      address {
        city
        deliveryInstructions
        name
        state
        stateName
        street
        street2
        street3
        zip
      }
      catererHandoffFoodTime
      contact {
        name
        phone
      }
      customerProvidedName
      headcount
      orderType
      thirdPartyDeliveryPartner
      timeZoneIdentifier
      timeZoneOffset
      timestamp
    }
    isTaxExempt
    lifecycle {
      orderIsCurrently
    }
    orderCustomer {
      firstName
      fullName
      lastName
    }
    orderNumber
    orderSourceType
    taxableAddress {
      city
      deliveryInstructions
      name
      state
      stateName
      street
      street2
      street3
      zip
    }
    totals {
      customerTotalDue {
        currency
        subunits
        subunitsV2
      }
      pointOfSaleIntegrationFee {
        currency
        subunits
        subunitsV2
      }
      salesTax {
        currency
        subunits
        subunitsV2
      }
      salesTaxRemittance {
        currency
        subunits
        subunitsV2
      }
      subTotal {
        currency
        subunits
        subunitsV2
      }
      tip {
        currency
        subunits
        subunitsV2
      }
    }
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables

```graphql
{
  "orderId": "your-ezcater-order-id",
  "types": ["ADJUSTMENT","DELIVERY_FEE","DISCOUNT","MISC_FEE"]
}
```
:::

### Arguments

| Argument Name                                                         | Description                                                                                |
| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `orderId`: [ID!](docId\:U2UigsYO0gfPXj-5tuif0)                        | The ezCater order UUID that was provided in the `Order` subscription notification payload. |
| `types`:  [\[FeeOrDiscountType!\]](docId\:U2UigsYO0gfPXj-5tuif0)      | A list of `FeeOrDiscountType` enums used to filter fees and discounts on an order.         |
| `shouldUseSearchAddress`: [Boolean](docId\:U2UigsYO0gfPXj-5tuif0)     | Includes the address the customer searched for (relevant for takeout orders)               |
| `perspective`: [OrderTypePerspective](docId\:U2UigsYO0gfPXj-5tuif0)   |                                                                                            |

### Return Type

Returns an [Order](docId\:U2UigsYO0gfPXj-5tuif0).

## Success Response

When the `order` query succeeds you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "order": {
      "deliveryId": "3593ce70-7227-4fd4-8a78-9591083d0674",
      "uuid": "your-ezcater-order-id",
      "caterer": {
        "address": {
          "city": "Boston",
          "deliveryInstructions": "Ask for Jane at front desk",
          "name": "",
          "state": "MA",
          "stateName": "Massachusetts",
          "street": "12345 Restaurant Avenue",
          "street2": null,
          "street3": null,
          "zip": "54321"
        },
        "live": true,
        "name": "My Caterer Name",
        "storeNumber": "00001",
        "uuid": "ezcater-caterer-id"
      },
      "catererCart": {
        "feesAndDiscounts": [
          {
            "cost": {
              "currency": "USD",
              "subunits": 2999,
              "subunitsV2": "2999"
            },
            "name": "Delivery Fee"
          },
          {
            "cost": {
              "currency": "USD",
              "subunits": -1199,
              "subunitsV2": "-1199"
            },
            "name": "Preferred Caterer Program"
          },
          {
            "cost": {
              "currency": "USD",
              "subunits": -1199,
              "subunitsV2": "-1199"
            },
            "name": "Rewards Promo"
          }
        ],
        "orderItems": [
          {
            "customizations": [
              {
                "customizationId": "ezcater-menu-version-customization-parmigiano-reggiano-choice-12-inch-selection-id",
                "customizationTypeId": "ezcater-menu-version-customization-type-cheese-addon-options-id",
                "customizationTypeName": "Cheese Addon",
                "name": "Parmigiano Reggiano",
                "posCustomizationId": "parmigiano-reggiano-choice-12-inch-selection-id",
                "quantity": 10
              }
            ],
            "labelFor": null,
            "menuItemSizeId": "ezcater-menu-version-size-12-inch-pizza-item-selection-id",
            "menuItemSizeName": "12\" Pizza",
            "name": "Margherita Pizza",
            "noteToCaterer": "12\" thin crust Margherita Pizza",
            "posItemId": "12-inch-pizza-item-selection-id",
            "quantity": 10,
            "specialInstructions": "Please be careful not to burn crust",
            "totalInSubunits": {
              "currency": "USD",
              "subunits": 16750,
              "subunitsV2": "16750"
            },
            "uuid": "83ec5c82-fa68-437c-90d7-ad861a2c151b"
          },
          {
            "customizations": [
              {
                "customizationId": "ezcater-menu-version-customization-brand-name-soda-choice-id",
                "customizationTypeId": "ezcater-menu-version-customization-type-soda-option-id",
                "customizationTypeName": "Soda",
                "name": "Select Soda",
                "posCustomizationId": "brand-name-soda-choice-id",
                "quantity": 10
              }
            ],
            "labelFor": null,
            "menuItemSizeId": "ezcater-menu-version-size-assorted-sodas-item-selection-id",
            "menuItemSizeName": "2ltr Soda",
            "name": "Assorted Sodas",
            "noteToCaterer": "2ltr brand name sodas from fridge",
            "posItemId": "assorted-sodas-item-selection-id",
            "quantity": 10,
            "specialInstructions": "Please bring cold soda if possible",
            "totalInSubunits": {
              "currency": "USD",
              "subunits": 2750,
              "subunitsV2": "2750"
            },
            "uuid": "c00e766f-e733-476a-939c-9aba59b4e93c"
          }
        ],
        "tableware": {
          "specialInstructions": null,
          "tablewareChoices": [
            {
              "choiceUuid": "7acc72ed-2240-4b9f-a903-f7873b94ba60",
              "isIncluded": true,
              "itemCount": 10,
              "name": "Napkins"
            },
            {
              "choiceUuid": "e8cb95f8-c2de-412d-a0de-d01e1879db83",
              "isIncluded": true,
              "itemCount": 10,
              "name": "Plates"
            },
            {
              "choiceUuid": "b73832f4-f8d8-4317-b93e-5788e926ab2c",
              "isIncluded": true,
              "itemCount": 10,
              "name": "Cups"
            }
          ]
        },
        "totals": {
          "catererTotalDue": 171.02
        }
      },
      "event": {
        "address": {
          "city": "Boston",
          "deliveryInstructions": "Ask for Jane at front desk",
          "name": "My Office",
          "state": "MA",
          "stateName": "Massachusetts",
          "street": "2345 Business Boulevard",
          "street2": null,
          "street3": null,
          "zip": "23456"
        },
        "catererHandoffFoodTime": "2025-03-27T16:15:00Z",
        "contact": {
          "name": "Jane Doe",
          "phone": "5555555555"
        },
        "customerProvidedName": "Team building event",
        "headcount": 10,
        "orderType": "DELIVERY",
        "thirdPartyDeliveryPartner": null,
        "timeZoneIdentifier": "America/New_York",
        "timeZoneOffset": "-04:00",
        "timestamp": "2025-03-27T16:30:00Z"
      },
      "isTaxExempt": false,
      "lifecycle": {
        "orderIsCurrently": "accepted"
      },
      "orderCustomer": {
        "firstName": "Jane",
        "fullName": "Jane Doe",
        "lastName": "Doe"
      },
      "orderNumber": "O1O1O1",
      "orderSourceType": "MARKETPLACE",
      "taxableAddress": {
        "city": "Boston",
        "deliveryInstructions": "Ask for Jane at front desk",
        "name": "",
        "state": "MA",
        "stateName": "Massachusetts",
        "street": "2345 Business Boulevard",
        "street2": null,
        "street3": null,
        "zip": "23456"
      },
      "totals": {
        "customerTotalDue": {
          "currency": "USD",
          "subunits": 23864,
          "subunitsV2": "23864"
        },
        "pointOfSaleIntegrationFee": {
          "currency": "USD",
          "subunits": 0,
          "subunitsV2": "0"
        },
        "salesTax": {
          "currency": "USD",
          "subunits": 1365,
          "subunitsV2": "1365"
        },
        "salesTaxRemittance": {
          "currency": "USD",
          "subunits": 0,
          "subunitsV2": "0"
        },
        "subTotal": {
          "currency": "USD",
          "subunits": 19500,
          "subunitsV2": "19500"
        },
        "tip": {
          "currency": "USD",
          "subunits": 0,
          "subunitsV2": "0"
        }
      }
    }
  }
}
```
:::

## Failure Response

When the `order` query fails because you do not have permission to access the order associated with the `uuid` provided you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "errors": [
    {
      "message": "You are not authorized to access this data",
      "path": [
        "order"
      ],
      "extensions": {
        "serviceName": "management-public",
        "code": "DOWNSTREAM_SERVICE_ERROR",
        "exception": {
          "message": "You are not authorized to access this data",
          "locations": [
            {
              "line": 1,
              "column": 99
            }
          ],
          "path": [
            "order"
          ],
          "type": "request",
          "statusCode": 403
        }
      }
    }
  ],
  "data": {
    "order": null
  }
}
```
:::


[title] Okta SCIM Instructions - Meal Program App Only
[path] Enterprise Account Integrations/SCIM for ezCater Marketplace & Relish/

- In the Okta Admin Portal within Applications, select the Meal Program application

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXeOXyxRvhnqAtiO-zeoU4x87i-tFyZwR7kQKgIEsRDkk2nbd4DcLXHM6aq19LnnT_TTlrhgFvIpiBAYyDwWJsxvlNMbQxTI-xk0GQrypkdQJpPt_B35lk8M-oVYk0FlQSDUWG-1mQ?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Click the **Provisioning tab** and select **Configure API Integration**

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfa0oiXvzLqzYilHrWPEAhhRAPLmZssCIggs5J4khWNiIS3RuEHvtwXV6-D_V2ToULFcIlpr_c7SkKldAf0qSzc139VgKderDGvtwBIj9GtNspcl9sUI5t770wWQ-stmtzlJ_lqLA?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Click the checkbox **Enable API Integration**
- Paste the **Base URL** and **API Token&#x20;**&#x61;nd click **Save**
  - **Base URL:&#x20;**[https://login.ezcater.com/scim/v2](https://login.ezcater.com/scim/v2)

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXci0V2-zMJueb_8vKOF8Wn5whUW5uq9IGp3UWo_1tQcparbM2AlW53q8uI5hCuOeSk6lcG4mz8zLXNVVXgvsbsWCfnkDN2-fcNZjE9Ydeu5Ggz7jd_8zlVa7tk6scqk4Uhnn0GjAg?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Navigate to the **To App&#x20;**&#x74;ab within the Provisioning Settings and **check each box&#x20;**&#x66;or the Meal Program's supported provisioning actions. Then, click **Save.**

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXe04UWkDtArDB4ccOMrm158r-k1kfvjc5n4paDZHWKScFYBGjvOMdJdEXmHytgS0qjklLgM_qxvWV4uTAFN8nI3Wp6K42xKQkBwqBqC7ELSNEuP3KWu7B4Ga4I2S0rqxVCHwKC9rA?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Click the **Sign On** tab and click **Edit**

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfDcxFt_Gwqjf0beMyKwF0OfbcUsnbJ6aax_X4dBEZUb8po-NrvsxZPmMLJnCZLBk8qhX5dMUPwvmPpi6PYtgGLX8Yk-0VTLL_HGMM1PnXMi-d0iTmf77998RTJFxhzSglAVTJGqA?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Select **Email&#x20;**&#x66;or the **Application username format&#x20;**&#x61;nd click **Save**

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfwWnGIYMmE-ej2RgWck8XJM5YhMwud_ovYnLobXZn-NsYFtCpRmVMeFpnhPL14fbX8OxgJKUnl7dhPUo5jVJEZ9wTPkKATWiDWF2C-FREtMr3ffpMBr7c6rWhrpr5U53Nmh4G2?key=AvWn09Y7CVz2HnQXem_NL67Q)

*Your SCIM configuration for the Meal Program is complete. You can start assigning people to the app.*


[title] FAQ - SAP Concur Enterprise
[path] Enterprise Account Integrations/SAP Concur Enterprise/

**Where can I get support?**

An SAP Concur user with authorized permissions can open a case through the Support Portal. To log a case, complete the following steps:

- After signing in to SAP Concur, select the “?” icon (top right), then select **Contact Support**.
- Select **Support**.
- Select **Create a Case**.
- Enter/select the required fields marked in red.
- Enter your email address to receive updates from Support.
- Click **Save** after completing the mandatory fields. This will generate a new case number for the issue reported.
- SAP Concur Support will triage the issue with the ezCater team to find a resolution.

The ezCater team can be reached at *enterprisesupport\@ezcater.com.*

 

**What is the SAP Concur Enterprise integration**?&#x20;

It is a centralized solution that enables account-wide automatic receipt forwarding and seamless user management via a roster sync.

 

**Is there a cost to use this integration?&#x20;**

No, there is no signup fee for an ezCater Enterprise Account, and accessing the SAP Concur integration is free of charge.

 

**How does the Enterprise integration differ from the Individual version?&#x20;**

The Enterprise version is managed by an admin for the whole company, while the Individual version requires each employee to connect manually. Additionally, only the Enterprise version supports optional Roster Sync.

 

**Who can enable the integration?**

The setup must be completed by a user who holds admin permissions in both ezCater and SAP Concur.

 

**Does this work for "Parent Child" account structures?**&#x20;

For receipt forwarding, yes, all accounts will be connected through the parent level enablement. However, Roster Sync is not yet available for parent-child structures.

 

**Is the integration available for the Meal Program ?**&#x20;

No, the SAP Concur Enterprise integration is not currently available for the Meal Program.

 

**When are receipts sent to Concur?**&#x20;

Receipts are transmitted automatically within 24 hours after the payment has been captured.

 

**What happens if an order is modified or refunded?&#x20;**

Correction receipts are automatically sent to SAP Concur, ensuring expense reports stay accurate without manual intervention.

 

**Are there any receipts that cannot be sent?&#x20;**

Receipts cannot be forwarded if it was paid for with a credit line, the receipt was created prior to the Enterprise integration, or if the payment hasn't been captured yet.

 

**How does Roster Sync work?&#x20;**

It automatically adds or removes employees from your ezCater Enterprise account based on your Concur Expense roster.

 

**What data is shared with ezCater?**&#x20;

ezCater only stores the employee's First Name, Last Name, and Email Address to manage the roster and confirm active status.

[title] Okta - Assign People & Groups to the App
[path] Enterprise Account Integrations/SSO for Marketplace & Relish/

- Log into Okta as an admin, go to **Applications > Applications**, and select the Meal Program integration.

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXeZBd7kTNX42GCyR2EodMCqtgMf6jaWJw7KuWpalZsmQPo7mruIq4blZOOqpMRt-EKk2AKHUElz02CnJGUG01EB-FlSJQEyt6gMUKeUrQcWB_QgIQliFS0pgrVzbwJdMIR2IfNPlQ?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Click the **Assignments&#x20;**&#x74;ab.

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXeZybkyQOcDMk6qCt1OREuLv7lqH0_2syle3dOWX2zGt354O7uNmj-MXPNQZ7hNSuKKNXP1Pz4Q4_yLjteO6FHqCKr--AhwoRIbVlf4Z4ljZW_qjU1AnnjS3gdqsMNMSp_Zivuf?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Select the **Assign** drop-down menu and select Assign to People or Assign to Group.
  - In the Search… box, enter and select the person or group you want to assign.
  - Select Assign.
  - Enter more details about the user if you want. When you’re done, select Save and Go Back.
- Note: When you assign a Group, and if it has users, they show up as a Group type instead of People.

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfMbVgCAwVuSVNtK0QxHrdyHntUVkk8vjBn0DRzAymtb4i2QYEYCybXFwqwDaKsiKSXQT1aUX_rq_moF37_oBT-0cnciHtYemeGY_zvPyPgFjdasTgZuoqXSLbBzJmWVImTbmGAlg?key=AvWn09Y7CVz2HnQXem_NL67Q)


[title] Courier Schema Reference
[path] API for Restaurant Partners/Delivery API/

# Courier Schema Reference

## Objects

### CourierAssignPayload

Return type of CourierAssign.

| Field Name                                                                 | Description                                                   |
| -------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `clientMutationId`: [String](docId:7gV344RnWmuokNj9u4rW7)                  | A unique identifier for the client performing the mutation.   |
| `delivery`: [Delivery](docId:7gV344RnWmuokNj9u4rW7)                        | The delivery where the courier was assigned.                  |
| `userErrors`: [\[CourierAssignUserError!\]!](docId:7gV344RnWmuokNj9u4rW7)  | The list of errors that happened from executing the mutation. |

:::CodeblockTabs
Example

```graphql
{
  "clientMutationId": "your-mutation-id",
  "delivery": {
    "id": "ezcater-delivery-id"
  },
  "userErrors": [CourierAssignUserError!]
}
```
:::

### CourierEventCreatePayload

Return type of CourierEventCreate.

| Field Name                                                                      | Description                                                   |
| ------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `clientMutationId`: [String](docId:7gV344RnWmuokNj9u4rW7)                       | A unique identifier for the client performing the mutation.   |
| `delivery`: [Delivery](docId:7gV344RnWmuokNj9u4rW7)                             | The delivery where the courier was assigned.                  |
| `userErrors`: [\[CourierEventCreateUserError!\]!](docId:7gV344RnWmuokNj9u4rW7)  | The list of errors that happened from executing the mutation. |

:::CodeblockTabs
Example

```graphql
{
  "clientMutationId": "your-mutation-id",
  "delivery": {
    "id": "ezcater-delivery-id"
  },
  "userErrors": [CourierAssignUserError!]
}
```
:::

### CourierImagesCreatePayload

Return type of CourierImagesCreate.

| Field Name                                                                       | Description                                                   |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `clientMutationId`: [String](docId:7gV344RnWmuokNj9u4rW7)                        | A unique identifier for the client performing the mutation.   |
| `userErrors`: [\[CourierImagesCreateUserError!\]!](docId:7gV344RnWmuokNj9u4rW7)  | The list of errors that happened from executing the mutation. |

:::CodeblockTabs
Example

```graphql
{
  "clientMutationId": "your-mutation-id",
  "userErrors": [CourierAssignUserError!]
}
```
:::

### CourierTrackingEventCreatePayload

Return type of CourierTrackingEventCreate.

| Field Name                                                                               | Description                                                   |
| ---------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `clientMutationId`: [String](docId:7gV344RnWmuokNj9u4rW7)                                | A unique identifier for the client performing the mutation.   |
| `userErrors`: [\[CourierTrackingEventCreateUserError!\]!](docId:7gV344RnWmuokNj9u4rW7)   | The list of errors that happened from executing the mutation. |

:::CodeblockTabs
Example

```graphql
{
  "clientMutationId": "your-mutation-id",
  "userErrors": [CourierAssignUserError!]
}
```
:::

### CourierUnassignPayload

Return type of CourierAssign.

| Field Name                                                                   | Description                                                   |
| ---------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `clientMutationId`: [String](docId:7gV344RnWmuokNj9u4rW7)                    | A unique identifier for the client performing the mutation.   |
| `delivery`: [Delivery](docId:7gV344RnWmuokNj9u4rW7)                          | The delivery where the courier was assigned.                  |
| `userErrors`: [\[CourierUnassignUserError!\]!](docId:7gV344RnWmuokNj9u4rW7)  | The list of errors that happened from executing the mutation. |

:::CodeblockTabs
Example

```graphql
{
  "clientMutationId": "your-mutation-id",
  "delivery": {
    "id": "ezcater-delivery-id"
  },
  "userErrors": [CourierAssignUserError!]
}
```
:::

### CouriersAssignPayload

Return type of CouriersAssign.

| Field Name                                                            | Description                                                   |
| --------------------------------------------------------------------- | ------------------------------------------------------------- |
| `clientMutationId`: [String](docId:7gV344RnWmuokNj9u4rW7)             | A unique identifier for the client performing the mutation.   |
| `delivery`: [Delivery](docId:7gV344RnWmuokNj9u4rW7)                   | The delivery where the courier was assigned.                  |
| `userErrors`: [CourierAssignUserError!](docId:7gV344RnWmuokNj9u4rW7)  | The list of errors that happened from executing the mutation. |

### DeliveryValidationError

A validation error, with a user-friendly message, that occurred while executing the mutation.

| Field Name                                            | Description                                      |
| ----------------------------------------------------- | ------------------------------------------------ |
| `message`: [String!](docId:7gV344RnWmuokNj9u4rW7)     | A description of the error.                      |
| `path`:  [\[String!\]!](docId:7gV344RnWmuokNj9u4rW7)  | A path to the input value that caused the error. |

:::CodeblockTabs
Example

```graphql
{
  "message": "It's too early to add the event for courier en route to pickup",
  "path": [
    "input",
    "occurredAt"
  ]
}
```
:::

## InputObjects

### CoordinatesInput

The latitude and longitude of where the event occurred by the courier.

| Field Name                                          | Description                       |
| --------------------------------------------------- | --------------------------------- |
| `latitude`: [Float!](docId:7gV344RnWmuokNj9u4rW7)   | The coordinate's latitude value.  |
| `longitude`: [Float!](docId:7gV344RnWmuokNj9u4rW7)  | The coordinate's longitude value. |

:::CodeblockTabs
Example

```graphql
{
  "latitude": 42.360081,
  "longitude": -71.058884
}
```
:::

### CourierAssignInput

The input object for mutation `CourierAssign`.

| Field Name                                                                                                                                                                                                                                 | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `allowMultipleCouriers`: [Boolean](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                                                            | When `true`, the provided `courier` input will be added to the delivery's existing assigned couriers without removing any current assignments. When `false` or omitted, any pre-existing assigned couriers for the delivery will be replaced by the provided `courier` input.                                                                                                                                                                                                                              |
| `clientMutationId`: [String](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                                                                  | A unique identifier for the client performing the mutation.                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `courier`: [CourierInput!](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                                                                    | The details of the courier that's being assigned. When provided details of a courier that doesn't exist, then the courier will be created. When provided details of an existing courier, then the courier will be updated to match the input if there's new or changed attributes.                                                                                                                                                                                                                         |
| `deliveryId`: [ID!](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                                                                           | The globally-unique identifier of the delivery.                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| <font color="#ff0000">**!**</font> <font color="#ff0000">**DEPRECATED**</font><br />`deliveryServiceProvider`: [String!](docId:7gV344RnWmuokNj9u4rW7) <br /><font color="#ff0000">**DEPRECATED** </font><font color="#ff0000">**!**</font> | <font color="#ff0000">**!**</font> <font color="#ff0000">**DEPRECATED**</font><br />The delivery platform that is providing the courier. For example, DoorDash, Uber, etc. This is only used for internal tracking and the information is not presented to the the customer.<br /><font color="#ff0000">**DEPRECATED**</font> <font color="#ff0000">**!**</font><br />Replaced by arguments: [courier.providerSource](docId:7gV344RnWmuokNj9u4rW7) and [courier.providerName](docId:7gV344RnWmuokNj9u4rW7) |

:::CodeblockTabs
Example

```graphql
{
  "clientMutationId": "your-mutation-id",
  "courier": CourierInput,
  "deliveryId": "ezcater-delivery-id",
  "occurredAt": "2024-02-05T17:27:55+0000"
}
```
:::

### CourierAssignmentInput

The input fields for creating or updating a delivery courier and its assignment to the delivery.

| Field Name                                                              | Description                                                                                                                                                                                                 |
| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`: [ID!](docId:7gV344RnWmuokNj9u4rW7)                                | The unique identifier for the courier. This is used to determine whether the courier exists in the system. If the courier does *not* exist then it can be created, if it does exist then it can be updated. |
| `firstName`﻿﻿: [String](docId:7gV344RnWmuokNj9u4rW7)                    | The courier's first name.                                                                                                                                                                                   |
| `lastName`: [String](docId:7gV344RnWmuokNj9u4rW7)                       | The courier's last name.                                                                                                                                                                                    |
| `phone`: [String](docId:7gV344RnWmuokNj9u4rW7)                          | The phone number of the courier. Formatted using E.164 standard. For example, +16175551234.                                                                                                                 |
| `providerName`: [String](docId:7gV344RnWmuokNj9u4rW7)                   | The name of the third-party service that's fulfilling the delivery. This is required when the `providerSource` is `THIRD_PARTY`.                                                                            |
| `providerSource`: [CourierProviderSource!](docId:7gV344RnWmuokNj9u4rW7) | Whether the courier is in-house or from a third-party service.                                                                                                                                              |
| `vehichle`: [CourierVehichleInput](docId:7gV344RnWmuokNj9u4rW7)         | The details on the courier's vehicle for the delivery.                                                                                                                                                      |

### CourierEventCreateInput

The input object for mutation `CourierEventCreate`.

| Field Name                                                                                                                                                                                                                      | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `clientMutationId`: [String](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                                                       | A unique identifier for the client performing the mutation.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `coordinates`: [CoordinatesInput](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                                                  | The latitude and longitude of where the event occurred by the courier.                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| <font color="#ff0000">**!**</font> <font color="#ff0000">**DEPRECATED**</font><br />`courier`: [CourierInput](docId:7gV344RnWmuokNj9u4rW7) <br /><font color="#ff0000">**DEPRECATED**</font> <font color="#ff0000">**!**</font> | <font color="#ff0000">**!** </font><font color="#ff0000">**DEPRECATED**</font><br />The details of the assigned courier that submitted the event. When provided details of a courier that doesn't exist, then the courier will be created. When provided details of an existing courier, then the courier will be updated to match the input if there's new or changed attributes. The courier will be assigned to the delivery if they're not already, which unassigns any existing courier.<br /><font color="#ff0000">**DEPRECATED !**</font> |
| `courierId`: [ID](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                                                                  | Replaces argument: `courier`. Courier creation, updating, and assignment changes should now be performed using the `courierAssign` or `couriersAssign` mutations. If the courier for the provided `courierId` has not yet been created or is not assigned, then an execution error will be returned.                                                                                                                                                                                                                                             |
| `deliveryId`: [ID!](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                                                                | The globally-unique identifier of the delivery.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `eventType`: [CourierEventCreateInputEventType! ](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                                  | The type of event by the courier for the delivery.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `occurredAt`: [ISO8601DateTime! ](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                                                  | The date and time (ISO 8601 format) when the event happened.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |

:::CodeblockTabs
Example

```graphql
{
  "clientMutationId": "your-mutation-id",
  "coordinates": Coordinates,
  "courier": CourierInput,
  "deliveryId": "ezcater-delivery-id",
  "eventType": "EN_ROUTE_TO_PICKUP",
  "occurredAt": "2024-02-05T17:27:55+0000"
}
```
:::

### CourierImagesCreateInput

The input object for mutation `CourierImagesCreate`.

| Field Name                                                                                                                                                                                     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientMutationId`: [String](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                      | A unique identifier for the client performing the mutation.                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| <font color="#ff0000">**!** </font><font color="#ff0000">**DEPRECATED**</font><br />`courier`: [CourierInput](docId:7gV344RnWmuokNj9u4rW7) <br /><font color="#ff0000">**DEPRECATED !**</font> | <font color="#ff0000">**! DEPRECATED**</font><br />The details of the assigned courier that submitted the event. When provided details of a courier that doesn't exist, then the courier will be created. When provided details of an existing courier, then the courier will be updated to match the input if there's new or changed attributes. The courier will be assigned to the delivery if they're not already, which unassigns any existing courier.<br /><font color="#ff0000">**DEPRECATED !**</font> |
| `courierId`: [ID](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                                 | Replaces argument: `courier`. Courier creation, updating, and assignment changes should now be performed using the `courierAssign` or `couriersAssign` mutations. If the courier for the provided `courierId` has not yet been created or is not assigned, then an execution error will be returned.                                                                                                                                                                                                            |
| `deliveryId`: [ID!](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                               | The globally-unique identifier of the delivery.                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `imageUrls`: [\[String!\]!](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                       | A list of remote image URLs. Each URL must respond to an HTTP HEAD request with a 2xx status code and an image Content-Type header.                                                                                                                                                                                                                                                                                                                                                                             |

:::CodeblockTabs
Example

```graphql
{
  "clientMutationId": "your-mutation-id",
  "courier": CourierInput,
  "deliveryId": "ezcater-delivery-id",
  "imageUrls": ["https://your-courier-company.com/your-courier-id-delivery.jpg"]
}
```
:::

### CourierInput

The details of the assigned courier that submitted the event. When provided details of a courier that doesn't exist, then the courier will be created. When provided details of an existing courier, then the courier will be updated to match the input if there's new or changed attributes. The courier will be assigned to the delivery if they're not already, which unassigns any existing courier.

| Field Name                                                              | Description                                                                                                                                                                                               |
| ----------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`: [ID!](docId:7gV344RnWmuokNj9u4rW7)                                | The unique identifier for the courier. This is used to determine whether the courier exists in the system. If the courier does not exist then it can be created, if it does exist then it can be updated. |
| `firstName`:  [String](docId:7gV344RnWmuokNj9u4rW7)                     | The courier's first name. This is required for new couriers.                                                                                                                                              |
| `lastName`:  [String](docId:7gV344RnWmuokNj9u4rW7)                      | The courier's last name. This is required for new couriers.                                                                                                                                               |
| `phone`:  [String](docId:7gV344RnWmuokNj9u4rW7)                         | The phone number of the courier. Formatted using E.164 standard. For example, +16175551234. This is required for new couriers.                                                                            |
| `providerName`: [String](docId:7gV344RnWmuokNj9u4rW7)                   | The name of the third-party service that's fulfilling the delivery. This is required when the `providerSource` is `THIRD_PARTY`.                                                                          |
| `providerSource`:  [CourierProviderSource](docId:7gV344RnWmuokNj9u4rW7) | Whether the courier is in-house or from a third-party service.                                                                                                                                            |
| `vehicle`: [CourierVehicleInput](docId:7gV344RnWmuokNj9u4rW7)           | The details on the courier's vehicle for the delivery                                                                                                                                                     |

:::CodeblockTabs
Example

```graphql
{
  "id": "your-courier-id",
  "firstName": "Test",
  "lastName": "Courier",
  "phone": "+15555555555",
  "providerSource": "THIRD_PARTY",
  "providerName": "DoorDash",
  "vehicle": CourierVehicleInput
}
```
:::

### CourierTrackingEventCreateInput

The input object for mutation `CourierTrackingEventCreate`.

| Field Name                                                                                                                                                                                     | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `clientMutationId`: [String](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                      | A unique identifier for the client performing the mutation.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `coordinates`: [CoordinatesInput](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                 | The latitude and longitude of where the event occurred by the courier.                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| <font color="#ff0000">**!** </font><font color="#ff0000">**DEPRECATED**</font><br />`courier`: [CourierInput](docId:7gV344RnWmuokNj9u4rW7) <br /><font color="#ff0000">**DEPRECATED !**</font> | <font color="#ff0000">**!** </font><font color="#ff0000">**DEPRECATED**</font><br />The details of the assigned courier that submitted the event. When provided details of a courier that doesn't exist, then the courier will be created. When provided details of an existing courier, then the courier will be updated to match the input if there's new or changed attributes. The courier will be assigned to the delivery if they're not already, which unassigns any existing courier.<br /><font color="#ff0000">**DEPRECATED !**</font> |
| `courierId`: [ID](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                                 | Replaces argument: `courier`. Courier creation, updating, and assignment changes should now be performed using the `courierAssign` or `couriersAssign` mutations. If the courier for the provided `courierId` has not yet been created or is not assigned, then an execution error will be returned.                                                                                                                                                                                                                                             |
| `deliveryId`: [ID!](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                               | The globally-unique identifier of the delivery.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `occurredAt`: [ISO8601DateTime! ](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                                 | The date and time (ISO 8601 format) when the event happened.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |

:::CodeblockTabs
Example

```graphql
{
  "clientMutationId": "your-mutation-id",
  "coordinates": Coordinates,
  "courier": CourierInput,
  "deliveryId": "ezcater-delivery-id",
  "occurredAt": "2024-02-05T17:27:55+0000"
}
```
:::

### CourierUnassignInput

The input fields for mutation `CourierUnassign`.

| Field Name                                                                                                                                                          | Description                                                                                                                                                                                                                                                                                                                                                                                                               |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientMutationId`: [String](docId:7gV344RnWmuokNj9u4rW7)                                                                                                           | A unique identifier for the client performing the mutation.                                                                                                                                                                                                                                                                                                                                                               |
| <font color="#ff0000">**! DEPRECATED**</font><br />`courier`: [CourierInput](docId:7gV344RnWmuokNj9u4rW7) <br /><font color="#ff0000">**DEPRECATED !**</font><br /> | <font color="#ff0000">**!** </font><font color="#ff0000">**DEPRECATED**</font><br />The details of the courier that's being assigned. When provided details of a courier that doesn't exist, then the courier will be created. When provided details of an existing courier, then the courier will be updated to match the input if there's new or changed attributes.<br /><font color="#ff0000">**DEPRECATED !**</font> |
| `courierId`: [ID](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                      | Replaces argument: `courier`. Courier creation, updating, and assignment changes should now be performed using the `courierAssign` or `couriersAssign` mutations. If the courier for the provided `courierId` has not yet been created or is not assigned, then an execution error will be returned.                                                                                                                      |
| `deliveryId`: [ID!](docId:7gV344RnWmuokNj9u4rW7)                                                                                                                    | The globally-unique identifier of the delivery.                                                                                                                                                                                                                                                                                                                                                                           |

:::CodeblockTabs
Example

```graphql
{
  "clientMutationId": "your-mutation-id",
  "courier": CourierInput,
  "deliveryId": "ezcater-delivery-id"
}
```
:::

### CourierVehicleInput

The input fields for specifying a delivery courier's `vehicle`.

| Field Name                                       | Description                            |
| ------------------------------------------------ | -------------------------------------- |
| `make`: [String](docId:7gV344RnWmuokNj9u4rW7)    | The vehicle's make. For example, Ford. |
| `model`:  [String](docId:7gV344RnWmuokNj9u4rW7)  | The vehicle's model.                   |
| `color`:  [String](docId:7gV344RnWmuokNj9u4rW7)  | The vehicle's color.                   |

:::CodeblockTabs
Example

```graphql
{
  "make": "Your Vehicle Make",
  "model": "Your Vehicle Model",
  "color": "Your Vehicle Color"
}
```
:::

### CouriersAssignInput

The input fields for mutation `CouriersAssign`.

| Field Name                                                               | Description                                                                                                                                                                                                                                                 |
| ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientMutationId`: [String](docId:7gV344RnWmuokNj9u4rW7)                | A unique identifier for the client performing the mutation.                                                                                                                                                                                                 |
| `couriers`: [CourierAssignmentInput!](docId:7gV344RnWmuokNj9u4rW7)<br /> | A list of couriers to be assigned to the delivery. Each courier will be created or updated with the provided details. Any existing assignments will be replaced with the provided list. Providing an empty list will remove all couriers from the delivery. |
| `deliveryId`: [ID!](docId:7gV344RnWmuokNj9u4rW7)                         | The globally-unique identifier of the delivery.                                                                                                                                                                                                             |

## Inputs

### Delivery

The identifier representing an ezCater delivery.

| Field Name                                | Description                                   |
| ----------------------------------------- | --------------------------------------------- |
| `id`: [ID!](docId:7gV344RnWmuokNj9u4rW7)  | A globally-unique identifier of the delivery. |

:::CodeblockTabs
Example

```graphql
{
  "id": "ezcater-delivery-id"
}
```
:::

## Unions

### CourierAssignUserError

| Field Name                                                                        | Description                          |
| --------------------------------------------------------------------------------- | ------------------------------------ |
| `CourierAssignUserError`: [DeliveryValidationError](docId:7gV344RnWmuokNj9u4rW7)  | List of UserErrors for CourierAssign |

### CourierEventCreateUserError

| **Field Name**                                                                         | **Description**                           |
| -------------------------------------------------------------------------------------- | ----------------------------------------- |
| `CourierEventCreateUserError`: [DeliveryValidationError](docId:7gV344RnWmuokNj9u4rW7)  | List of UserErrors for CourierEventCreate |

### CourierImagesCreateUserError

| **Field Name**                                                                          | **Description**                            |
| --------------------------------------------------------------------------------------- | ------------------------------------------ |
| `CourierImagesCreateUserError`: [DeliveryValidationError](docId:7gV344RnWmuokNj9u4rW7)  | List of UserErrors for CourierImagesCreate |

### CourierTrackingEventCreateUserError

| **Field Name**                                                                                 | **Description**                                   |
| ---------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| `CourierTrackingEventCreateUserError`: [DeliveryValidationError](docId:7gV344RnWmuokNj9u4rW7)  | List of UserErrors for CourierTrackingEventCreate |

### CourierUnassignUserError

| **Field Name**                                                                      | **Description**                        |
| ----------------------------------------------------------------------------------- | -------------------------------------- |
| `CourierUnassignUserError`: [DeliveryValidationError](docId:7gV344RnWmuokNj9u4rW7)  | List of UserErrors for CourierUnassign |

## Enums

### CourierEventCreateInputEventType

The status by the courier that describes the current state of the delivery lifecycle.

| Enum Name             | Description                                                     |
| --------------------- | --------------------------------------------------------------- |
| `ARRIVED_AT_DROPOFF`  | The courier has arrived at the dropoff location.                |
| `ARRIVED_AT_PICKUP`   | The courier has arrived at the location to pickup the delivery. |
| `DROPPED_OFF`         | The courier has dropped off the delivery.                       |
| `EN_ROUTE_TO_DROPOFF` | The courier is on their way to the dropoff location.            |
| `EN_ROUTE_TO_PICKUP`  | The courier is on their way to pickup the delivery.             |
| `PICKED_UP`           | The courier has picked up the delivery.                         |

### CourierProviderSource

Specifies whether a delivery is being fulfilled through self-delivery or from an external third-party service.

| **Enum name** | **Description**                                                                 |
| ------------- | ------------------------------------------------------------------------------- |
| IN\_HOUSE     | The delivery is being fulfilled through self-delivery with an in-house courier. |
| THIRD\_PARTY  | The delivery is being fulfilled by a third-party service.                       |

## Scalars

### BigInt

Represents non-fractional signed whole numeric values. Since the value may exceed the size of a 32-bit integer, it's encoded as a string.

### Boolean

The Boolean scalar type represents true or false.

### Date

ISO-8601 Date-only string, e.g. 2017-12-14

### Float

The Float scalar type represents signed double-precision fractional values as specified by IEEE 754.

### ID

The ID scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as "4") or integer (such as 4) input value will be accepted as an ID.

### ISO8601DateTime

An ISO 8601-encoded datetime @specifiedBy(url: [https://tools.ietf.org/html/rfc3339](https://tools.ietf.org/html/rfc3339)).

### Int

The Int scalar type represents non-fractional signed whole numeric values. Int can represent values between `-(2^31)` and `2^31 - 1`.

### JSON

Represents untyped JSON.

### String

The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.

### UTCTimestamp

iso8601 formatted date & timestamp in UTC.

### UUID

Universally unique identifier as defined by RFC 4122.

[title] Using GraphQL
[path] API for Restaurant Partners/Overview/

:::hint{type="warning"}
**Heads up!** The remainder of this guide assumes that your team is familiar with the use of API Clients, and are able to set up a connection via a client of your choice.&#x20;

All requests must be made to our GraphQL endpoint at [https://api.ezcater.com/graphql](https://api.ezcater.com/graphql) via HTTP POST with an ‘Authorization’ header using the generated token as its value.

If you have never used GraphQL before, there is a lot of good information and examples to be found at [https://graphql.org/learn](https://graphql.org/learn)
:::

GraphQL leverages a pattern called introspection, which allows you to query the endpoint for information about the schema and structures you can request. Tools like GraphQL will handle this automatically, providing an easy-to-navigate documentation that you can use to see what queries are available, what fields you can ask for and what the return values will look like.

***

# Building a Request

Make a POST request with your Query body to [https:/api.ezcater.com/graphql](https://https:/api.ezcater.com/graphql), using the following **headers**:

- `Content-Type`: `application/json`
- `Authorization`: `<Your API Token>`
- `Apollographql-client-name`: `<Your Organization Name/Identifier>`
- `Apollographql-client-version`: `<Your Software Version>`

In order for ezCater to properly track and troubleshoot requests to our API, all requests must be named. A collection of our naming convenstions for each query can be found at the bottom of this document.

:::hint{type="info"}
We recommend using a tool like **GraphiQL** for viewing all the fields that can be queried from the API. This section will give a brief overview of our top-level queries.
:::

### Template Query

```graphql
query <NAMEOFQUERY> {
     menus {
           Nodes {
               Id
               Name
               startDate
               endDate
           }
     }
}
```

### Query Examples

:::CodeblockTabs
menusByCaterer

```graphql
query menusByCaterer {
     menus {
          nodes {
               id
               name
               startDate
               endDate
          }
     }
}
```

\_\_schema

```graphql
query fullschema {
     __schema {
          types {
               name
               kind
               description
               fields {
                    name
               }
          }
     }
}
```

\_\_type

```graphql
query {
     __type(name: "Menu" ) {
          name
          kind
          description
          fields {
               name
          }
     }
}
```
:::

Once you have your API Token and have connected to our endpoint via an API Client, you can begin setting up your integration with the API.

[title] Features
[path] Restaurant Partner Integrations/General Menu Guidance/

:::ExpandableHeading
# Supported Features

The following provides a list and details regarding which menu features are supported by ezCater presently with the Menu Integration.

## Menu Per Location

Integrated menus are managed by location. Attributes of the menu can be modeled differently per location.  For pricing differences per location please ensure your pricing approach conforms with ezCater’s [pricing policy](https://catering.ezcater.com/en/help/what-are-the-pricing-requirements-for-my-menu).

## Categories

Sections that group items together.

## Items

The items you sell.

### Item Prices

The price of an item measured in cents. Item prices must be greater than $0.

### Item Sizes

Indicates the size of the item (e.g. Small, Medium, Large). If items only have one size, this field can be left blank. Some integrations only support one size per item. Please check your specific integration provider’s size support.

### Item Serving Sizes

A numeric field that allows the customer to know how much each item serves. We cannot accommodate ranges.

### Item Min and Max

Indicates the item minimum, maximum, or increment of ordering.

### Item Descriptions

A text field that includes level-setting information about what the item is

### Images

An image representative of the menu item. Review ezCater’s [technical requirements for photos](https://catering.ezcater.com/en/help/what-are-the-technical-requirements-for-photos-on-ezcater) to ensure they meet our technical requirements for images on ezCater menus.

### Tax Classifications

The tax designation of each item. Values stored by menu items describing tax classifications. The classification is used by ezCater to look up tax rates and charge taxes per order. Tags used to classify how a given item is taxed.
Values include:

- *BAKERY\_ITEMS*
- *CAKES\_AND\_PIES*
- *CANDY*
- *CHIPS\_AND\_SNACKS*
- *COFFEE\_TEA\_MILK*
- *DRESSINGS\_AND\_CONDIMENTS*
- *EXEMPT*
- *ICE\_CREAM*
- *MISCELLANEOUS*
- *NON\_SODA\_DRINKS*
- *PREPARED\_FOOD*
- *SANDWICHES*
- *SODA*
- *WATER*

## Tags

### Food Labeling and Dietary&#x20;

Describe qualities of an item or choice related to labeling.

- Values include: *GLUTEN\_FREE, HALAL, HEALTHY, KOSHER, SPICY, VEGAN, VEGETARIAN.*
- If an item is “*vegetarian*” when certain option choices are selected, then the option choices that are also vegetarian should also be tagged as “*vegetarian*” in addition to the item.

### Item Type and Choice Type

These values are specifically used for upsell opportunities. Please ensure all beverage and dessert items are tagged accordingly.

- Values include: *DESSERT, DRINKS, UTENSILS, ICE*  
- For items tagged as utensils, refer to the Utensils section.

## Quantity Unit

A Unit of Measure (UOM) for ordering items. Default to “*ITEM*” if not provided.

- Values include: *BAR, BOTTLE, BOWL, BOX, BUFFET, CAKE, CAN, CARAFE, DOZEN, FOOT, FULL\_PAN, GALLON, HALF\_GALLON, HALF\_PAN, ITEM, KIT, LITER, PACKAGE, PAN, PERSON, PIE, PIECE, PINT, PIZZA, PLATTER, POUND, QUART, ROLL, SIX\_PACK, SKEWER, SLIDER, TACO, TRAY, TWELVE\_PACK, TWO\_LITER*

## Options

A group of choices or item modifier selections. There are various features built into options:

### Required Option Choices

This feature requires customers to select a choice within an option before adding the item to cart.

These should only be turned on when there is a “selection” option where the customer is selecting a choice that is included with the menu item (i.e. selecting cheese for a sandwich). Required options should not be added to “optional” modifiers such as add-on options where every choice is an additional cost or in substitution options where the customer can substitute one choice for another (i.e. subbing gluten-free bread).

If there is a “*Most Popular*” or “*Assorted*” choice, those choices default to being selected.

### Min and Max Option Choices

The number of choices the customer can make for a given option. This number can be anywhere from 0 to unlimited.

### Option Prompts

The field on each option that dictates the prompt to the customer (i.e. “*Select Cheese*” or “*Add*”)

### Caterer Labels

Text fields within options that generate on the ezCater invoice for partners. This field can serve as a connector between the item and choice selection.

## Choices

The individual selections available for a given option.

### Choice Descriptions

A text field that includes level-setting information about what the choice is.

## Identification Mapping Data

An external id representing the third party identifier.

## Individual Wrap Status

Identifies if the item is individually wrapped.

## Sized Based Items

Used to delineate small, medium, large for items.

## Utensils

A general term used to describe the varying utensil items a customer will need. See the [Utensils Section](https://api.ezcater.io/utensils) for more information. 
:::

::::ExpandableHeading
# Unsupported Features

The following provides a list and details regarding which menu features are not currently supported by ezCater presently with the Menu Integration, and recommendations for workarounds where they may exist.

## Dayparts

ezCater currently does not support designating times of day for specific items on the menu.

:::hint{type="info"}
**RECOMMEND**: Add context in the item description (i.e. “Only available from 8am to 10am”).
:::

:::hint{type="danger"}
**NOTE:** This will not stop the customer from adding the item to their cart outside of the desired time frame.
:::

## 86’ing Items

ezCater currently does not support temporarily de-activating menu items. Items added to your menu should be considered highly available and stable items so that customers can order many weeks in advance.

:::hint{type="info"}
**RECOMMEND**: If items are marked as inactive or not sent to ezCater’s menu, the item will not be available for ordering.  This includes short term outages and many weeks into the future.

**NOTE:&#x20;**&#x49;f participating in the Menus API, light 86ing is available.
:::

## Quantity Modifiers

ezCater currently does not have the functionality for customers to add option quantities to an item (i.e. a customer selecting 4 turkey sandwiches, 5 ham sandwiches, and 1 hummus sandwich in a sandwich platter).

:::hint{type="info"}
**RECOMMEND**: Add option groups with naming to represent the selections. (Select First Sandwich, Select Second Sandwich, etc)
:::

## Nested Modifiers

ezCater currently does not have the functionality to have secondary options nested into initial options (i.e. a boxed lunch that comes with a choice of salad, which when selected, would open up a choice of salad dressing).

:::hint{type="info"}
**RECOMMEND**: Consider expanding choices to include the level of detail needed (i.e. House Salad w/ Ranch Dressing, House Salad w/ Italian Dressing, Spinach Salad w/ Italian Dressing, etc).
:::

## Pricing

### Zero Dollar Items

Items that do not have a price (items priced at $0) will not show on the ezCater marketplace.

:::hint{type="info"}
**RECOMMEND**: Determining a base price for an item and utilizing options if there are variations of price based on choice selection.
:::

### Negative Dollar Amount Option or Choice

ezCater does not support choice selections to decrease the price of an item.

:::hint{type="info"}
**RECOMMEND**: Create a separate item with a lower price.
:::
::::


[title] Other IdPs SSO Instructions - Meal Program Only
[path] Enterprise Account Integrations/SSO for Marketplace & Relish/

- Configure the following **SAML settings** in your IdP:
  - **Metadata URL:** [https://www.ezcater.com/saml/metadata.xml](https://www.ezcater.com/saml/metadata.xml)&#x20;**&#xA0;**
  - **Reply URL (ACS URL):&#x20;**[https://www.ezcater.com/saml/consume](https://www.ezcater.com/saml/consume)
  - **Audience URI (SP Entity ID)/Issuer/Entity ID:** ezcater.com
    - *Do NOT add https or www*
  - Release first name, last name, and email.
  - Use email as Name ID.
- **Redirect Meal Program app&#x20;**&#x75;ser sign-in: 
  - **User sign-in URL:&#x20;**[https://login.ezcater.com/relish/sso/domain\_redirect?domain=mycompany.com](https://login.ezcater.com/relish/sso/domain_redirect?domain=mycompany.com) (change this to your domain)
    - *Example:&#x20;*[https://login.ezcater.com/relish/sso/domain\_redirect?domain=example.com](https://login.ezcater.com/relish/sso/domain_redirect?domain=example.com)
  - Without redirection, IdP-initiated login will not be supported. 

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/ftA9FBWT5HmSVP-S-PYLT_ezcater-logo-dark-primary-symbol-300dpi.png" size="36" width="2084" height="1918" position="center" showCaption="false"}

- Submit your metadata through the [ezCater/Meal Program SSO Form](https://ezcaterforms.formstack.com/forms/ezcater_sso). These fields include:
  - **Your Domain(s)&#x20;**- any top level domain where the users receive emai&#x6C;*&#x20;Example: company.com*
  - **IdP SSO URL** - URL that ezCater will use to redirect a user to in order to authenticate with the IdP. *Example:&#x20;*[https://idp.example.com/sso/saml](https://idp.example.com/sso/saml)
  - **IdP Entity ID** - Unique identifier that ensures proper routing of authentication requests and responses. Also called Issuer. *Example:&#x20;*[https://idp.example.com/entity](https://idp.example.com/entity)
  - **Public Certificate&#x20;**- Also known as a digital certificate or an SSL/TLS certificate.


[title] Caterer Schema Reference
[path] API for Restaurant Partners/Caterers API/

# Caterer Schema Reference

## Objects

### Address

An address record. Can be for users, caterers, brands, etc.

| Field Name                                                     | Description                                                                                                               |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `city`: [String!](docId\:U2UigsYO0gfPXj-5tuif0)                | The name of the city where the address is located.                                                                        |
| `deliveryInstructions`: [String](docId\:U2UigsYO0gfPXj-5tuif0) | Specific instructions provided for the delivery, such as parking details or particular points of entry.                   |
| `name`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                 | The name associated with the address, which could be a business name or a contact person.                                 |
| `state`: [String!](docId\:U2UigsYO0gfPXj-5tuif0)               | The two-letter abbreviation for the state in which the address is located (e.g., MA for Massachusetts).                   |
| `stateName`: [String](docId\:U2UigsYO0gfPXj-5tuif0)            | The full name of the state corresponding to the address (e.g., Massachusetts).                                            |
| `street`: [String!](docId\:U2UigsYO0gfPXj-5tuif0)              | The primary street address or street line 1.                                                                              |
| `street2`: [String](docId\:U2UigsYO0gfPXj-5tuif0)              | The secondary street address or street line 2, used for additional address components such as apartment or suite numbers. |
| `street3`: [String](docId\:U2UigsYO0gfPXj-5tuif0)              | An additional address field for further granularity, often used for large complexes or extended addresses.                |
| `zip`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                  | The postal code for the address location.                                                                                 |

:::CodeblockTabs
Example

```graphql
{
  "city": "Boston",
  "deliveryInstructions": null,
  "name": "",
  "state": "MA",
  "stateName": "Massachusetts",
  "street": "12345 Restaurant Avenue",
  "street2": null,
  "street3": null,
  "zip": "54321"
}
```
:::

### Caterer

Return type of Caterer, representing a specific location providing catering.

| Field Name                                            | Description                                                                                                                                  |
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `address`: [Address](docId\:U2UigsYO0gfPXj-5tuif0)    | The physical location or mailing address of a store or entity, which can include various subfields such as street, city, state, and zip code |
| `live`: [Boolean!](docId\:U2UigsYO0gfPXj-5tuif0)      | Indicates whether an the caterer location is currently active, or operational.                                                               |
| `name`: [String!](docId\:U2UigsYO0gfPXj-5tuif0)       | The name associated with the caterer location.                                                                                               |
| `storeNumber`: [String](docId\:U2UigsYO0gfPXj-5tuif0) | A unique identifier assigned to each store. It is used to differentiate between different stores in a chain or franchise.                    |
| `uuid`: [UUID!](docId\:U2UigsYO0gfPXj-5tuif0)         |                                                                                                                                              |

:::CodeblockTabs
Example

```graphql
{
  "address": Address,
  "live": true,
  "name": "My Caterer Name",
  "storeNumber": "00001",
  "uuid": "ezcater-caterer-id"
}
```
:::

## Scalars

### Boolean

The Boolean scalar type represents true or false.

### ID

The ID scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as "4") or integer (such as 4) input value will be accepted as an ID.

### String

The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.

### UUID

Universally unique identifier as defined by RFC 4122



:::GraphiQL
```json
{
  "endpoint": "https://app.archbee.com/api/graphql",
  "query": "{\n  status,\n  people\n}"
}
```
:::


[title] Okta SSO Instructions - Meal Program App Only
[path] Enterprise Account Integrations/SSO for Marketplace & Relish/

- In the Okta Admin Portal within Applications, click on **Create App Integration**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd6mYD1fgzlZCOUWX_97XUkPC1_aqiNdmd98MQBRz8hw8kWvJDttDL8pK30xp0MPe5GUo6sX8IFgp7mbuxSDrnRoxZISVeZysdsFk3ilIvwyVSQRE-FOQAD6MEzl2gtcve8TgKqTw?key=AvWn09Y7CVz2HnQXem_NL67Q" size="42" width="494" height="330" position="center" darkWidth="494" darkHeight="330" showCaption="false"}

- Select **SAML 2.0** and click **Next**



::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd6H0ELb0znHrdBwicmc_i9XwfpdZKyToxkYy7x9Tuxysz2B8LUDq7sDo5j5U8ABLmwZQ92apfUPTzKuCN2ja5fFsEVBpAfo9S3-96kMIt0O-MZArbIFXQDD6zXnxIGReMTQVzN?key=AvWn09Y7CVz2HnQXem_NL67Q" size="68" width="1600" height="965" position="center" darkWidth="1600" darkHeight="965" showCaption="false"}

- Name this integration something like **“Meal Program SAML Configuration”&#xA0;**
- In App Settings, check the App visibility box **“Do not display application icon to users”**. The visible app will be configured as a bookmark with a specific redirect link. 
- Complete the fields as follows:
  - **Single sign-on URL:** [https://www.ezcater.com/saml/consume](https://www.ezcater.com/saml/consume)
  - **Audience URI (SP Entity ID):** ezcater.com
    - *Do&#x20;****NOT****&#x20;add https or www*
  - **Name ID format:&#x20;**&#x45;mailAddress
  - **Application username:** Okta username
- **&#xA0;  Update application username on:** Create and update

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcSsaE2H4Uw33AvQn8o5JTKwU0bX5YxNhPTHAwKnmEMSTb_A0Svyf_PS4ZxQWN1yBeW_UzauWu_aPF4gILID8id3r2KPMeZB3JaK4YNy_X954Pr2KtT8L3n4TsJ3rGIUZ3yyG3tLQ?key=AvWn09Y7CVz2HnQXem_NL67Q" size="78" width="1600" height="1423" position="center" darkWidth="1600" darkHeight="1423" showCaption="false"}



- In the final step, check the **This is an internal app…&#x20;**&#x6F;ption and click **Finish**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfVZcLvd5HYydagS-wQtQGYzwV1tYxNk7lVy8LfhvZjHieac-U7NnbGnL8VRpfudWA-uJfbAP0RDyUqJkgONNRUFFcfryLFUPk0rGRf_ycxNXeWym9MjMrSEPaxQ4pXPmt-bsUy?key=AvWn09Y7CVz2HnQXem_NL67Q" size="70" width="1600" height="734" position="center" darkWidth="1600" darkHeight="734" showCaption="false"}

- To add the Meal Program Bookmark App, return to your Okta Admin dashboard and click on the option to **Browse App Catalog**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdkAsACn3z5RvTQ36UotChmiCTHoWCS36mHI3p82Cn475v0_ZMDjvyMK2Rg_bNMcwepExRlhjEoBb30ys5BT__t5G1IPI1dh_UQMpg10S0mSFgM_IRFlY9eIKfj81Edr6Gng9t4Xg?key=AvWn09Y7CVz2HnQXem_NL67Q" size="70" width="678" height="236" position="center" darkWidth="678" darkHeight="236" showCaption="false"}

- Search for **Bookmark App&#x20;**&#x69;n the search bar and click on it

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXemcMTvWFjx53D2mTTFOmlFz4bLKLL6fTPSCLPX6bvWNzAZHbeIlMqL7bIHhX0wNhn70onthT8MzMkeHUwzBrJD-4qzMMy2DKW6w6_NAyF6dHD7iZhIeKp0wq4v5dPzuG7Nh4gPiQ?key=AvWn09Y7CVz2HnQXem_NL67Q" size="74" width="1186" height="554" position="center" darkWidth="1186" darkHeight="554" showCaption="false"}



- Click on where it says **Add Integration**

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXezc-qyOMYT7ZN3BQ6qU3rrheUbZ5M86KQvOkwWolUFhAt3JqcyaDgSpsp9amsdjr96Hab_YEECafKqISX17PkQCoWndUhhnc_vzOjc7uFstiDKaYCcumkd1XIunKvVE9MEuUpqiw?key=AvWn09Y7CVz2HnQXem_NL67Q)

- *Complete the fields as follows.  This is the app that will be visible to end users!*
- **Application label**: Meal Program&#x20;
  **URL**: [https://login.ezcater.com/relish/sso/domain\_redirect?domain=mycompany.com](https://login.ezcater.com/relish/sso/domain_redirect?domain=mycompany.com) (change this to your domain)
- Leave the rest of the fields as default and click on Done

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfwqkx3TN7XwVj0jccMU0HjMwnaMC4DKvXXrt8xbjmdum6IIhfE1mb_m9FyaOqXt-uSo3Xu9pSmranNd_uYNcyxGys8BbJU5VKXpmxxFFokfNIWvHRbKBXrbehEJeYogYOibkZLOw?key=AvWn09Y7CVz2HnQXem_NL67Q" size="76" width="1600" height="1359" position="center" darkWidth="1600" darkHeight="1359" showCaption="false"}

- To update the logo, click on the bookmark app and click on the **Pencil icon&#x20;**&#x6E;ext to the default star.

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdS5jvyJcsdz6CbVKc1F3Pp7lKH--6xiW3hiUa8NZsVYibDWaqKcTo0sJDc7NdkmWcstJX6TxHvzNYInazx4_DndHnbenwVKncqH7gaKdp2FfupXvngu_uDP8J5yRWMqKOm2ZZO8g?key=AvWn09Y7CVz2HnQXem_NL67Q" size="72" width="1090" height="414" position="center" darkWidth="1090" darkHeight="414" showCaption="false"}

- Add the Relish logo 

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/x_Rp2u8-R26CjgzzDcSaN_ezcater-logo-dark-primary-symbol-300dpi.png" size="34" width="2084" height="1918" position="center" showCaption="false"}

- Go back to the Meal Program app In Okta Admin and click on the **Sign On** tab

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeFmFhc4Y2Ehky85T8B9TwwGzAHx3bCV6PlTW82hsHUEPVqHtlbYijQMC178lDV27RbPnEFs3wVm_uMtTaC0qFlMdmJoTCzRpotsq1DLEuxucsziApwa7dd1SqGojHog1Yvo4ynqQ?key=AvWn09Y7CVz2HnQXem_NL67Q" size="76" width="869" height="385" position="center" darkWidth="869" darkHeight="385" showCaption="false"}

- On the right side of the page, click on the link for **View SAML setup instructions**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd6GB4bkBS3_7RcA-21YErSMidkt768eUqIDJDtuMG1SUg9QUs2AR32zGAtjr7k_3S3ZwoRDSU9JgcFt_3jWUDlh7yYeuzarIRlXpGxlCLvOZkEnkZOxXoEvp11ONRibO93CFOzCQ?key=AvWn09Y7CVz2HnQXem_NL67Q" size="28" width="548" height="1070" position="center" darkWidth="548" darkHeight="1070" showCaption="false"}

- Submit these settings through the [ezCater/Meal Program SSO Form ](https://ezcaterforms.formstack.com/forms/ezcater_sso)

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc-7Wk41WFmTME2JFwgyiPucidz-E7iZiOSgvEckajnehe7NnXpf0jZte5Q0c6tNsRgV03vPZFKnoo5TebrVGkaS1fSd_QX1PnYAnnVywtOYvbhn9rLbTSOZHVaJRoJqwblFdyUgw?key=AvWn09Y7CVz2HnQXem_NL67Q" size="84" width="1486" height="1410" position="center" darkWidth="1486" darkHeight="1410" showCaption="false"}


[title] Order Reject
[path] API for Restaurant Partners/Orders API/

# Rejecting Orders

Rejecting an **Order** requires a call to a mutation with the order `uuid` that is being rejected and some information about the reason why it is being rejecting. To be automatically be informed when an order has been `submitted` and can be `rejected` please see [Subscribing to Order Notifications](docId\:RwXIHCSBkoW9Wv238Z7mh) .

## Mutation

:::CodeblockTabs
Mutation

```graphql
mutation RejectOrder($orderId: ID!, $rejectOrderInput: RejectOrderInput!) {
  rejectOrder(orderId: $orderId, rejectOrderInput: $rejectOrderInput) {
    order {
      uuid
      lifecycle {
        orderIsCurrently
      }
    }
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables

```graphql
{
  "orderId": "your-ezcater-order-id",
  "rejectOrderInput": {
    "explanation": "This location can't accept any more orders for that delivery date",
    "reason": "AT_DAILY_CAPACITY"
  }
}
```
:::

### Arguments

| Argument Name                                                           | Description                                                                                       |
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `orderId`: [ID! ](docId\:U2UigsYO0gfPXj-5tuif0)                         | The ezCater order UUID that is provided within the payload of `Order` subscription notifications. |
| `rejectOrderInput`: [RejectOrderInput! ](docId\:U2UigsYO0gfPXj-5tuif0)  | A object providing an explanation for the rejection and the reason.                               |

### Return Type

Returns a [RejectOrderPayload](docId\:U2UigsYO0gfPXj-5tuif0).

## Success Response

When the `rejectOrder` mutation succeeds you can expect the response payload to look like:

:::CodeblockTabs
Response - Rejected

```graphql
{
  "data": {
    "rejectOrder": {
      "order": {
	    "uuid": "your-ezcater-order-id",
        "lifecycle": {
          "orderIsCurrently": "rejected"
        }
      }
    }
  }
}
```

Response - Cancelled

```graphql
{
  "data": {
    "rejectOrder": {
      "order": {
        "uuid": "aac3c94d-d4a5-456d-82b8-bbe7b4263cd5",
        "lifecycle": {
          "orderIsCurrently": "cancelled"
        }
      }
    }
  }
}
```
:::

:::hint{type="info"}
We have also created a new `rejected` order event notification which you will receive shortly afterwards, if you choose to subscribe to it via [Subscription Create](docId\:YWDS1a-gxebJWknE8V90S).
:::

## Failure Responses

`RejectOrder` calls may fail for a variety of reasons, such a: the order not being found, or the feature not being enabled for your brand. In the event that a `RejectOrder` call fails, one of the below errors will be returned.

### 404 Couldn’t find Order

You will get a 404 error when the specified order couldn’t be found.

:::CodeblockTabs
Response

```graphql
{
  "data": {
      "rejectOrder": null
    },
  "errors": [
        {
      	"message": "Couldn't find Order",
      	"locations": [
        	{
              "line": 6,
              "column": 3
    		}
		],
      	"path": [
          "rejectOrder"
        ],
      	"extensions": {
       		"type": "request",
        	"statusCode": 404
      		}
    	}
  	]
}

```
:::

### 403 Unauthorized

You will get a 403 error when the API user account doesn’t have permission to perform this action for this caterer location.

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "rejectOrder": null
  },
  "errors": [
    {
      "message": "You are not authorized to access this data",
      "locations": [
        {
          "line": 6,
          "column": 3
        }
      ],
      "path": [
        "rejectOrder"
      ],
      "extensions": {
        "type": "request",
        "statusCode": 403
      }
    }
  ]
}
```
:::

### Feature Not Enabled (feature\_not\_enabled)

You will get this error if this API feature has not yet been enabled for your brand.

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "rejectOrder": null
  },
  "errors": [
    {
      "message": "Feature not enabled for this caterer",
      "locations": [
        {
          "line": 6,
          "column": 3
        }
      ],
      "path": [
        "rejectOrder"
      ],
      "extensions": {
        "type": "summary",
        "code": "feature_not_enabled"
      }
    }
  ]
}
```
:::

### Invalid State Transition (invalid\_state\_transition)

You will get this error when the order is no longer in a valid state to be rejected (the order hasn’t been submitted yet, the customer may have canceled it, it may have already been accepted or rejected by API or one of the other channels for accepting / rejecting orders).

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "rejectOrder": null
  },
  "errors": [
    {
      "message": "Sorry, we were unable to reject this order.",
      "locations": [
        {
          "line": 6,
          "column": 3
        }
      ],
      "path": [
        "rejectOrder"
      ],
      "extensions": {
        "type": "summary",
        "code": "invalid_state_transition"
      }
    }
  ]
}
```
:::

##


[title] Integrations
[path] /


[title] Caterer List
[path] API for Restaurant Partners/Caterers API/

# Viewing Caterers

This query will return a list of all of the **Caterers** that your user has access to. It may be useful to include the address information so that you can know which `UUID` corresponds to which location.

:::hint{type="info"}
Currently, this query does not have paging. If your user has access to many locations, you may experience a large load time when running this.
:::

## Query

:::CodeblockTabs
Query

```graphql
query Caterers($ids: [ID!], $uuids: [ID!]) {
  caterers(ids: $ids, uuids: $uuids) {
    address {
      city
      deliveryInstructions
      name
      state
      stateName
      street
      street2
      street3
      zip
    }
    live
    name
    storeNumber
    uuid
  }
}
```

Query Alternate

```graphql
query Caterers {
  caterers {
    address {
      city
      deliveryInstructions
      name
      state
      stateName
      street
      street2
      street3
      zip
    }
    live
    name
    storeNumber
    uuid
  }
}
```
:::

### Variables

:::hint{type="info"}
The `ids` and `uuids` arguments are only necessary to if you want to filter the results to specific caterer locations. To return all caterers remove the arguments from the query or pass `NULL`.
:::

:::CodeblockTabs
Variables - UUIDs

```graphql
{
  "ids": null,
  "uuids": ["ezcater-caterer-1-id", "ezcater-caterer-2-id"]
}
```

Variables - NULL

```graphql
{
  "ids": null,
  "uuids": null
}
```
:::

### Arguments

| Argument Name                                    | Description                                                         |
| ------------------------------------------------ | ------------------------------------------------------------------- |
| `ids`: [\[ID!\]](docId\:pL8pdCBB1ebL-U3_fQodC)   | The ID for the caterer(s) for which you wish to view information    |
| `uuids`: [\[ID!\]](docId\:pL8pdCBB1ebL-U3_fQodC) | The UUID for the caterer(s) for which you wish to view information  |

### Return Type

Returns a [Caterer](docId\:pL8pdCBB1ebL-U3_fQodC).

## Successful Responses

When the `caterers` query succeeds you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "caterers": [
      {
        "address": {
          "city": "Boston",
          "deliveryInstructions": null,
          "name": "",
          "state": "MA",
          "stateName": "Massachusetts",
          "street": "12345 Restaurant Avenue",
          "street2": null,
          "street3": null,
          "zip": "54321"
        },
        "live": true,
        "name": "My First Caterer Name",
        "storeNumber": "0001",
        "uuid": "ezcater-caterer-1-id"
      },
      {
        "address": {
          "city": "Boston",
          "deliveryInstructions": null,
          "name": "",
          "state": "MA",
          "stateName": "Massachusetts",
          "street": "54321 Caterer Street",
          "street2": null,
          "street3": null,
          "zip": "12345"
        },
        "live": true,
        "name": "My Second Caterer Name",
        "storeNumber": "00002",
        "uuid": "ezcater-caterer-1-id"
      }
    ]
  }
}
```
:::

## Failure Responses

When the `caterers` query fails because you do not have permission to access the caterer location associated with the `uuid` provided you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "caterers": []
  }
}
```
:::


[title] Other IdPs SSO Instructions - ezCater Marketplace Only
[path] Enterprise Account Integrations/SSO for Marketplace & Relish/

- Configure the following **SAML settings** in your IdP:
  - **Metadata URL:&#x20;**[https://www.ezcater.com/saml/metadata.xml](https://www.ezcater.com/saml/metadata.xml)  
  - **Reply URL (ACS URL):&#x20;**[https://www.ezcater.com/saml/consume](https://www.ezcater.com/saml/consume)
  - **Audience URI/Issuer/Entity ID:&#x20;**&#x65;zcater.com
    - *Do NOT add https or www*
  - Release first name, last name, and email. 
  - Use email as Name ID
- Update the app logo with the image below:

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/LBf1IChgokNNZVeHcv3Wu_ezcater-logo-bright-primary-symbol-300dpi.png" size="44" width="2084" height="1918" position="center" showCaption="false"}

- Submit your metadata through the [ezCater/Meal Program SSO Form](https://ezcaterforms.formstack.com/forms/ezcater_sso). These fields include:
  - **Your Domain(s)&#x20;**- any top level domain where the users receive emai&#x6C;*&#x20;Example: company.com*
  - **IdP SSO URL** - URL that ezCater will use to redirect a user to in order to authenticate with the IdP. *Example:&#x20;*[https://idp.example.com/sso/saml](https://idp.example.com/sso/saml)
  - **IdP Entity ID** - Unique identifier that ensures proper routing of authentication requests and responses. Also called Issuer. *Example:&#x20;*[https://idp.example.com/entity](https://idp.example.com/entity)
  - **Public Certificate&#x20;**- Also known as a digital certificate or an SSL/TLS certificate.


[title] Order Schema Reference
[path] API for Restaurant Partners/Orders API/

# Order Schema Reference

## Objects

### Address

An address record. Can be for users, caterers, brands, etc

| Field Name                                                     | Description                                                                                                               |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `city`: [String!](docId\:U2UigsYO0gfPXj-5tuif0)                | The name of the city where the address is located.                                                                        |
| `deliveryInstructions`: [String](docId\:U2UigsYO0gfPXj-5tuif0) | Specific instructions provided for the delivery, such as parking details or particular points of entry.                   |
| `name`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                 | The name associated with the address, which could be a business name or a contact person.                                 |
| `state`: [String!](docId\:U2UigsYO0gfPXj-5tuif0)               | The two-letter abbreviation for the state in which the address is located (e.g., MA for Massachusetts).                   |
| `stateName`: [String](docId\:U2UigsYO0gfPXj-5tuif0)            | The full name of the state corresponding to the address (e.g., Massachusetts).                                            |
| `street`: [String!](docId\:U2UigsYO0gfPXj-5tuif0)              | The primary street address or street line 1.                                                                              |
| `street2`: [String](docId\:U2UigsYO0gfPXj-5tuif0)              | The secondary street address or street line 2, used for additional address components such as apartment or suite numbers. |
| `street3`: [String](docId\:U2UigsYO0gfPXj-5tuif0)              | An additional address field for further granularity, often used for large complexes or extended addresses.                |
| `zip`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                  | The postal code for the address location.                                                                                 |

:::CodeblockTabs
Example

```graphql
{
  "city": "Boston",
  "deliveryInstructions": "Ask for Jane at front desk",
  "name": "",
  "state": "MA",
  "stateName": "Massachusetts",
  "street": "12345 Restaurant Avenue",
  "street2": null,
  "street3": null,
  "zip": "54321"
}
```
:::

### AcceptOrderPayload

Return type of AcceptOrder.

| Field Name                                       | Description                      |
| ------------------------------------------------ | -------------------------------- |
| `order`: [Order!](docId\:U2UigsYO0gfPXj-5tuif0)  | A customer's order for catering. |

:::CodeblockTabs
Example

```graphql
{
  "order": Order!
}
```
:::

### Caterer

A caterer representing a specific location providing catering

| Field Name                                            | Description                                                                                                                                  |
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `address`: [Address](docId\:U2UigsYO0gfPXj-5tuif0)    | The physical location or mailing address of a store or entity, which can include various subfields such as street, city, state, and zip code |
| `live`: [Boolean!](docId\:U2UigsYO0gfPXj-5tuif0)      | Indicates whether an the caterer location is currently active, or operational.                                                               |
| `name`: [String!](docId\:U2UigsYO0gfPXj-5tuif0)       | The name associated with the caterer location.                                                                                               |
| `storeNumber`: [String](docId\:U2UigsYO0gfPXj-5tuif0) | A unique identifier assigned to each store. It is used to differentiate between different stores in a chain or franchise.                    |
| `uuid`: [UUID!](docId\:U2UigsYO0gfPXj-5tuif0)         |                                                                                                                                              |

:::CodeblockTabs
Example

```graphql
{
  "address": Address,
  "live": true,
  "name": "My Caterer Name",
  "storeNumber": "00001",
  "uuid": "ezcater-caterer-id"
}
```
:::

### CatererCart

Information about items on an order, from the caterer's perspective.

| Field Name                                                                                       | Description                                                                                                                                                                                        |
| ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `feesAndDiscounts(types: [FeeOrDiscountType!])`: [\[LineItem!\]!](docId\:U2UigsYO0gfPXj-5tuif0)  | Enumeration of various fees and discounts provided to the caterer.                                                                                                                                 |
| `orderItems`: [\[OrderItem!\]!](docId\:U2UigsYO0gfPXj-5tuif0)                                    | The specific items ordered by a customer. Each order item typically includes details such as the item's name, price, quantity, special instructions, and any associated options or customizations. |
| `tableware`: [Tableware](docId\:U2UigsYO0gfPXj-5tuif0)                                           | The collection of utensils and other tableware items included with the order, such as forks, knives, or plates                                                                                     |
| `totals`: [CatererTotals](docId\:U2UigsYO0gfPXj-5tuif0)                                          | The summarized financial details of the order, including subtotals, total due, taxes, tips, and overall amounts payable by the customer.                                                           |

:::CodeblockTabs
Example

```graphql
{
  "feesAndDiscounts": [LineItem!]!,
  "orderItems": [OrderItem!]!,
  "tableware": Tableware,
  "totals": CatererTotals
}
```
:::

### CatererTotals

Various order totals, from the caterer's perspective

| Field Name                                                | Description                                                                                 |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `catererTotalDue`: [Float](docId\:U2UigsYO0gfPXj-5tuif0)  | The sum of all order item prices, line items, and tip with commission and cc fee subtracted |

:::CodeblockTabs
Example

```graphql
{
  "catererTotalDue": 171.02
}
```
:::

### Event

Information about the event an order is associated with (e.g. time, date, location, etc.)

| Field Name                                                                                       | Description                                                                                                                                                                                                                                               |
| ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `address(shouldUseSearchAddress: Boolean = false)`: [Address](docId\:U2UigsYO0gfPXj-5tuif0)      | The location at which the order is expected to be delivered by the caterer. When `shouldUseSearchAddress: Boolean = true` then it includes the address the customer searched for (relevant for takeout orders)                                            |
| `catererHandoffFoodTime`: [UTCTimestamp](docId\:U2UigsYO0gfPXj-5tuif0)                           | The UTC timestamp indicating when the caterer must be ready to give prepared food to the customer or delivery partner.                                                                                                                                    |
| `contact`: [EventContact](docId\:U2UigsYO0gfPXj-5tuif0)                                          | On-site contact who will receive order on day-of event                                                                                                                                                                                                    |
| `customerProvidedName`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                                   | The name for the event that was provided by the customer                                                                                                                                                                                                  |
| `headcount`: [Int](docId\:U2UigsYO0gfPXj-5tuif0)                                                 | The number of people that an order is intended to serve                                                                                                                                                                                                   |
| `orderType(perspective: OrderTypePerspective)`: [ OrderTypeEnum!](docId\:U2UigsYO0gfPXj-5tuif0)  | The specific manner in which an order is processed or fulfilled.                                                                                                                                                                                          |
| `thirdPartyDeliveryPartner`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                              | The third party delivery partner's name.                                                                                                                                                                                                                  |
| `timeZoneIdentifier`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                                     | The Time Zone identifier of the event in a format like 'America/New\_York'. Full list of Time Zone Identifiers here:   [https://en.wikipedia.org/wiki/List\_of\_tz\_database\_time\_zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)  |
| `timeZoneOffset`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                                         | The UTC offset for time zone identifier, for example `-4:00`                                                                                                                                                                                              |
| `timestamp`: [UTCTimestamp](docId\:U2UigsYO0gfPXj-5tuif0)                                        | The UTC timestamp indicating when the customer expects to receive food.                                                                                                                                                                                   |

:::CodeblockTabs
Example

```graphql
{
  "address": Address,
  "catererHandoffFoodTime": "2025-03-27T16:15:00Z",
  "contact": EventContact,
  "customerProvidedName": "Team building event",
  "headcount": 10,
  "orderType": "DELIVERY",
  "thirdPartyDeliveryPartner": null,
  "timeZoneIdentifier": "America/New_York",
  "timeZoneOffset": "-04:00",
  "timestamp": "2025-03-27T16:30:00Z"
}
```
:::

### EventContact

On-site contact who will receive order on day-of event

| Field Name                                      | Description                                                         |
| ----------------------------------------------- | ------------------------------------------------------------------- |
| `name`: [String](docId\:U2UigsYO0gfPXj-5tuif0)  | The name of the on-site contact who will receive the order.         |
| `phone`: [String](docId\:U2UigsYO0gfPXj-5tuif0) | The phone number of the on-site contact who will receive the order. |

:::CodeblockTabs
Example

```graphql
{
  "name": "Jane Doe",
  "phone": "5555555555"
}
```
:::

### Money

Monetary information on tip and totals for an order

| Field Name                                              | Description                                                                                                                                                    |
| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `currency`: [Currency!](docId\:U2UigsYO0gfPXj-5tuif0)   | Allowed currency values for money.                                                                                                                             |
| `subunits:` [Int!](docId\:U2UigsYO0gfPXj-5tuif0)        | Monetary amount in currency sub-units (e.g. For US Dollars, this would be an amount in pennies); limited to 32-bit integer (`2_147_483_647 == $21_474_836.47`) |
| `subunitsV2`: [BigInt! ](docId\:U2UigsYO0gfPXj-5tuif0)  | Monetary amount in currency sub-units (e.g. For US Dollars, this would be an amount in pennies)                                                                |

:::CodeblockTabs
Example

```graphql
{
  "currency": "USD",
  "subunits": 23864,
  "subunitsV2": "23864"
}
```
:::

### LineItem

Order line items like taxes, fees, and discounts

| Field Name                                     | Description                                   |
| ---------------------------------------------- | --------------------------------------------- |
| `cost`: [Money](docId\:U2UigsYO0gfPXj-5tuif0)  | Monetary information for the order line item. |
| `name`: [String](docId\:U2UigsYO0gfPXj-5tuif0) | Name of the order line item.                  |

:::CodeblockTabs
Example

```graphql
{
  "cost": Money,
  "name": "Delivery Fee"
}
```
:::

### Order

A customer's catering order.

| Field Name                                                      | Description                                                                                                                              |
| --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `caterer`: [Caterer](docId\:U2UigsYO0gfPXj-5tuif0)              | A caterer representing a specific location  or store providing catering.                                                                 |
| `catererCart`: [CatererCart](docId\:U2UigsYO0gfPXj-5tuif0)      | The information about items on the order, from the caterer's perspective.                                                                |
| `deliveryId`: [ID](docId\:U2UigsYO0gfPXj-5tuif0)                | The globally-unique identifier of the delivery for the order.                                                                            |
| `event`: [Event](docId\:U2UigsYO0gfPXj-5tuif0)                  | Information about the order's event (e.g. time, date, location, etc.).                                                                   |
| `isTaxExempt`: [Boolean!](docId\:U2UigsYO0gfPXj-5tuif0)         | Whether or not this order is tax exempt.                                                                                                 |
| `lifecycle`: [OrderLifecycle](docId\:U2UigsYO0gfPXj-5tuif0)     | A description of where an Order is in it's lifecycle                                                                                     |
| `orderCustomer`: [OrderCustomer](docId\:U2UigsYO0gfPXj-5tuif0)  | Customer's contact information. For privacy reasons, this may not always be provided.                                                    |
| `orderNumber`: [String](docId\:U2UigsYO0gfPXj-5tuif0)           | Reference identifier to be used when interacting with support at ezCater                                                                 |
| `orderSourceType`: [OrderSource](docId\:U2UigsYO0gfPXj-5tuif0)  | The channel that an order comes in through                                                                                               |
| `taxableAddress`: [Address!](docId\:U2UigsYO0gfPXj-5tuif0)      | The address used to calculate sales tax for an order. This will either be the origin (store) address or the destination (event) address. |
| `totals`: [OrderTotals](docId\:U2UigsYO0gfPXj-5tuif0)           | Monetary information on order's tip and totals                                                                                           |
| `uuid`: [UUID!](docId\:U2UigsYO0gfPXj-5tuif0)                   | The ID of the specific order.                                                                                                            |

:::CodeblockTabs
Example

```graphql
{
  "caterer": Caterer,
  "catererCart": CatererCart,
  "deliveryId": "3593ce70-7227-4fd4-8a78-9591083d0674",
  "event": Event,
  "isTaxExempt": false,
  "lifecycle": OrderLifecycle,
  "orderCustomer": OrderCustomer,
  "orderNumber": "O1O1O1",
  "orderSourceType": "MARKETPLACE",
  "taxableAddress": Address!,
  "totals": OrderTotals,
  "uuid": "your-ezcater-order-id"
}
```
:::

### OrderCustomer

A copy of the customer's contact information associated with an order

| Field Name                                          | Description           |
| --------------------------------------------------- | --------------------- |
| `firstName`: [String](docId\:U2UigsYO0gfPXj-5tuif0) | Customers first name. |
| `lastName`: [String](docId\:U2UigsYO0gfPXj-5tuif0)  | Customers last name.  |
| `fullName`: [String](docId\:U2UigsYO0gfPXj-5tuif0)  | Customers full name.  |

:::CodeblockTabs
Example

```graphql
{
  "firstName": "Jane",
  "lastName": "Doe",
  "fullName": "Jane Doe"
}
```
:::

### OrderItem

Individual selections from the menu a customer has made for an order.

| Field Name                                                                      | Description                                                                                                         |
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `customizations`: [\[OrderItemCustomization!\]!](docId\:U2UigsYO0gfPXj-5tuif0)  | Selected customizations for the order item.                                                                         |
| `labelFor`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                              | The name of the person attached to the order item.                                                                  |
| `menuItemSizeId`: [UUID](docId\:U2UigsYO0gfPXj-5tuif0)                          | The ID corresponding with a specifically sized item in the caterer's menu.                                          |
| `menuItemSizeName`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                      | Size selected by the customer in string format.                                                                     |
| `name`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                                  | Name of the order item.                                                                                             |
| `noteToCaterer`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                         | A note to describe what's included in the item. Only visible to the caterer.                                        |
| `posItemId`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                             | The the posId for the size specified by the order item. This id represents the id of this item in an external API.  |
| `quantity`: [Int!](docId\:U2UigsYO0gfPXj-5tuif0)                                | Quantity of the specific order item.                                                                                |
| `specialInstructions`: [String](docId\:U2UigsYO0gfPXj-5tuif0)                   | Specific instructions written by the customer for this item                                                         |
| `totalInSubunits`: [Money](docId\:U2UigsYO0gfPXj-5tuif0)                        | Total cost of item, including customizations, in currency sub-units                                                 |
| `uuid`: [UUID!](docId\:U2UigsYO0gfPXj-5tuif0)                                   | The ID of the specific order item.                                                                                  |

:::CodeblockTabs
Example

```graphql
{
  "customizations": [OrderItemCustomization!]!,
  "labelFor": null,
  "menuItemSizeId": "ezcater-menu-version-size-12-inch-pizza-item-selection-id",
  "menuItemSizeName": "12\" Pizza",
  "name": "Margherita Pizza",
  "noteToCaterer": "12\" thin crust Margherita Pizza",
  "posItemId": "12-inch-pizza-item-selection-id",
  "quantity": 10,
  "specialInstructions": "Please be careful not to burn crust",
  "totalInSubunits": Money,
  "uuid": "83ec5c82-fa68-437c-90d7-ad861a2c151b"
}
```
:::

### OrderItemCustomization

Customizations for an order item

| Field Name                                                        | Description                                                                                       |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `customizationId`: [ID!](docId\:U2UigsYO0gfPXj-5tuif0)            | ID corresponding with a specifically sized item customization in the caterer's menu.              |
| `customizationTypeId`: [ID!](docId\:U2UigsYO0gfPXj-5tuif0)        | ID corresponding with a specific customization label in the caterer's menu.                       |
| `customizationTypeName`:  [String!](docId\:U2UigsYO0gfPXj-5tuif0) | Name corresponding with a specific customization label in the caterer's menu.                     |
| `name`:  [String!](docId\:U2UigsYO0gfPXj-5tuif0)                  | Name of the order item customization.                                                             |
| `posCustomizationId`: [String](docId\:U2UigsYO0gfPXj-5tuif0)      | POS ID corresponding with a specific customization in the caterer's menu.                         |
| `quantity`: [Int](docId\:U2UigsYO0gfPXj-5tuif0)                   | Count of items with this customization. Note that these items may also have other customizations. |

:::CodeblockTabs
Example

```graphql
{
  "customizationId": "ezcater-menu-version-customization-parmigiano-reggiano-choice-12-inch-selection-id",
  "customizationTypeId": "ezcater-menu-version-customization-type-cheese-addon-options-id",
  "customizationTypeName": "Cheese Addon",
  "name": "Parmigiano Reggiano",
  "posCustomizationId": "parmigiano-reggiano-choice-12-inch-selection-id",
  "quantity": 10
}
```
:::

### OrderLifecycle

Describes where an Order is in it's lifecycle

| Field Name                                                 | Description                         |
| ---------------------------------------------------------- | ----------------------------------- |
| `orderIsCurrently`: [String](docId\:U2UigsYO0gfPXj-5tuif0) | Where the Order is in its lifecycle |

:::CodeblockTabs
Example

```graphql
{
  "orderIsCurrently": "accepted"
}
```
:::

### OrderTotals

Monetary information on tip and totals for an order

| Field Name                                                          | Description                                                              |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| `customerTotalDue`: [Money!](docId\:U2UigsYO0gfPXj-5tuif0)          | The total amount that the customer owes for their order.                 |
| `pointOfSaleIntegrationFee`: [Money!](docId\:U2UigsYO0gfPXj-5tuif0) | Fee charged for using a specific pos system.                             |
| `salesTax`: [Money!](docId\:U2UigsYO0gfPXj-5tuif0)                  | The sales tax collected for the order.                                   |
| `salesTaxRemittance`: [Money!](docId\:U2UigsYO0gfPXj-5tuif0)        | The sales tax remitted by ezCater.                                       |
| `subTotal`: [Money!](docId\:U2UigsYO0gfPXj-5tuif0)                  | Total cost of all food items in an order.                                |
| `tip`: [Money](docId\:U2UigsYO0gfPXj-5tuif0)                        | The gratuities added to the order for the delivery or kitchen personnel. |

:::CodeblockTabs
Example

```graphql
{
  "customerTotalDue": Money!,
  "pointOfSaleIntegrationFee": Money!,
  "salesTax": Money!,
  "salesTaxRemittance": Money!,
  "subTotal": Money!,
  "tip": Money!
}
```
:::

### RejectOrderPayload

Return type of RejectOrder

| Field Name                                       | Description                     |
| ------------------------------------------------ | ------------------------------- |
| `order`: [Order!](docId\:U2UigsYO0gfPXj-5tuif0)  | A customer's order for catering |

:::CodeblockTabs
Example

```graphql
{
  "order": Order!
}
```
:::

### Tableware

A collection of tableware choices

| Field Name                                                                | Description                                            |
| ------------------------------------------------------------------------- | ------------------------------------------------------ |
| `specialInstructions`: [String](docId\:U2UigsYO0gfPXj-5tuif0)             | Instructions written by customer about tableware needs |
| `tablewareChoices`: [\[TablewareChoice!\]](docId\:U2UigsYO0gfPXj-5tuif0)  | Tableware selections a customer has made for the order |

:::CodeblockTabs
Example

```graphql
{
  "specialInstructions": null,
  "tablewareChoices": [TablewareChoice!]
}
```
:::

### TablewareChoice

Complimentary tableware items, such as plates, napkins, utensils

| Field Name                                             | Description                                                                 |
| ------------------------------------------------------ | --------------------------------------------------------------------------- |
| `choiceUuid`: [UUID!](docId\:U2UigsYO0gfPXj-5tuif0)    | ID corresponding with the tableware item in the caterer's menu.             |
| `isIncluded`: [Boolean!](docId\:U2UigsYO0gfPXj-5tuif0) | This boolean term indicates whether the tableware is included on the order. |
| `itemCount`: [Int!](docId\:U2UigsYO0gfPXj-5tuif0)      | The number of pieces of tableware included on the order.                    |
| `name`: [String!](docId\:U2UigsYO0gfPXj-5tuif0)        | The name or description of the tableware item on the order.                 |

:::CodeblockTabs
Example

```graphql
{
  "choiceUuid": "7acc72ed-2240-4b9f-a903-f7873b94ba60",
  "isIncluded": true,
  "itemCount": 10,
  "name": "Napkins"
}
```
:::

## Input Objects

### RejectOrderInput

Parameters for rejecting an order

| Field Name                                                       | Description                                                                                           |
| ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `explanation`: [String](docId\:U2UigsYO0gfPXj-5tuif0)            |                                                                                                       |
| `reason`: [RejectionReasonEnum! ](docId\:U2UigsYO0gfPXj-5tuif0)  | Provides a reason for rejecting the order. Not all of the reasons are relevant to an API integration. |

:::CodeblockTabs
Example

```graphql
{
  "explanation": "This location can't accept any more orders for that delivery date",
  "reason": "AT_DAILY_CAPACITY"
}
```
:::

## Enums

### Currency

Allowed currency values for money

| Enum Name | Description                      |
| --------- | -------------------------------- |
| `USD`     | Currency is in US dollars (USD). |

### FeeOrDiscountType

A list of fee or discounts types that can be included on an order. Applied to the `feesAndDiscounts` as a filter on the field's return type.

| Enum Name      | Description                                                                                                                                   |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `ADJUSTMENT`   | Adjustments can represent various alterations to the order total, such as refunds or corrections to previous charges.                         |
| `DELIVERY_FEE` | Delivery fees are charged to cover the cost associated with delivering the order from the caterer to the customer.                            |
| `DISCOUNT`     | Discounts are applied to reduce the total amount due for the customer, often as a promotional offer or incentive.                             |
| `MISC_FEE`     | Miscellaneous fees can include various charges that do not fall under standard categories, such as concierge or specific administrative fees. |

### OrderTypeEnum

Allowed values for order type

| Enum Name              | Description                                                                                                              |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `DELIVERY`             | The customer selects delivery, and the caterer is responsible for delivering the order themselves using their own fleet. |
| `TAKEOUT`              | The customers selects to pick up their order directly from the caterer's location, eliminating the need for delivery.    |
| `THIRD_PARTY_DELIVERY` | The customer selects delivery, and the caterer uses Dispatch, to deliver the order to the customer.                      |

### OrderTypePerspective

Allowed values for an order type perspective. Applied to the `orderType` as a filter on the field's return type.

| Enum Name  | Description                                                                    |
| ---------- | ------------------------------------------------------------------------------ |
| `CATERER`  | Filters `orderType` information to align with the perspective of the Caterer.  |
| `CUSTOMER` | Filters `orderType` information to align with the perspective of the Customer. |
| `EZCATER`  | Filters `orderType` information to align with the perspective of ezCater.      |

### OrderSource

Allowed values for order sources. An order source represents what user flow the order originated from

| Enum Name      | Description                                                                                                                                                                                                    |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CLUB_SODA`    | Order was placed through Club Soda, also known as Meal Program, a service that allows for grouping individual catering orders from multiple people into one larger order, typically for workplace consumption. |
| `DIRECT_ENTRY` | Order was placed through Direct Entry, a feature within ezCater that allows restaurant partners to submit their own orders directly into the system                                                            |
| `EZ_ORDERING`  | Order was placed through Online Ordering, an ordering platform supported by ezCater that enables restaurant partners to facilitate online orders through their own websites.                                   |
| `MARKETPLACE`  | Order was placed through the Marketplace, ezCater’s primary platform where users can place catering orders from a broad range of partner restaurants.                                                          |

### RejectionReasonEnum&#x20;

Allowed values for an order rejection reason, though some are unlikely to be relevant to an API integration.

| Enum Name                                  | Description                                                                                                         |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `AT_DAILY_CAPACITY`                        | Used when the caterer has reached their maximum order capacity for the entire day.                                  |
| `AT_HOURLY_CAPACITY`                       | Used when the caterer has reached their maximum number of orders for a specific hour, rather than for the full day. |
| `COMMISSION_OR_FEES_TOO_HIGH`              | Used when the caterer rejects an order because the commission or fees associated with it are deemed too high.       |
| `DISTANCE_TOO_FAR`                         | Used when the caterer rejects an order because the delivery distance is beyond their serviceable range.             |
| `DOES_NOT_OFFER_TAKE_OUT_OR_DELIVERY`      | Used when the caterer doesn't provide either takeout or delivery services.                                          |
| `DOES_NOT_REMEMBER_SIGNING_UP_FOR_EZCATER` | Used when the caterer claims no recollection of subscribing to ezCater services.                                    |
| `EMERGENCY_CLOSURE`                        | Used when unforeseen circumstances cause the caterer to shut down temporarily.                                      |
| `HOLIDAY_CLOSURE`                          | Used when the caterer has planned closures on holidays.                                                             |
| `LACK_OF_INVENTORY`                        | Used when the caterer has insufficient stock or ingredients.                                                        |
| `LEAD_TIME_TOO_SHORT_TO_DELIVER`           | Used when there's insufficient time to deliver the order as requested.                                              |
| `LEAD_TIME_TOO_SHORT_TO_PREPARE`           | Used when there's not enough time to prepare the order.                                                             |
| `MENU_INCORRECT`                           | Used when there are issues with the menu items specified in the order.                                              |
| `MISSING_CUSTOMER_CONTACT_INFORMATION`     | Used when the order cannot be fulfilled due to the lack of necessary customer contact details.                      |
| `NO_DRIVERS_AVAILABLE`                     | Used when there are no drivers available to deliver the order.                                                      |
| `NO_TIP`                                   | Used when the lack of a tip influences the caterer's decision to reject the order.                                  |
| `OWNERSHIP_CHANGED`                        | Used when the ownership of the caterer has changed, which affects the order fulfillment capabilities.               |
| `PERMANENTLY_CLOSED`                       | Used when the caterer has ceased operations permanently.                                                            |
| `REASON_NOT_LISTED`                        | Used when none of the listed reasons accurately describe the rejection. This is a catch-all category.               |
| `STAFF_SHORTAGE`                           | Used when there are not enough staff members to handle the order.                                                   |
| `TEMPORARILY_CLOSED`                       | Used when the caterer is temporarily closed for short-term reasons.                                                 |
| `WEATHER`                                  | Used when adverse weather conditions preventing order fulfillment.                                                  |
| `WRONG_HOURS`                              | Used when the order is placed outside of the caterer's operational hours.                                           |

## Scalars

### BigInt

Represents non-fractional signed whole numeric values. Since the value may exceed the size of a 32-bit integer, it's encoded as a string.

### Boolean

The Boolean scalar type represents true or false.

### Date

ISO-8601 Date-only string, e.g. 2017-12-14

### Float

The Float scalar type represents signed double-precision fractional values as specified by IEEE 754.

### ID

The ID scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as "4") or integer (such as 4) input value will be accepted as an ID.

### ISO8601DateTime

An ISO 8601-encoded datetime @specifiedBy(url: [https://tools.ietf.org/html/rfc3339](https://tools.ietf.org/html/rfc3339)).

### Int

The Int scalar type represents non-fractional signed whole numeric values. Int can represent values between `-(2^31)` and `2^31 - 1`.

### JSON

Represents untyped JSON.

### String

The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.

### UTCTimestamp

iso8601 formatted date & timestamp in UTC.

### UUID

Universally unique identifier as defined by RFC 4122.


[title] Public API for Catering Partners
[path] /

# Welcome to the ezCater Public API!

ezCater is excited to provide you with solutions and guidance focusing on business class food for the workplace integration solutions.  This site describes solutions focusing on connecting ezCater to Menu Management solutions, Order Management platforms and Delivery Management solutions.

This guide provides an overview of the processes involved in setting up ezCater’s Public API functionality and information about specific solutions and features. It also provides examples of how you can use these tools to pull information from ezCater and into your solutions. The Public API utilizes webhooks to allow you to pull information on order events and store menus into a Point of Sale or other integrated platforms, as well as exchange information regarding menu and delivery updates. In a general sense, you’ll need to:

1. Connect your ecosystem to ezCater via API users and tokens via GraphQL.&#x20;
2. Listen for events related to menu and order use cases.
3. Map stores from ezCater to your store technology.
4. Send menu content from your content management systems to ezCater’s menu catalog.
5. Orders API:  Process orders by accepting and rejecting orders via Partner Portal’s auto/manual processes or via integration and inject order data into store systems for fulfillment and other use cases.
6. Provide delivery tracking information to help consumers and support teams to assist with order fulfillment. This includes information such as: assigned courier, delivery lifecycle events, real time lat/lng information and delivery dropoff images.

***

:::ExpandableHeading
## Example Public API Workflow

1. **A brand team member creates or updates menu content to ensure customers have current and accurate information when placing an order**
2. **Customer places order on ezCater Marketplace**
3. **Customer receives Order Placed notification**
4. **Caterer receives Order Placed notification & accepts order**
   1. The order is accepted or rejected manually via Partner Portal, automatically via Partner Portal or via integration.
   2. 'Accepted' webhook notification sent to all Subscribed webhook URLs
      - Integrating Platform (vendor or brand) makes API Request Query using the order entity ID received within webhook payload
5. **Customer receives 'Order Accepted' notification**
6. **Optional: Customer initiates Modification or Cancellation**
   1. **Customer modifies order**
      - Customer may request modification online until Store’s Lead Time Cutoff time
      - ezCater Customer Service may execute modification at any time, including after order fulfillment, with approval from Store if under Lead Time Cutoff
      - Customer receives Modification Accepted notification after Caterer Accept
   2. **Customer cancels order**
      - Customer may request cancellation up to 24 hours of order fulfillment
      - ezCater Customer Service may cancel order at any time, with approval from Caterer if under 24 hours
7. **Optional: Caterer confirms Modification or Cancellation**
   1. **Cater confirms modification**
      - Modifications require additional Caterer Accept action
        - Once completed a new 'Accepted' webhook notification will be sent out, there is no 'Updated' notification
        - Integrating Partner/Brand is expected to check if 'Accepted' webhook is for new or existing order and handle accordingly
        - Caterer Accept may be completed either ezCater Customer Service with authorization from Store
   2. **Caterer confirms cancellation**
      - 'Canceled' webhook notification sent out
8. **Optional: Customer receives notification of confirmation of Modification or Cancellation**
9. **Customer gets 'Day of Confirmation' text**
10. **Food arrives right on time**
    - Store prepares food
    - Store may use Dispatch or their own drivers for delivery/setup
11. **Customer receives 'Receipt' email**
:::

:::hint{type="warning"}
**Special Call-Outs**

- Strategies on managing your brand's need for API Users and their subsequent Tokens will be discussed throughout the Implementations process.
- Order Query will advise whether Third Party Delivery (Dispatch) is active on the order, which means ezCater will not pay restaurant for either tip/gratuity or delivery fee, even if those values are present in the Order Query Response.
- The catering use case includes orders having multiple modifications prior to preparing the order.  ezCater recommends that prior to pushing orders to the POS for fulfillment that you ensure you have the latest order modifications.  This can be attained by performing an Order Query immediately prior to sending the order for fulfillment.
- Menu synchronization is an important part of the solution.
- Bulk updates to Store configuration cannot be made through the API

:::


[title] Menu Errors & Warnings
[path] API for Restaurant Partners/Menus API/

# Submission Errors&#x20;

**These errors are returned immediately to the API User, and prevent a Menu Creation Request from being created.**

| <font color="#0C121D">**Error Type**</font>    | <font color="#0C121D">**Example Responses**</font>                                                                                                                                                                                                                                                                                             | <font color="#0C121D">**Description**</font>                                                                                                                                                                                                                   | <font color="#0C121D">**Recommended Actions**</font>                                                                                                                                                              |
| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <font color="#0C121D">Required Fields</font>   | <font color="#0C121D">{"errors": [  ...  Field \"locationId\" of required type \"UUID!\" was not provided.",  ...]}</font><br /><font color="#0C121D"> </font><br /><font color="#0C121D">{"errors": [  ...  message": "Variable $menu of type MenuInput! was provided invalid value for locationId (\"\" is not a valid UUID)",  ...]}</font> | <font color="#0C121D">Fields that cannot be blank/null:
• location_id (UUID format required)
• pos_id (string)
• name (string)
• start_date (date format, cannot be blank)
• categories (array, minimum 1 required)
• items (array, minimum 1 required)</font> | - <font color="#0C121D">Ensure all required fields are provided</font>
- <font color="#0C121D">Verify UUID format for location_id</font>
- <font color="#0C121D">Use proper date format for start_date</font>     |
| <font color="#0C121D">Collection Length</font> | <font color="#0C121D">{"errors": [  ...  "message": "items is too short (minimum is 1)",  ...]}</font><br /><font color="#0C121D"> </font><br /><font color="#0C121D">{"errors": [  ...  "message": "selections is too short (minimum is 1)",  ...]}</font>                                                                                    | <font color="#0C121D">• Categories and items arrays must have at least 1 element
• Item selections must have 1-5 elements  
• Choice selections must have 1-5 elements</font>                                                                                  | * <font color="#0C121D">Provide at least one category and one item</font>
* <font color="#0C121D">Ensure each item has 1-5 selections</font>
* <font color="#0C121D">Ensure each choice has 1-5 selections</font> |
| <font color="#0C121D">Item Type Tag</font>     | <font color="#0C121D">{"errors": [  ...  "message": "The 'individuallyPackagedRelishSide' tag is only valid for choices, not for items",  ...]}</font>                                                                                                                                                                                         | - <font color="#0C121D">Specific business rule validation - this tag can only be applied to choices.</font>                                                                                                                                                    | * <font color="#0C121D">Remove 'individuallyPackagedRelishSide' from item item_type_tags</font>
* <font color="#0C121D">Apply this tag to appropriate choices instead</font>                                      |

# Runtime Errors

These errors are aggregated throughout the course of the Menu Creation, and are returned when the API user queries the [Status of a Menu Creation](https://api.ezcater.io/menu-creation-request).  If any of these errors are returned, the menu is not created

| <font color="#0C121D">**Error Type**</font>                 | <font color="#0C121D">**Example Responses**</font>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | <font color="#0C121D">**Description**</font>                                                                                                                                                                                                                                                                                                | <font color="#0C121D">**Recommended Actions**</font>                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <font color="#0C121D">Duplicate Property</font>             | <font color="#0C121D">{  "data": {    "menuCreationRequest": {      "status": "completed",      "outcome": "failure",      ...      "errors": [        {          "message": "Each member of the 'items' collection must have a unique 'pos_id'",          "details": {            "count": 2,            "pos_id": "item-1"          }        }        ...</font>                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | - <font color="#0C121D">Applies to categories, items, options, choices</font>
- <font color="#0C121D">pos_id must be unique within each collection</font>                                                                                                                                                                                   | * <font color="#0C121D">Ensure each pos_id is unique within categories, items, options, choices</font>
* <font color="#0C121D">Use consistent ID naming scheme (e.g., CAT001, CAT002 for categories)</font>
* <font color="#0C121D">Validate uniqueness before submission</font>                                                                                                                                                                                                                |
| <font color="#0C121D">Reference Validation</font>           | <font color="#0C121D">{  "data": {    "menuCreationRequest": {      "status": "completed",      "outcome": "failure",      ...      "errors": [        {          "message": "Referenced entity is not defined",          "details": {            "source": "categories",            "source_name": "Catering Packages",            "source_pos_id": "category-1",            "reference_type": "items",            "referenced_pos_id": "item-2"          }        }        ...</font>                                                                                                                                                                                                                                                                                                                                                       | <font color="#0C121D">• Items referenced by categories must exist (item_pos_ids)
• Options referenced by items must exist (option_pos_ids)
• Choices referenced by options must exist (choice_pos_ids)</font>                                                                                                                               | - <font color="#0C121D">Verify all referenced pos_id values exist in their collections</font>                                                                                                                                                                                                                                                                                                                                                                                                   |
| <font color="#0C121D">Selection Size</font>                 | <font color="#0C121D">{  "data": {    "menuCreationRequest": {      "status": "completed",      "outcome": "failure",      ...      "errors": [        {          "message": "Entity has duplicate selection sizes",          "details": {            "size": "1-5",            "entity_name": "XL Deep Dish Pizza",            "entity_pos_id": "item-1"          }        }      ]...</font>                                                                                                                                                                                                                                                                                                                                                                                                                                                | * <font color="#0C121D">Items cannot have multiple selections with the same size name</font>                                                                                                                                                                                                                                                | - <font color="#0C121D">Use distinct size names for item selections</font>
- <font color="#0C121D">Consider using size codes instead of names if needed</font>                                                                                                                                                                                                                                                                                                                                  |
| <font color="#0C121D">Choice Selection Logic</font>         | <font color="#0C121D">"menuCreationRequest": {      "status": "completed",      "outcome": "failure",      "menuUuid": null,      "errors": [        {          "message": "maxChoiceSelections must be greater than or equal to minChoiceSelections",          "details": {            "maxchoices": 1,            "minchoices": 5,            "entity_name": "Taco Bar",            "entity_pos_id": "option-2"          }        },        {          "message": "minChoiceSelections must be less than or equal to count of Choices",          "details": {            "minchoices": 5,            "entity_name": "Taco Bar",            "entity_pos_id": "option-2",            "choices_present": 3          }        }      ],</font>                                                                                                  | <font color="#0C121D">For an Option Group</font><br />- <font color="#0C121D">The Maximum number of choices must be greater than or equal to the required minimum</font>
- <font color="#0C121D">A minimum choices requirement must be less than or equal to the total number of choices available</font>                                   | * <font color="#0C121D">Ensure max_choice_selections &gt;= min_choice_selections</font>
* <font color="#0C121D">Set min_choice_selections = 0 if selections are optional</font>
* <font color="#0C121D">Reduce min_choice_selections to match available choices</font>
* <font color="#0C121D">Add more choices to the option</font>
* <font color="#0C121D">Review option design for usability</font>                                                                                          |
| <font color="#0C121D">Item-Choice Selection Mismatch</font> | <font color="#0C121D">{  "data": {    "menuCreationRequest": {      "status": "completed",      "outcome": "failure",      "menuUuid": null,      "errors": [        {          "message": "Choice must have either 1 selection, or &gt;= selections than associated item",          "details": {            "item_pos_id": "item-1",            "choice_pos_id": "choice-1",            "option_pod_id": "option-1"          }        }      ],</font>                                                                                                                                                                                                                                                                                                                                                                                       | - <font color="#0C121D">To ensure pricing structure is consistent between items and choices, a choice must have either 1 selection, or greater than or equal to the number of selections of the associated item</font>                                                                                                                      | * <font color="#0C121D">Standardize selection structures across items and choices</font>
* <font color="#0C121D">Use single-selection choices when possible</font>                                                                                                                                                                                                                                                                                                                              |
| <font color="#0C121D">Zero Priced Items</font>              | <font color="#0C121D">{  "data": {    "menuCreationRequest": {      "status": "completed",      "outcome": "failure",      "menuUuid": null,      "errors": [        {          "message": "Too many zero priced items",          "details": {            "threshold": 100,            "zero_price_percentage": 100          }        }      ],</font>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | - <font color="#0C121D">This error is returned when no menu items have a price</font>                                                                                                                                                                                                                                                       | * <font color="#0C121D">Review pricing strategy</font>
* <font color="#0C121D">Ensure at least some items have prices &gt; 0</font>
* <font color="#0C121D">Consider if zero-priced items are intentional</font>                                                                                                                                                                                                                                                                                |
| <font color="#0C121D">Meal Program Channel</font>           | <font color="#0C121D">{  "data": {    "menuCreationRequest": {      "status": "completed",      "outcome": "failure",      "menuUuid": null,      "errors": [        {          "message": "Item must have quantityOptions of '&gt;1'",          "details": {            "item_pos_id": "item-1",            "quantity_options": "&gt;5"          }        },        {          "message": "Selection must have serves = 1",          "details": {            "serves": 5,            "item_pos_id": "item-1",            "selection_pos_id": null          }        },        {          "message": "Item cannot have a choice with enableSubQuantities = true",          "details": {            "item_pos_id": "item-1",            "choice_pos_id": "choice-1",            "option_pos_id": "option-1"          }        }      ],</font> | <font color="#0C121D">If an item services the “Meal Program” channel </font><br />* <font color="#0C121D">It must be available to the customer in quantities of 1</font>
* <font color="#0C121D">All selection sizes within the item must serve 1</font>
* <font color="#0C121D">It cannot have a choice with sub quantities enabled</font> | - <font color="#0C121D">Set quantity_options: "&gt;1" for Meal Program items</font>
- <font color="#0C121D">Review channel-specific requirements</font>
- <font color="#0C121D">Set serves: 1 for all selections on Meal Program items</font>
- <font color="#0C121D">Review serving size logic</font>
- <font color="#0C121D">Remove enable_sub_quantities from choices on Meal Program items</font>
- <font color="#0C121D">Review choice configuration for Meal Program compatibility</font> |
| <font color="#0C121D">Utensils</font>                       | <font color="#0C121D">{  "data": {    "menuCreationRequest": {      "status": "completed",      "outcome": "failure",      "menuUuid": null,      "errors": [        {          "message": "Option 'Toppings Deep Dish Catering' mixes utensil and non-utensil choices.",          "details": {            "option_name": "Toppings Deep Dish Catering",            "option_pos_id": "option-1"          }        },        {          "message": "Option 'Utensils' with utensil choices must not have min_choice_selections &gt; 0.",          "details": {            "option_name": "Utensils",            "option_pos_id": "utensils-1"          }        }      ],</font>                                                                                                                                                               | * <font color="#0C121D">An Option Group cannot mix utensil and non utensil choices</font>
* <font color="#0C121D">A Utensil Option Group cannot have required choices, utensils should always be optional</font>                                                                                                                            | - <font color="#0C121D">Separate utensil choices into dedicated options</font>
- <font color="#0C121D">Review utensil choice categorization</font>
- <font color="#0C121D">Use choice_type_tags properly</font>
- <font color="#0C121D"> Set min_choice_selections: 0 for utensil options</font>
- <font color="#0C121D">Make utensil selection customer-optio</font>nal                                                                                                                        |

# Runtime Warnings

These are warnings that are aggregated during the course of Menu Creation.  They do not prevent the menu from being created but are intended to highlight what we consider menu deficiencies.  These are also returned as an array within the [Status of a Menu Creation](https://api.ezcater.io/menu-creation-request)

| <font color="#0C121D">**Warning Type**</font>          | <font color="#0C121D">**Example Responses**</font>                                                                                                                                                                                                                                                                                                                                                                                                                                              | <font color="#0C121D">**Description**</font>                                                                                                                                                               | <font color="#0C121D">**Recommended Actions**</font>                                                                                                                                                                             |
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <font color="#0C121D">Image Extension</font>           | <font color="#0C121D">{  "data": {    "menuCreationRequest": {      "status": "completed",      "outcome": "success_with_warnings",      "menuUuid": "8eedb10c-8766-4241-9b66-cf471ad73534",      "warnings": [        {          "message": "Invalid extension for file referenced by imageUrl.  Image will not be displayed.",          "details": {            "imageUrl": "test_image.xml",            "entityType": "item",            "entityPosId": "item-1"          }        },</font> | <font color="#0C121D">Acceptable Image Extensions</font><br />* <font color="#0C121D">gif</font>
* <font color="#0C121D">jpg</font>
* <font color="#0C121D">jpeg</font>
* <font color="#0C121D">png</font> | - <font color="#0C121D">Convert images to supported formats</font>
- <font color="#0C121D">Update image URLs to point to supported formats</font>
- <font color="#0C121D">Verify image URLs are accessible</font>                |
| <font color="#0C121D">Mutually Exclusive Fields</font> | <font color="#0C121D">{  "data": {    "menuCreationRequest": {      "status": "completed",      "outcome": "success_with_warnings",      "menuUuid": "0c44976c-cef3-436c-96d3-91d470a8decf",      "errors": [],      "warnings": [        {          "message": "Item 'item-1' has both 'lead_time' and 'day_before_cutoff_time' defined, please provide only one.",          "details": {}        },</font>                                                                                    | * <font color="#0C121D">Items with both lead_time and day_before_cutoff_time will default to lead_time</font>                                                                                              | - <font color="#0C121D">Choose appropriate timing method for your business model</font>
- <font color="#0C121D">Remove one of the conflicting fields</font>
- <font color="#0C121D">Review timing logic consistency</font>       |
| <font color="#0C121D">Missing Utensils</font>          | <font color="#0C121D">{  "data": {    "menuCreationRequest": {      "status": "completed",      "outcome": "success_with_warnings",      "menuUuid": "0c44976c-cef3-436c-96d3-91d470a8decf",      "warnings": [        {          "message": "Item does not have a utensil choice mapped",          "details": {            "item_name": "Taco Bar",            "item_pos_id": "item-2"          }        },</font>                                                                             | * <font color="#0C121D">ezCater encourages all Items have a utensils option associated with it.  </font>                                                                                                   | - <font color="#0C121D">Add utensil options to items</font>
- <font color="#0C121D">Create utensil choices with proper choice_type_tags</font>
- <font color="#0C121D">Review if utensils are required for specific items</font> |
| <font color="#0C121D">Zero Priced Item</font>          | <font color="#0C121D">{  "data": {    "menuCreationRequest": {      "status": "completed",      "outcome": "success_with_warnings",      "menuUuid": "0c44976c-cef3-436c-96d3-91d470a8decf",      "errors": [],      "warnings": [        {          "message": "Item with pos_id item-2-sel-1 has a price of $0.00.  It will not be displayed.",          "details": {}        }</font>                                                                                                        | * <font color="#0C121D">We do not support $0 Items on the Marketplace, they will be created but not shown to customers</font>                                                                              |                                                                                                                                                                                                                                  |


[title] Okta SSO Instructions - ezCater Marketplace App Only
[path] Enterprise Account Integrations/SSO for Marketplace & Relish/

- In the Okta Admin Portal within Applications, click on **Create App Integration**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd6mYD1fgzlZCOUWX_97XUkPC1_aqiNdmd98MQBRz8hw8kWvJDttDL8pK30xp0MPe5GUo6sX8IFgp7mbuxSDrnRoxZISVeZysdsFk3ilIvwyVSQRE-FOQAD6MEzl2gtcve8TgKqTw?key=AvWn09Y7CVz2HnQXem_NL67Q" size="42" width="494" height="330" position="center" darkWidth="494" darkHeight="330" showCaption="false"}

- Select **SAML 2.0** and click **Next**



::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd6H0ELb0znHrdBwicmc_i9XwfpdZKyToxkYy7x9Tuxysz2B8LUDq7sDo5j5U8ABLmwZQ92apfUPTzKuCN2ja5fFsEVBpAfo9S3-96kMIt0O-MZArbIFXQDD6zXnxIGReMTQVzN?key=AvWn09Y7CVz2HnQXem_NL67Q" size="68" width="1600" height="965" position="center" darkWidth="1600" darkHeight="965" showCaption="false"}

- Name this integration **“ezCater”&#xA0;**
- In App Settings, check the App visibility box **“Do not display application icon to users”**. The visible app will be configured as a bookmark with a specific redirect link. 
- Complete the fields as follows:
  - **Single sign-on URL:** [https://www.ezcater.com/saml/consume](https://www.ezcater.com/saml/consume)
  - **Audience URI (SP Entity ID):** ezcater.com
    - *Do&#x20;****NOT****&#x20;add https or www*
  - **Name ID format:&#x20;**&#x45;mailAddress
  - **Application username:** Okta username
- **&#xA0;  Update application username on:** Create and update

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcSsaE2H4Uw33AvQn8o5JTKwU0bX5YxNhPTHAwKnmEMSTb_A0Svyf_PS4ZxQWN1yBeW_UzauWu_aPF4gILID8id3r2KPMeZB3JaK4YNy_X954Pr2KtT8L3n4TsJ3rGIUZ3yyG3tLQ?key=AvWn09Y7CVz2HnQXem_NL67Q" size="78" width="1600" height="1423" position="center" darkWidth="1600" darkHeight="1423" showCaption="false"}



- In the final step, check the **This is an internal app…&#x20;**&#x6F;ption and click **Finish**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfVZcLvd5HYydagS-wQtQGYzwV1tYxNk7lVy8LfhvZjHieac-U7NnbGnL8VRpfudWA-uJfbAP0RDyUqJkgONNRUFFcfryLFUPk0rGRf_ycxNXeWym9MjMrSEPaxQ4pXPmt-bsUy?key=AvWn09Y7CVz2HnQXem_NL67Q" size="70" width="1600" height="734" position="center" darkWidth="1600" darkHeight="734" showCaption="false"}

- Return to your Okta Admin dashboard and click on the option to **Browse App Catalog**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdkAsACn3z5RvTQ36UotChmiCTHoWCS36mHI3p82Cn475v0_ZMDjvyMK2Rg_bNMcwepExRlhjEoBb30ys5BT__t5G1IPI1dh_UQMpg10S0mSFgM_IRFlY9eIKfj81Edr6Gng9t4Xg?key=AvWn09Y7CVz2HnQXem_NL67Q" size="70" width="678" height="236" position="center" darkWidth="678" darkHeight="236" showCaption="false"}

- Search for **ezCater&#x20;**&#x69;n the search bar and click on it
- To update the logo, click on the **Pencil icon** next to the default star.

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdq2RB0jhKM4eW1DaFpPhsTpqe_DD5CGVIz7AXNgDi9W4h8Hsb-cH3H6QN_veH2qy2BtbAXE5ku92dAFOn39FCx5SYBDG5JULC1lhUmx1MIMESNfEqsx0N4Fhxd1KVqfpb5cv2QJQ?key=AvWn09Y7CVz2HnQXem_NL67Q" size="78" width="884" height="392" position="center" darkWidth="884" darkHeight="392" showCaption="false"}

- Add the ezCater logo 

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/TRsMpEF1r0r8OdMQMq48n_ezcater-logo-bright-primary-symbol-300dpi.png" size="26" width="2084" height="1918" position="center" showCaption="false"}

- Go back to the ezCater app in the Okta Admin App Catalog and click on the **Sign On** tab

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeHl2lmHVj5qIB6ydcYrQcfMyNqzCDOFEiFCqA6pJlhVLfyNnkHc_jUjzlSZV4cR8ltnOq5fGhcnjFmR5yFMEVpatkyEsNBW7R0NPYXC__BHcJsASrBa8XAjrqYqORhnNeAIHU-YQ?key=AvWn09Y7CVz2HnQXem_NL67Q" size="62" width="867" height="375" position="center" darkWidth="867" darkHeight="375" showCaption="false"}

- On the right side of the page, click on the link for **View SAML setup instructions**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd6GB4bkBS3_7RcA-21YErSMidkt768eUqIDJDtuMG1SUg9QUs2AR32zGAtjr7k_3S3ZwoRDSU9JgcFt_3jWUDlh7yYeuzarIRlXpGxlCLvOZkEnkZOxXoEvp11ONRibO93CFOzCQ?key=AvWn09Y7CVz2HnQXem_NL67Q" size="28" width="548" height="1070" position="center" darkWidth="548" darkHeight="1070" showCaption="false"}

- Submit these settings through the [ezCater/Meal Program SSO Form ](https://ezcaterforms.formstack.com/forms/ezcater_sso)

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc-7Wk41WFmTME2JFwgyiPucidz-E7iZiOSgvEckajnehe7NnXpf0jZte5Q0c6tNsRgV03vPZFKnoo5TebrVGkaS1fSd_QX1PnYAnnVywtOYvbhn9rLbTSOZHVaJRoJqwblFdyUgw?key=AvWn09Y7CVz2HnQXem_NL67Q" size="84" width="1486" height="1410" position="center" darkWidth="1486" darkHeight="1410" showCaption="false"}


[title] Courier Unassign
[path] API for Restaurant Partners/Delivery API/

# Unassigning a Courier

In the event that you previously had a courier assigned to a delivery but no longer do, you can use our `courierUnassign` mutation to let us know that no courier is currently assigned to the delivery.

## Mutation

:::CodeblockTabs
Mutation

```graphql
mutation CourierUnassign($input: CourierUnassignInput!) {
  courierUnassign(input: $input) {
    clientMutationId
    delivery {
      id
    }
    userErrors {
      ... on DeliveryValidationError {
        message
        path
      }
    }
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables

```graphql
{
  "input": {
    "clientMutationId": "your-mutation-id",
    "courier": {
      "id": "your-courier-id",
      "firstName": "Test",
      "lastName": "Courier",
      "phone": "+15555555555",
      "vehicle": {
        "make": "Your Vehicle Make",
        "model": "Your Vehicle Model",
        "color": "Your Vehicle Color"
      }
    },
    "deliveryId": "ezcater-delivery-id"
  }
}
```
:::

### Arguments

| Argument Name                                                   | Description                                 |
| --------------------------------------------------------------- | ------------------------------------------- |
| `input`: [CourierUnassignInput! ](docId:7gV344RnWmuokNj9u4rW7)  | The Input object for unassigning a courier. |

### Return Type

Returns a [CourierUnassignPayload](docId:7gV344RnWmuokNj9u4rW7).

## Success Response

When the `courierUnassign` mutation succeeds you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "courierUnassign": {
      "clientMutationId": "your-mutation-id",
      "delivery": {
        "id": "8eb96ea0-2018-4f6a-9b00-75b169aaebd9"
      },
      "userErrors": []
    }
  }
}
```
:::




[title] Olo Rails Integration
[path] Restaurant Partner Integrations/

## Olo Rails Integration Overview

The Catering Integration functions for sales and inventory reconciliation. It reduces the operational lift from the store operators by not requiring them to manually enter every order into the POS system, ultimately reducing errors and helping ensure proper sales are being recorded.&#x20;

![Olo rails Integrated Order Flow](https://archbee-image-uploads.s3.amazonaws.com/CnBnWfHDNa9lZK7nmY_mG-UJmkKAE8xmloKnRF_0X_g-20250127-181806.png "Olo Rails Integrated Order Flow")

## Order Acceptance

:::hint{type="warning"}
How are orders accepted?
:::

As a part of the natural workflow with ezCater, all orders when placed, must be accepted via Partner Portal. Store Managers and/or those managing the catering orders will be notified of new orders via email, SMS or iOS Push Notifications.

This notification then leads the operator into Partner Portal, where they will review the order details and click a button to acknowledge and “Accept” the order.

By doing so, they are making a commitment to fulfill and should be considered aware of the order. If this is a new ezCater Brand/Caterer, as a part of onboarding, we will train this process as well provide details on additional reminder notifications.

## Order Transmission

:::hint{type="warning"}
Once the order has been accepted, when is it sent over to Olo?
:::

Immediately upon acceptance, the order is sent to Olo Rails.&#x20;

From there, the configuration of Olo Rails determines how the order is treated. It will sit in a scheduled state and be visible in Olo Rails until the configured Lead Time. Order will push to the POS based on Olo’s “Fire to POS” setting.

Further details on this should be explored with your Olo Rep as at this point, the order resides within the Olo environment.

:::hint{type="warning"}
What ezCater orders will transmit through the API?
:::

ezCater Marketplace and Online Ordering orders will transmit through the API. Off menu items are not supported through the integration.

## Order Fire

:::hint{type="warning"}
When does the order fire? Does it fire based on some preset make time, or do all advance orders fire at the same time?
:::

Ultimately, this is for your Olo Rep to provide details. ezCater does not control what happens on the Olo side.&#x20;

That being said, it is our understanding that each order will fire to the POS based on your Olo configured Lead times.

## Data Transmission

:::hint{type="warning"}
Once the order has been accepted, when is it sent over to Olo? What information about the order / delivery is passed through to Olo and visible in Olo?
:::

At this time, the Order details (Menu Items and selections) are passed through based on mapped ID’s between Olo Rails and ezCater. The Fulfillment date/time is also provided. The customer for all of these orders is ezCater. As such the customer information is all based on ezCater. The Email address passed is an ezCater email that references the order number. There is no phone number passed. Any questions should go through ezCater Customer Support (This will be trained as well during onboarding). Self delivery and Dispatch are supported through this integration. We send through all delivery details (delivery address, delivery fee, delivery time, delivery instructions, and tip).

Today, the time in Olo will be the customer’s requested event time, not when the driver will be picking up the order. Please use Partner Portal to verify pick up and delivery times.

## Order Failures

:::hint{type="warning"}
What are the reasons an order might fail?
:::

There are a number of reasons for an order to fail. A few are as follows:

- Store Closed
- System Timeout
- Updated/Canceled order – Locked/in past
- Error Validating Basket
- Missing Required Selection
- Online Ordering unavailable
- Time settings and lead times not matching between the platforms
- Incorrect configurations in Olo/POS
- Order throttling
- POS is offline at time of transmission
- Incomplete order details

## Payment Processing

:::hint{type="warning"}
Is ezCater still acting as the payment processor and the billing/commission structure is the same?
:::

Yes, that is correct. Please note though, that with the Olo Integration comes an additional fee per order. The integration fee will be taken from the weekly payments that are remitted to the stores.

Please be aware that Promotions, Preferred Partner Program, Rewards, and Commissions are not passed through the integration. You will receive the value of the order to the guest in Olo.&#x20;

## Unscheduled Outages

:::hint{type="warning"}
What are your operational practices if Olo is offline (either due to disabling/closure or due to internet connection/outages)? If the order doesn’t fire, what happens?What are your operational practices if Olo is offline (either due to disabling/closure or due to internet connection/outages)? If the order doesn’t fire, what happens?
:::

In the event that Olo is unreachable, a notification via email and/or SMS is sent to the team. Failure notifications will be sent to all who receive new order notifications that the order was not able to be passed into Olo and thus this order will need to be manually entered.&#x20;

There is no cancellation of the order, it is still expected to be fulfilled as the details remain available via Partner Portal.

## Get Started

:::hint{type="warning"}
Interested in our Olo Rails integration?
:::

Our team at ezCater is currently working through a long list of partners to get them onboarded with [Olo Rails](https://olosupport.zendesk.com/hc/en-us/articles/115005664963-Rails-Overview). If you’re interested in this integration, please reach out to [integrations@ezcater.com](https://integrations@ezcater.com) to begin the next steps.&#x20;


[title] Error Code Reference
[path] Restaurant Partner Integrations/Olo Rails Integration/

This document outlines error codes and recommendations for order transmission between ezCater and Olo. Although the majority of the specific error codes pertain to menu discrepancies, the more general codes others are due to factors such as store availability, required lead times, or point-of-sale system settings and issues.

For a downloadable version please use the link below:

::File{src="https://archbee-doc-uploads.s3.amazonaws.com/CnBnWfHDNa9lZK7nmY_mG-wOOf24CsPuS926qSXJqWz-20250319-224101.pdf" label="ezCater & Olo - Error Code Reference.pdf"}

::::ExpandableHeading
# Example

Each error code in this document can be expanded or collapsed and displays as follows:

:::hint{type="warning"}
***Error Message(s)***

- Example error message text
- Different example error message text
:::

:::hint{type="info"}
Suggestions and/or recommendations for how to correct for the error messages received.&#x20;
:::
::::

***

::::ExpandableHeading
# 1. Deserialized Request

:::hint{type="warning"}
***Error Definition***

- Invalid request, missing fields, incomplete data, etc
:::

:::hint{type="info"}
Most often is an issue with the menu data being sent from ezCater to Olo. Menu updates might be required. Please reach out to ezCater support integrations\@ezcater.com or use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 3. Insufficient Access to Vendor

:::hint{type="warning"}
***Error Definition***

- ezCater does not have access to the requested restaurant
:::

:::hint{type="info"}
Verify that the correct Olo Location/Store ID is being used for order transmissions, and ensure ezCater has been granted access through the Olo dashboard. If you are unsure how to grant access, please review [this](https://olosupport.zendesk.com/hc/en-us/articles/360045286812-Rails-Management-Control-access-markup-pricing-and-roundup) document.&#x20;
If you still need assistance, you can use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center.
:::
::::

::::ExpandableHeading
# 10. Generic Error Code

:::hint{type="warning"}
***Error Definition***

- Awide variety of possible errors, but is often a menu related issue on the ezCater end
:::

:::hint{type="info"}
Please reach out to ezCater support [integrations@ezcater.com](mailto\:integrations@ezcater.com) and / or use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 200. Generic Error Code

:::hint{type="warning"}
***Error Definition***

- A wide variety of possible errors, but is often related to lead time discrepancies or menu related issues.
:::

:::hint{type="info"}
Please reach out to ezCater support [integrations@ezcater.com](mailto\:integrations@ezcater.com) and / or use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 206. Invalid Advance Time

:::hint{type="warning"}
***Error Definition***

- The order cannot be prepared before the guests Event Time.
:::

:::hint{type="info"}
Internal Olo settings can cause additional lead time calculations to an order, like Estimated Lead Times, Self-Delivery Lead Times, etc. Please use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue. If you need to update hours of operation and lead times, please do so in [Partner Portal](https://catering.ezcater.com/en/help/how-do-i-update-my-store-hours). 
:::
::::

::::ExpandableHeading
# 209. Already Submitted

:::hint{type="warning"}
***Error Definition***

- The current order has already been successfully submitted.
:::

:::hint{type="info"}
Please reach out to ezCater support [integrations@ezcater.com](mailto\:integrations@ezcater.com) and / or use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 210. Order Throttling

:::hint{type="warning"}
***Error Definition***

- The store no longer has the availability to prepare the guests order within the given timeframe.
:::

:::hint{type="info"}
Review the current Order Throttling strategy configured in Olo. It is suggested to turn off this feature as it is not supported in ezCater. Please review this document or use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center if you have further questions.
:::
::::

::::ExpandableHeading
# 211. Menu Item Eighty-Sixed

:::hint{type="warning"}
***Error Definition***

- One or more menu items on the current order is/was 86’d (unavailable)at the time of order acceptance.
:::

:::hint{type="info"}
The error message will indicate which item was 86’d. Either remove the 86 flag from the item to prevent future failures, or remove the item from the Olo menu completely.
:::
::::

::::ExpandableHeading
# 212. Menu Item Not Available at Specified Time

:::hint{type="warning"}
***Error Definition***

- One or more menu items on the current order is not available at the specified time.
:::

:::hint{type="info"}
The error message will indicate which item was unavailable at that time. Please update or remove the availability restriction in Olo or request item to be removed in ezCater.
:::
::::

::::ExpandableHeading
# 213. Transmission Failure

:::hint{type="warning"}
***Error Definition***

- There was an error validating the order and transmitting it to the store.
:::

:::hint{type="info"}
This can often indicate an issue between Olo and the POS and will require the Olo Team to help investigate and correct the issue. Please use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center for assistance.
:::
::::

::::ExpandableHeading
# 217. Store Unreachable

:::hint{type="warning"}
***Error Definition***

- The store could not be reached due to the POS being offline.
:::

:::hint{type="info"}
Please ensure the POS is online. If issue persists, please reach out to a POS Specialist and use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center for additional assistance.
:::
::::

::::ExpandableHeading
# 218. Store Hours Unavailable

:::hint{type="warning"}
***Error Definition***

- The store is not open for ordering at the specified time.
:::

:::hint{type="info"}
Ensure the hours between Olo and ezCater either match or ensure Olo is configured to have longer operational hours than ezCater.
:::
::::

::::ExpandableHeading
# 219. Store Temporarily Unavailable

:::hint{type="warning"}
***Error Definition***

- The store has been manually disabled.
:::

:::hint{type="info"}
Further investigation by the Brand/Olo is needed to determine why the restaurant has been disabled. Please reference the store’s "vendoronline" or restaurant "isavailable" fields as they can help show a stores status.
:::
::::

::::ExpandableHeading
# 220. Invalid POS Configuration

:::hint{type="warning"}
***Error Definition***

- The restaurant's POS refused the order due to an invalid configuration.
:::

:::hint{type="info"}
A POS configuration update would need to be made by the brand to resolve this error. Please use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 222. Incorrect Mapping/Menu Setup

:::hint{type="warning"}
***Error Definition***

- One or more menu items on the order was refused by the stores POS due to incorrect mapping or set between Olo and the POS.
:::

:::hint{type="info"}
Review Olo Mismatch Report and run Olo basket tests to review and correct mapping issues. Then, confirm menu updates are ingested by EzCater. Reach out to Olo using the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center with any additional questions.
:::
::::

::::ExpandableHeading
# 223. POS System Busy

:::hint{type="warning"}
***Error Definition***

- The POS refused the order due to a busy system
:::

:::hint{type="info"}
Please use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 225. POS Timeout

:::hint{type="warning"}
***Error Definition***

- The POS did not respond to Olo in a timely manner, causing the order transmission to timeout.
:::

:::hint{type="info"}
Please use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::


[title] Microsoft SSO Instructions - Meal Program App Only
[path] Enterprise Account Integrations/SSO for Marketplace & Relish/

- In the Microsoft Entra Admin Center, navigate to **Identity > Applications > Enterprise applications&#x20;**&#x61;nd click on **Create your own application**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcSaPzNY5aVi6D0DYKTl6hYveySHTrFtZtJEkvNu-B3QzrXiF6PLeQOg1ZFCCWD63IjdsEuYyQa4xoy0I7VW-bScyZYaUTy3sPiyauDp24XyMjsXwaS9bISagSi9tttGWWc7LcE?key=AvWn09Y7CVz2HnQXem_NL67Q" size="68" width="964" height="490" position="center" darkWidth="964" darkHeight="490" showCaption="false"}

- Name the app Meal Program and select the “non-gallery” option for this application

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfPNILGHVtS4TheOt1FXWHAmrEXZdsr3Y93AhxZIURrJGdZFSDHdbYrubMo3C0kzKH6Euz9RbvMGZE-2JfU6I9NMrgTnR-dCbQwlwZZGL-tTuDhCNQqtppbIKnGWNz88oN_yuqPzg?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Once the app is created, click on the **Set up single sign on&#x20;**&#x74;ile

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXf0_v3Yi6Xd9rDnp8ARsxB_29osxLFO9o33_8CWa-Mli1RcstVQyIZ3ThIl3Nlas5WJV2YOSSCXXuTpp4gSlyQ5RWGJlUzhB9QLD0YsOGt_kI5GT6N3np9zOB5PPTQVof9lNJ2V3g?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Click on the **SAML&#x20;**&#x6F;ption for the SSO method

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfwPim_3UAvv0SHbcvSzSYSzSP-5Nd2yEO_qDSscgdp_mD6yV-nNsvyytHkqPCcuJ1HaXHcYYxBSPVNT8Q3bz79NXOQWM7Y5JR9eqdTywKjdShsLgHZuxnir78JBGsQJ7nlwek_?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Click on the **Edit&#x20;**&#x62;utton in the first section

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXcahCAFY88BuhHsNgCSUTxiES19gDNWkurAlTHqIIxLN2elpr78N6OcFhEb9QFfGapXzrTAeeTjX2PA9N5KD0aBzULaxZrrNRPozcsAwR8N5BM5xkNpQv8pzmDTDiYEHv4UIjTFLA?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Use the following values for the SAML configuration:
  - Identifier (Entity ID): **ezcater.com**
    - *Do NOT add https or www*
  - Reply URL (Assertion Consumer Service URL): [https://www.ezcater.com/saml/consume](https://www.ezcater.com/saml/consume)
  - Reply URL Index:**&#x20;0**
  - Sign on URL: [https://login.ezcater.com/relish/sso/domain\_redirect?domain=mycompany.com](https://login.ezcater.com/relish/sso/domain_redirect?domain=mycompany.com) *(change this to your domain)*

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfH6FyZldU-aSMMqxQBS4dRQ9hJsbMLI96e6_x5eUVVCOPUeoUgl99-LlwkQYKeazXmUFlq-VShF6VR-jCZuDY9STwcwFyQnot5trUhWjJNtrjUtRD4v1z25JoKEBj--1zZI2aw?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Once the settings are saved, scroll down the SAML Certificates and click on **Download&#x20;**&#x6E;ext to Certificate (Base64). &#x20;

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXc8a-ggwKzgv1QqlZaDjilbAZBWe6Fk6iR9vGObgSQEuX2JLhW_9WaAAyg6zwmq6Mf39s7wX4KgkeZnfmk_Yo4EJDrTFXo5bcPXzB-N4ONPBVJQW2dQ7b37NQ0NGTsFec6lVnUBLw?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Submit the **public certificate** in plaintext along with copied app settings (**Login URL** and **Microsoft Entra Identifier**) through the [ezCater/Meal Program SSO Form ](https://ezcaterforms.formstack.com/forms/ezcater_sso)

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXdKumzEGaFXSDXfn6rxT7wkPJDmpqU-BP9L7y6O_ZJrc9t5DJTiuanwIi_cBwbL6JSQBzjjaz2R0odN7OsWSCWMDuRSMAhmDmuHDyg-D2_UN_g_RTcqZ09DNtI41RAiXcXn9Xzs?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Navigate back to **App Registrations,** click on the Meal Program application. Then, navigate to **Branding & properties** to update the logo. 



::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/m6ts5EhWXT6Qg3ljv-I7K_ezcater-logo-dark-primary-symbol-300dpi.png" size="38" width="2084" height="1918" position="center" showCaption="false"}


[title] Error Message Examples
[path] Restaurant Partner Integrations/Olo Rails Integration/

This document provides a summary of error messages and suggestions for resolving them when integrating ezCater with Olo. It serves as a guide to help identify and correct issues that may arise during the integration process.

For a downloadable version please use the link below:

::File{src="https://archbee-doc-uploads.s3.amazonaws.com/CnBnWfHDNa9lZK7nmY_mG-6-f7OAIq05emuSNu5aThz-20250319-224049.pdf" label="ezCater & Olo - Error Code Examples.pdf"}

***

::::ExpandableHeading
# Example

Each error code in this document can be expanded or collapsed and displays as follows:

:::hint{type="warning"}
***Error Message(s)***

- Example error message text
- Different example error message text
:::

:::hint{type="info"}
Suggestions and/or recommendations for how to correct for the error messages received.&#x20;
:::
::::

***

::::ExpandableHeading
# 1. Deserialized Request

:::hint{type="warning"}
***Error Message(s)***

- Could not be deserialized or is missing required fields
- At least one product is required
- selfdelivery is not a valid pickuptype
:::

:::hint{type="info"}
Most often is an issue with the menu data being sent from ezCater to Olo. Menu updates might be required. Please reach out to ezCater support [integrations@ezcater.com](mailto\:integrations@ezcater.com) or use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 3. Insufficient Access to Vendor

:::hint{type="warning"}
***Error Message(s)***

- Insufficient access to vendor
- Cannot change basket owner
:::

:::hint{type="info"}
Verify that the correct Olo Location/Store ID is being used for order transmissions, and ensure ezCater has been granted access through the Olo dashboard. If you are unsure how to grant access, please review this document, or use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center for further assistance.
:::
::::

::::ExpandableHeading
# 10. Generic Error Code

:::hint{type="warning"}
***Error Message(s)***

- Please try this operation again or restart your application
- Cannot find vendor product with ProductId: \{123} for VendorId: \{123}
- Unable to find option productId=\{123}; chainChoiceId=\{123}
:::

:::hint{type="info"}
Please reach out to ezCater support [integrations@ezcater.com](mailto\:integrations@ezcater.com) and / or use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 200. Generic Error Code

:::hint{type="warning"}
***Error Message(s)***

- Order cannot be ready
- This location is currently unavailable
- Product is not available at the specified time
- Item(s) are not available for pickup orders
- Item(s) have been removed from the menu
- Self Delivery not Valid
- Order Value Too Low
- Min qty not met
- Online ordering will be unavailable at specific time
- This location does not offer online ordering
- Please choose a time in the future, Missing Contact Details
- Missing Selections
- Too Many Selection(s)
:::

:::hint{type="info"}
Please reach out to ezCater support [integrations@ezcater.com](mailto\:integrations@ezcater.com) and / or use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 206. Invalid Advance Time

:::hint{type="warning"}
***Error Message(s)***

- Order cannot be ready
:::

:::hint{type="info"}
Internal Olo settings can cause additional lead time calculations to an order, like Estimated Lead Times, Self-Delivery Lead Times, etc. Please use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 209. Already Submitted

:::hint{type="warning"}
***Error Message(s)***

- This order has already been placed
:::

:::hint{type="info"}
Please use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 210. Order Throttling

:::hint{type="warning"}
***Error Message(s)***

- High order volume
:::

:::hint{type="info"}
Review the current Order Throttling strategy configured in Olo to determine if any adjustments are needed. Please review [this ](https://olosupport.zendesk.com/hc/en-us/articles/115002752386-Order-Throttling-Strategies-Overview)document or use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center if you have additional questions.
:::
::::

::::ExpandableHeading
# 211. Menu Item Eighty-Sixed

:::hint{type="warning"}
***Error Message(s)***

- Item not available
:::

:::hint{type="info"}
The error message will indicate which item was 86’d. Either remove the 86 flag from the item to prevent future failures, or remove the item from the Olo menu completely. 
:::
::::

::::ExpandableHeading
# 212. Menu Item Not Available at Specified Time

:::hint{type="warning"}
***Error Message(s)***

- Item Not Yet Available
:::

:::hint{type="info"}
The error message will indicate which item was unavailable at that time. Please update or remove the availability restriction in Olo or request item to be removed in ezCater.
:::
::::

::::ExpandableHeading
# 213. Transmission Failure

:::hint{type="warning"}
***Error Message(s)***

- Error Validating Basket
:::

:::hint{type="info"}
This can often indicate an issue between Olo and the POS and will require the Olo Team to help. Please use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 217. Store Unreachable

:::hint{type="warning"}
***Error Message(s)***

- Store POS Offline
- Error Validating Basket
- Order could not be placed
:::

:::hint{type="info"}
Please ensure the POS is online. If issue persists, please reach out to a POS Specialist and use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 218. Store Hours Unavailable

:::hint{type="warning"}
***Error Message(s)***

- Store closed for business at the time you have specified
- Store Needs More Time
:::

:::hint{type="info"}
Ensure the hours between Olo and ezCater either match or ensure Olo is configured to have longer operational hours than ezCater.
:::
::::

::::ExpandableHeading
# 219. Store Temporarily Unavailable

:::hint{type="warning"}
***Error Message(s)***

- This location is currently closed
- Online ordering is unavailable at this time
- Currently unavailable to accept online orders
:::

:::hint{type="info"}
Further investigation by the Brand/Olo is needed to determine why the restaurant has been disabled. Please reference the store’s "vendoronline" or restaurant "isavailable" fields as they can help show a stores status.
:::
::::

::::ExpandableHeading
# 220.  Invalid POS Configuration

:::hint{type="warning"}
***Error Message(s)***

- Error Validating Basket
:::

:::hint{type="info"}
A POS configuration update would need to be made by the brand to resolve this error. Please use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 222. Incorrect Mapping/Menu Setup

:::hint{type="warning"}
***Error Message(s)***

- Item not available
- Error Validating Basket
- There is an issue with the contents of your order
:::

:::hint{type="info"}
Please use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 223. POS System Busy

:::hint{type="warning"}
***Error Message(s)***

- Error Validating Basket
:::

:::hint{type="info"}
Please use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::

::::ExpandableHeading
# 225. POS Timeout

:::hint{type="warning"}
***Error Message(s)***

- Error Validating Basket
:::

:::hint{type="info"}
Please use the [Dedicated Intake Form ](https://olosupport.zendesk.com/hc/en-us/requests/new)within the Olo Help Center to help identify and correct the issue.
:::
::::


[title] Prerequisites
[path] API for Restaurant Partners/Delivery API/

Before using the Delivery API, you must implement a listener for new order events. While the Delivery API is used to transmit updates \_to\_ ezCater, it does not provide notifications for new orders. That is handled by the Orders API.

How the APIs Work Together
1\. **Subscribe to order notifications**: Use the [Orders API](https://api.ezcater.io/subscribing-to-order-notifications) to subscribe to the `submitted` event for your caterer ID. This ensures ezCater alerts your system the moment a new order is placed.
2\. **Receive the webhook**: When a delivery order is placed, you will receive an asynchronous notification containing the core order details.
3\. **Retrieve the** `deliveryId`: Use the information from the webhook to call the [Order Details](https://api.ezcater.io/order-details) query. This step is required to obtain the unique `deliveryId` required for tracking.
4\. **Send delivery updates**: Using the `deliveryId`, you can now submit courier assignments, real-time status updates, and other delivery events via the **Delivery API** as documented above.

[title] Microsoft SSO Instructions - ezCater Marketplace & Meal Program Apps
[path] Enterprise Account Integrations/SSO for Marketplace & Relish/

## Overview

Create two separate setups in Microsoft Applications: the ezCater SAML app AND a linked app that uses the ezCater SAML settings and redirects users to the Meal Program sign on URL.

- **ezCater Marketplace App**In the Microsoft Entra Admin Center, navigate to **Identity > Applications > Enterprise applications&#x20;**&#x61;nd click on **Create your own application**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcSaPzNY5aVi6D0DYKTl6hYveySHTrFtZtJEkvNu-B3QzrXiF6PLeQOg1ZFCCWD63IjdsEuYyQa4xoy0I7VW-bScyZYaUTy3sPiyauDp24XyMjsXwaS9bISagSi9tttGWWc7LcE?key=AvWn09Y7CVz2HnQXem_NL67Q" size="68" width="964" height="490" position="center" darkWidth="964" darkHeight="490" showCaption="false"}

- Name the app **ezCater&#x20;**&#x61;nd select the “non-gallery” option for this application

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfPNILGHVtS4TheOt1FXWHAmrEXZdsr3Y93AhxZIURrJGdZFSDHdbYrubMo3C0kzKH6Euz9RbvMGZE-2JfU6I9NMrgTnR-dCbQwlwZZGL-tTuDhCNQqtppbIKnGWNz88oN_yuqPzg?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Once the app is created, click on the **Set up single sign on&#x20;**&#x74;ile

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXf0_v3Yi6Xd9rDnp8ARsxB_29osxLFO9o33_8CWa-Mli1RcstVQyIZ3ThIl3Nlas5WJV2YOSSCXXuTpp4gSlyQ5RWGJlUzhB9QLD0YsOGt_kI5GT6N3np9zOB5PPTQVof9lNJ2V3g?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Click on the **SAML&#x20;**&#x6F;ption for the SSO method

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfwPim_3UAvv0SHbcvSzSYSzSP-5Nd2yEO_qDSscgdp_mD6yV-nNsvyytHkqPCcuJ1HaXHcYYxBSPVNT8Q3bz79NXOQWM7Y5JR9eqdTywKjdShsLgHZuxnir78JBGsQJ7nlwek_?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Click on the **Edit&#x20;**&#x62;utton in the first section

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXcahCAFY88BuhHsNgCSUTxiES19gDNWkurAlTHqIIxLN2elpr78N6OcFhEb9QFfGapXzrTAeeTjX2PA9N5KD0aBzULaxZrrNRPozcsAwR8N5BM5xkNpQv8pzmDTDiYEHv4UIjTFLA?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Use the following values for the SAML configuration:
  - Identifier (Entity ID): **ezcater.com**
    - *Do NOT add https or www*
  - Reply URL (Assertion Consumer Service URL): [https://www.ezcater.com/saml/consume](https://www.ezcater.com/saml/consume)
  - Reply URL Index:**&#x20;0**
  - **Sign on URL:&#x20;**[https://www.ezcater.com/sso\_session/new](https://www.ezcater.com/sso_session/new)

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXf4naMREExMMt0bhicndqKh3en5Doccewv-4-IM30T_mGmihWUcozv6E7_95KK7Bwn3luVpZ9-uhDG67sN-XZG0YU_LJwL-0s1CX5O1o-_kgFYsUAAesJY00Tsf-VXDcNnZUgfG?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Once the settings are saved, scroll down the SAML Certificates and click on **Download&#x20;**&#x6E;ext to Certificate (Base64). &#x20;

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXc8a-ggwKzgv1QqlZaDjilbAZBWe6Fk6iR9vGObgSQEuX2JLhW_9WaAAyg6zwmq6Mf39s7wX4KgkeZnfmk_Yo4EJDrTFXo5bcPXzB-N4ONPBVJQW2dQ7b37NQ0NGTsFec6lVnUBLw?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Submit the **public certificate** in plaintext along with copied app settings (**Login URL** and **Microsoft Entra Identifier**) through the [ezCater/Meal Program SSO Form ](https://ezcaterforms.formstack.com/forms/ezcater_sso)

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXdKumzEGaFXSDXfn6rxT7wkPJDmpqU-BP9L7y6O_ZJrc9t5DJTiuanwIi_cBwbL6JSQBzjjaz2R0odN7OsWSCWMDuRSMAhmDmuHDyg-D2_UN_g_RTcqZ09DNtI41RAiXcXn9Xzs?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Navigate back to **App Registrations,** click on the Meal Program application. Then, navigate to **Branding & properties** to update the logo. 



::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/T5VuAImYb2cDWftVARYJ2_ezcater-logo-bright-primary-symbol-300dpi.png" size="36" width="2084" height="1918" position="center" showCaption="false"}

## Meal Program Linked App

*Meal Program SAML will be enabled through the ezCater configuration, this linked application directs the users to the Meal Program SSO sign in link.&#xA0;*

- In the Microsoft Entra Admin Center, navigate to **Identity > Applications > Enterprise applications&#x20;**&#x61;nd click on **Create your own application**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcSaPzNY5aVi6D0DYKTl6hYveySHTrFtZtJEkvNu-B3QzrXiF6PLeQOg1ZFCCWD63IjdsEuYyQa4xoy0I7VW-bScyZYaUTy3sPiyauDp24XyMjsXwaS9bISagSi9tttGWWc7LcE?key=AvWn09Y7CVz2HnQXem_NL67Q" size="68" width="964" height="490" position="center" darkWidth="964" darkHeight="490" showCaption="false"}

- Name the app Meal Program and select the “non-gallery” option for this application

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfPNILGHVtS4TheOt1FXWHAmrEXZdsr3Y93AhxZIURrJGdZFSDHdbYrubMo3C0kzKH6Euz9RbvMGZE-2JfU6I9NMrgTnR-dCbQwlwZZGL-tTuDhCNQqtppbIKnGWNz88oN_yuqPzg?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Once the app is created, click on the **Set up single sign on&#x20;**&#x74;ile

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXf0_v3Yi6Xd9rDnp8ARsxB_29osxLFO9o33_8CWa-Mli1RcstVQyIZ3ThIl3Nlas5WJV2YOSSCXXuTpp4gSlyQ5RWGJlUzhB9QLD0YsOGt_kI5GT6N3np9zOB5PPTQVof9lNJ2V3g?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Select **Linked**.

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXdSh5H-GI6JTzfbjrN1f26fdZYO9t_iOIDeVFZC62kfLS-PNwlZejJLA6DHAOvCe3dOkm_wm1ketHlkIJj6Xv376GQ3BMhp4_j8hs768M0-i7CiYXvgQ0a_o8aM78vtttnbnYVETw?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Enter the URL: [https://login.ezcater.com/relish/sso/domain\_redirect?domain=mycompany.com](https://login.ezcater.com/relish/sso/domain_redirect?domain=mycompany.com) (change this to your domain)

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfiQVgzLR2MSovqdOym8AyrqHmx_hTpchRF6PLsoXx4FiqNn0PePmspahLmqW2t4_-1XRpdkU6a0p_nbAiuqcxEdbxiC2yPABJCg-n-XkIJ-sPbJw8PT_mW15KbTHSn-tg58sV9?key=AvWn09Y7CVz2HnQXem_NL67Q)

- Select **Save**.
- Navigate back to **App Registrations,** click on the Meal Program application. Then, navigate to **Branding & properties** to update the logo. 



::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/TkVhkzs8MkAPDnh6S4JmQ_ezcater-logo-dark-primary-symbol-300dpi.png" size="30" width="2084" height="1918" position="center" showCaption="false"}


[title] SAP Concur Enterprise
[path] Enterprise Account Integrations/

Account-wide automatic receipt forwarding and seamless user management via a roster sync.

## Features

- **Organization-Wide Enablement:&#x20;**&#x41; single step for the entire company, delivering immediate receipt integration for all employees
- **Effortless Receipt Management:** Order receipts from every employee are automatically sent to SAP Concur, improving compliance and reimbursement&#x20;
- **Automatic Receipt Correction:** When an order is refunded or updated, correction receipts are automatically transmitted to SAP Concur, keeping expense reports accurate and up-to-date without requiring manual intervention.&#x20;
- **Unified Spending & Audit Visibility:&#x20;**&#x46;inance teams gain a complete view of organization-wide food orders and expenses matched in SAP Concur
- **(Optional) Automatic Roster Sync:&#x20;**&#x4E;ew US-based users receive instant invites to ezCater, and departing employees are promptly deactivated\*

*\*Note: Roster Sync is currently unavailable for accounts with a parent child structure.*

## SAP Concur Enterprise Integrated Experience

**Employee Experience&#x20;**

- When an employee purchases a meal on ezCater, their receipt will automatically be uploaded to their SAP Concur dashboard. Any changes to the order will send a corrected receipt to SAP Concur.&#x20;
- Employees don’t need to individually enable the integration or manually upload their receipts to SAP Concur.&#x20;

**Admin Experience &#x20;**

- **Simple Roster Management:** With a single click, admins can sync their entire SAP Concur US employee roster into ezCater—including automatic updates for new hires and departures.
- **Automated Compliance & Expense Accuracy:** Each receipt sent to SAP Concur includes all custom checkout fields that employee enters, ensuring expenses are tracked according to internal budgeting and reporting requirements. Admins can set spending policies directly within ezCater to maintain policy adherence without extra effort.

 

**SAP Concur Individual Integration v. Enterprise Integration&#x20;**

*The enterprise integration is a more powerful, centralized solution designed to support your company’s expense program at scale.*

|                    | **Enterprise Integration**                                                | **Individual Integration**                                                |
| ------------------ | ------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| Ideal for          | Large organizations / Finance Teams                                       | Casual users / Small teams                                                |
| Onboarding         | Centralized (Admin-led)                                                   | Decentralized (User-led)                                                  |
| Receipt Forwarding | Automatic for all employees                                               | Configurable setting for each individual                                  |
| Expense Creation   | - Receipt PDF
- Vendor name & address (ezCater)
- Payment amount and type | * Receipt PDF
* Vendor name & address (ezCater)
* Payment amount and type |
| Cost               | Free                                                                      | Free                                                                      |
| Roster Sync        | Available                                                                 | Unavailable                                                               |
| Availability       | Only ezCater Enterprise Accounts                                          | Any ezCater user                                                          |


[title] General Menu Guidance
[path] Restaurant Partner Integrations/

This section provides comprehensive guidance for preparing menus for integration with ezCater. It outlines menu features, requirements, best practices, and integration-specific configuration guidance to ensure a smooth integration process.

Expand the navigation bar on the left to navigate this documentation.


[title] Courier Image Create
[path] API for Restaurant Partners/Delivery API/

# Creating Delivery Images

Upon completion of a delivery, providing an image of the food having securely arrived at the delivery site is important. Delivery images allow both customer(s) and partner(s) to confirm that everything that was ordered arrived safely, and provides a rough indication of where the courier delivered the food and in what state it arrived.

:::hint{type="info"}
If you already had a courier assigned to a delivery and are now assigning a new courier, we automatically take care of un-assigning the previous courier.
:::

## Mutation

:::CodeblockTabs
Mutation

```graphql
mutation CourierImagesCreate($input: CourierImagesCreateInput!) {
  courierImagesCreate(input: $input) {
    clientMutationId
    userErrors {
      ... on DeliveryValidationError {
        message
        path
      }
    }
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables

```graphql
{
  "input": {
    "clientMutationId": "your-mutation-id",
    "courier": {
      "id": "your-courier-id",
      "firstName": "Test",
      "lastName": "Courier",
      "phone": "+15555555555",
      "vehicle": {
        "make": "Your Vehicle Make",
        "model": "Your Vehicle Model",
        "color": "Your Vehicle Color"
      }
    },
    "deliveryId": "ezcater-delivery-id",
    "imageUrls": ["https://your-courier-company.com/your-courier-id-delivery.jpg"]
  }
}
```
:::

### Arguments

| Argument Name                                                      | Description                               |
| ------------------------------------------------------------------ | ----------------------------------------- |
| `input`: [CourierImagesCreateInput!](docId:3eKot5kW3kMh9s1x3o-HY)  | The Input object for creating a new menu. |

### Return Type

Returns a [CourierImagesCreatePayload](docId:7gV344RnWmuokNj9u4rW7).&#x20;

## Success Responses

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "courierImagesCreate": {
      "clientMutationId": "your-mutation-id",
      "userErrors": []
    }
  }
}
```
:::

## Failure Responses

### 400 Bad Request

When the `courierImagesCreate` mutation fails due to bad user input, such as an invalid field, you can expect a HTTP 400 Bad Request and the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "errors": [
    {
      "message": "Variable \"$input\" got invalid value { clientMutationId: \"your-mutation-id\", coordinates: { latitude: 42.360081, longitude: -71.058884 }, courier: { id: \"your-courier-id\", firstName: \"Test\", lastName: \"Courier\", phone: \"+15555555555\", vehicle: [Object] }, deliveryId: \"your-ezcater-delivery-id\", eventType: \"PICKED_UP\", occurredAt: \"2025-05-07T19:52:32.841Z\" }; Field \"eventType\" is not defined by type \"CourierTrackingEventCreateInput\".",
      "extensions": {
        "code": "BAD_USER_INPUT"
      }
    }
  ]
}
```

Response

```graphql
{
  "errors": [
    {
      "message": "Variable \"$input\" got invalid value null at \"input.imageUrls\"; Expected non-nullable type \"[String!]!\" not to be null.",
      "extensions": {
        "code": "BAD_USER_INPUT"
      }
    }
  ]
}
```
:::




[title] Request ezCater Dispatch
[path] API for Restaurant Partners/Delivery API/

This mutation allows partners to request **ezCater Dispatch** (ezCater-managed third-party delivery drivers) for an existing order directly through the **Delivery API**. The GraphQL mutation name is `thirdPartyDeliveryCreate`.

In a partner’s interface, this mutation will typically power an action such as **“Request ezCater Dispatch”**, **“Request Delivery Driver”**, or **“Send to ezCater Dispatch”**. Selecting this UI action should trigger the `thirdPartyDeliveryCreate` mutation in the background.

***

### Request ezCater Dispatch on an existing delivery

When you determine that an order should use third-party delivery via ezCater Dispatch, call the `thirdPartyDeliveryCreate` mutation on the existing order/delivery in the Delivery API.

On the ezCater side:

- The order’s `orderType` will initially be DELIVERY.
- `order.event.catererHandoffFoodTime` will already be populated with the **event time** for that order/delivery (the initial, pre-dispatch pickup time).

Treat this initial `order.event.catererHandoffFoodTime` as the **pre-dispatch pickup time**.

***

### How ezCater updates the pickup time

After ezCater Dispatch has been requested:

1. The order’s `orderType` is updated from DELIVERY to **THIRD\_PARTY\_DELIVERY**.
   - This change **does not** mean the final pickup time has been set.
2. ezCater asynchronously computes the **final ezCater Dispatch pickup time**
3. Once that computation is complete, we **update&#x20;**`order.event.catererHandoffFoodTime` with the new ezCater Dispatch pickup time.
   - There is **no separate&#x20;**`pickupAt`**&#x20;field**—you should always read the pickup time from `order.event.catererHandoffFoodTime`.

***

### Querying for the updated pickup time

Once you’ve requested ezCater Dispatch, query the Delivery/Orders API for that delivery to retrieve the updated `order.event.catererHandoffFoodTime` value.

**Recommended integration pattern:**

1. Call `thirdPartyDeliveryCreate`.
2. Wait a short period (approximately **10 seconds**).
3. Call your standard order/delivery details query and read `order.event.catererHandoffFoodTime`.
4. If the value still matches the original event time and you require the ezCater Dispatch pickup time (for example, to display to store staff), you can **retry with a short backoff** until it is updated, within reasonable limits.

***

### UI labeling guidance

In your restaurant-facing UI, label this function as **“ezCater Dispatch”**. Please avoid using “ezDispatch” in the UI copy.

[title] Subscriber Create
[path] API for Restaurant Partners/Subscription API/

# Creating Subscribers

A **Subscriber** represents the integration itself. The **Subscriber** will manage where event notifications are sent to as well as what events you want to subscribe to.&#x20;

:::hint{type="info"}
We currently only support creating one **Subscriber** per API user. If you are seeing errors that your subscriber could not be created, it may be that one has already been set up. Try running the [Subscriber List](docId:9DzcbPmXX-vinLGLpRqhR)  query to see if any already exist.
:::

## Mutation

To create the **Subscriber**, simply make a `createSubscriber` mutation request as seen in the example below.

:::hint{type="warning"}
Make sure you include the `webhookSecret` fields in the mutation, it will only be returned when initially creating a subscription, so be sure to save the value!&#x20;
:::

:::hint{type="info"}
You will also need the **Subscriber** `id` in subsequent steps, so we recommend keeping track of it now.
:::

:::CodeblockTabs
Mutation

```graphql
mutation CreateSubscriber($subscriberParams: CreateSubscriberFields!) {
  createSubscriber(subscriberParams: $subscriberParams) {
    subscriber {
      id
      name
      subscriptions {
        eventEntity
        eventKey
        parentEntity
        parentId
        subscriberId
      }
      webhookSecret
      webhookUrl
    }
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables

```graphql
{
  "subscriberParams": {
    "name": "Example Provider - Example Brand",
    "webhookUrl": "https://example.net/subscriptions"
  }
}
```
:::

### Arguments

| Argument Name                                                                | Description                                   |
| ---------------------------------------------------------------------------- | --------------------------------------------- |
| `subscriberParams`: [CreateSubscriberFields! ](docId:_6fu5DGR5rPbWAT27Pcxz)  | The input object for making a new subscriber. |

### Return Type

Returns a [CreateSubscriberPayload](docId:_6fu5DGR5rPbWAT27Pcxz).

## Successful Responses

When the `createSubscriber` mutation succeeds you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "createSubscriber": {
      "subscriber": {
        "id": "your-subscriber-id",
        "name": "Example Provider - Example Brand",
        "subscriptions": [],
        "webhookSecret": "be6efd0f8e88fec0d51364559ca9a258e70031f7f38448ea2e9705928a929a8d",
        "webhookUrl": "https://example.net/subscriptions"
      }
    }
  }
}
```
:::

## Failure Responses

When the `createSubscriber` mutation fails you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "errors": [
    {
      "message": "Subscriber could not be created.",
      "path": [
        "createSubscriber"
      ],
      "extensions": {
        "type": "summary",
        "serviceName": "external-events",
        "code": "DOWNSTREAM_SERVICE_ERROR",
        "exception": {
          "message": "Subscriber could not be created.",
          "locations": [
            {
              "line": 1,
              "column": 90
            }
          ],
          "path": [
            "createSubscriber"
          ]
        }
      }
    }
  ],
  "data": {
    "createSubscriber": null
  }
}
```
:::


[title] Courier Tracking Event Create
[path] API for Restaurant Partners/Delivery API/

# Creating Courier Tracking Events

When couriers are out for delivery, it is important to understand exactly where the courier is so that the appropriate parties have an accurate idea of how the delivery is progressing. This information can be used to provide a tracking status and also give us insight into delivery events that are taking place event if an explicit event has not been provided.

:::hint{type="info"}
If you already had a courier assigned to a delivery and are now assigning a new courier, we automatically take care of un-assigning the previous courier.
:::

## Mutation

:::CodeblockTabs
Mutation

```graphql
mutation CourierTrackingEventCreate($input: CourierTrackingEventCreateInput!) {
  courierTrackingEventCreate(input: $input) {
    clientMutationId
    userErrors {
      ... on DeliveryValidationError {
        message
        path
      }
    }
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables

```graphql
{
  "input": {
    "clientMutationId": "your-mutation-id",
    "coordinates": {
      "latitude": 42.360081,
      "longitude": -71.058884
    },
    "courier": {
      "id": "your-courier-id",
      "firstName": "Test",
      "lastName": "Courier",
      "phone": "+15555555555",
      "vehicle": {
        "make": "Your Vehicle Make",
        "model": "Your Vehicle Model",
        "color": "Your Vehicle Color"
      }
    },
    "deliveryId": "ezcater-delivery-id",
    "occurredAt": "2024-02-05T17:27:55+0000"
  }
}
```
:::

### Arguments

| Argument Name                                                             | Description                               |
| ------------------------------------------------------------------------- | ----------------------------------------- |
| `input`: [CourierTrackingEventCreateInput!](docId:7gV344RnWmuokNj9u4rW7)  | The Input object for creating a new menu. |

### Return Type

Returns a [CourierTrackingEventCreatePayload](docId:7gV344RnWmuokNj9u4rW7).

## Success Responses

When the `courierTrackingEventCreate` mutation succeeds you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "courierTrackingEventCreate": {
      "clientMutationId": "your-mutation-id",
      "userErrors": []
    }
  }
}
```
:::

## Failure Responses

### User Errors

When the `courierTrackingEventCreate` mutation fails because it is too early to add courier events you can expect the response payload to look like:

:::CodeblockTabs
Response - Too Early

```graphql
{
  "data": {
    "courierTrackingEventCreate": {
      "clientMutationId": "your-mutation-id",
      "userErrors": [
        {
          "message": "It's too early to add the event for courier en route to pickup",
          "path": [
            "input",
            "occurredAt"
          ]
        }
      ]
    }
  }
}
```

Response - Too Late

```graphql
{
  "data": {
    "courierTrackingEventCreate": {
      "clientMutationId": "your-mutation-id",
      "userErrors": [
        {
          "message": "Delivery cannot receive updates 2 hours past its event time",
          "path": [
            "input",
            "deliveryId"
          ]
        }
      ]
    }
  }
}
```
:::

### 400 Bad Request

When the `courierTrackingEventCreate` mutation fails due to bad user input, such as an invalid field, you can expect a HTTP 400 Bad Request and the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "errors": [
    {
      "message": "Variable \"$input\" got invalid value { clientMutationId: \"your-mutation-id\", coordinates: { latitude: 42.360081, longitude: -71.058884 }, courier: { id: \"your-courier-id\", firstName: \"Test\", lastName: \"Courier\", phone: \"+15555555555\", vehicle: [Object] }, deliveryId: \"your-ezcater-delivery-id\", eventType: \"PICKED_UP\", occurredAt: \"2025-05-07T19:52:32.841Z\" }; Field \"eventType\" is not defined by type \"CourierTrackingEventCreateInput\".",
      "extensions": {
        "code": "BAD_USER_INPUT"
      }
    }
  ]
}
```
:::




[title] Overview
[path] API for Restaurant Partners/

# Welcome to the ezCater API!

ezCater is excited to provide you with solutions and guidance focusing on business class food for the workplace integration solutions.  This site describes solutions focusing on connecting ezCater to Menu Management solutions, Order Management platforms and Delivery Management solutions.

This guide provides an overview of the processes involved in setting up ezCater’s API functionality and information about specific solutions and features. It also provides examples of how you can use these tools to pull information from ezCater and into your solutions. The API utilizes webhooks to allow you to pull information on order events and store menus into a Point of Sale or other integrated platforms, as well as exchange information regarding menu and delivery updates. In a general sense, you’ll need to:

1. Connect your ecosystem to ezCater via API users and tokens via GraphQL.&#x20;
2. Listen for events related to menu and order use cases.
3. Map stores from ezCater to your store technology.
4. Send menu content from your content management systems to ezCater’s menu catalog.
5. Orders API:  Process orders by accepting and rejecting orders via Partner Portal’s auto/manual processes or via integration and inject order data into store systems for fulfillment and other use cases.
6. Provide delivery tracking information to help consumers and support teams to assist with order fulfillment. This includes information such as: assigned courier, delivery lifecycle events, real time lat/lng information and delivery dropoff images.

***

:::ExpandableHeading
## Example API Workflow

1. **A brand team member creates or updates menu content to ensure customers have current and accurate information when placing an order**
2. **Customer places order on ezCater Marketplace**
3. **Customer receives Order Placed notification**
4. **Caterer receives Order Placed notification & accepts order**
   1. The order is accepted or rejected manually via Partner Portal, automatically via Partner Portal or via integration.
   2. 'Accepted' webhook notification sent to all Subscribed webhook URLs
      - Integrating Platform (vendor or brand) makes API Request Query using the order entity ID received within webhook payload
5. **Customer receives 'Order Accepted' notification**
6. **Optional: Customer initiates Modification or Cancellation**
   1. **Customer modifies order**
      - Customer may request modification online until Store’s Lead Time Cutoff time
      - ezCater Customer Service may execute modification at any time, including after order fulfillment, with approval from Store if under Lead Time Cutoff
      - Customer receives Modification Accepted notification after Caterer Accept
   2. **Customer cancels order**
      - Customer may request cancellation up to 24 hours of order fulfillment
      - ezCater Customer Service may cancel order at any time, with approval from Caterer if under 24 hours
7. **Optional: Caterer confirms Modification or Cancellation**
   1. **Cater confirms modification**
      - Modifications require additional Caterer Accept action
        - Once completed a new 'Accepted' webhook notification will be sent out, there is no 'Updated' notification
        - Integrating Partner/Brand is expected to check if 'Accepted' webhook is for new or existing order and handle accordingly
        - Caterer Accept may be completed either ezCater Customer Service with authorization from Store
   2. **Caterer confirms cancellation**
      - 'Canceled' webhook notification sent out
8. **Optional: Customer receives notification of confirmation of Modification or Cancellation**
9. **Customer gets 'Day of Confirmation' text**
10. **Food arrives right on time**
    - Store prepares food
    - Store may use Dispatch or their own drivers for delivery/setup
11. **Customer receives 'Receipt' email**
:::

:::hint{type="warning"}
**Special Call-Outs**

- Strategies on managing your brand's need for API Users and their subsequent Tokens will be discussed throughout the Implementations process.
- Order Query will advise whether Third Party Delivery (Dispatch) is active on the order, which means ezCater will not pay restaurant for either tip/gratuity or delivery fee, even if those values are present in the Order Query Response.
- The catering use case includes orders having multiple modifications prior to preparing the order.  ezCater recommends that prior to pushing orders to the POS for fulfillment that you ensure you have the latest order modifications.  This can be attained by performing an Order Query immediately prior to sending the order for fulfillment.
- Menu synchronization is an important part of the solution.
- Bulk updates to Store configuration cannot be made through the API

:::


[title] Data Sharing Permissions - SAP Concur Enterprise
[path] Enterprise Account Integrations/SAP Concur Enterprise/

ezCater minimizes data storage, fetching only the necessary information for automatic receipt forwarding or roster sync while maintaining strict data privacy and transparency.

For accounts who enable only the receipt integration without roster sync, ezCater acts purely as a data forwarding service. ezCater fetches the [user identities from Concur](https://developer.concur.com/api-reference/profile/v4.scope-mapping.html). The only data accessed during the process is the Concur User\_ID and email, which are used solely to confirm the user’s active status within SAP Concur before forwarding the receipt.

For accounts enabling employee roster sync, the only data stored and visible within the Admin dashboard includes:

- First Name
- Last Name
- Email Address

Additionally, the Concur User\_ID is stored but is not visible or synced to the dashboard.

[title] Olo Orders <> Olo Menu API Conversion Overview
[path] Restaurant Partner Integrations/Olo Rails Integration/

# What is an Olo Orders \<> Olo Menu API Conversion?

- Eligible brands already live on the Olo Orders Integration can be added to the Olo Menu API Integration as well, allowing them to seamlessly integrate their Olo menu to the ezCater Marketplace.
- **Note:** *This applies only to brands currently live on the Olo Orders Integration; all new brands joining ezCater are already onboarded through the Menu API.*

**

# What Does the Conversion Involve?

- The primary action required is **menu tagging** - adding metadata tags to an existing menu directly in the Olo menu editor. 
  - In some cases, minor menu adjustments may be needed, such as restructuring nested modifiers or adding a Meal Program Category, but these are situational and will be clearly communicated upfront. 
- Compared to the original integration process, conversion is a significantly smaller lift with a much more focused effort. 
- Brands will work with the ezCater Software Configuration Specialists to finalize and approve the menu tagging for conversion. 



# What Support is Provided?

- Each brand going through a conversion will be paired with a dedicated Project Manager and Software Configuration Specialist who work together to provide 1:1 support throughout the entire process - from initial setup through final conversion.



# Key Benefits

- Location Menu flexibility: Maintain a unique menu per location, no cap on menu tiers.
- Easier Menu management: Streamlined item and pricing updates, reducing manual intervention by ezCater.
- Accurate, reliable menu syncing: Syncing your menu directly between Olo and ezCater keeps your menu and menu images consistent in real time.



# Considerations

- [Menu Tagging ](https://api.ezcater.io/menu-sync)will need to be completed in its entirety, including [Meal Program ](https://api.ezcater.io/meal-program-menu-set-up#meal-program-menu-set-up)if the restaurant partner is participating in the program at even one location.
- 86ing, deeply nested modifiers, and quantity modifiers are not yet supported on the Menu API at this time.
  - **86’ing:&#x20;**&#x49;tems must be removed from the menu or ezCater’s visibility must be removed from the items in Olo to accomplish removing an item from the ezCater marketplace.
  - **Quantity Modifiers:&#x20;**&#x57;e can accommodate certain configurations using minimums and maximums, but not when the goal is to be able to select multiple of one option.
    - Example:
      - Choose 3 sandwiches:
        - Grilled Cheese 
        - Club 
        - Mediterranean Veggie
        - Italian

:::Paragraph{indent="4"}
*This should be configured using a minimum of 3 and maximum of 3 on the group in Olo. If the goal was to have *up to* 3 sandwich types selected, you would instead configure this as a minimum of 1 and maximum of 3.*
:::

:::Paragraph{listStyleType="square" listStart="2" indent="3"}
Example of Not Supported Quantity Modifiers:
:::

:::Paragraph{listStyleType="disc" indent="4"}
Choose 10 sandwiches:
:::

:::Paragraph{listStyleType="circle" indent="5"}
Grilled Cheese + 3 -
:::

:::Paragraph{listStyleType="circle" listStart="2" indent="5"}
Club + 0 -
:::

:::Paragraph{listStyleType="circle" listStart="3" indent="5"}
Mediterranean Veggie + 2 -
:::

:::Paragraph{listStyleType="circle" listStart="4" indent="5"}
Italian + 5 -
:::

:::Paragraph{listStyleType="circle" listStart="3" indent="2"}
**Nested Modifiers:&#x20;**&#x57;e can only support a single level of nesting. Any nesting past that first level will cause menu ingestion failures.
:::

:::Paragraph{listStyleType="square" indent="3"}
Example:
:::

:::Paragraph{indent="3"}
**(**<font color="#15803D">**SUPPORTED**</font>**/**<font color="#EF4444">**NOT SUPPORTED**</font>**)**
:::

:::Paragraph{indent="3"}
<font color="#15803D">Sandwich Box (Item)</font>
:::

:::Paragraph{listStyleType="disc" indent="2"}
<font color="#15803D">Choose Sandwich (Modifier Group) </font>
:::

:::Paragraph{listStyleType="circle" indent="3"}
<font color="#15803D">Grilled Cheese (Modifier option)</font>
:::

:::Paragraph{listStyleType="circle" listStart="2" indent="3"}
<font color="#15803D">Club (Modifier option)</font>
:::

:::Paragraph{listStyleType="circle" listStart="3" indent="3"}
<font color="#15803D">Mediterranean Veggie (Modifier option)</font>
:::

:::Paragraph{listStyleType="circle" listStart="4" indent="3"}
<font color="#15803D">Italian (Modifier option)</font>
:::

:::Paragraph{listStyleType="square" indent="4"}
<font color="#15803D">Toasted (Nested Modifier, single choice)</font>
:::

:::Paragraph{listStyleType="disc" indent="5"}
<font color="#EF4444">Cut in half (Second Nested Modifier)</font>
:::

:::Paragraph{listStyleType="square" listStart="2" indent="4"}
<font color="#15803D"></font>
:::

:::Paragraph{listStyleType="disc" indent="5"}
<font color="#EF4444">Cut in half (Second Nested Modifier)</font>
:::

- Most brands opt to convert all locations at once, rather than smaller piloting periods for menu maintenance purposes. 



# What Action Items Are Required to Convert?

The following steps outline the full conversion process that the ezCater team will work alongside Brand technical contacts to complete:

1. **Review documentation** — Start with the [Menu API documentation ](https://api.ezcater.io/menu-sync)for metadata tagging guidance, as well as the [ezCater Metadata Tagging Video](https://ezcater.wistia.com/medias/8ehlcu9tng) for any guided step by step that may be beneficial. 
   - If any locations participate in the Meal Program, also review the[ Meal Program Setup](https://api.ezcater.io/meal-program-menu-set-up#meal-program-menu-set-up), as this is an additional required step. 
2. **Apply metadata tags** — Tag all menu items in the Olo Company menu, then assign all menu categories and items to the Olo Demo Vendor.
3. **Initial menu import** — Work with the ezCater team to import the menu into ezCater's POS testing environment, error-free.
4. **Menu review** — ezCater will review the menu and produce a Menu Consult Doc with any identified requirements or recommendations.
5. **Revisions** — Work through any of the feedback from the Menu Consult Doc to resolve any missing tags or errors.
6. **Final approval & rollout** — Once all tagging and requirements are approved by a Menu Configuration Specialist, the project manager can then convert all locations.



# Menu Tagging Requirements

Menu tagging is the core of the conversion process. The following requirements apply to all menus going through a conversion, and ezCater resources are available to identify both the Key and the Value for each Metadata Tag.

- All items must include the following Metadata Tags:
  - CateringServeSize
  - TaxCategory
  - QuantityUnit
  - Utensils (Free or Paid)
- Where applicable, tags should be added such as the FoodLabelingTags, ItemTypeTags, and ChoiceTypeTags, as these will be reviewed during the Menu Review portion of the project. If a required tag is missing or needs to be updated, this detail will be added to the Menu Consult document. 
- Special Call Out: Utensils
  - *Utensils are required on every item,&#x20;*&#x77;ith the exception of beverages, and can be configured as both free (most common!) or as paid options. 
  - Free Utensils:
    - While hidden on the ezCater menu, they are presented as part of the checkout experience.
    - Free utensils are modeled as an Option/Choice, and are tagged as “UTENSILS.”
    - To create free utensils specifically for ezCater, do not use the Single Use Category functionality. Instead, create a modifier group (typically just called Utensils) and attach to each ezCater specific item.
    - Add in the appropriate choices from the [Menu Sync Utensils Setup](https://api.ezcater.io/menu-sync#free-utensils-specific-metadata) chart.
    - Add Metadata tag with the Key of ChoiceTypeTags and a Value of Utensils and apply the modifier to all items.



# Menu Tagging Requirements: Meal Program

***Meal Program tagging is an additional step required for any brand that has locations that participate in ezCater's Meal Program (formerly Relish), but is not required for brands that do not.&#xA0;***

The following requirements ensure Meal Program orders flow correctly through the API for reporting and menu maintenance purposes. Review the [Meal Program Setup documentation](https://api.ezcater.io/menu-sync#meal-program-menu-set-up) for full tagging guidance and requirements.

**Key Considerations**

- Orders may fail due to a "Relish Finalized" status that occurs approximately 90 minutes before the customer's requested event time, which can differ from lead times of other menu categories. Using ezCater-specific menu categories/items in the Olo menu admin allows for a custom lead time to be set independently for these orders, helping prevent these failures.
- All Meal Program orders are still fulfilled through the Portal — but Olo tagging is required to ensure the existing Meal Program menu is not overwritten with the menu sync.

**Menu Setup**

- The Meal Program menu must be configured within the **Olo Menu Company Admin**, either within its own dedicated Olo category or tagged onto existing menu items that are shared between both Marketplace and Meal Program menus.
  - **Option 1 — Existing categories:** Meal Program tags can be applied to existing menu items, but lead time must be carefully accounted for to prevent syncing issues. **This set up is highly discouraged due to order failure potential.**
  - **Option 2 — Dedicated category (highly recommended):** A separate Meal Program category can be created in Olo to house these items, keeping them clearly isolated from standard menu items, or to include menu items that would not typically be available for the standard Catering menus.

**Required Tagging**

- Lead time configuration must be considered for the ezCater-specific Meal Program category/items to account for the “Relish Finalized Window” which occurs approximately 90 minutes prior to the order event time.
- Any item that is not physically included with the main ordered item — meaning it will not arrive inside or with the primary item automatically— must be tagged with **INDIVIDUALLY\_PACKAGED\_RELISH\_SIDE = T**. This tag triggers a separate label to be generated for that item from the Portal.
  - *Example: If a bowl is ordered and mac and cheese is available as an add-on at an additional cost, the mac and cheese arrives separately from the bowl and will require this tag to generate its own label.*
- **ChoiceTypeTags** should also be applied to any Drinks or Desserts included as part of a package, as these will similarly generate a separate label.
- **Utensils are not required** for any menu items created or duplicated specifically for the Meal Program.

# Resources

- [Menu Sync Tagging Instructions](https://api.ezcater.io/menu-sync)
- [Menu Tagging Video](https://ezcater.wistia.com/medias/8ehlcu9tng)
- [Menu Sync Utensils Setup](https://api.ezcater.io/menu-sync#free-utensils-specific-metadata)
- [Menu Sync Utensils Video](https://youtu.be/VqEmuk-GWF4)
- [Meal Program Menu Set Up](https://api.ezcater.io/meal-program-menu-set-up#meal-program-menu-set-up)


[title] Enterprise Account Integrations
[path] /

This documentation provides guidance on integrating ezCater products with procurement systems and identity providers. It covers integration for PunchOut Ordering, Single Sign-On, and SCIM provisioning. These integrations aim to streamline procurement, enhance security, and improve user experience.


[title] SCIM for ezCater Marketplace & Meal Program
[path] Enterprise Account Integrations/

**System for Cross-domain Identity Management (SCIM)&#x20;**&#x73;implifies the management and provisioning of user identities across multiple applications.

**SCIM Use Cases**

- **Enhanced Security:** Ensures that only authorized users can log in.
- **Simplified User Management:** 
  - If auto-provisioning is enabled, user accounts will automatically be created when the user is assigned to the Meal Program app. 
  - If SSO is required, when an employee leaves the company, they will be removed from the Meal Program , reducing the risk of unauthorized access. 
  - Updates a user’s attributes within the Meal Program when the app is assigned.
- **Improved User Experience:&#x20;**&#x45;liminates the need for users to remember separate passwords for the Meal Program .

**SCIM Integration Availability**

Currently available for Meal Program customers who use Okta as their identity provider (IdP).

Available for early access testing with ezcater Marketplace customers who use Okta as their identity provider (IdP). early access testing will require a meeting with our engineers to configure SCIM for marketplace.

[Interested in a different identity provider?](https://docs.google.com/forms/d/e/1FAIpQLSeo0FeDGIpa7_ke_PQke0gLVMa9Hp0_x6kaHKzj6OGDDmljbg/viewform)

**Support SCIM Functionality**

- **Create Users:** Creates or links a user in Meal Program when assigning the Meal Program app to a user in Okta. 
- **Deactivate Users:** Deactivating the user or disabling the user's access to the application through Okta will remove the user in the Meal Program . 
  - Note: For Meal Program, deactivated users are denied access to sign in, but their existing corporate data is retained.
- **Update Users:&#x20;**&#x4F;kta updates a user’s attributes within the Meal Program when the app is assigned. Future attribute changes made to the Okta user profile will automatically overwrite the corresponding attribute value in the Meal Program. 

**SCIM Configuration Process**

The [ezCater Meal Program SSO Form](https://ezcaterforms.formstack.com/forms/ezcater_sso) provides the ability to set up and update SAML and SCIM configurations. The form is intended to be completed by an IT contact. Once filled out, ezCater’s Integrations & Implementations team will securely email the SCIM Bearer Token.

**SCIM User Experience**

- For users assigned to the app, the Meal Program is found within their company’s identity provider (IdP) dashboard/bookmarks. 
- Users login with their company’s identity provider credentials, which eliminates the need for users to remember separate passwords for ezCater and/or the Meal Program.
- For companies with the setting to require SSO enabled, if a user tries to login with username and password the page will redirect them to the SSO sign in page and state “Your company requires you to use Single Sign On”.
- For companies with the setting to autoprovision new users enabled, new users are sent an email to set up their account when SCIM is enabled. When the user logs in for the first time, they will select their drop location.


[title] How It Works - SAP Concur Enterprise
[path] Enterprise Account Integrations/SAP Concur Enterprise/

## Enterprise Integration Enablement

**ezCater Account**

- Must have an ezCater Enterprise Account.&#x20;
- Only one instance of Concur can be connected to an ezCater Enterprise account.&#x20;
- Parent child accounts will all be connected through the parent level enablement.&#x20;
- Not available for the Meal Program.

**SAP Concur Account**

- Expense - Standard
- Expense - Professional

**Permissions:&#x20;**&#x54;he user enabling the integration must be an ezCater account admin AND a SAP Concur admin.

**Cost:&#x20;**&#x54;here is no signup fee for ezCater Enterprise Account, and there is no cost to access the integration with SAP Concur.

## Receipt Sending

After an order is completed, ezCater automatically sends the associated PDF receipt to Concur’s eReceipt API and Concur generates a receipt in the employee’s account, eliminating manual entries.

**Content**

- ezCater transactions are sent to Concur as line items with a PDF attached. The PDF exactly matches what the user sees in the Receipts section of their account.
- When an order is refunded or updated, correction receipts are automatically transmitted to SAP Concur, keeping expense reports accurate and up-to-date without requiring manual intervention.&#x20;
  - The total on the correction receipt is the difference between the original receipt amount and the new order total.
  - Concur creates a new receipt and expense for either the newly-charged or newly-refunded amount.

**Timing:** Receipts are sent automatically within 24 hours after payment has been captured.

**Account:&#x20;**

- Receipts are posted to the account of the user who pays for the order.&#x20;
- On enabling SAP Concur Enterprise automatic receipt forwarding, any existing employee-level integrations will be overridden to prevent duplicate entries.

*Receipts cannot be sent to Concur if:*

- The receipt was created prior to the Enterprise integration
- The receipt has already been sent
- The order was paid for with credit line
- Payment has not yet been captured

## Automated Expense Creation

When an receipt is forwarded to Concur, it automatically creates an expense  with key details pre-filled, including:

- Receipt
- Vendor name & address (ezCater)
- Payment amount and type

![](https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/WnGewQsdkE-_2GgltHHzp_cdn-1.png)

If an order is updated after the receipt is sent, a correction expense will be created with the amount as the difference between the original receipt amount and the new order total.

## Roster Sync

Roster Sync automatically keeps your employees in ezCater up-to-date by connecting with your Concur Expense roster.&#x20;

- Automatically adds and removes employees from your ezCater Enterprise account based on your Concur roster.&#x20;
- The sync includes all US employees in Concur; specific groups or departments cannot be selected. International employees are excluded by default.
- New users receive instant invites to ezCater and departing employees are promptly deactivated. Track who has accepted their invite and who has been removed in the ezCater Admin Portal. Only employees who haven’t been invited before will receive an invitation. Once enabled, new employees will automatically have automatic receipt forwarding turned on - no additional setup required.
- The roster is updated by a continual sync of events sent from SAP Concur to ezCater for accuracy.
- While receipt forwarding is supported for parent level enablement, Roster Sync is currently unavailable for accounts with a parent child structure.

[title] Slack Integration
[path] Enterprise Account Integrations/

It just got even easier for your team to order food at work — without interrupting their workflow.

Introducing the ezCater app in Slack, now available to existing [Meal Program ](https://relish.ezcater.com/)customers.

This integration lets employees view their [Meal Program ](https://relish.ezcater.com/) schedule, browse restaurant options, receive weekly & daily order reminders, delivery updates, reorder past meals, and leave reviews — all directly within Slack. As we continue to learn from usage and feedback, additional features and improvements will be introduced to better serve your needs.

### Why Use Slack + Meal Program Integration?

This integration is designed to save you time and make recurring meal ordering more convenient. With simple, built-in functionality, you’ll avoid missed meals caused by overlooked emails or last-minute decisions.

### How to Get Started

Simply link your Meal Program account with Slack and start experiencing a more convenient way to order meals. Once the integration is live in your Slack workspace, you can provide feedback directly to help improve the service. [Follow the information here](https://api.ezcater.io/slack-with-meal-program) to set set up.&#x20;

### FAQ

1. **What is the Slack + Meal Program Integration?** This integration allows you to manage your recurring meal orders directly within Slack by connecting your Meal Program. You can view restaurant options, receive reminders, reorder meals quickly, and track delivery status.

2. **What are the benefits of using this integration?** The main benefits are time-saving, convenience, and ease of use. You no longer need to check emails for meal reminders or miss ordering due to forgetfulness.

3. **Do I have to use it to order my meals?** No, but we recommend it when available!&#x20;

4. **Who can use this integration?** Any employee that has a Meal Program account can use the ezCater Slack App.****


Need help getting started? Please reach out to [integrations@ezcater.com](https://integrations@ezcater.com)

View our [Demo Video here](https://ezcater.wistia.com/medias/edo70eolid)!&#x20;

[ezCater Privacy Policy](https://www.ezcater.com/privacy_policy)

[title] Requirements
[path] Restaurant Partner Integrations/General Menu Guidance/

# Equal Price Guarantee

ezCater’s[ pricing policy](https://catering.ezcater.com/en/help/what-are-the-pricing-requirements-for-my-menu) ensures that the pricing restaurant partners provide for menu items, service and other fees to display on their ezCater pages for a given location will match the lowest prices and fees that are charged through any other website or online channel for substantially similar offerings at that location. This can also be found in the [restaurant operating procedures](https://www.ezcater.com/restaurant_operating_procedures).

# Item Images

The integration supports item-level images only. These are supported through URLs where ezCater can download images and attach them to your menu. Review ezCater’s[ technical requirements for photos](https://catering.ezcater.com/en/help/what-are-the-technical-requirements-for-photos-on-ezcater) to ensure they meet our technical requirements for images on ezCater menus.

If images do not follow our technical requirements, your images may not be processed:

- File types: jpg, png
- Size: Minimum 1200x800 pixels
- Horizontal orientation


[title] Best Practices
[path] Restaurant Partner Integrations/General Menu Guidance/

# Category Standardization

Customers routinely look for categories like breakfast, boxed lunches, catering packages, and most popular items at the start of the menu while they look for sides, desserts, drinks and miscellaneous categories at the end of the menu.

# Maximum Choices

Maximum choices should be present for items that need them. For example, if there is a sandwich item with one choice of cheese, the max choice should be 1. This will only allow customers to make 1 cheese selection. Otherwise, they could make multiple selections which could cause caterer confusion and potential order fulfillment issues.

# Option Prompts

Option prompts should be clear and succinct (“*Select X*,” “*Choose X*,” etc).

# Descriptions

It is ideal to have expectation-setting descriptions on menu items and choices, especially for items customers may not be familiar with.

# Professionalism and Organization

Menus should be rid of typos, punctuation, spelling and grammatical errors and be clear so that customers can move quickly while placing an order.


[title] Menu Sync
[path] Restaurant Partner Integrations/Olo Rails Integration/

ezCater and Olo have two integrations available to our restaurant partners: Orders API and Menus API. The Orders API transmits order data, while the Menus API syncs the ezCater menu with your Olo Rails menu, allowing for menu per location.

This documentation provides comprehensive guidance for preparing menus for integration with ezCater. It outlines menu features, requirements, best practices, and integration-specific configuration guidance to ensure a smooth integration process.&#x20;

To get the Menus API configured, ezCater requires additional metadata tagging to automate the menu build. 

The purpose of this document is to explain the steps needed to build and tag your menu with the necessary metadata tagging to automate the menu build.

To ensure a smooth transition, we highly recommend you add all Metadata tags as soon as you can. This will allow the ezCater team to streamline the process and work on getting your brand live as soon as possible. 

For assistance or questions about the **integration functionality or what metadata Key/Value to use**, please reach out to [integrations@ezcater.com](https://integrations@ezcater.com)

For assistance or questions regarding your **Olo menu (Metadata placement, Rails visibility settings, basket errors)&#x20;**&#x70;lease contact your Olo Customer Experience Manager or your Olo Project Manager. 

Additional Resources:

- [ezCater Menu Requirements](https://api.ezcater.io/general-menu-guidance)
- [ezCater and Olo Rails FAQ](https://api.ezcater.io/olo-rails-integration)
- [Rails Filters/Menu Visibility ](https://olosupport.zendesk.com/hc/en-us/articles/360028092432-Rails-Filters-Marketplace-Menu-Visibility)

***

# Metadata Setup&#x20;

The purpose of this document is to identify and walk through the requried steps needed to set up metadata within Olo Menu Management to ensure a smooth sync with ezCater via the Menu API.

Metadata is data that is entered in key/value pairs (also known as metadata tags) in Menu Admin. In the case of ezCater specific metadata, the key/values are passed onto the ezCater platform to create a specific user experience.&#x20;

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc9Oxdq0CwdpA3BKviBsAOzDo67j3-wribuNSRd1Kq2iwRtsDztEcFuVvjIb1gpHmynjG3AS3KO5mqeM5-elnGpJbRZgFoNTDieUdYxf4VaiQ0RRVE3VBwvXCnk4mz8J8jKnzC0mQ?key=_46Fq1j0Q7fQBmsk96bXc_rr" size="50" width="884" height="330" position="center" caption="Example: the food labeling tags will flag dietary preferences on the ezCater front end." darkWidth="884" darkHeight="330" showCaption="true"}

For best practices and information on the metadata Keys/Values available for use, please follow below or reference [ezCater’s features list](https://api.ezcater.io/features). 

**How to set up metadata in the Olo Menu Management**

- Click the metadata tag on the category, product, modifier group or modifier choice.

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXckmajUX6UMLr_zx-kocl2S10jUcaIuJ0pgvzJSCmk_-XM3PqOW-CGN1zxDIRCf0o5lLDYDD8Vjr8XD89ZDhUrnYyg7EStZj4zwTNcox52PY5vUS4SG4PpxIbHqVDWXug3Et_7M?key=_46Fq1j0Q7fQBmsk96bXc_rr)

- Enter the Key | Value pair

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXcox8KSwUWvw1J72f5x1Gcp4oaIfOJ-UM19PUSnB1Ds05Fh8q5Qe9J-rhK_TOJ3jOqOpxOia-SX6E3ec3B_dK_wkMYaa19Al_e39ig6pmjMsLtdkJ0wbKJXC3IPJI2vHrAxen0SOg?key=_46Fq1j0Q7fQBmsk96bXc_rr)

:::hint{type="info"}
For a more in-depth walkthrough of the steps above, please utilize the video below.
:::

::embed[]{url="https://www.youtube.com/watch?v=VqEmuk-GWF4"}

**Metadata Callouts**

- If you need to duplicate a product for ezCater and would like to use the same tags for the product make sure to keep the “Keep existing metadata for product” checked.
- *Do not delete any metadata from live ezCater products unless advised otherwise by ezCater/Olo.*
- *There are&#x20;****no negative implications****&#x20;to adding metadata in advance to a live ezCater menu prior to onboarding with the ezCater Menus API.*
- *Remove the spacing that is present in the Key or Value field. For example: if a value is written VEGETARIAN, GLUTEN\_FREE it will fail. Instead remove the space: VEGETARIAN,GLUTEN\_FREE*
- *Keys and values are not case sensitive*

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXf4jl55jqh2rqABMPBG-hB6mxzZH8nUHgZSJbLFvAZi8UEk0ToAPV9yOOVd7X3Ly_JOj6i-B_8sShtCHjNAatnZFBME9Qgk-bvE9zQyW04B-Nchzbq9z9aM6Wec1kmPBw5eoUyLbQ?key=_46Fq1j0Q7fQBmsk96bXc_rr" size="50" width="890" height="830" position="center" darkWidth="890" darkHeight="830" showCaption="false"}

## Utensils-Specific Metadata

Utensils is a general term used to describe the varying utensil items a customer will need. Utensils can include utensils; forks, knives, spoons, plates, bowls, and/or napkins. We can accommodate free or paid utensils.&#x20;

:::hint{type="info"}
*Utensils selections from customers can be found in Partner Portal.&#xA0;*
:::

- ezCater requires **all menus** to have a utensil configuration.
- ezCater provides consumers the ability to select or deselect their utensil requirements as the order forms in the cart. The experience includes:
  - As items are added to the cart, tableware options appear in the cart in a dedicated section.
  - Upon edit the consumer can select or deselect “tableware” as needed. The options available for selection change based on the item’s option/choices selected.

**80% of orders on ezCater are placed with restaurants who offer free plates & utensils.&#x20;**&#x4F;ffering **plates, napkins, and utensils** helps ensure a positive experience for customers, especially if they do not have these items in-office.

Many customers appreciate **offering sustainable or recyclable utensils or packaging.**

## Free Utensils-Specific Metadata

Free utensils are modeled as an Option/Choice, are tagged as “UTENSILS”, while hidden on the ezCater menu, they are presented as part of the checkout experience. If utensils are free, all items will need to have a utensil configuration with the exception of individual drinks. 

- To create free utensils specifically for ezCater you will not use the Single Use Category functionality. Instead you will create a modifier group under each ezCater specific item.

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdydBSR158uL0PhEgMXe2jjAVWYbOOa7vGE_MJobWdnWxOlhOZxDzmMyu6awSVwSeIrKsiViUADMwRQiOwARjEoX-at8rsU0wzicSigLoO7qVogAHQ4H6yyBIAltNkGWVEFzu5N?key=_46Fq1j0Q7fQBmsk96bXc_rr" size="50" width="784" height="170" position="center" darkWidth="784" darkHeight="170" showCaption="false"}

- The table below highlights the possible configurations for utensils depending on the menu items offered. Utensils must be applied to all food items.

| **Item**                  | **Modifier Group** | **Choices**                                           |
| ------------------------- | ------------------ | ----------------------------------------------------- |
| **Standard Items**        | Utensils           | * Utensils
* Plates
* Napkins                         |
| **Soups**                 | Soup Utensils      | - Bowls
- Napkins
- Spoons                            |
| **Non-Individual Drinks** | Cups & Ice         | * Cups
* Ice                                          |
| **Coffee**                | Coffee Utensils    | - Cups
- Stirrers
- Sugar
- Diet Sweeteners
- Creamer |

:::hint{type="warning"}
Exceptions that would not require utensils: Individual drinks.
:::

- Create a utensils modifier within the group and map it to the POS.
- Add metadata by clicking the “tag” button, enter the Key + Value as shown below.
  1. Key: **ChoiceTypeTags**
  2. Value: Utensils

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXf2V1r9UIi6ezfA79NHIAcvGIZ6xum_c9FVHvhXu2-NTlY1j-VDk-WjipufB7IyBgwRlw7ZW-eqCgaC82r9mqrAbSCtfyPdfNC3_z_kGzRmnMVqMjKsMbXYE1JEDamqZQZGOgTSbQ?key=_46Fq1j0Q7fQBmsk96bXc_rr" size="50" width="1600" height="346" position="center" darkWidth="1600" darkHeight="346" showCaption="false"}

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXf9clkCbMc_NAm7njIJGDoNQZIWNCHrviHQ_C4bIBHeKCNv2d_RCpJq6hVYsajwkBgu22xOE7cv0Qi-7CkmMd733izQirLWtMMNQ7PoByyL34-UnOxSGFysf-grCqsmk9-t3Zo4Xg?key=_46Fq1j0Q7fQBmsk96bXc_rr" size="48" width="1600" height="345" position="center" darkWidth="1600" darkHeight="345" showCaption="false"}

:::hint{type="info"}
For a more in-depth walkthrough of the steps above, please utilize the video below.**&#x9;**
:::

::embed[]{url="https://www.youtube.com/watch?v=TUX5qvnv66M"}

## Paid Utensils-Specific Metadata

Paid for items are tagged as “UTENSILS” and presented in the menu as an item. Customers can select these items and add them to the cart as they build their order.

- Paid utensils are set up by creating a utensils item with a cost under a “Miscellaneous” category.
- Add Metadata by clicking the “tag” button, enter in Key + Value as shown. 
  - Key: **ItemTypeTags, TaxCategory** 
  - Value: Utensils, Miscellaneous 
- Add Option Level for Utensils and the necessary choices using the configuration below depending on the menu items offered.  

| **Item**          | **Choices**                   |
| ----------------- | ----------------------------- |
| **Utensils**      | * Utensils
* Plates
* Napkins |
| **Soup Utensils** | - Bowls
- Napkins
- Spoons    |
| **Cups**          | * Cups                        |
| **Ice**           | - Ice                         |

:::hint{type="warning"}
Exceptions that would not require utensils: Individual drinks.
:::

:::hint{type="info"}
For a more in-depth walkthrough of the steps above, please utilize the video below.**&#x9;**
:::

::embed[]{url="https://www.youtube.com/watch?v=BBx_Mfjv2Bc"}

***

# Metadata Tag Configurations

Below are the necessary Keys and Values that need to be entered for all items. Keys are indicated by **bold** text, values are indicated by sub-bullets.

## Item Level Tagging

### CateringServeSize

:::hint{type="info"}
**Required&#x20;**&#x66;or all items.

A numeric value indicating the serving size. Sorry, we cannot support ranges (ex. Serves 4-8). Ranges can be added to the item's descriptions.&#x20;
Supported values:
:::

- [ ] Any positive non-zero integer

::::ExpandableHeading
### TaxCategory

:::hint{type="info"}
**Required&#x20;**&#x66;or all items. Please note, we can only support one TaxCategory tag per item.&#x20;

Tax designations of each item. 
Supported values:
:::

- [ ] BAKERY\_ITEMS
- [ ] CAKES\_AND\_PIES
- [ ] CANDY
- [ ] CHIPS\_AND\_SNACKS
- [ ] COFFEE\_TEA\_MILK
- [ ] DRESSINGS\_AND\_CONDIMENTS
- [ ] EXEMPT
- [ ] ICE\_CREAM
- [ ] MISCELLANEOUS
- [ ] NON\_SODA\_DRINKS
- [ ] PREPARED\_FOOD
- [ ] SANDWICHES
- [ ] SODA
- [ ] WATER
::::

### FoodLabelingTags

:::hint{type="info"}
**Required** when applicable.

**Customers frequently filter on ezCater for dietary friendly options.** 1 in 5 orders on ezCater include items that accomodate dietary restrictions. Many of our customers say that they are unable to order from a menu without anything gluten-free or vegan.

These values will tag an item with the flag in ezCater. These flags will be searchable by the customers.
Supported values:
:::

- [ ] HEALTHY
- [ ] VEGETARIAN
- [ ] VEGAN
- [ ] KOSHER
- [ ] HALAL
- [ ] GLUTEN\_FREE
- [ ] SPICY

### ItemTypeTags

:::hint{type="info"}
**Required** when applicable.

1 in 3 ezCater orders includes beverages, and 1 in 5 includes desserts

These values are specifically used for upsell opportunities. Please ensure all beverage and dessert items are tagged accordingly, including items that include a drink or dessert.
Supported values:
:::

- [ ] DESSERT
- [ ] DRINKS
- [ ] UTENSILS
- [ ] ICE

### IndividualWrapStatus

:::hint{type="info"}
**Required** when True.

27% of ezCater orders include individually packaged items

A value indicating whether the product can be individually wrapped or not.&#x20;
Supported values:
:::

- [ ] T
- [ ] F 

::::ExpandableHeading
### QuantityUnit

:::hint{type="info"}
**Required&#x20;**&#x66;or all items. Please note, we can only support one QuantityUnit tag per item.&#x20;
Unit of Measure for items.&#x20;
Supported values:
:::

- [ ] BAR
- [ ] BOTTLE
- [ ] BOWL
- [ ] BOX
- [ ] BUFFET
- [ ] CAKE
- [ ] CAN
- [ ] CARAFE
- [ ] DOZEN
- [ ] FOOT
- [ ] FULL\_PAN
- [ ] GALLON
- [ ] HALF\_GALLON
- [ ] HALF\_PAN
- [ ] ITEM
- [ ] KIT
- [ ] LITER
- [ ] PACKAGE
- [ ] PAN
- [ ] PERSON
- [ ] PIE
- [ ] PIECE
- [ ] PINT
- [ ] PIZZA
- [ ] PLATTER
- [ ] POUND
- [ ] QUART
- [ ] ROLL
- [ ] SIX\_PACK
- [ ] SKEWER
- [ ] SLIDER
- [ ] TACO
- [ ] TRAY
- [ ] TWELVE\_PACK
- [ ] TWO\_LITER
::::

## Option Level Tagging

### FoodLabelingTags

:::hint{type="info"}
**Required** where applicable.

These fields will tag an item’s choice with the flag in ezCater. These flags are not searchable by customers but will be tagged on the choice option. 
Supported values:
:::

- [ ] HEALTHY
- [ ] VEGETARIAN
- [ ] VEGAN
- [ ] KOSHER
- [ ] HALAL
- [ ] GLUTEN\_FREE
- [ ] SPICY

### ChoiceTypeTags

:::hint{type="info"}
**Required** where applicable.

These values are specifically used for upsell opportunities. Please ensure all beverage and dessert items are tagged accordingly. 
Supported values:
:::

- [ ] DESSERT
- [ ] DRINKS
- [ ] UTENSILS
- [ ] ICE

## Sized Based Items Tagging

### IsSelectionSizeGroup

:::hint{type="info"}
**Required** where applicable.

For Sized Based Items, the above tags will still be required on the Parent/Item level with the exception of CateringServeSize that will live on the Option level.&#x20;

- Parent/Item Level:
  - TaxCategory (Required)
  - FoodLabelingTags
  - ItemTypeTags
  - IndividualWrapStatus
  - QuantityUnit (Required)
- Option **GROUP**
  - IsSelectionSizeGroup = T
- Option 
  - CateringServeSize

These tags are specifically referring to size based items and are used to delineate small, medium, large for items. The product size selection names should not include the product name. The option group with this metatag should also be given the smallest sortOrder.

Products with selection sizes must have matching option and modifier structure across all sizes. Different selection sizes must have the same structure/names so the logic knows how to match options under the same option but with selection sizes.

- Option groups under each size must have exactly the same description, sortOrder, mandatory, minSelects, maxSelects, choiceQuantityIncrement, supportChoiceQuantities for each selection size.

Metadata tag will need to be added to the “**Option Group**”, **not the Parent/Item or the Option.**
Supported values:
:::

- [ ] T

### CateringServeSize

:::hint{type="info"}
**Required**.

A numeric value indicating the serving size. For sized based items, these need to exist on the option level, not item level. Sorry, we cannot support ranges (ex. Serves 4-8). Ranges can be added to the item's descriptions.&#x20;
Supported values:
:::

- [ ] Any positive non-zero integer&#x20;

***

# Zero Dollar Parent Items

- Items where the price lives on the option level, but is not a size. 
  - Priced options within the first option group with a “sortOrder” of 0.
  - Option Group must have minSelects = 1 and  maxSelects = 1 and be mandatory.
    - If these rules are not applied, the item will not be built.&#x20;
- "IsSelectionSizeGroup" metadata should not be added to the “Option Group”

***

# Lead Time for Menu Items

:::hint{type="info"}
The Item lead time indicates how far in advance the order for the specific item must be placed from when it will be ready. This field should be used **only** when a menu item has a **longer** lead time than your ezCater Marketplace store.&#x20;
*Please note, if an item lead time is shorter than your business lead time, these items will be available for order.&#x20;*&#xA;
When considering adding longer lead times to menu items, it’s helpful to remember that many customers search based on the store’s lead time. Adjusting lead times thoughtfully and having lower lead times helps ensure customers can easily find and order the items they want.
:::

### LeadTime

- Supported values will be in **minutes** starting at 5 hours and up to 72. Only whole hours will be supported.

| **Hours** | **Minutes** |
| --------- | ----------- |
| 5         | 300         |
| 6         | 360         |
| 7         | 420         |
| 8         | 480         |
| 9         | 540         |
| 10        | 600         |
| 15        | 900         |
| 20        | 1200        |
| 24        | 1440        |
| 30        | 1800        |
| 35        | 2100        |
| 40        | 2400        |
| 45        | 2700        |
| 48        | 2880        |
| 50        | 3000        |
| 55        | 3300        |
| 60        | 3600        |
| 65        | 3900        |
| 70        | 4200        |
| 72        | 4320        |

# Meal Program Menu Set Up

We are able to support menu syncing with your Meal Program locations with some caveats:
Meal Program menus and items need to be tagged according to these guidelines.

Like Marketplace orders, Meal Program orders will need to be sent through the API, but may fail due to “Relish Finalized” status happening \~90 minutes prior to the customer’s requested event time. Usage of ezCater specific menu items in Olo can assist with a specific lead time for the Meal Program items.&#x20;

This timing is an estimate and dependent on:

- Brand’s set required “Relish Finalized” timing
- Customer’s distance from location
- Dispatch pick-up time if applicable

**Item level:**

- **RelishChannel**= T (required)
- **Marketplacechannel**=T (Required only if items will be shared between Marketplace & Meal Program, otherwise the item will only be available on Meal Program)
  - RelishChannel=T can be used by itself or in combination with Marketplacechannel=T.&#x20;
    - Marketplacechannel= T cannot be standalone.&#x20;
- **CateringServeSize** (required)
- **TaxCategory** (required) 
- **QuantityUnit** (required) 
- **FoodLabelingTags** (required when applicable)
- **ItemTypeTags** (required when applicable)

**Choice Level:**

- **FoodLabelingTags** (required when applicable)
- **ChoiceTypeTags** for Drinks, Desserts\* (required when applicable)
  - This is needed for tracking and upsell opportunities 
- Sides: **INDIVIDUALLY\_PACKAGED\_RELISH\_SIDE** = T. (required when applicable)
  - This is only for printing an additional label.

**Meal Program Tagging Logic**

- When there is an item that is not a part of the main item and will not come in or on the ordered item, we will require “INDIVIDUALLY\_PACKAGED\_RELISH\_SIDE = T”. 
  - For example, if there is a bowl being ordered and there is the ability to add mac and cheese as a side to the item at an additional cost, the mac and cheese would not come inside the bowl, so it will need to be tagged in order to generate another label. 
- ChoiceTypeTags will also generate another label for Drinks or Desserts that come with the package. 
- If you duplicate/ add menu items specifically for Meal Program, Utensils are NOT required for Meal Program items. 



# Photos

Our research shows that **customers find photos more important than both menu item descriptions and user reviews** when determining where to order from.&#x20;

ezCater ordering data has shown that the more photos on the menu, the better. Menus with photos convert up to 60% higher.&#x20;

**Need photography for newly added items?**

- To book an ezCater photo shoot, [click here](https://www.smartshoot.com/go/ezcater)
- Check out the [ezPhoto Guide](https://catering.ezcater.com/en/help/ezphoto-guide-a-step-by-step-tutorial-for-food-photography) for instructions on how to take great food photos.

**Already have photos of your menu offerings?**

- Upload the photos to your Olo menu and ensure access is shared with ezCater!&#x20;

# Rails Visibility

When using ezCater specific menu categories you will need to adjust the Rails visibility setting to filter off all other ordering channels.

## Category Level Settings

- Navigate to the “Edit Category” button with a category.
- Under “Category Visibility” deselect all ordering channels with the exception of ezCater.

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeOdYAy_vhV6GWyJzeFx2Vce7HV8GMzO_HGtj1SR-P4fJUZoQdyLIl_8JvOAMWdPYUnme4Z9stjfhKj38bSP5c_nQUOwkyKtOWtjwXgcIWjs9T4LS-pCD2fBTsBtoxSJG10wx5h?key=_46Fq1j0Q7fQBmsk96bXc_rr" size="50" width="688" height="792" position="center" darkWidth="688" darkHeight="792" showCaption="false"}

## Item Level Settings

- Navigate to the product and click into the product name.
- Scroll down to get to the Menu Product Visibility feature&#x20;
  and change the visibility to be ezCater specific.

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeWZEGRpFeXmQAStXVYWL8bDM9yjlORRWYPagn4my49hYvHaO7CO1jJjoGguzpaeUuWOYrzPbPwsH1XwfzBZGajHsqHkMnFnq-xnzkRwVRXbHsUzayPYMoDaDFlgSlVGSmyjYwiKQ?key=_46Fq1j0Q7fQBmsk96bXc_rr" size="50" width="1430" height="1534" position="center" darkWidth="1430" darkHeight="1534" showCaption="false"}


[title] Overview
[path] Enterprise Account Integrations/

This help center provides guidance on how to connect ezCater with your existing systems.

&#x20;Here, you’ll find documentation to help you enable and manage integrations with expense management software, procurement systems, and identity providers—including **SAP Concur, PunchOut Ordering, Single Sign-On (SSO), and SCIM**.&#x20;

These resources are designed to help you automate receipt forwarding, synchronize employee rosters, streamline procurement workflows, enhance security, and improve the experience for your teams.


If you’re looking for a high-level view of what integrations ezCater offers—across expense, procurement, collaboration, and identity—and how they can benefit your business, visit our enterprise integrations page: [Explore all enterprise integrations.](https://www.ezcater.com/company/lp/enterprise-integrations/)


Please reach out to [enterprisesupport@ezcater.com](mailto\:enterprisesupport@ezcater.com) if you have any questions or concern

[title] Okta SSO Instructions - ezCater Marketplace & Meal Program Apps
[path] Enterprise Account Integrations/SSO for Marketplace & Relish/

## Overview

Create TWO separate SAML setups in your IdP. Note the SAML setups are identical, but the bookmarks redirect users to the specific sign-in URL. Without a bookmark, the Meal Program app will not support IdP-initiated logins.

## ezCater Marketplace App

- In the Okta Admin Portal within Applications, click on **Create App Integration**



::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd6mYD1fgzlZCOUWX_97XUkPC1_aqiNdmd98MQBRz8hw8kWvJDttDL8pK30xp0MPe5GUo6sX8IFgp7mbuxSDrnRoxZISVeZysdsFk3ilIvwyVSQRE-FOQAD6MEzl2gtcve8TgKqTw?key=AvWn09Y7CVz2HnQXem_NL67Q" size="42" width="494" height="330" position="center" darkWidth="494" darkHeight="330" showCaption="false"}

- Select **SAML 2.0** and click **Next**



::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXd6H0ELb0znHrdBwicmc_i9XwfpdZKyToxkYy7x9Tuxysz2B8LUDq7sDo5j5U8ABLmwZQ92apfUPTzKuCN2ja5fFsEVBpAfo9S3-96kMIt0O-MZArbIFXQDD6zXnxIGReMTQVzN?key=AvWn09Y7CVz2HnQXem_NL67Q" size="68" width="1600" height="965" position="center" darkWidth="1600" darkHeight="965" showCaption="false"}

- Name this integration **“ezCater”&#xA0;**
- In App Settings, **uncheck** the App visibility box “Do not display application icon to users”.
- Complete the fields as follows:
  - **Single sign-on URL:** [https://www.ezcater.com/saml/consume](https://www.ezcater.com/saml/consume)
  - **Audience URI (SP Entity ID):** ezcater.com
    - *Do&#x20;****NOT****&#x20;add https or www*
  - **Name ID format:&#x20;**&#x45;mailAddress
  - **Application username:** Okta username
- **&#xA0; &#xA0;**&#x4C;eave all other fields as default and click **Next**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcSsaE2H4Uw33AvQn8o5JTKwU0bX5YxNhPTHAwKnmEMSTb_A0Svyf_PS4ZxQWN1yBeW_UzauWu_aPF4gILID8id3r2KPMeZB3JaK4YNy_X954Pr2KtT8L3n4TsJ3rGIUZ3yyG3tLQ?key=AvWn09Y7CVz2HnQXem_NL67Q" size="78" width="1600" height="1423" position="center" darkWidth="1600" darkHeight="1423" showCaption="false"}

- In the final step, check the **This is an internal app…&#x20;**&#x6F;ption and click **Finish**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfVZcLvd5HYydagS-wQtQGYzwV1tYxNk7lVy8LfhvZjHieac-U7NnbGnL8VRpfudWA-uJfbAP0RDyUqJkgONNRUFFcfryLFUPk0rGRf_ycxNXeWym9MjMrSEPaxQ4pXPmt-bsUy?key=AvWn09Y7CVz2HnQXem_NL67Q" size="70" width="1600" height="734" position="center" darkWidth="1600" darkHeight="734" showCaption="false"}

- Return to your Okta Admin dashboard and click on the option to **Browse App Catalog**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdkAsACn3z5RvTQ36UotChmiCTHoWCS36mHI3p82Cn475v0_ZMDjvyMK2Rg_bNMcwepExRlhjEoBb30ys5BT__t5G1IPI1dh_UQMpg10S0mSFgM_IRFlY9eIKfj81Edr6Gng9t4Xg?key=AvWn09Y7CVz2HnQXem_NL67Q" size="70" width="678" height="236" position="center" darkWidth="678" darkHeight="236" showCaption="false"}

- Search for **ezCater&#x20;**&#x69;n the search bar and click on it
- To update the logo, click on the **Pencil icon** next to the default star.

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdq2RB0jhKM4eW1DaFpPhsTpqe_DD5CGVIz7AXNgDi9W4h8Hsb-cH3H6QN_veH2qy2BtbAXE5ku92dAFOn39FCx5SYBDG5JULC1lhUmx1MIMESNfEqsx0N4Fhxd1KVqfpb5cv2QJQ?key=AvWn09Y7CVz2HnQXem_NL67Q" size="78" width="884" height="392" position="center" darkWidth="884" darkHeight="392" showCaption="false"}

- Add the ezCater logo 

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/i3w_jkaAgSiRgn26Daen8_ezcater-logo-bright-primary-symbol-300dpi.png" size="38" width="2084" height="1918" position="center" showCaption="false"}

## Okta SSO Instructions - Meal Program App

- In the Okta Admin Portal within Applications, click on **Create App Integration**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcmsfHvm2k5j0RBJ6OotFpeQfdvcXJrIKb9LO-p4olUCUkjQSm9IDSjn_caaDU7PQTJ8JPx4B0lzJCL9M9TOzq41yux6Sm-1uCXw2vVuouKECqPj_8Z39OHN-WuGHG25gOc72Mq9A?key=AvWn09Y7CVz2HnQXem_NL67Q" size="62" width="494" height="330" position="center" darkWidth="494" darkHeight="330" showCaption="false" indent="2"}

- Select **SAML 2.0** and click **Next**

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXdLNVI2kcAKywE-ar-blBSrd82iCfpF1YIfie4jW4lRZCgRNFytZKIr_LK7tUErUWzcwYk1EeLeKuZWgr_0g-_iJxmDEquTnijY1mOVc1aEiei5iX0zu819csK5qmrVBeKWdsIMpA?key=AvWn09Y7CVz2HnQXem_NL67Q)



- Name this integration something like **“Meal Program SAML Configuration”&#xA0;**
- In App Settings, check the App visibility box **“Do not display application icon to users”**. The visible app will be configured as a bookmark with a specific redirect link. 
- Complete the fields as follows:
  - **Single sign-on URL:&#x20;**[https://www.ezcater.com/saml/consume](https://www.ezcater.com/saml/consume)
  - **Audience URI (SP Entity ID):&#x20;**&#x65;zcater.com
    - *Do NOT add https or www*
  - **Name ID format:&#x20;**&#x45;mailAddress
  - **Application username:&#x20;**&#x4F;kta username
  - **Update application username on:&#x20;**&#x43;reate and update

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXctXcT1pyhUUZqHHrhDhbrMvnanYPOkSualspVRhCEJ5DuuJhNlugX_QRPBs0qUZcrTqQs41PwNGOO0LBiocPxAoe98H7Pr3kaal5-H1MG2rYGHCmZTF2nCY7Wx7xhesDJEkJDA?key=AvWn09Y7CVz2HnQXem_NL67Q" size="82" width="1600" height="1423" position="center" darkWidth="1600" darkHeight="1423" showCaption="false"}

- In the final step, check the **This is an internal app…&#x20;**&#x6F;ption and click **Finish**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeym13ka7OIfBCQ766UelJoDdo0jwC4FzBkZB5Ji07mqnScUr4U0tFXMK0AHM4LZIh0VYmqMUAKIVBypx2Z0M3urdvR953-9L7W2b-ENloIrMbDSrvqTp8Ucnnz1HkN-_IzHkKJTg?key=AvWn09Y7CVz2HnQXem_NL67Q" size="64" width="1600" height="734" position="center" darkWidth="1600" darkHeight="734" showCaption="false"}

- To add the Meal Program Bookmark App, return to your Okta Admin dashboard and click on the option to **Browse App Catalog**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcy7W_IWpgxBfdoE-n7dFWHXQ4_jaYEiLKP6_WvRSJeWZM-XiDKL-DCeqSlTsKrgru_qiYz-yF4p3_bAWokyA4lK-l1wvJL-U0Yvz948NaiBtuIZCBEGkPDTE8TKsXEypWc11fU2g?key=AvWn09Y7CVz2HnQXem_NL67Q" size="76" width="678" height="236" position="center" darkWidth="678" darkHeight="236" showCaption="false"}

- Search for **Bookmark App** in the search bar and click on it

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc6Etx60zSMrEwnAOHVcxJXo95CjapShkgZJ36CTdhjVF8Dn3lG7F96bGcfitPMy1aaGwIUtgEnb-i6U207KtlABpO3QBtMqI3LbaesRLE02JYDkx-BivWniZjZKIxiD9NdWFq09A?key=AvWn09Y7CVz2HnQXem_NL67Q" size="74" width="1186" height="554" position="center" darkWidth="1186" darkHeight="554" showCaption="false"}

- Click on where it says **Add Integration**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc4xfjA0Wb33KFmhxFsVRxEM6fpPuOc73C-gKOYVys3x7ZHeHmN4drRG4fr4UdP_vcUgxArRE1duETcUwPtPydz5zphAWfxemi49xDhHOd-7CRIU-oEfHmFLobHW1Tgce7Gzxfo-A?key=AvWn09Y7CVz2HnQXem_NL67Q" size="62" width="1418" height="612" position="center" darkWidth="1418" darkHeight="612" showCaption="false"}



- Complete the fields as follows.  This is the app that will be visible to end users!
  - **Application label:&#x20;**&#x4D;eal Program&#x20;
  - **URL:&#x20;**[https://login.ezcater.com/relish/sso/domain\_redirect?domain=mycompany.com](https://login.ezcater.com/relish/sso/domain_redirect?domain=mycompany.com) *(change this to your domain)*
  - Leave the rest of the fields as default and click on Done

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXfI9EwXP48G-yrJDL-kmmQXA6Lekx_OSNBvjCuDEQbTew6-kTyxQl1mH6GUtWw4DhRBSGNtuzf5SzDi_lqOKZj--YCDUs1ATHoLtm_lxHpKYLrLQBevze3LaVjia88hZDommyt6?key=AvWn09Y7CVz2HnQXem_NL67Q)

- To update the logo, click on the bookmark app and click on the **Pencil icon&#x20;**&#x6E;ext to the default star.

![](https://lh7-rt.googleusercontent.com/docsz/AD_4nXeIc5sLQ-eSz6BUi_wr18TuoSPNwu2_oUF-A4uNoF1Gi1dXc2JfXeBF4O9GGQ_Q81pHkkeK_QvZzGB6eCC5Ku4SNiMTfLzM-DPm3NUrs1HhIBk8FY8G1saKV384CSqkQocJxFZl?key=AvWn09Y7CVz2HnQXem_NL67Q)



- Add the Meal Program logo 

::Image[]{src="https://archbee-image-uploads.s3.amazonaws.com/zoZH4pB9Qa_1x2l_Cdx7R/971JIikf0WhcG1HAiaQlQ_ezcater-logo-dark-primary-symbol-300dpi.png" size="36" width="2084" height="1918" position="center" showCaption="false"}

- Go back to the Meal Program app In Okta Admin and click on the **Sign On&#x20;**&#x74;ab

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc8ydPmOonQ7FyacHX4nvCqTTtmDDWkwr10iW5BP7hPdRu-JxBeNdVBiHvl0OBPkUEc6ZPd3V0mzTI5CPAL9RyTKRGse3dn3JTSI4P_2V5IbInFBMlF2GMRUF812mlPTAsGxMpUaA?key=AvWn09Y7CVz2HnQXem_NL67Q" size="62" width="869" height="385" position="center" darkWidth="869" darkHeight="385" showCaption="false"}

- On the right side of the page, click on the link for **View SAML setup instructions&#x20;**

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdSwEB95Mk3rxrrzG_zUbMdRIjuYbISozUJNPzRDczCqUXGkHAw68MAR3kytYStBoOyOM5DZwYuhSKbrbTvZ9umXIFq5SU5anaQ9qPtJPy23Bu1J5NgqTbvdKpD_IOT2QtSW__G2A?key=AvWn09Y7CVz2HnQXem_NL67Q" size="56" width="548" height="1070" position="center" darkWidth="548" darkHeight="1070" showCaption="false"}

- Submit these settings through the [ezCater/Meal Program SSO Form ](https://ezcaterforms.formstack.com/forms/ezcater_sso)

::Image[]{src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc2pioD-XcUlEE_2gySMGZq56t_i1P1uGroaXTXVs-js8Pasx7XJclaTVv_ArlvseRMikXlBeK0B_VJ9uN0r7nDqfWFWt9v3W9z34oYNKd9HSt4Z45ErpJb958atO7pBcFRi2au?key=AvWn09Y7CVz2HnQXem_NL67Q" size="66" width="1486" height="1410" position="center" darkWidth="1486" darkHeight="1410" showCaption="false"}


[title] Couriers Assign (Preferred)
[path] API for Restaurant Partners/Delivery API/

# Assigning a Courier

Use `couriersAssign` for new integrations; it supports assigning one or more couriers in a single call.

The `couriersAssign` mutation is for managing the individual(s) assigned to fulfill the ezCater delivery. That includes creating or updating couriers in the ezCater system.

The list of `couriers` provided to the mutation will replace any existing assigned couriers. Providing an empty list will unassign all the couriers.

:::hint{type="info"}
The `providerSource` should be IN\_HOUSE for all orders delivered by a restaurant’s own in-house drivers. If you have dispatched the delivery to another 3rd party (e.g. DoorDash, Uber Direct, etc.) the `providerSource` will be THIRD\_PARTY. It is important for you to fill in the `deliveryServiceProvider` with the name of that delivery provider. Otherwise, you may populate the value of this field with the name of your company.
:::



## Mutation

:::CodeblockTabs
Mutation

```graphql
mutation CouriersAssign($input: CouriersAssignInput!) {
  couriersAssign(input: $input) {
    delivery {
      id
    }
    userErrors {
      ... on UserError {
        message
        path
      }
    }
  }
}
```
:::

### Variables

:::CodeblockTabs
Variables

```graphql
{
  "input": {
    "couriers": [
      {
        "id": "your-courier-id1",
        "firstName": "Jane",
        "lastName": "Doe",
        "phone": "+16175551234",
        "providerSource": "IN_HOUSE",
        "vehicle": {
          "color": "silver",
          "make": "Toyota",
          "model": "RAV4"
        }
      },
      {
        "id": "your-courier-id2",
        "providerSource": "IN_HOUSE"
      },
      {
        "id": "your-courier-id3",
        "firstName": "John",
        "lastName": "Smith",
        "phone": "+16175554567",
        "providerSource": "THIRD_PARTY",
        "providerName": "DoorDash",
        "vehicle": {
          "color": "blue",
          "make": "Honda",
          "model": "Accord"
        }
      }
    ],
    "deliveryId": "ezcater-delivery-id"
  }
}
```
:::

### Arguments

| Argument Name                                                | Description                               |
| ------------------------------------------------------------ | ----------------------------------------- |
| `input`: [CouriersAssignInput!](docId:7gV344RnWmuokNj9u4rW7) | The Input object for assigning a courier. |

### Return Type

Returns a [CouriersAssignPayload](docId:7gV344RnWmuokNj9u4rW7).

## Success Response

When the `couriersAssign` mutation succeeds you can expect the response payload to look like:

:::CodeblockTabs
Response

```graphql
{
  "data": {
    "couriersAssign": {
      "delivery": {
        "id": "ezcater-delivery-id"
      },
      "userErrors": []
    }
  }
}
```
:::

## Failure Response

### User Errors

When the `couriersAssign` mutation fails due to user errors you can expect a HTTP 200  and the response payload to look like:

:::CodeblockTabs
Invalid Courier Attributes

```json
{
  "data": {
    "couriersAssign": {
      "delivery": null,
      "userErrors": [
        {
          "message": "Phone can't be blank",
          "path": [
            "input",
            "couriers",
            "0",
            "phone"
          ]
        },
        {
          "message": "First name can't be blank",
          "path": [
            "input",
            "couriers",
            "0",
            "firstName"
          ]
        },
        {
          "message": "Phone is invalid for U.S.",
          "path": [
            "input",
            "couriers",
            "2",
            "phone"
          ]
        },
        {
          "message": "Last name can't be blank",
          "path": [
            "input",
            "couriers",
            "2",
            "lastName"
          ]
        }
      ]
    }
  }
}
```

Past Event Time

```json
{
  "data": {
    "couriersAssign": {
      "delivery": null,
      "userErrors": [
        {
          "message": "Delivery cannot receive updates 2 hours past its event time",
          "path": [
            "input",
            "deliveryId"
          ]
        }
      ]
    }
  }
}

```

Delivery Completed

```json
{
  "data": {
    "couriersAssign": {
      "delivery": null,
      "userErrors": [
        {
          "message": "Delivery is finalized and cannot receive any more updates",
          "path": [
            "input",
            "deliveryId"
          ]
        }
      ]
    }
  }
}
```

Delivery Cancelled

```json
{
  "data": {
    "couriersAssign": {
      "delivery": null,
      "userErrors": [
        {
          "message": "Delivery is inactive and cannot receive any more updates",
          "path": [
            "input",
            "deliveryId"
          ]
        }
      ]
    }
  }
}
```
:::

### 404 Not Found Request

When a Delivery is not found for the provided `deliveryId` you can expect a HTTP 200 and the response payload to look like:

```json
{
  "errors": [
    {
      "message": "Delivery not found",
      "path": [
        "couriersAssign"
      ],
      "extensions": {
        "type": "request",
        "statusCode": 404,
        "serviceName": "delivery-public",
        "code": "DOWNSTREAM_SERVICE_ERROR",
        "exception": {
          "message": "Delivery not found",
          "locations": [
            {
              "line": 1,
              "column": 72
            }
          ],
          "path": [
            "couriersAssign"
          ]
        }
      }
    }
  ],
  "data": {
    "couriersAssign": null
  }
}
```

