Order Editing

Customers change their minds. Someone orders lunch for six, a seventh person joins, and the order has already been sent to the kitchen. Order editing lets that customer add the extra sandwich without cancelling and starting again — and without your support team having to intervene.

The mechanism is simpler than it sounds: editing an order loads its items into a new cart. From there you use the ordinary Cart 2.0 endpoints you already know, and when you place that cart it revises the original order instead of creating a second one.

Order editing requires a signed-in customer, since it reads and modifies their own order.

Before you offer the option

Not every order can be edited, and the rules are set by the brand. An order is editable only while all of these hold:

  • The brand has order editing switched on for that order type. It is off by default.
  • The order is still in Init, SendDelayed, SendTried or Sent. Once the kitchen has it — InPreparation, Ready, Final — editing is over.
  • The editing time limit has not passed. Brands set this as a number of hours before preparation starts.
  • If the order needs approval, that approval is still pending.

Rather than reproducing that logic in your client, ask.

Step 1 — Ask what would change

Call Validate Order Edit with the order's UUID. Nothing is written and no cart is created, so this is safe to call whenever you are deciding whether to show an "Edit order" button.

Request

{
  "method": "post",
  "url": "https://api-public-demo.menu.app/api/orders/9f1c0f3a-2b7c-4a66-9f1e-2c9a1c9a1c9a/edit/validate",
  "headers": {
    "X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
    "Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
    "Api-Version": "4.78.0",
    "Authorization": "Bearer {customer_token}",
    "Content-Type": "application/json"
  },
  "body": {}
}

Send Content-Type: application/json even though the body is empty, or the request is rejected before it reaches the API.

Read can_proceed first.

When it is false, errors tells you why. The common case is 1004, meaning the order is no longer editable — the status has moved on, the time limit has passed, or the brand does not allow it. Show the customer why they cannot edit, and offer cancellation or a new order instead.

When it is true, status describes the consequences of editing, and this is the part worth surfacing to the customer before they commit:

Field What it means for the customer
unavailable_items Items on the original order that the store no longer offers. They will not survive the edit.
item_price_changes Items whose price has moved, with original_price and reorder_price.
fee_price_changes The delivery fee has changed.
is_price_summary_changed The totals differ from the original order.
is_discount_changed A discount on the original order no longer applies.
is_venue_changed, is_order_type_changed Set when you asked to validate against a different store or order type.
is_delivery_location_valid For delivery orders, whether the address is still servable.

A customer who is told "two of your items are no longer available and the total goes up by $3" before they start is far less likely to abandon halfway.

Note that a 200 with can_proceed set to false is the normal way of reporting "not editable" — it is not an error response.

Step 2 — Start the edit

Call Start Order Edit. This one does write: it creates a cart seeded with the order's items and returns it.

Request

{
  "method": "post",
  "url": "https://api-public-demo.menu.app/api/orders/9f1c0f3a-2b7c-4a66-9f1e-2c9a1c9a1c9a/edit",
  "headers": {
    "X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
    "Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
    "Api-Version": "4.78.0",
    "Authorization": "Bearer {customer_token}",
    "Content-Type": "application/json"
  },
  "body": {}
}

The response is a normal cart. Two fields in metadata mark it as an edit:

{
  "status": "OK",
  "code": 200,
  "data": {
    "cart": {
      "id": "b1946ac92492d2347c6235b4d2611184f1f3f4b4a1c0a7c5d9e8f7a6b5c4d3e2",
      "order_edit_status": { "has_changes": false },
      "metadata": {
        "is_order_edit": true,
        "original_order_id": "9f1c0f3a-2b7c-4a66-9f1e-2c9a1c9a1c9a"
      }
    }
  }
}

order_edit_status.has_changes tracks whether the customer has actually altered anything yet, which is useful for enabling a "Save changes" button.

Unlike edit/validate, this endpoint refuses outright with 400 when the order is not editable. Validate first if you want to fail gracefully.

This replaces the customer's current cart. The edit cart is written to the customer's single cart slot, so anything they had in their basket is gone. If that is a realistic situation in your app — someone browsing a new order while an old one is still editable — warn them before you call this.

Step 3 — Change the cart

From here nothing is special. Use the cart endpoints exactly as described in Server Side Cart:

  1. PUT /cart/{cart_id} to add, remove or change items, discounts and the tip.
  2. POST /cart/{cart_id}/checkout to re-price against the POS.
  3. POST /cart/{cart_id}/payments/init, but only if more money is now due.

Only catering order types can be swapped for one another during an edit — catering delivery and catering take-out. Every other order type is fixed for the life of the order, so do not offer a "change to delivery" option on a takeout order.

Step 4 — Commit the change

There is no separate save-the-edit call. Place the cart with Order Create as you would any other cart:

{
  "method": "post",
  "url": "https://api-public-demo.menu.app/api/cart/b1946ac92492d2347c6235b4d2611184f1f3f4b4a1c0a7c5d9e8f7a6b5c4d3e2/order",
  "headers": {
    "X-Request-ID": "8bf3c1d0-11ae-4a2f-9f77-0c1d2e3f4a5b",
    "Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
    "Api-Version": "4.78.0",
    "Authorization": "Bearer {customer_token}",
    "Content-Type": "application/json"
  },
  "body": {
    "customer_info": {
      "first_name": "Ada",
      "last_name": "Lovelace",
      "email": "ada@example.com",
      "phone_number": "+15550000000"
    }
  }
}

Because the cart carries is_order_edit, this revises the original order rather than placing a new one.

Editability is checked again at this point. If the time limit expired while the customer was deliberating, the call fails even though edit succeeded earlier. Handle that: tell the customer the window closed and that their original order stands unchanged.

What happens to the original order

A revision is not an update in place. A new order is created and the original is retired:

  • The new order inherits the customer-facing order code, so the customer keeps the same reference they have always had. The original order is given a new internal code.
  • The original order moves to status Revised and disappears from normal order lookups. Fetching it by UUID afterwards returns 404.
  • Payments follow the new order. If the total went up, the difference is charged; if it went down, the difference is refunded.
  • Feedback requests and house account invoice entries are moved across too.
  • The POS and other integrations are updated in the background, so the kitchen sees the revised order.

In practice this means your client should treat the response of the commit call as the order to display from then on, and should not keep polling the old UUID.

Abandoning an edit

If the customer changes their mind about changing their mind, call POST /cart/{cart_id}/reset. That empties the cart and clears the edit context, so the cart stops being an edit and the original order is left exactly as it was. Nothing was ever written to the original order, so there is nothing to undo.

Abandoned edit carts are also cleaned up on their own: a stored edit cart whose original order is gone or no longer editable is discarded the next time the customer initializes a cart.

Errors worth handling

Situation What you get
Order no longer editable, on edit 400, with a message naming the reason — settings, status, time limit or approval
Order no longer editable, on edit/validate 200 with can_proceed false and errors[].code of 1004
Time limit expired between edit and checkout Failure on POST /cart/{cart_id}/order
Order not found, or already revised 404
Brand not on the NMG product structure 403
Store inactive error 1001 in errors
Order type not available at the target store error 1002 in errors
Cart could not be rebuilt from the order error 1003 in errors