Store Hugs Developers

Products

The shop's catalog: titles and text in every language, prices, stock, categories and images.

Reach them through $admin->products. Reading needs the products:read scope, changing them products:write. To set stock for many products at once, use inventory.

List products

$admin->products->list(array $query = []): array

One page of the shop's products, by words in the title, SKU or part number, by status, or by an exact SKU; or oldest change first with updatedSince. Read the next page with meta.nextCursor as cursor. Scope: products:read.

Parameters

Parameter Type
$query array The query fields below, by name.

Query fields

ParameterTypeDescription
searchstringAt most 200 characters.
skustringAn exact SKU. At most 255 characters.
statusstringOne of active, hidden.
limitintegerAt least 1. At most 100. Default 50.
cursorstringmeta.nextCursor (or the cursor in links.next) of the previous page. At most 1000 characters.
updatedSincestring (date-time)Records changed at or after this time (ISO 8601, any offset or Z), oldest change first, for incremental sync.

Returns

An array with data (a list of AdminProduct), links and meta:

FieldTypeDescription
linksobject
links.firstnull
links.lastnull
links.prevstring (uri) or null
links.nextstring (uri) or null
metaobject
meta.pathstring (uri)
meta.perPageinteger
meta.nextCursorstring or null
meta.prevCursorstring or null
dataarray of AdminProduct
data[].idinteger
data[].slugstring
data[].titleLocalizedTextText by language code. An empty value is returned as an empty array [].
data[].shortDescriptionLocalizedTextText by language code. An empty value is returned as an empty array [].
data[].descriptionLocalizedTextText by language code. An empty value is returned as an empty array [].
data[].skustring or null
data[].partNumberstring or null
data[].typestringOne of physical, digital.
data[].downloadLimitinteger or null
data[].documentUrlstring or null
data[].statusbooleanTrue when published.
data[].isFeaturedboolean or null
data[].noindexboolean or null
data[].pricenumber or null
data[].salePricenumber or null
data[].isSaleScheduledboolean or null
data[].saleStartsAtstring (date-time) or null
data[].saleEndsAtstring (date-time) or null
data[].wholesalePricenumber or null
data[].manageStockboolean or null
data[].stockQuantityinteger or null
data[].lowStockAmountinteger or null
data[].stockStatusstring or nullOne of in_stock, out_of_stock.
data[].unitIdinteger or null
data[].taxClassIdinteger or null
data[].weightnumber or null
data[].lengthnumber or null
data[].widthnumber or null
data[].heightnumber or null
data[].taxonomyTermIdsarray of integer
data[].relatedProductIdsarray of integerThe products shown as applicable products on the product page, in order.
data[].recommendedProductIdsarray of integerThe merchant's picks for the product page's You May Also Like section, in order. Without picks, the page shows the closest matches.
data[].specTemplateIdinteger or null
data[].variableProductIdinteger or null
data[].thumbnailstring (uri) or null
data[].galleryarray of string
data[].createdAtstring (date-time) or null
data[].updatedAtstring (date-time) or null

Errors

StatusWhen
401invalid_api_key: no active Admin key in Authorization: Bearer.
403admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope.
422Validation errors ({ message, errors }), or an idempotency refusal(idempotency_key_reused, idempotency_key_invalid).
429Rate limited.

Example

$page = $admin->products->list(['sku' => 'MUG-01']);
$product = $page['data'][0] ?? null;

Iterate over every product

$admin->products->all(array $query = []): Generator

Every product matching the query, one at a time, fetching the next page as you read. It takes the same query as list, without cursor. Scope: products:read.

Returns

A generator of AdminProduct arrays, each:

