Overview
Henry’s server SDK exposes three primitives -products.search, products.details, and the cart.* family - that compose into a handful of recurring app patterns. Pick the flow below that matches where your users start:
Every flow ends the same way - a Henry cart with a
checkoutUrl you can hand to your user, or a headless cart.checkout.purchase call that places the order from your server.
Building blocks
The four search modes
products.search is one endpoint with four useful shapes, switched by type and filters.type:
Variant resolution on details
products.details returns an options tree under result.options. Each option’s values[].nextOption is recursive - selecting one value reveals the next axis (e.g. size → colour → length). To walk it:
- Call
products.detailswithlink. - Read
result.optionsto discover the first axis (say, “fit”). - Re-call
products.detailswithselectedOptions: ['regular']to surface the next axis (say, “colour”). - Re-call with
selectedOptions: ['regular', 'black']for the next (size), etc.
selectedOptions array is positional - values are applied in order against the option chain. The same array drops straight into cart.item.{ ..., selectedOptions } when you’re ready to add the item.
Async vs sync
Every async operation (products.search, products.details, cart.checkout.details, cart.checkout.purchase) accepts mode: 'async' | 'sync'. Sync waits up to 30 seconds; async returns immediately with a refId you poll via the matching poll* helper. See Polling for the reusable helper - this guide assumes it’s imported as pollJob.
Flow 1 - Shopping agent / chatbot
Use this when your app takes a free-text user intent (“find me a quiet hairdryer under $200”) and returns purchasable products. Typical surfaces: AI assistants, conversational commerce, MCP tools.1
Search globally with filters
Use
type: 'global' with filters.type: 'text' and any of country, price, sortBy.2
Enrich the top candidate
Search results are catalog-grade. For prices, availability, and variants accurate enough to commit to, fetch details on the candidate you want.
3
Drop into a cart
Flow 2 - Visual / “shop the look” app
Use this when your users upload or screenshot something they want to buy. Typical surfaces: Lens-style apps, social shopping, photo-to-buy.filters.imageUrl accepts an HTTP(S) URL, a data: URL, or a raw base64 payload. Results route through shopping.google.com regardless of which merchant ends up matching.
1
Run an image search
2
Let the user pick, then enrich
Image search produces visually-similar candidates - present them as a grid, then fetch full details once the user commits.
3
Cart + hosted checkout
Price filters (
filters.price.min/max) and sortBy are text-search only. Image search returns visually-similar matches, ordered by relevance.Flow 3 - Product recommendation feed
Use this when you’re powering a recommendation or deal feed by mirroring a merchant’s catalog. A periodic crawl plus change detection lets you surface fresh picks, price drops, or restocks to your users. Typical surfaces: recommendation feeds, deal sites, comparison engines, RSS-style product feeds, price trackers. The trick:products.search in merchant mode with no query returns the merchant’s broad catalog. Cache the cheap fields (link, price, availability), then only spend a products.details call on items that actually changed.
1
Browse the catalog page by page
2
Spend details calls only on diffs
Compare each row against your cached snapshot. Re-fetch details when
price moves or availability flips.3
One-click buy from a deal alert
When a subscriber clicks through, the link they already have on the alert is the same
link that goes into cart.create - no extra search needed.Flow 4 - Embedded merchant storefront
Use this when you’re building a branded buy-button or niche storefront scoped to a specific merchant - your user starts inside one brand and you want to walk them through size / colour / length variants. Typical surfaces: white-label merchant search, creator-led storefronts, brand-specific buy-buttons. This is the flow whereselectedOptions does the heaviest lifting.
1
Search within the merchant
2
Walk the option tree
Each
products.details call surfaces the next axis. Re-call as the user picks values, feeding the running array back in.3
Add the fully-specified item to a cart
When
result.options.status === 'unknown' Henry couldn’t determine variants for that product - send the user straight to cart with the link only and let the hosted checkout collect any
remaining selections.Flow 5 - “Buy with Henry” from any link
Use this when the user (or your agent) already has a product URL and you want to skip search entirely. Typical surfaces: browser extensions, recipe sites, social-post buy-buttons, AI agents that receive a URL directly.1
(Optional) preview the product
Useful if you want to show price / availability / image before sending the user to checkout.
2
Create the cart and hand off
3
(Optional) take payment headlessly
If you’re collecting card details in your own UI via the Card Element, skip the hosted URL and call
cart.checkout.purchase directly. See Headless Checkout for the full pattern.Error handling & retries
Every flow above touches the same async machinery, so the same handling applies:
For long-running purchases, prefer Webhooks over polling - register a
webhookUUID on the cart’s settings.events and Henry will push completion events to you.
Next steps
Product discovery
Full reference for
products.search and products.details parametersUniversal cart
Cart settings, items, tags, and lifecycle events
Checkout
Hosted iframe / redirect or headless
cart.checkout.purchasePolling
The reusable
pollJob helper used throughout this guideWebhooks
Skip polling entirely - have Henry push order events to you
Merchants
Look up which merchants are supported before scoping a flow