POST /api/v2/buyer/discovery/{discoveryId}/products
Adds products to the session selection. Pass the productId from your Discover products or Browse products results. When a result includes inventorySourceId, preserve it in the selection so identical product IDs from different inventory sources remain unambiguous. salesAgentId, groupId, and groupName are optional and resolved server-side from those results, so pass them only to disambiguate a product that appears in more than one group. Optionally pin a budget, pricing option, bid, or per-line-item targeting. By default products merge into the existing selection; set replace: true to swap the whole set.
When you pass pricingOptionId, Apostra validates it against the exact pricing
in the session’s current discovery result and carries that option into campaign
staging. A separate catalog refresh cannot invalidate an option that result
just returned. Re-run discovery when the option is no longer present in the
current result or its quoted price has expired. Older sessions whose results
predate pricing evidence recording use current catalog validation and may also
require a new discovery run.
To select the same product more than once, omit selectionId for its single base selection and give each repeat a distinct selectionId. Each selection becomes an independent media-buy line item. Re-sending an existing selectionId updates that instance instead of adding another copy.
Request
Parameters
Response
selectionId; the base instance omits it. Keep that value when updating or removing one repeat. Reconciliation preserves repeat instances as distinct line items, so their budget and targeting do not collapse into the base selection.
If two or more submitted selections share the same identity — no selectionId, or the same selectionId — they merge into a single package instead of staying separate. The response then includes a warnings array (list of strings) naming each collapsed product. Treat that warning as a sign the request needs distinct selectionId values on the repeats, not as a successful add of multiple line items.
Do not resend every collapsed selection with a new selectionId. The merge is additive by instance identity, and a brand-new selectionId never matches the surviving base instance, so resending all of them adds that many more entries on top of the one already stored — three collapsed selections resent with three new selectionIds produces four line items, not three. Instead, call Get products (or read the products array in this response) to see which configuration survived as the base instance — it holds whichever collapsed selection was submitted last — then resend only the configurations that did not survive, each with its own new selectionId.
Errors
400 VALIDATION_ERROR— emptyproducts, missing a required selection field, or aproductIdnot present in the session’s discovery results.404 NOT_FOUND—discoveryIddoes not exist or is not visible to the authenticated account.
Related
Discovery overview
Selection model and budget allocation
Get products
List the current selection
Remove products
Drop products from the selection
Apply proposal
Add a whole proposal at once