Group Ordering
Group ordering lets several people build one order together. A host picks the store and the order type, shares a link, and everyone who joins adds their own items to their own slice of the basket. When everyone is done the host checks out once and pays for the whole thing.
It is new in 4.78.
How it is put together
Three ideas carry the whole feature.
A group cart session is what the host creates. It fixes the store and the order type for everybody, and it has a status that moves from open to locked to placed. The session UUID is what every path in this guide takes.
A participant is one person in the session. The host is a participant too — they have a slice like everyone else. Each participant has their own cart, which this guide calls their slice; the group cart is the session plus the merge of all the slices, not a single basket everyone edits at once. That matters: two people adding items at the same time never collide, because they are writing to different carts.
An invite is how people get in. The host's session comes with a share_url and an invite_token; a guest opens the link, previews it, and joins. Guests do not need an account — they can join anonymously with just a display name.
Two tokens, and why you need both
This is the thing to get right before you write any code.
Joining gives you a participant_access_token. Every participant endpoint — the overview, your own slice, ready, leave — is authenticated with that token in the X-Mt-Group-Participant-Token header, not with a customer bearer token. That is exactly what lets a guest with no account take part.
The invite_token is a different thing: it only works for previewing and joining, and it is cleared the moment the host locks the session.
Persist the participant token. A signed-in customer can recover their session with Group Cart Active, but an anonymous guest cannot — if your app loses their token, they have to re-join, and re-joining anonymously creates a new participant rather than resuming the old one.
Check it is available first
Group ordering is off by default and has to be switched on for the brand, the store and the specific order type. The order type tells you: read is_group_ordering_enabled on it, from init-application or the venue response.
Offer the option only when that is true. Creating a session for an order type that does not allow it returns 1214.
The flow
1. The host starts the session
Group Cart Init with the store and order type. The host must be a registered customer — a guest account cannot host, which is 1204.
Two options are worth surfacing in your UI. max_amount_per_participant caps what each guest may spend, in minor units, which is how a host stops a team lunch getting out of hand; it does not apply to the host. modifications_deadline_at is a soft deadline shown to participants — it is a prompt, not an enforcement.
{
"method": "post",
"url": "https://api-public-demo.menu.app/api/group-cart/init",
"headers": {
"X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
"Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
"Api-Version": "4.78.0",
"Device-UUID": "b6f0a5f2-2f1e-4a3c-9a1e-2c4c9f0d7f11",
"Authorization": "Bearer {customer_token}",
"Content-Type": "application/json"
},
"body": {
"venue_id": "8d2f2c42-2f1e-4a3c-9a1e-2c4c9f0d7f11",
"order_type": {
"id": 6,
"properties": { "pickup_asap": true }
},
"max_amount_per_participant": 5000,
"display_name": "Alex"
}
}
A customer may only have one active group order per brand. If they already have one, this returns 1201 — read it with Group Cart Active and offer to resume or cancel it rather than treating it as an error.
2. Everyone else joins
The host shares share_url. Your join screen should call Group Cart Invite Preview with the token first, so the guest can see the store and who invited them before committing.
A 200 from the preview does not mean the invite is still usable — a locked or expired session answers 200 as well. Check status and expires_at, and let the join call be the authority.
Then Group Cart Join. Send display_name for anyone joining without an account; it is required in that case, and it is what the rest of the group sees in the roster.
{
"method": "post",
"url": "https://api-public-demo.menu.app/api/group-cart/join",
"headers": {
"X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
"Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
"Api-Version": "4.78.0",
"Device-UUID": "b6f0a5f2-2f1e-4a3c-9a1e-2c4c9f0d7f11",
"Content-Type": "application/json"
},
"body": {
"token": "4f1c0f3a2b7c4a669f1e2c9a1c9a1c9a4f1c0f3a2b7c4a669f1e2c9a1c9a1c9a",
"display_name": "Sam"
}
}
3. Everyone builds their slice
Each participant edits their own cart with Group Cart Update My Cart. It behaves like PUT /cart/{cart_id} — send the whole slice, not a delta — and the response is a normal cart object.
Read the group context from metadata.group_session on that response rather than tracking it yourself. It carries the session status, the deadline, the per-guest cap and this participant's own status, which is everything a participant screen needs.
Two rules differ from a personal cart. Guests are held to max_amount_per_participant and get 1211 if they go over. And discounts and donations belong to the order, not to a slice, so only the host's slice may carry them; a guest sending them gets 1204.
4. Following along
Participants poll Group Cart Overview to see who is in, who is ready and what they have added.
Use the interval the response gives you, in poll_interval_seconds. It is there so you do not have to guess, and polling faster than it earns a 429.
The host has a second, richer read in Group Cart Show, which adds the combined cart with order-level totals and fees. It is the more expensive call, so use it for the checkout screen and poll the overview for everything else.
5. Marking ready
When a participant has finished they call Group Cart Mark Ready. An empty slice cannot be marked ready — that is 1215. Reopen puts them back to editing.
Ready is not just a status for display. It decides who survives the next step.
6. The host locks the session
Group Cart Lock closes the session for editing so the host can check out. Nobody can join afterwards.
Locking removes people. Guests who have not marked themselves ready, and guests whose slice is empty, are dropped from the session. Tell the host that before they tap it — from their point of view it is "everyone who hasn't finished gets left behind".
The host is always kept, and is marked ready automatically. Unlock reopens the session if the host changes their mind, but only before a payment exists, and it does not bring back the guests the lock removed.
7. Checkout, payment, order
From here it mirrors a personal cart exactly:
- Group Cart Checkout merges the slices and prices the result against the POS.
- Group Cart Payment Initialization — the same envelope, the same
actionscontract, everything in Make a Payment applies unchanged. - Group Cart Order Create places it.
The host pays once, for everything. There is no per-participant payment and no splitting the bill between participants. A tip on a guest's slice is not charged; tips, discounts and donations are order-level and come from the host.
The order call is idempotent on Idempotency-Key — after a timeout, retry with the same key.
8. What you get back
The order has is_group set to true, a participants list of { id, display_name, role }, and participant_id on each line. That is what lets you render "Sam's burrito, Alex's tacos" on the receipt instead of an undifferentiated basket.
Re-checkout is the trap
Checkout produces a priced snapshot, and almost anything that changes the session invalidates it: a guest leaving, the host removing someone, any slice being edited, a PATCH to the session. Paying or ordering against a stale checkout returns 1220.
The fix is always the same — check out again — so it is worth handling 1220 generically rather than case by case.
In the other direction, once payment has been initialized the session is frozen: unlocking, checking out again, removing participants and editing slices all return 1206. If the customer abandons the payment, cancel the session or start over.
Leaving, removing and cancelling
A guest can leave at any point until payment starts. The host cannot leave their own session — that is 1210 — they cancel it instead, which is final and kills the invite link.
The host can remove a participant, but only while the session is open, and they cannot remove themselves. They can also edit someone else's slice — useful when an item has gone out of stock or a guest has stopped responding. That deliberately bypasses the ready state.
Statuses
Session:
| Status | Meaning |
|---|---|
open |
Accepting edits and new participants |
locked |
Closed for editing while the host checks out |
placed |
The order has been created |
cancelled |
The host abandoned it |
expired |
It timed out |
Participant:
| Status | Meaning |
|---|---|
editing |
Still choosing |
ready |
Finished, slice frozen to their own edits |
left |
Left voluntarily |
removed |
Removed by the host, or dropped by a lock |
completed |
The order was placed |
Repeating or editing a group order
A placed group order cannot be reordered or edited with the personal endpoints — those return 1216 and 1218. Use Group Reorder and Group Edit, each with a validate call alongside it.
Both create a new host-only session seeded from the original: is_reorder or is_edit is true, there is no invite token, and nobody can join. The host adjusts all the slices themselves and checks out again. Practically, it means "repeat what the group had last time" is a host-driven flow, not another round of invitations.
Limits
- Up to 100 participants per session, which only constrains new joins.
- Sessions expire — read
expires_atrather than assuming a duration. - Starting sessions and joining are both throttled to five per minute; the read endpoints are throttled around
poll_interval_seconds. - One active session per customer per brand.
What can go wrong
| Code | Meaning |
|---|---|
1201 |
The customer already has an active group order |
1204 |
The caller is not the host, or a guest tried to do something host-only |
1205 |
Unknown invite token |
1206 |
The session state does not allow this |
1207 |
Nothing to resume |
1208 |
The session is no longer joinable |
1209 |
The host cannot remove themselves |
1210 |
The host cannot leave |
1211 |
A guest is over their cap |
1212 |
Mark yourself not ready first |
1213 |
The session is full |
1214 |
Group ordering is not enabled |
1215 |
An empty slice cannot be ready |
1220 |
The checkout is stale |
See Error Codes for the full list.