Public previewSee what changed →
All guides

Build on the Partner API

View as Markdown

Syncing the catalog

Nobody reads documentation.

Here are the instructions for your agent. Give it this prompt: it reads the guides and the API contract, then walks you through the integration step by step, what to do, where and how.

Download agent instructions

This guide is for builders of a website or app on the Partner API.

Keep your own copy of the offers in your inventory scope and render your site from it, never live from Groupon. Every field of a product is in the API documentation.

What to list

  • List a product only when its status is active and availabilityRequired is false, and an option only when its active is not false (null means unknown: treat it as sellable). A product with availabilityRequired: true needs a booked time slot and cannot be added to a cart.
  • option.price.retail is the per-unit price the shopper pays: send it as expectedPrice on cart calls. option.price.original is the strike-through price.
  • option.promotion is informational: the shopper enters promotion.promoCode on Groupon's checkout page. Cart totals always use retail.
  • Pick a picture from media by its role (small, medium, large, extra_large, wide_crop), falling back to the largest width. Not every size exists on every offer.

Keeping your catalog fresh

RunWhenWhat it reads
Full syncFirst, onceEvery product in your scope
Daily resyncEvery day: the minimumEvery product again, then stop listing what the walk did not return
Delta refreshEvery two hours: optionalOnly what changed since your last refresh (updatedSince)

A delta alone is not enough. It cannot show you an offer that left your scope, and when a promotion starts Groupon ignores updatedSince and returns the whole catalog, so handle a delta of any size.

One walk serves all three runs:

text
seen = empty set                                     # resync only
params = { country: "US", limit: 100 }               # delta: add updatedSince: lastRefreshAt
cursor = none
repeat:
    page = GET https://api-core.livingsocial.com/partner_storefront/products?params (+ cursor if set)
    upsert every product in page.data by its id      # replace options, prices, status
    add every id in page.data to seen                # resync only
    cursor = page.nextCursor
until page.hasMore == false
stop listing every product whose id is not in seen   # resync only; keep the row
lastRefreshAt = page.timestamp                       # the final page's timestamp

Rules for every walk

  • Send the same parameters on every page; only cursor changes. Keep paging until hasMore is false: a page can be short, or empty, while more follow.
  • A page holds at most 100 products (limit), and 10 when you send none.
  • Save lastRefreshAt and stop listing missing products only after a whole walk succeeds. If a walk fails part-way, change nothing and run it again. lastRefreshAt is the final page's timestamp, Groupon's clock, never your own.
  • Never send active on a delta: you need the deactivated rows to stop listing them.
  • Run one walk at a time: skip a delta that falls due during a resync.
  • If a page answers BAD_REQUEST for its cursor, discard the cursor and restart the walk.
  • Your database is a cache. The cart re-checks price and availability live.