Guides
Audit drift across stores
In a multi-store catalog, each store's version of an entity can override the canonical values. Sometimes that's deliberate localization; sometimes it's drift — a title edited on one store and forgotten everywhere else. Two reads per entity find every difference.
What drift means
Every entity has canonical values every store inherits and one store version per store that can override them. When a store version's attribute differs from the canonical attribute with the same key, that store is publishing something different from the rest of the account. An audit's job is to surface those differences so a merchant can decide which are intentional (a German title on the German store) and which are drift (a stale price).
The two reads
/api/v1/products/{id}pim:read/api/v1/products/{id}/storespim:read
The first answers the canonical values; the second answers every store version in
one response (it is bounded by the account's stores, so next_cursor
is always null). The same pattern works for variants, collections, and media.
stores[].
The entity's stores[] array carries publish state only. The store values live on the store subresources — that's why the audit needs the second read.
# Canonical values
curl -s https://api.peak-pim.com/api/v1/products/0e8f... \
-H "Authorization: Bearer pk_live_..."
{"id": "0e8f...", "type": "product", "title": "Trail Runner 2",
"attributes": [
{"key": "title", "value": "Trail Runner 2", "type": "text"},
{"key": "vendor", "value": "Peak Outfitters", "type": "text"}
],
"draft_revision": 7, "pending_publish": false, "last_publish_status": "published",
"variant_ids": ["9c1d..."], "media_ids": ["77aa..."],
"stores": [
{"store_id": "a1b2...", "store_domain": "acme-us.myshopify.com",
"pending_publish": false, "last_publish_status": "published"},
{"store_id": "c3d4...", "store_domain": "acme-de.myshopify.com",
"pending_publish": true, "last_publish_status": "pending"}
]}
# Every store version
curl -s https://api.peak-pim.com/api/v1/products/0e8f.../stores \
-H "Authorization: Bearer pk_live_..."
{"data": [
{"store_id": "a1b2...", "store_domain": "acme-us.myshopify.com",
"attributes": [{"key": "title", "value": "Trail Runner 2", "type": "text"}],
"pending_publish": false, "last_publish_status": "published"},
{"store_id": "c3d4...", "store_domain": "acme-de.myshopify.com",
"attributes": [{"key": "title", "value": "Trailrunner 2 Laufschuh", "type": "text"}],
"pending_publish": true, "last_publish_status": "pending"}
], "next_cursor": null}
Walking the attributes
Attributes are flat {key, value, type} triples, so the comparison is
a dictionary diff:
- Index the canonical
attributesbykey. - For each store version, index its
attributesthe same way. - For every key present in both, compare
value— a mismatch is an override on that store. - Record misses too: a key present canonically but absent on a store (or the reverse) is also a difference worth showing.
In the example above, title diverges on acme-de.myshopify.com.
Whether that's localization or drift is a merchant call — an audit reports, it
doesn't judge.
Auditing the whole catalog
The list rows from a catalog walk carry
store_ids[], so you can skip single-store entities — an entity on one
store has nothing to diverge from. For the rest, the two reads above are 2 requests
per entity; with the 120/minute per-key budget, plan the sweep accordingly or run
it against your own mirrored copy.
For a server-computed answer, the data-health divergence dimension scans multi-store entities for exactly this and lists the diverging fields per entity — and its reconcile endpoint can harmonize them as drafts.
The MCP alternative
On the MCP connector, one tool answers both reads at once:
get_master_with_projections_v1 returns the item plus its per-store
versions. An assistant on the read tier can run the whole audit conversationally:
"Show me product Trail Runner 2 on each of my stores — where do titles differ?"
The assistant fetches the item with its projections, diffs the attributes, and reports per store. Follow-ups like "which of those differences look like stale copies rather than translations?" cost nothing extra to build — that's the point of the AI catalog operator pattern.
Related
- Data health — the divergence scan and the reconcile batch.
- Monitor publishes — drift's sibling problem: changes that never went live.
- Stores — where
store_idcomes from.