FieldTypeDescription
[].idinteger
[].slugstring
[].titleLocalizedTextText by language code. An empty value is returned as an empty array [].
[].shortDescriptionLocalizedTextText by language code. An empty value is returned as an empty array [].
[].descriptionLocalizedTextText by language code. An empty value is returned as an empty array [].
[].skustring or null
[].partNumberstring or null
[].typestringOne of physical, digital.
[].downloadLimitinteger or null
[].documentUrlstring or null
[].statusbooleanTrue when published.
[].isFeaturedboolean or null
[].noindexboolean or null
[].pricenumber or null
[].salePricenumber or null
[].isSaleScheduledboolean or null
[].saleStartsAtstring (date-time) or null
[].saleEndsAtstring (date-time) or null
[].wholesalePricenumber or null
[].manageStockboolean or null
[].stockQuantityinteger or null
[].lowStockAmountinteger or null
[].stockStatusstring or nullOne of in_stock, out_of_stock.
[].unitIdinteger or null
[].taxClassIdinteger or null
[].weightnumber or null
[].lengthnumber or null
[].widthnumber or null
[].heightnumber or null
[].taxonomyTermIdsarray of integer
[].relatedProductIdsarray of integerThe products shown as applicable products on the product page, in order.
[].recommendedProductIdsarray of integerThe merchant's picks for the product page's You May Also Like section, in order. Without picks, the page shows the closest matches.
[].specTemplateIdinteger or null
[].variableProductIdinteger or null
[].thumbnailstring (uri) or null
[].galleryarray of string
[].createdAtstring (date-time) or null
[].updatedAtstring (date-time) or null

Example

foreach ($admin->products->all(['updatedSince' => $lastSyncedAt]) as $product) {
    $erp->save($product);
    $lastSyncedAt = $product['updatedAt'] ?? $lastSyncedAt;
}

Get a product

$admin->products->get(int $id): array

One product by its id, with every language's text. Scope: products:read.

Parameters

Parameter Type
$id int The product's id.

Returns

An AdminProduct:

FieldTypeDescription
idinteger
slugstring
titleLocalizedTextText by language code. An empty value is returned as an empty array [].
shortDescriptionLocalizedTextText by language code. An empty value is returned as an empty array [].
descriptionLocalizedTextText by language code. An empty value is returned as an empty array [].
skustring or null
partNumberstring or null
typestringOne of physical, digital.
downloadLimitinteger or null
documentUrlstring or null
statusbooleanTrue when published.
isFeaturedboolean or null
noindexboolean or null
pricenumber or null
salePricenumber or null
isSaleScheduledboolean or null
saleStartsAtstring (date-time) or null
saleEndsAtstring (date-time) or null
wholesalePricenumber or null
manageStockboolean or null
stockQuantityinteger or null
lowStockAmountinteger or null
stockStatusstring or nullOne of in_stock, out_of_stock.
unitIdinteger or null
taxClassIdinteger or null
weightnumber or null
lengthnumber or null
widthnumber or null
heightnumber or null
taxonomyTermIdsarray of integer
relatedProductIdsarray of integerThe products shown as applicable products on the product page, in order.
recommendedProductIdsarray of integerThe merchant's picks for the product page's You May Also Like section, in order. Without picks, the page shows the closest matches.
specTemplateIdinteger or null
variableProductIdinteger or null
thumbnailstring (uri) or null
galleryarray of string
createdAtstring (date-time) or null
updatedAtstring (date-time) or null

Errors

StatusWhen
401invalid_api_key: no active Admin key in Authorization: Bearer.
403admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope.
404not_found: the shop has no such record.
429Rate limited.

Create a product

$admin->products->create(array $input, string|false|null $idempotencyKey = null): array

A new product, written with the panel's rules and plan limits; hidden unless status is true. Images are https URLs or base64; one that can't be stored is skipped with a message in warnings. Scope: products:write.

Parameters

Parameter Type
$input array The product's fields, below.
$idempotencyKey string|false|null Your own Idempotency-Key, or false for none. One is made for you when null.

Request fields

