Catalog
Variants
A variant belongs to exactly one product — its product_id — and, like
every entity, its values exist twice: the canonical values every store inherits and
one store version per store that can override them. Variants are a top-level list,
so a price or inventory integration can walk them without touching products at all.
List variants
/api/v1/variantspim:read
One cursor page of the account's variants, ordered oldest change first so a
poller can walk the whole catalog and stop when next_cursor is
null.
Query parameters
| Parameter | Type | Description |
|---|---|---|
limit | integer | Rows per page. Default 50, maximum 250; a value above the maximum is clamped and a non-numeric value falls back to the default. |
cursor | string | The next_cursor of the previous page. Opaque — do not build or parse one. A cursor from a different list is rejected with validation_failed. |
updated_since | RFC3339 date-time | Only variants whose own canonical record changed at or after this time. Store-version edits do not widen it. A non-RFC3339 value is rejected with validation_failed. |
status | enum | Publish-state filter: never_published, pending, published, failed. |
search | string | Free-text match on the variant's name, SKU, or the parent product's name, title, vendor, or tags. |
Response
The same list-item shape as every entity list: id, type
(here variant), title, draft_revision,
pending_publish, last_publish_status, and
store_ids. last_publish_status takes the same values as
the status filter, so a response value can be fed straight back in.
# Find a variant by SKU
curl -s "https://api.peak-pim.com/api/v1/variants?search=TR2-BLK-42&limit=50" \
-H "Authorization: Bearer pk_live_..."
{
"data": [
{
"id": "c7a1d2e3-5b6f-4890-a1b2-c3d4e5f60718",
"type": "variant",
"title": "Trail Runner 2 — Black / 42",
"draft_revision": 6,
"pending_publish": false,
"last_publish_status": "published",
"store_ids": ["9b2f6c1a-7d3e-4f80-b1c5-6a4e8d2b9c30"]
}
],
"next_cursor": null
}
Get a variant
/api/v1/variants/{id}pim:read
One variant's canonical values, the product it belongs to
(product_id), its media files, and its per-store publish state.
An unknown id — including another account's — answers 404 not_found.
| Field | Type | Description |
|---|---|---|
id, type, title | — | As on the list row; type is variant. |
attributes | array | The canonical values every store inherits, as {key, value, type} triples (all strings). |
draft_revision | integer | The optimistic-concurrency handle a later write sends back to prove it read the current state. |
pending_publish, last_publish_status | — | As on the list row. |
product_id | uuid | The product this variant belongs to. Fetch it via GET /api/v1/products/{id}. |
media_ids | uuid[] | The media files this variant uses, in gallery order, across every store. |
stores[] | array | Publish state per store: store_id, store_domain, pending_publish, last_publish_status. Publish state only — values live on the store subresources below. |
{
"id": "c7a1d2e3-5b6f-4890-a1b2-c3d4e5f60718",
"type": "variant",
"title": "Trail Runner 2 — Black / 42",
"attributes": [
{ "key": "sku", "value": "TR2-BLK-42", "type": "single_line_text_field" },
{ "key": "price", "value": "129.00", "type": "single_line_text_field" }
],
"draft_revision": 6,
"pending_publish": false,
"last_publish_status": "published",
"product_id": "5e0deff8-4b6f-4a24-9d6d-2f8c2f2a9a11",
"media_ids": ["1f2e3d4c-5b6a-4798-8172-635a4b3c2d1e"],
"stores": [
{
"store_id": "9b2f6c1a-7d3e-4f80-b1c5-6a4e8d2b9c30",
"store_domain": "acme.myshopify.com",
"pending_publish": false,
"last_publish_status": "published"
}
]
}
variant_ids exists on products only, and product_id on variants only — the relationship is stored once and readable from both ends.
List a variant's store versions
/api/v1/variants/{id}/storespim:read
Every store version of the variant. Bounded by the account's stores, so the
whole list is returned and next_cursor is always null.
Each item carries store_id, store_domain,
attributes, pending_publish, and
last_publish_status.
{
"data": [
{
"store_id": "9b2f6c1a-7d3e-4f80-b1c5-6a4e8d2b9c30",
"store_domain": "acme.myshopify.com",
"attributes": [
{ "key": "price", "value": "119.00", "type": "single_line_text_field" }
],
"pending_publish": false,
"last_publish_status": "published"
}
],
"next_cursor": null
}
Get one store's version
/api/v1/variants/{id}/stores/{store_id}pim:read
One store's version of the variant: the values that store publishes — a
per-store price, for instance — which may differ from every other store's.
store_id comes from
GET /api/v1/stores. A variant with no
version on the requested store answers 404 not_found.
curl -s "https://api.peak-pim.com/api/v1/variants/c7a1d2e3-5b6f-4890-a1b2-c3d4e5f60718/stores/9b2f6c1a-7d3e-4f80-b1c5-6a4e8d2b9c30" \
-H "Authorization: Bearer pk_live_..."
Subresources
Variants carry two more reads, documented on their own pages:
| Endpoint | Returns | Docs |
|---|---|---|
GET /api/v1/variants/{id}/sales-channels?store_id=… | The Shopify sales channels the variant is published to on one store. Reaches Shopify live, so it can answer 502. | Sales channels |
GET /api/v1/variants/{id}/drops | The drops that will change this variant, each narrowed to the changes that touch it. | Drops |