For the complete documentation index, see llms.txt. This page is also available as Markdown.

Catalog Sync

What publication-scoped syncing changes for your Violet API integration: which products you receive, the product lifecycle, and webhook behavior.

This page is for developers building against the Violet API for channels configured as a Shopify sales channel. It assumes the concepts on Sales Channel Publishing on Shopify.

What changes for your integration

Your catalog for a Shopify merchant is now the set of products that merchant has published to your channel, not their whole store. Three consequences worth designing for:

  1. Catalog size is merchant-controlled and can change without warning. A merchant can unpublish a hundred products in one bulk action. Your integration should handle the catalog shrinking as a normal event, not an error condition.

  2. A newly connected merchant may sync zero products. Products are not published to a new channel automatically. Until the merchant publishes some, their catalog is legitimately empty. Do not treat an empty catalog after connection as a failed sync.

  3. Unpublishing is an update, not a deletion. The Offer stays exactly where it is (same id, same data, same SKUs) with its publishing_status set to NOT_PUBLISHED. Read that field to know whether an Offer belongs in your catalog. See Webhooks below.

Everything else (order submission, inventory, pricing, refunds, the shape of the Offer and SKU models) is unchanged.

Which products you receive

A product appears in your catalog only when all of the following are true:

  • The merchant has published it to your channel in Shopify.

  • Its Shopify status is Active.

  • It is not excluded by the channel's existing catalog rules: collection filters, excluded collections, excluded tags, or excluded vendors. Publication filtering is applied in addition to these rules, not instead of them.

Publication filtering is applied consistently on every path that reads products: the product count, the paged catalog sync, the bulk catalog sync, the per-product webhook sync, and the direct product sync API. There is no route through which an unpublished product can enter your catalog.

Product lifecycle

Merchant action in Shopify
What Violet does
Resulting Offer state
Webhook

Publishes a product to your channel

Fetches the product and creates or republishes the Offer

publishing_status: PUBLISHED

OFFER_ADDED for a newly created Offer; OFFER_UPDATED and OFFER_ADDED when republishing one that already existed

Edits a published product

Re-fetches and updates the Offer

Offer updated

OFFER_UPDATED, when there are material changes

Unpublishes the product from your channel

Withdraws the Offer from your catalog

publishing_status: NOT_PUBLISHED. status, available, visible, and SKU statuses are unchanged

OFFER_UPDATED and OFFER_REMOVED

Deletes the product in Shopify

Archives the Offer

status: ARCHIVED, available: false, visible: false, every SKU status: ARCHIVED

OFFER_UPDATED

Re-publishes a previously unpublished product

Re-fetches and republishes the Offer

publishing_status: PUBLISHED again, same Offer id

OFFER_UPDATED and OFFER_ADDED

Note the difference between the middle two rows. Unpublishing from your channel is neither an archive nor a deletion. It is an update to one field. The product is still active and selling in the merchant's own store; only its membership of your catalog changed, so its status and availability are left untouched. A product actually deleted in Shopify still archives, because it genuinely is gone.

Publish and unpublish are event-driven. In normal operation the catalog reflects a merchant's change within seconds, though delivery is not instantaneous and should not be relied on as synchronous.

Webhooks

The event name is delivered in the X-Violet-Topic header. The request body is the Offer itself. For the full offer event reference, see Offer Webhooks.

Unpublishing is an update, not a deletion

When a merchant unpublishes a product from your channel, Violet sets the Offer's publishing_status to NOT_PUBLISHED and sends both OFFER_UPDATED and OFFER_REMOVED.

Despite the event name, nothing is deleted. The Offer keeps its id, its data, and its SKUs; only the publishing status changed. That is what allows a re-publish to restore the same Offer rather than create a new one. (OFFER_DELETED is a separate event, for Offers that are genuinely removed.)

publishing_status is the field that tells you whether an Offer belongs in your catalog. status and available describe the product in the merchant's own store, and an unpublished product is often still AVAILABLE there because it is still selling on their other channels. Both values are accurate; they answer different questions.

The two events are delivered independently and may arrive in either order, so don't depend on the sequence; publishing_status is correct in both.

Other webhook behavior

  • Offers you never received stay silent. If an Offer was never published to your app, no webhook is sent when it changes. This matches existing Violet behavior.

  • OFFER_UPDATED is suppressed when nothing material changed. A re-sync that produces an identical Offer does not generate an event.

  • Relay channels receive additional events. Channels on the Relay plan also receive RELAY_OFFER_UPDATED when a product is published or edited, and RELAY_OFFER_REMOVED when it is unpublished, delivered directly from the sync layer.

  • Your channel's catalog rules still apply. If a product is withheld by a collection, tag, or vendor rule (or if offers for that merchant are configured not to publish automatically), ticking the channel in Shopify does not override that. Channel membership and Violet publishing are separate gates, and a product must clear both.

Reconciliation

Publication changes are delivered by webhook. If your integration needs to confirm the current state of a merchant's catalog (after downtime on your side, for example), re-read the catalog through the standard Violet catalog endpoints. The result is already scoped to the merchant's published set.

Testing your integration

On a Shopify development store connected to your channel:

  1. Publish a product to your channel and confirm you receive OFFER_ADDED.

  2. Edit the product's title and confirm you receive OFFER_UPDATED.

  3. Unpublish the product. Confirm you receive OFFER_REMOVED with publishing_status: NOT_PUBLISHED, and that your integration withdraws it. Note that status will still read AVAILABLE; the product is still selling in the merchant's store.

  4. Re-publish it and confirm it returns with the same Offer id and publishing_status: PUBLISHED.

  5. Confirm a product you have never published to the channel never reaches your catalog.

Last updated

Was this helpful?