Order Submission

Provider Enablement / Endpoints

Create Order Submission

Ready Times

For the order_submission response, if the merchant doesn’t give an actual ready time for an order, please still include the expected_ready_at attribute, just have it be null. We only want it if an actual order ready time estimate is returned from the merchant. In the case LevelUp receives an expected_ready_at of nil we will generate our best estimation.

Special Instructions

Special_instructions on both the order and items are optional. If either is included in the post, they should be submitted along with the order. If they are omitted, then you don’t need to do anything relating to special instructions. Please also account for cases where “special_instructions”: null included is in the post.

Also note that, for delivery orders only, the delivery_address may include delivery_instructions for the driver such as Ring doorbell or Leave order on porch.

Order ID

This should be from the merchant (if available) to assist our users in retrieving their orders. String/integer are both accepted.

Handling Changes Between OV and OS

There are scenarios when certain attributes (special instructions on the order level, tips and desired_ready_time) may change between the OV and the OS. In this case, LevelUp will send order-scoped metadata to detail which attributes are changing. In this scenario, please update the relevant attributes on the providers cart before submitting the order.

In scenarios where the OV and OS are handled entirely separately (i.e. an OV redoes an OS) this should happen naturally.

In scenarios where you take advantage of a server-side cart and echo that token back to us, you either need to:

  • Be able to update those three attributes without re-creating the entire cart.
  • Recreate the cart entirely if those attributes do change between OV and OS.

Request Endpoint

POST /locations/:provider_location_id/order_submissions

Example Request Body

{
  "order_submission": {
    "credit_card": {
      "number": "4111111111111111",
      "cvv": "1234",
      "zip": "02110",
      "type": "American Express",
      "expiration_month": 2,
      "expiration_year": 2020,
      "city": "boston",
      "address": "One Federal St.",
      "postal_code": "02110",
      "reused_token": true,
      "state": "ma"
    },
    "desired_ready_time": "2016-03-11T11:44:08",
    "fulfillment_type": "pickup",
    "grubhub_order_number": "430515324805810",
    "items": [
      {
        "item": {
          "category_group_id": "6734384",
          "category_id": "11124",
          "name": "Turkey Sandwich",
          "price": 679,
          "provider_id": "1324",
          "quantity": 1,
          "recipient_name": "Joe Smith",
          "metadata": {
            "integration_id_needed_for_submission": "1234"
          },
          "special_instructions": "Hold the mayo",
          "options": [
            {
              "option": {
                "metadata": {
                  "integration_id_needed_for_submission": "1111"
                },
                "price": 100,
                "option_group_display_order": 4,
                "provider_id": "67478",
                "option_group_id": "565",
                "quantity": 2
              }
            },
            {
              "option": {
                "price": 0,
                "option_group_display_order": 2,
                "provider_id": "32791",
                "option_group_id": "577",
                "quantity": 1
              }
            }
          ],
        }
      },
      {
        "item": {
          "category_group_id": "6734384",
          "category_id": "75759",
          "name": "Slice of cake",
          "price": 199,
          "provider_id": "9876",
          "quantity": 2,
          "recipient_name": "Jane Smith",
          "options": [
            {
              "option": {
                "price": 0,
                "option_group_display_order": 1,
                "provider_id": "62459",
                "option_group_id": "123",
                "quantity": 1
              }
            }
          ]
        }
      }
    ],
    "location_time_zone": "America/New_York",
    "metadata": {
      "revel_authentication_token": "asdf232342453asdTSfs"
    },
    "paid_via_ach": false,
    "tip": 100,
    "merchant_funded_discount": 100,
    "special_instructions": "please double bag my order",
    "include_disposable_utensils": true,
    "user": {
      "born_at": "1986-03-11T11:44Z",
      "first_name": "joe",
      "gender": "male",
      "last_name": "smith",
      "email": "example@gmail.com",
      "password": "password123",
      "phone": "4445556666"
    }
  }
}

Example Response Body

{
  "order_submission": {
    "order_id": 15612,
    "tax": 123,
    "total": 978,
    "tip": 100,
    "provider_funded_discount": 100,
    "merchant_funded_discount": 100,
    "service_fee": 50,
    "expected_ready_at": "2016-03-11T11:44:08",
    "metadata": {
      "authentication_token": "asdf232342453asdTSfs"
    }
  }
}

Example Request Body (Delivery)