FieldTypeDescription
title requiredstringThe title in the shop's default language. At most 255 characters.
translationsobject (map) or nullTitles in the shop's other languages.
shortDescriptionstring or nullIn the default language. Bold, underline, strikethrough, overline and lists are kept.
shortDescriptionTranslationsobject (map) or null
descriptionstring or nullIn the default language. HTML is kept; plain text becomes paragraphs.
descriptionTranslationsobject (map) or null
taxonomyTermIdsarray of integer or nullCategory, brand, tag and other term ids, from GET /api/admin/v1/taxonomies/{taxonomy}/terms. At most 50 items.
imagesarray of object or nullThe first is the thumbnail. At most 6 items.
images[].urlstring (uri) or nullAn https URL. Required without data. At most 2048 characters.
images[].datastring or nullThe image in base64, at most 5 MB.
imageUrlsarray of string (uri) or nullOlder form of images. At most 6 items.
skustring or nullAt most 100 characters.
partNumberstring or nullAt most 100 characters.
pricenumber or nullAt least 0. At most 99999999.99.
salePricenumber or nullAt least 0. At most 99999999.99.
isSaleScheduledboolean or null
saleStartsAtstring (date-time) or null
saleEndsAtstring (date-time) or null
wholesalePricenumber or nullAt least 0. At most 99999999.99.
manageStockboolean or null
stockQuantityinteger or nullAt least 0.
stockStatusstring or nullOne of in_stock, out_of_stock.
lowStockAmountinteger or nullAt least 0.
unitIdinteger or nullThe unit it is sold in, from GET /api/admin/v1/units.
taxClassIdinteger or null
typestringOne of physical, digital. Default "physical".
digitalUrlstring (uri) or nullRequired for a digital product; a public https file URL. At most 2048 characters.
downloadLimitinteger or nullAt least 1. At most 1000.
documentUrlstring (uri) or nullAt most 2048 characters.
statusbooleanPublished. Defaults to false (hidden) when creating.
isFeaturedboolean or null
noindexboolean or null
weightnumber or nullAt least 0. At most 999999.99.
lengthnumber or nullAt least 0. At most 999999.99.
widthnumber or nullAt least 0. At most 999999.99.
heightnumber or nullAt least 0. At most 999999.99.
specTemplateIdinteger or nullPlans with specification templates only. From GET /api/admin/v1/spec-templates.
specsobject (map) or nullSpecification values by property id, as GET /api/admin/v1/spec-templates/{template} lists the properties; a text property's string is its default-language value.
relatedProductIdsarray of integer or nullThe shop's own products shown as applicable products on the product page, in order; replaces the current list.
recommendedProductIdsarray of integer or nullUp to 8 of the shop's own products for the product page's You May Also Like section, in order, shown in place of the closest matches; replaces the current list. At most 8 items.
wholesalePricesarray of object or nullB2B plans only.
wholesalePrices[].wholesaleMembershipId requiredinteger
wholesalePrices[].pricenumber or nullAt least 0. At most 99999999.99.
quantityTiersarray of object or nullB2B plans only. At most 20 items.
quantityTiers[].minQuantity requiredintegerAt least 1. At most 1000000.
quantityTiers[].price requirednumberAt least 0. At most 99999999.99.

Returns

A ProductWriteResult array: the new AdminProduct in data, and the images that couldn't be stored in warnings.

FieldTypeDescription
dataAdminProduct
data.idinteger
data.slugstring
data.titleLocalizedTextText by language code. An empty value is returned as an empty array [].
data.shortDescriptionLocalizedTextText by language code. An empty value is returned as an empty array [].
data.descriptionLocalizedTextText by language code. An empty value is returned as an empty array [].
data.skustring or null
data.partNumberstring or null
data.typestringOne of physical, digital.
data.downloadLimitinteger or null
data.documentUrlstring or null
data.statusbooleanTrue when published.
data.isFeaturedboolean or null
data.noindexboolean or null
data.pricenumber or null
data.salePricenumber or null
data.isSaleScheduledboolean or null
data.saleStartsAtstring (date-time) or null
data.saleEndsAtstring (date-time) or null
data.wholesalePricenumber or null
data.manageStockboolean or null
data.stockQuantityinteger or null
data.lowStockAmountinteger or null
data.stockStatusstring or nullOne of in_stock, out_of_stock.
data.unitIdinteger or null
data.taxClassIdinteger or null
data.weightnumber or null
data.lengthnumber or null
data.widthnumber or null
data.heightnumber or null
data.taxonomyTermIdsarray of integer
data.relatedProductIdsarray of integerThe products shown as applicable products on the product page, in order.
data.recommendedProductIdsarray of integerThe merchant's picks for the product page's You May Also Like section, in order. Without picks, the page shows the closest matches.
data.specTemplateIdinteger or null
data.variableProductIdinteger or null
data.thumbnailstring (uri) or null
data.galleryarray of string
data.createdAtstring (date-time) or null
data.updatedAtstring (date-time) or null
warningsarray of string

