Orders
The order management module allows for retrieving and managing orders placed for a given location.
Basic Workflow
- Receive Orders
- Either by polling for orders by merchant or group or by subscribing to webhook notifications
- Identify new orders by filtering for the
RESTAURANT_CONFIRMABLEstatus - Future orders are available by filtering for the
ANTICIPATEDstatus - Future orders will automatically transition to
RESTAURANT_CONFIRMABLEat the promise time, less the default delivery or pickup fulfillment duration configured for the merchant. For Grubhub Managed Delivery restaurants, the default kitchen prep time configured for the merchant is used for this purpose.
- Confirm the Order Inserted to the POS
- On successful insertion of an order to the POS, update order status to
CONFIRMED, optionally indicating an estimate of when the order will be prepared (for pickup or managed delivery) or delivered (for self-delivery). - If the order failed to insert to the POS, update order status to
REJECTEDwith a reason code.
- Handle Change Requests
- If the restaurant needs to change an order or cancel an order, you can submit a Change Request on their behalf.
- Handle Grubhub Managed Delivery Updates
- If Grubhub is providing the delivery driver--as denoted by
order.delivery_info.is_managed_delivery == true--you can either poll for delivery updates or subscribe to webhook notifications for delivery updates. These will include driver contact information, driver arrival ETAs, and driver lat/lng.
- Update order status when prepared and/or fulfilled
- Updating the status of an order as it proceeds through the fulfillment workflow will enable Grubhub to relay notifications to the driver (if managed delivery) and the diner.
- Update order status to
PICKUP_READYwhen a pickup order or a managed delivery order is ready to be picked up by the diner or Grubhub driver. - Update order status to
OUT_FOR_DELIVERYwhen self-delivery takes the order out. - Update order status to
FULFILLEDupon self-delivery completion.
Order Validation
Order Validation Workflow
Order Status for Pre-Checkout Validation that partners can subscribe to through a webhook. Grubhub sends webhook prior to the diner placing orders. Partner should attempt to plug this into the relevant order validation endpoint at the merchant POS to perform real-time check as to whether the incoming order would be a successful one or not. The Partner is expected to respond with a Confirmed or a Rejected status.
Partners can expect to receive several validation requests per order as this is driven by cart alterations performed by customers. If Partner responds back with a rejected status , Grubhub prevents customers from placing the order by displaying an error when attempting to check-out.
- Grubhub sends a POS_VALIDATION webhook request.
{
"uuid": "AQ2X8qgOEe2X8yWWroS6Vg",
"merchant_uuid": "B-GlkOqmEemWQeGu2Sk9uQ",
"order_number": "",
"is_test": false,
"status": "POS_VALIDATING",
"statusHistory":
[
{
"status": "ANTICIPATED",
"timestamp": "2023-02-09T00:42:23.605Z",
"update_source": "DINER"
}
- Partner responds with POS_VALIDATED or POS_VALIDATION_REJECTED as a response.
- If a POS_VALIDATION_REJECTED is sent to Grubhub, an error message is also required
- If the response is POS_VALIDATED, Grubhub will send a RESTAURANT_CONFIRMABLE webhook.
Example of Expected Partner Responses
- Rejected Response
{
"updated_status": "POS_VALIDATION_REJECTED",
"reason_code": "RESTAURANT_OFFLINE",y^
"description": "Restaurant Closed"
}
- Validated Response
{
"updated_status": "POS_VALIDATED"
}
Order Validation Webhook Specification
Paths
Get Orders By Merchant, Status and Date Range
GET /pos/v1/merchant/{merchant_id}/ordersPolling endpoint for getting all orders for a merchant in a given state in the given time range.
Maximum time range for polling is 15 minutes.
Get Orders By Group, Status and Date Range
GET /pos/v1/group/{group_key}/ordersPolling endpoint for getting all orders for a group of merchants in a given state in the given time range.
Get Order by UUID
GET /pos/v1/merchant/{merchant_id}/orders/{order_uuid}Returns the single order requested by its UUID.
Update Order Status
PUT /pos/v1/merchant/{merchant_id}/orders/{order_uuid}/statusUpdate the order status.
Order Validation Outgoing Webhook
POST /{partner outgoing webhook url for validation}Partners may register, via Partner Accounts, webhook callback endpoints to be notified of order validation requests. For security, a Callback url is expected to use HTTPS, enforced at registration time (Partner Accounts). Order Example
{
"uuid": "1A5tVq6dQEq0w_5BeIEyag",
"order_number": "1",
"is_test": true,
"status": "POS_VALIDATING",
"statusHistory": [],
"updated_at": "2021-12-02T17:29:16.877Z",
"merchant_id": "-963301469",
"fulfillment_info": {},
"brand": "BRAND",
"time_placed": "2021-12-02T17:29:16.877Z",
"when_for": "2021-12-02T17:29:16.877Z",
"restaurant_timezone_id": "UTC",
"payments": {
"total": 0,
"adjusted_total": 0
},
"charges": {
"fees": {
"total": 0,
"delivery": 0
},
"taxes": {
"total": 0,
"sales": 0,
"delivery": 0,
"restaurant": 0
},
"tip": {
"amount": 0,
"type": "INCLUDE_IN_BILL"
},
"diner_grand_total": 0,
"grand_total": 0,
"line_groups": [
{
"lines": [
{
"name": "food",
"line_options": [
{
"price": 177,
"id": "1152700327",
"name": "salt",
"line_sub_options": [
{
"id": "1352704759",
"name": "lots",
"price": 361,
"choice_category_id": "439607686"
}
],
"quantity": 1
}
],
"price": 1899,
"quantity": 34,
"id": "946118396",
"menu_item_id": "855724817",
"item_type": "test",
"variation_id": "1487364520"
}
]
}
],
"coupons": []
},
"tax_withheld": false,
"handoff_options": []
}
Request Change to Order
POST /pos/v1/merchant/{merchant_id}/orders/{order_uuid}/changerequestsRequest a change (cancellation, refund, upcharge, etc.) to an existing order.
Get Status of Order Changes
GET /pos/v1/merchant/{merchant_id}/orders/{order_uuid}/changerequestsReturns the status of all order changes for a single order.
Models
Address
Physical street address
Brand
The brand that the order was placed on
string
- GRUBHUB
- SEAMLESS
- YELP
- GROUPON
- EAT24
- UNKNOWN
Catering
Catering details for an order
Change Action
The type of change action requested.
string
- adjust.action
- cancel.action
Charges
Contains information about the contents of the order including the financial totals and items ordered.
Contact Info
Basic diner contact information
Coupon
Coupons applied to the order
Delivery Info
Delivery Information
Fees
Base fees paid by the diner for the line items and delivery charges before taxes and tip
Fulfillment Info
Information about how to fulfill the order. If delivery info is provided, this is a delivery order, otherwise this is a pickup order. Exactly one property will be set on this object as delivery and pickup are mutually exclusive and required for fulfillment.
Line
A line item for the order
Line Group
A group of line items. Currently, the entire order is within one line group; as group ordering features are rolled out, orders will include multiple line groups.
Line Sub Option
Sub Options that are applied to an Option or other Sub Option. These can be nested up to ten levels deep.
LineOption
Options applied to a Line Item
Order
The order model is the basis for all Grubhub orders. This contains all necessary information for fulfilling and processing orders.
{
"uuid": "JylzkoC0Ee2zk-PUFdlLqg",
"merchant_uuid": "0OfxgNelEey87BGSJG9AHg",
"order_number": "604721063804098",
"is_test": false,
"status": "REJECTED",
"statusHistory": [
{
"status": "REJECTED",
"timestamp": "2022-12-20T22:46:01.582Z",
"update_source": "CONFIRMATION_AUTOMATION"
},
{
"status": "STALE",
"timestamp": "2022-12-20T22:36:00.864Z",
"update_source": "GRUBHUB_ORDERS_REAPER",
"reason": "Stuck status RESTAURANT_CONFIRMABLE at 2022-12-20T22:36:00.864Z"
},
{
"status": "RESTAURANT_CONFIRMABLE",
"timestamp": "2022-12-20T22:18:07.810Z",
"update_source": "TXS"
},
{
"status": "ANTICIPATED",
"timestamp": "2022-12-20T22:18:07.430Z",
"update_source": "DINER",
"reason": "non-GHD"
}
],
"updated_at": "2022-12-20T22:46:01.582Z",
"merchant_id": "10004116752",
"fulfillment_info": {
"pickup_info": {
"name": "John Doe",
"contact_info": {
"phone": "(222) 222-2222",
"name": "John Doe"
},
"instructions": "",
"is_green_indicated": true
}
},
"brand": "GRUBHUB",
"time_placed": "2022-12-20T22:18:06.214Z",
"confirmation_code": "6335",
"when_for": "2022-12-20T22:28:06.221Z",
"restaurant_timezone_id": "America/New_York",
"payments": {
"payments": [
{
"payment_type": "CREDIT_CARD",
"amount": 472,
"tax_application": "POST_TAX"
}
],
"total": 472,
"adjusted_total": 472
},
"charges": {
"fees": {
"total": 0,
"delivery": 0
},
"taxes": {
"total": 32,
"sales": 32,
"delivery": 0,
"restaurant": 32,
"merchant_sales_total": 32,
"merchant_total": 32
},
"tip": {
"amount": 0,
"type": "CASH"
},
"diner_grand_total": 472,
"grand_total": 472,
"adjusted_grand_total": 472,
"line_groups": [
{
"lines": [
{
"name": "Avocado Cherry Tomato",
"line_options": [],
"price": 440,
"merchant_price": 440,
"quantity": 1,
"menu_item_id": "2426676565",
"menu_item_uuid": "AAAAAAAAAAasdAkadss",
"diner_total": 440,
"total": 440,
"tags": [],
"external_id": "Salad|Avocado Salad",
"metadata": "{\"internal_id\":1123234}",
"routing_tags": [],
"line_uuid": "J5AkoIC0Ee2koy&8hjj",
"packaging_options": []
}
]
}
],
"coupons": [],
"merchant_total": 472,
"merchant_subtotal": 440,
"restaurant_subtotal": 440,
"merchant_subtotal_before_coupons": 440
},
"tax_withheld": true,
"jit_enabled": true,
"just_in_time_fired": false,
"diners": [
{
"status": "ACTIVE",
"diner_info": {
"phone": "(222) 222-2222",
"name": "John Doe"
},
"charges": {
"fees": {
"total": 0,
"delivery": 0
},
"taxes": {
"total": 32,
"sales": 32,
"delivery": 0,
"restaurant": 32,
"merchant_sales_total": 32,
"merchant_total": 32
},
"tip": {
"amount": 0,
"type": "CASH"
},
"diner_grand_total": 472,
"grand_total": 472,
"adjusted_grand_total": 472,
"line_groups": [
{
"lines": [
{
"name": "Avocado Salad",
"line_options": [],
"price": 440,
"merchant_price": 440,
"quantity": 1,
"menu_item_id": "2426676565",
"diner_total": 440,
"total": 440,
"tags": [],
"routing_tags": [],
"line_uuid": "J5AkoIC0Ee2koy&8hjj",
"packaging_options": []
}
]
}
],
"coupons": [],
"merchant_total": 472,
"merchant_subtotal": 440,
"restaurant_subtotal": 440,
"merchant_subtotal_before_coupons": 440
},
"payments": {
"payments": [
{
"payment_type": "CREDIT_CARD",
"amount": 472,
"payment_source": "UNKNOWN",
"tax_application": "POST_TAX"
}
],
"total": 472,
"adjusted_total": 472
},
"order_diner_number": "1232132343",
"cart_uuid": "JylzkIC0Ee2zkePUaHjs",
"participation": "HOST"
}
],
"order_type": "STANDARD",
"order_taking_system": "CARTING",
"handoff_options": [],
"restaurant_version_id": {
"catalog_version": {
"version_id": "v1:VoNHjJPBjGrXXThkLnOrrgVAmwBG3yR2"
}
},
"fulfillment_scheduling": "ASAP",
"transmission_id": "IwsfGSpHM461UOWnLXHf6g",
"order_merchant_id": "9CvhTfZvNvqR8_WRGSjL9Q"
}
Order Change Request
Payload required to change an order state
Order Change Request Status
Status of a submitted order change request.
Order Delivery Type
This indicates whether food is delivered by Grubhub or the restaurant.
string
- GRUBHUB
- SELF
Payment
A single payment source
Payments
Payments on the order
Pickup Info
Information about the pickup order
PosFulfillmentScheduling
Order fulfillment type.
- ASAP
- FUTURE
- UNKNOWN
Reason Code
Status update reason code. Currently used only for updating status to REJECTED.
string
- RESTAURANT_OFFLINE
- MENU_ITEM_NOT_FOUND
- PRICE_MISMATCH
- OTHER
Security for Order Validation
Callback url is expected to use HTTPS, enforced at registration time (Partner Accounts).
authorization
- None = No authorization sent with webhook request.
- Basic = Basic auth credentials using username and password
- HMAC = Client Id, Client Secret, and issue Date used in construction of MAC header. Initial implementation identical to our internal server-to-server tokens.
- OAuth2 = client_credentials flow supported. Client Id and Secret are used to obtain an access token, which is used for subsequent webhook requests. A leader elected process will support maintaining a valid access token for each OAuth2 integration.
Status
The status of an order as it passes through the Grubhub fulfillment flow.
- ANTICIPATED denotes a future order, which may be cancelled by diner.
- RESTAURANT_CONFIRMABLE is pending confirmation of receipt by the restaurant. These are effectively new ASAP orders. ANTICIPATED orders will automatically become RESTAURANT_CONFIRMABLE at the promise time, less the restaurant's configured pickup or delivery prep time.
- DINER_CONFIRMABLE is a status held for future use.
- CONFIRMED denotes that the order was received by restaurant, even if the restaurant is unable to fulfill it.
- REJECTED is an error status. For example, if an order is unable to be inserted to the POS, due to menu item mismatch, restaurant offline, etc., the status should be updated to REJECTED. This is not to be used when the order was successfully transmitted, but the restaurant is unable to fulfill it for operational reasons. In that scenario, a Change Request should be submitted to cancel the order.
- CANCELLED means that a cancellation request by the diner or restaurant has been processed by Grubhub Customer Care.
- PICKUP_READY indicates that the food is prepared and ready for pickup by the diner or a Grubhub delivery courier.
- OUT_FOR_DELIVERY means the food is on the way to the diner.
- FULFILLED denotes that the food has been delivered to or picked up by the diner.
- UNKNOWN is provided for error handling of strings unmappable to known enumeration values.
Deprecated statuses will be provided when including a legacyStatus query parameter set to TRUE when polling orders. Similarly, legacy statuses will be translated when passed into the order status update endpoint. Confirmation of legacy status translation should be tested with individual integrations.
string
- ANTICIPATED
- RESTAURANT_CONFIRMABLE
- DINER_CONFIRMABLE
- CONFIRMED
- REJECTED
- CANCELLED
- PICKUP_READY
- OUT_FOR_DELIVERY
- FULFILLED
- UNKNOWN
Status Update Request
Payload to request a status change
{
"status": "CONFIRMED",
"wait_time_in_minutes": 60,
"tax_total": {
"tax" : 3,
"type": "ABSOLUTE"
}
"sub_total": 2345
}
StatusUpdate
A status update reflects each successive change in the status of an order.
Tax total
Corrected tax for an order.
Taxes
Taxes paid by the diner
Tip
Information about tip. Note that tip may not be included in bill
Tip Type
Whether the tip was included in the bill (i.e., prepaid) or to be collected in cash.
string
- CASH
- INCLUDE_IN_BILL
- UNKNOWN
Update Source
Source of a status update in the status history.
string
- DINER
- RESTAURANT
- GRUBHUB
- UNKNOWN
Validate Order Webhook Response
The current state or result of a menu ingestion job. Each status will be communicated with both a standardized status string and a human-readable description.