Public previewSee what changed →
All guides

Checkout and order confirmation

Sending the shopper to checkout

Before showing Buy now, read the cart and confirm every line is available.

Link the button to buyLink. It opens Groupon's checkout page for that cart. If you have added CJ, the shopper passes through CJ first; this is what credits your commission. The page shows your logo if you gave one (see Get your API key).

Keep the cartId in the shopper's server-side session so you can tie the returning shopper to the cart they bought.

The return redirect

If you gave no redirect URL, the shopper ends on Groupon's receipt page and gets Groupon's confirmation email, and your site does not receive a grouponOrderUuid.

If you gave a redirect URL, Groupon redirects the shopper's browser there after a successful payment, with the order id added:

text
https://your-site.example/checkout/complete?grouponOrderUuid=5d0c2f3a-8b1e-4c7d-a9f0-1e2d3c4b5a69

Your handler for that URL must:

  1. Read grouponOrderUuid and check it looks like a UUID. Ignore any other parameter. Handle each grouponOrderUuid once: a repeat visit shows the result you saved.
  2. Call the booking endpoint from your server.
  3. Match the order's items to the cart in the shopper's session. If there is no session or no match, show a neutral "check your Groupon email" page and do not mark any cart as purchased.
  4. Keep the cartId and a snapshot of its lines until the order status is final. On success, mark the cart as purchased. On REJECTED or EXPIRED, read the cart; if it is gone, create a new one from the snapshot.
  5. Render the confirmation page.

A shopper who closes the tab before the redirect still has a valid order: they receive Groupon's confirmation email and can find the purchase in their Groupon account.

Reading the order

bash
curl -s "https://api-core.livingsocial.com/partner_storefront/bookings/5d0c2f3a-8b1e-4c7d-a9f0-1e2d3c4b5a69" \
  -H "Authorization: Bearer $GROUPON_API_KEY" \
  -H "User-Agent: MyStore/1.0 (+https://mystore.example)"

The order's own facts sit at the top level. Everything about what was bought is under items: one entry per product and option, in the order they were bought. An order placed from a cart has one item per cart line, and every unit item belongs to exactly one item.

This example is an order from a two-line cart. The second line is still awaiting fulfilment, so the whole order reads ON_HOLD:

json
{
  "id": "5d0c2f3a-8b1e-4c7d-a9f0-1e2d3c4b5a69",
  "status": "ON_HOLD",
  "supplierReference": "LG-ABCD-1234-EFGH",
  "createdAt": "2026-09-18T12:10:44Z",
  "items": [
    {
      "productId": "0b6f7a52-3c1d-4e8a-9f20-5d7c1a2b3c4d",
      "optionId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "quantity": 2,
      "status": "CONFIRMED",
      "unitItems": [
        { "id": "a1b2c3d4-0000-4000-8000-000000000001", "status": "CONFIRMED",
          "myGrouponUrl": "https://www.groupon.com/mygroupons/users/<purchaserId>/details/a1b2c3d4-0000-4000-8000-000000000001?inventory_service=vis" },
        { "id": "a1b2c3d4-0000-4000-8000-000000000002", "status": "CONFIRMED",
          "myGrouponUrl": "https://www.groupon.com/mygroupons/users/<purchaserId>/details/a1b2c3d4-0000-4000-8000-000000000002?inventory_service=vis" }
      ]
    },
    {
      "productId": "1c7e8b63-4d2e-4f9b-a031-6e8d2b3c4d5e",
      "optionId": "8d0f7780-8536-41ef-a55f-f18fd2a01bf8",
      "quantity": 1,
      "status": "ON_HOLD",
      "unitItems": [
        { "id": "a1b2c3d4-0000-4000-8000-000000000003", "status": "ON_HOLD",
          "myGrouponUrl": "https://www.groupon.com/mygroupons/users/<purchaserId>/details/a1b2c3d4-0000-4000-8000-000000000003?inventory_service=vis" }
      ]
    }
  ]
}

The full field list is in the API reference.

Matching an order to your cart

items[].productId and items[].optionId are the same ids you sent as productId and optionId on the cart lines, and the same as the ids from the products list. Join each order item to your cart and your catalog on optionId without any translation. If productId is null, the product has since left Groupon's catalog; optionId still identifies what was bought.

Status meaning

StatusMeaningWhat to show
ON_HOLDNo payment has been taken yet, or it was taken but the vouchers' state could not be read yet. Normal for the first seconds after the redirect."Finalizing your order..." and poll again.
CONFIRMEDPaid. Vouchers are issued.Success page.
REDEEMEDEvery voucher has been used at the merchant.Success page, marked as used.
REJECTEDPayment failed. No order was completed."Payment failed" and a link back to the cart.
CANCELLEDThe order was cancelled or refunded."This order was cancelled."
EXPIREDThe order was not paid for in time."This order was not completed" and a link back to the cart.
PENDINGPayment is being processed, or it has been taken and the vouchers are still being issued."Finalizing your order..." and poll again.

The same statuses apply at three levels: the order (status), each item (items[].status) and each voucher (items[].unitItems[].status). The order's status is never more advanced than its least-advanced item: one item still ON_HOLD keeps the whole order ON_HOLD, and the order reads REDEEMED only when every item does.

Cancelled items are set aside. An item is CANCELLED once all its vouchers are, and the order once all its items are. An order with some items cancelled takes the status of the rest, and each cancelled voucher reads CANCELLED in unitItems.

Treat any status you do not recognize as unresolved: show it as not completed, keep the cart, and never start a new purchase because of it. This keeps your code working if a new status is added.

Polling

Right after the redirect the status is often ON_HOLD or PENDING. Poll from your server: wait 2 s, then 4 s, 8 s, 15 s, 30 s (about one minute in total). Stop as soon as the status is neither ON_HOLD nor PENDING. If it is still ON_HOLD or PENDING after the last try, show "Your order is being processed, you will receive a confirmation email from Groupon" together with the voucher buttons below.

The voucher buttons

Each item's unitItems has one entry per purchased unit of that item: an item with quantity: 2 has two entries. Render the order grouped by item. For each item, show the product and option (joined to your catalog on optionId), then for each of its unitItems render a button such as "View voucher 1 on Groupon" whose href is that entry's myGrouponUrl.

The shopper must log in to their Groupon account to open it. That page is where they view and redeem the voucher.

An item can still be ON_HOLD or PENDING while others are CONFIRMED. Show the buttons you have and a "still processing" note on that item.

A voucher whose status is CANCELLED was cancelled or refunded. Show it as cancelled, without a voucher button.

Treat grouponOrderUuid as sensitive. Do not log it in analytics or expose it on public pages.

Errors

See Handling errors for the full code table. On the booking endpoint, INVALID_BOOKING_UUID means no order with that id, or the order was not placed from one of your carts: do not retry, show a neutral message. A booking read never changes the order, so it is always safe to retry UPSTREAM_UNAVAILABLE with the same backoff as polling.