Errors

StatusWhen
401invalid_api_key: no active Admin key in Authorization: Bearer.
403The key's refusals (see AdminForbidden), or plan_limit_reached.
409idempotency_in_progress: a request with this Idempotency-Key is still running. Retry with the same key after Retry-After seconds; the first answer is then replayed.
422Validation errors ({ message, errors }), or an idempotency refusal(idempotency_key_reused, idempotency_key_invalid).
429Rate limited.

Example

$result = $admin->products->create([
    'title' => 'Ceramic mug',
    'translations' => ['ar' => 'كوب سيراميك'],
    'sku' => 'MUG-01',
    'price' => 24,
    'salePrice' => 19.5,
    'manageStock' => true,
    'stockQuantity' => 40,
    'taxonomyTermIds' => [4],
    'imageUrls' => ['https://cdn.example.com/mug.jpg'],
]);

$product = $result['data'];

Update a product

$admin->products->update(
    int $id,
    array $changes,
    DateTimeInterface|string|null $unmodifiedSince = null,
    string|false|null $idempotencyKey = null,
): array

Changes only the fields sent. Images are added after the current ones, or replace them with imageMode replace. Scope: products:write.

Parameters

Parameter Type
$id int The product's id.
$changes array The fields to change, below.
$unmodifiedSince DateTimeInterface|string|null The product's updatedAt as you read it. If it changed since, the change is refused with 409 edit_conflict.
$idempotencyKey string|false|null Your own Idempotency-Key, or false for none.

Request fields

FieldTypeDescription
titlestringThe title in the shop's default language. At most 255 characters.
translationsobject (map) or nullTitles in the shop's other languages.
shortDescriptionstring or nullIn the default language. Bold, underline, strikethrough, overline and lists are kept.
shortDescriptionTranslationsobject (map) or null
descriptionstring or nullIn the default language. HTML is kept; plain text becomes paragraphs.
descriptionTranslationsobject (map) or null
taxonomyTermIdsarray of integer or nullCategory, brand, tag and other term ids, from GET /api/admin/v1/taxonomies/{taxonomy}/terms. At most 50 items.
imagesarray of object or nullThe first is the thumbnail. At most 6 items.
images[].urlstring (uri) or nullAn https URL. Required without data. At most 2048 characters.
images[].datastring or nullThe image in base64, at most 5 MB.
imageUrlsarray of string (uri) or nullOlder form of images. At most 6 items.
skustring or nullAt most 100 characters.
partNumberstring or nullAt most 100 characters.
pricenumber or nullAt least 0. At most 99999999.99.
salePricenumber or nullAt least 0. At most 99999999.99.
isSaleScheduledboolean or null
saleStartsAtstring (date-time) or null
saleEndsAtstring (date-time) or null
wholesalePricenumber or nullAt least 0. At most 99999999.99.
manageStockboolean or null
stockQuantityinteger or nullAt least 0.
stockStatusstring or nullOne of in_stock, out_of_stock.
lowStockAmountinteger or nullAt least 0.
unitIdinteger or nullThe unit it is sold in, from GET /api/admin/v1/units.
taxClassIdinteger or null
typestringOne of physical, digital. Default "physical".
digitalUrlstring (uri) or nullRequired for a digital product; a public https file URL. At most 2048 characters.
downloadLimitinteger or nullAt least 1. At most 1000.
documentUrlstring (uri) or nullAt most 2048 characters.
statusbooleanPublished. Defaults to false (hidden) when creating.
isFeaturedboolean or null
noindexboolean or null
weightnumber or nullAt least 0. At most 999999.99.
lengthnumber or nullAt least 0. At most 999999.99.
widthnumber or nullAt least 0. At most 999999.99.
heightnumber or nullAt least 0. At most 999999.99.
specTemplateIdinteger or nullPlans with specification templates only. From GET /api/admin/v1/spec-templates.
specsobject (map) or nullSpecification values by property id, as GET /api/admin/v1/spec-templates/{template} lists the properties; a text property's string is its default-language value.
relatedProductIdsarray of integer or nullThe shop's own products shown as applicable products on the product page, in order; replaces the current list.
recommendedProductIdsarray of integer or nullUp to 8 of the shop's own products for the product page's You May Also Like section, in order, shown in place of the closest matches; replaces the current list. At most 8 items.
wholesalePricesarray of object or nullB2B plans only.
wholesalePrices[].wholesaleMembershipId requiredinteger
wholesalePrices[].pricenumber or nullAt least 0. At most 99999999.99.
quantityTiersarray of object or nullB2B plans only. At most 20 items.
quantityTiers[].minQuantity requiredintegerAt least 1. At most 1000000.
quantityTiers[].price requirednumberAt least 0. At most 99999999.99.
imageModestring or nullOne of add, replace. Default "add".
updatedAtstring (date-time) or nullThe record's updatedAt as you read it; a newer record gets 409 edit_conflict.

