List product questions
Every question shoppers have asked on this store’s products, in EVERY state, together with the merchant’s answers to each. A question is pre-moderated: it sits pending until someone publishes or rejects it, so most of what this route serves is words the merchant has not published, attached to the customer id of the account that asked. THIS IS WHY IT IS NOT read_products. That grant is the first call a catalogue integration makes and is already minted on live keys, and scopes are immutable after mint, so folding questions into it would have handed every existing key this disclosure retroactively. Treat a pending body as unpublished content: do not syndicate it and do not show it to other customers. THERE IS NO DEFAULT FILTER. Omitting ?status= returns every status, which is what makes this usable for mirroring moderation state; pass ?status=pending for the queue proper. Only pending, published and rejected are accepted. Note that the publish state is spelled “published” while the route that sets it is called /approve, so ?status=approved is a 400 rather than an empty page: an empty page would read as an empty queue. IT BUYS DISCLOSURE, NOT AUTHORITY. Publishing, rejecting and answering is write_product_questions, a different grant that this one does not imply and that does not imply this one; a tool that both shows the queue and clears it asks for both. IT PUBLISHES THE QUESTION, NOT THE QUESTIONER. customer_id is the shopper who asked and is all this grant carries about them; the name, email and address behind it are read_customers, so resolve them there if your key holds it. NO PRODUCT TITLE. product_id is flat, because filling a nested reference would mean a join that silently drops a question whose product row was deleted, leaving it queued forever and invisible to every client. Resolve the product through the products family. answers is NEVER null. An unanswered question serialises an empty array, because absent would say “unknown” where the truth is “none yet”.
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
Narrows to one moderation state. OMIT IT FOR EVERY STATE: there is no default filter, because a default would be a hidden WHERE clause and a client paging what it believed were the store's questions could not tell "only the pending ones" from "a store with nothing held". Pass pending for the moderation queue proper. A value outside this set is a 400 rather than an empty page, and "approved" is the one to watch: the route that sets the state is called /approve but the state itself is "published", so an empty page there would read as an empty queue.
pending, published, rejected 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.
