Product Optimizations API
Last updated: August 20, 2026
Generate AI-optimized product descriptions from review data and publish them to Shopify. The optimization workflow is: start → poll → edit (optional) → approve → publish.
Availability: all endpoints in this section require the product_pages entitlement. Without it, write calls return 403 entitlement_required and reads return 200 with content: null. Current plans (Unlimited, Studio) include it. On legacy plans (no longer sold), it is available on Growth and above, and on legacy Pro and Enterprise; stores on the legacy Starter plan do not have it. A store with no active subscription — never subscribed, or cancelled — is in the free state and holds none of the gated entitlements: entitlement-gated endpoints return 403 entitlement_required, and every LLM-backed endpoint returns 402 subscription_required. See Pricing.
Note: Product IDs in these endpoints are internal BetterReviews IDs, not Shopify IDs. Use GET /products/lookup/:platform_id to convert a Shopify product ID first.
Start Optimization
POST /api/v1/products/:product_id/optimize
Starts an async AI optimization job. Returns immediately with status pending.
Request
{
"feedback": "Focus on fabric quality and comfort",
"blocksToOptimize": ["description", "features"]
} | Field | Type | Required | Description |
|---|---|---|---|
feedback | string | No | Instructions for the AI (tone, focus areas, keywords) |
blocksToOptimize | string[] | No | Specific sections to optimize |
Response (202)
{
"id": "uuid",
"status": "pending",
"version": 1,
"created_at": "2026-03-27T10:00:00Z"
} 429 unpublished_optimization_limit — you've reached the per-period maximum of products optimized-but-not-published. Applies on stores with credit-based publishing enabled. Publish a draft to unlock the next, or wait for the next billing period. Re-optimizing a product you've already drafted this period is exempt.
Get Current Optimization
GET /api/v1/products/:product_id/optimization
Poll this endpoint after starting an optimization to check status and get results.
Response (200)
{
"id": "uuid",
"version": 3,
"status": "draft",
"content": {
"description": "...",
"features": ["..."],
"seo_title": "...",
"seo_description": "..."
},
"created_at": "2026-03-27T10:00:00Z",
"published_at": null,
"error_message": null
} List All Versions
GET /api/v1/products/:product_id/optimizations?limit=10&offset=0
Returns paginated list of all optimization versions for a product.
Edit Optimization
PATCH /api/v1/products/:product_id/optimization
Request
{
"content": {
"description": "Updated description text..."
}
} Regenerate
POST /api/v1/products/:product_id/optimization/regenerate
Creates a new version. Accepts same parameters as Start (feedback, blocksToOptimize).
Approve
POST /api/v1/products/:product_id/optimization/approve
Marks the optimization as approved and ready to publish.
Publish to Shopify
POST /api/v1/products/:product_id/optimization/publish
Writes the optimization content to the Shopify product metafield. The storefront updates with the new content.
Cost: generating and regenerating drafts are always free. Publishing draws 5 AI credits per distinct product, per billing period (re-publishing the same product in the same period is free) only on stores with credit-based publishing enabled, a per-store setting that is off by default on every plan. With it off, publishing draws nothing.
402 credit_limit_reached — returned on publish when credit-based publishing is enabled for the store and its credit pool for the period is exhausted. Enable auto-recharge and extra credits bill at the plan's block rate; with auto-recharge active, publish proceeds and bills the overage. Stores with credit-based publishing off never receive this error.
Discard
DELETE /api/v1/products/:product_id/optimization
Optimization Statuses
| Status | Meaning |
|---|---|
pending | Processing (async job running) |
draft | Generated, ready for review |
approved | Merchant approved, ready to publish |
published | Live on Shopify storefront |
failed | Generation failed (check error_message) |
discarded | Merchant discarded |