Returns

A ProductWriteResult array: the changed AdminProduct in data, and the images that couldn't be stored in warnings.

FieldTypeDescription
dataAdminProduct
data.idinteger
data.slugstring
data.titleLocalizedTextText by language code. An empty value is returned as an empty array [].
data.shortDescriptionLocalizedTextText by language code. An empty value is returned as an empty array [].
data.descriptionLocalizedTextText by language code. An empty value is returned as an empty array [].
data.skustring or null
data.partNumberstring or null
data.typestringOne of physical, digital.
data.downloadLimitinteger or null
data.documentUrlstring or null
data.statusbooleanTrue when published.
data.isFeaturedboolean or null
data.noindexboolean or null
data.pricenumber or null
data.salePricenumber or null
data.isSaleScheduledboolean or null
data.saleStartsAtstring (date-time) or null
data.saleEndsAtstring (date-time) or null
data.wholesalePricenumber or null
data.manageStockboolean or null
data.stockQuantityinteger or null
data.lowStockAmountinteger or null
data.stockStatusstring or nullOne of in_stock, out_of_stock.
data.unitIdinteger or null
data.taxClassIdinteger or null
data.weightnumber or null
data.lengthnumber or null
data.widthnumber or null
data.heightnumber or null
data.taxonomyTermIdsarray of integer
data.relatedProductIdsarray of integerThe products shown as applicable products on the product page, in order.
data.recommendedProductIdsarray of integerThe merchant's picks for the product page's You May Also Like section, in order. Without picks, the page shows the closest matches.
data.specTemplateIdinteger or null
data.variableProductIdinteger or null
data.thumbnailstring (uri) or null
data.galleryarray of string
data.createdAtstring (date-time) or null
data.updatedAtstring (date-time) or null
warningsarray of string

Errors

StatusWhen
401invalid_api_key: no active Admin key in Authorization: Bearer.
403admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope.
404not_found: the shop has no such record.
409edit_conflict (the record changed after If-Unmodified-Since or updatedAt), or idempotency_in_progress.
422Validation errors ({ message, errors }), or an idempotency refusal(idempotency_key_reused, idempotency_key_invalid).
429Rate limited.

Example

$product = $admin->products->get(12);
$admin->products->update(12, ['price' => 19.5], unmodifiedSince: $product['updatedAt']);

Delete a product

$admin->products->delete(int $id): void

Deletes a product. Scope: products:write.

Parameters

Parameter Type
$id int The product's id.

Returns

Nothing.

Errors

StatusWhen
401invalid_api_key: no active Admin key in Authorization: Bearer.
403admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope.
404not_found: the shop has no such record.
409idempotency_in_progress: a request with this Idempotency-Key is still running. Retry with the same key after Retry-After seconds; the first answer is then replayed.
422Validation errors ({ message, errors }), or an idempotency refusal(idempotency_key_reused, idempotency_key_invalid).
429Rate limited.