{
  "order_submission": {
    "credit_card": {
      "number": "4111111111111111",
      "cvv": "1234",
      "zip": "02110",
      "type": "American Express",
      "expiration_month": 2,
      "expiration_year": 2020,
      "city": "boston",
      "address": "One Federal St.",
      "postal_code": "02110",
      "reused_token": true,
      "state": "ma"
    },
    "delivery_fee": 300,
    "delivery_address": {
      "street_address": "One Federal Street",
      "extended_address": "Floor 6",
      "locality": "Boston",
      "region": "MA",
      "postal_code": "02110",
      "latitude": 42.356257,
      "longitude": -71.057225,
      "delivery_instructions": "Ring doorbell"
    },
    "desired_ready_time": "2016-03-11T11:44:08",
    "fulfillment_type": "delivery",
    "grubhub_order_number": "443213323803422",
    "items": [
      {
        "item": {
          "category_group_id": "6734384",
          "category_id": "11124",
          "name": "Turkey Sandwich",
          "price": 878,
          "provider_id": "1324",
          "quantity": 1,
          "recipient_name": "Joe Smith",
          "options": [
            {
              "option": {
                 "metadata": {
                   "integration_id_needed_for_submission": "1111"
                },
                "price": 100,
                "option_group_display_order": 2,
                "provider_id": "67478",
                "option_group_id": "565",
                "quantity": 2
              }
            }
          ]
        }
      }
    ],
    "location_time_zone": "America/New_York",
    "merchant_funded_discount": 100,
    "metadata": {
       "revel_authentication_token": "asdf232342453asdTSfs"
    },
    "paid_via_ach": false,
    "special_instructions": "sauce on the side",
    "include_disposable_utensils": false,
    "tip": 100,
    "user": {
      "born_at": "1986-03-11T11:44Z",
      "first_name": "joe",
      "gender": "male",
      "last_name": "smith",
      "email": "example@gmail.com",
      "password": "password123",
      "phone": "4445556666"
    }
  }
}

Example Response Body (Delivery)

{
  "order_submission": {
    "order_id": 15612,
    "delivery_fee": 300,
    "tax": 123,
    "total": 978,
    "tip": 100,
    "provider_funded_discount": 100,
    "merchant_funded_discount": 100,
    "service_fee": 0,
    "expected_ready_at": "2016-03-11T11:44:08",
    "metadata": {
      "authentication_token": "asdf232342453asdTSfs"
    }
  }
}

Errors

When errors occur, we will expect a response of the format:

{
  "error": {
    "type": "provider",
    "message": "ITEM NOT AVAILABLE ERROR: Italian B.M.T.",
    "error_details": {
      "failed_items": [
        {
          "provider_id": "/Cart/Product2.aspx?ID=30106&gID=3",
          "name": "Italian B.M.T."
        }
      ]
    }
  }
}

There are several types of errors that could occur:

  • Site Errors: 422 HTTP status code

    • The underlying merchant ordering site renders an error that would have been displayed to the user to explain something like “Sorry, this location is closed right now” or “Oh no! We’re out of guacamole”. In this case, please return the actual error message the site renders to the user, an error code of 422.
  • Item Or Option Unavailable Errors: 422 HTTP status code

    • This is a subset of the case above, but should be handled with the following criteria in mind:
    • Please attempt to return an error message to us with the item/option name to us, rather than the ID, so that the user can amend their order appropriately. We will pass this message along to the user.
    • Please also include extra attributes of failed_items and/or failed_options with an array of the item_ids and/or option_ids that are problematic.
    • Problematic item_ids or option_ids might be items or options that are:
      • Not available at this time
      • No longer on the menu
      • Out of stock at the moment
      • Simply unrecognized from your perspective
  • Integration Errors: 500 HTTP status code

    • If your service cannot interact with the merchant for some reason, please pass back a relevant message to help us understand what’s going wrong along with an error code 500. LevelUp will display its own error message to the user.
    • This should include the scenario when the underlying merchant is non-responsive, i.e. perhaps their location ordering provider is down, in which case your integration let LevelUp know so we can communicate to the user.
  • Parameter Errors: 500 HTTP status code

    • If we send you parameters that do not match your expectations and a message telling us the error. This error will not be shown to the user, but may be used for informing us we need to refresh our menu for the location. Send an error code of 500.
  • Menu Not found: 404 Error Code

    • If LevelUp attempts to issue a call and the merchant/location is no longer available from the provider (whether temporarily or permanently) subsequent requests from LevelUp for actions on that merchant should return a 404.
  • Service Down

    • If your service is down, LevelUp will return a generic error to the user. Error code 500.
  • Timeout Threshold

    • Order submission request expects a response within 90 seconds.