Shopify collection.products trigger: one Sume job per product added
Shopify Events' collection.products trigger fires when a product joins or leaves a collection. Key one Sume image job on collection and product ids.

Subscribe to collection.products in Shopify Events and Shopify's example delivery names the collection and the product that joined it. Start a Sume job only for an addition, and set the Idempotency-Key to the collection id plus the product id, so a redelivery returns the original job instead of billing a second time.
Shopify details are from its Next Gen Events announcement, read 2026-10-01; Sume retry rules from Jobs and results and Webhooks.
What does the collection.products trigger send?
Shopify says Events are generally available with the 2026-10 API version. You configure a subscription in shopify.app.toml with triggers, a GraphQL query and an optional query_filter. Its example subscribes to collection.products and, when product 456 is added to collection 123, the payload carries the collection id and the product id as query variables.
| Piece | From Shopify's page |
|---|---|
| Trigger | collection.products |
| Ids in the payload | collectionId and productsId |
| Action on an add | update |
| What changed | fields_changed.added |
How do I stop a retry from billing twice?
Sume's video submit route accepts Idempotency-Key: a replay returns the original job. The jobs docs say that on a retry you reuse the same key and do not submit a new paid job for the same intent. Build the key from the ids in the delivery, for example bfcm:123:456, so the same product added to the same collection always maps to the same job. The Image API also lists an optional Idempotency-Key header.
async function onProductAdded(collectionId, productsId) {
const res = await fetch("https://api.sume.com/v1/images", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.SUME_API_KEY,
"Content-Type": "application/json",
"Idempotency-Key": "bfcm:" + collectionId + ":" + productsId,
},
body: JSON.stringify({
model: "openai/gpt-image-2.5",
prompt: "Black Friday banner for a new product, bold clean layout",
image_size: "1536x640",
}),
});
if (!res.ok) throw new Error("Sume returned " + res.status);
return res.json();
}What about a product that is removed?
Shopify's collection example shows an add only, so check fields_changed on every delivery: Shopify's changelog says it is now an object with added, updated and removed arrays. Only added should call Sume. Removals are a cleanup in your own store, not a paid job. The same split is covered in the variants wildcard post.
How do I dedupe on my side?
Sume's webhook docs tell receivers to treat job_id as the idempotency key for Sume's own callbacks. For Shopify's side, the changelog says the shopify-event-id header is removed from Events deliveries, so use your own key from the ids instead; see the removed header post.
Sources
Related posts
More in Integrations
- Shopify Events fields_changed: only added should start a Sume job
Shopify Events' fields_changed is now an object with added, updated and removed. Start a paid Sume job from added only, and key it so replays are safe.
- Shopify Events query_filter: ACTIVE products only for Sume runs
Shopify Events' query_filter can limit deliveries to ACTIVE products. Filter at Shopify so draft products never reach a Sume submit or a bulk queue.
- Shopify's Meta AI channel: product image variants from Sume
Shopify now lists Meta as an AI channel and shares products through Shopify Catalog. Here is what Sume can make for those listings: image variants and a video.
- Slack incoming webhook 1/sec: when 100 Sume jobs finish together
Slack incoming webhooks allow about 1 message per second. When 100 Sume jobs finish at once, store each webhook, then post to Slack from a paced queue.
Written by Sume