List wishlist items
Every product a shopper on this store has saved and not bought, newest first. This is the record back-in-stock, price-drop and win-back programmes are built on, and it was reachable only from the storefront until now, which authenticates a shopper rather than the merchant. ONE LIST ANSWERS BOTH QUESTIONS. ?customer_id= is “what has this person saved”, which is what the storefront widget shows; ?product_id= is “who is waiting on this product”, which the storefront cannot ask at all and which is the reason to integrate. Send both to intersect them, or neither for the store’s whole wishlist, which is the shape a first sync wants. AN ID THAT NAMES NOTHING IS AN EMPTY PAGE, not a 404. The honest answer for a customer with nothing saved and for a customer who does not exist is the same empty list, and answering not-found to the second would make this route a probe for which customer ids exist in the store. PAGED BY CREATION TIME, which is the only ordered column: wishlist_item has no updated_at, and a row is written once and never rewritten, so re-saving a product the shopper already has keeps the original date rather than refreshing it. Read created_at as “wanted since”, which is what makes it worth segmenting on. THIS FAMILY IS READ ONLY and there is no write half to add later. Saving a product asserts that a NAMED PERSON wants it, and on this surface the caller supplies the customer id, so a key could write a row indistinguishable from one the shopper made by tapping a heart, which a back-in-stock programme would then send on. Removing one destroys a shopper’s saved list with no restore. Both stay on the storefront, where the shopper owns the decision, and apiscope mints no write_wishlists at all.
Authorizations
A secret API key. Publishable keys cannot reach this API. A key may carry an expiry, and an expired key is refused exactly like an unknown one, with a 401 that names no reason; check the key's expires_at in the dashboard rather than inferring it from a response. When a merchant rolls a key's secret they choose a grace window of up to 3 days, and for its duration BOTH the new secret and the one it replaced authenticate, so an integration moves over on its own deploy schedule instead of at the instant the button is pressed. Move before the window closes: after it, the old secret is refused. Nothing else about this contract moves with a roll. The key keeps its id and its scopes, so the only thing an integration updates is the credential itself.
Query Parameters
Narrow the page to one shopper's saved products, which is what the storefront wishlist widget shows. NOT validated against the customer table: an id that names nobody returns an empty page rather than a 404, because the honest answer for a customer with nothing saved is the same empty list, and not-found would make this a probe for which customer ids exist.
Narrow the page to everyone waiting on one product, which is the question a back-in-stock or price-drop programme asks and the storefront cannot answer at all. An id that names nothing is an empty page, as above. Send it together with customer_id to intersect the two rather than either being ignored.
Rows per page. Out of range is a 400 rather than a silent clamp, so a client asking for more than 100 learns it did not get it.
1 <= x <= 100The next_cursor from the previous page. Opaque: decode nothing from it and construct nothing by hand, since its encoding is not part of this contract. Omit it to read the first page.
