Product groups
Product groups connect products that represent the same model or family. A group defines stable option axes, such as color or material. Each product membership supplies the value selected for those axes.
Use product groups when the assistant should understand that several catalog products are alternatives within one family. Collections serve a different purpose: they organize products for merchandising and recommendation scopes.
Recommended sync order
- Create or update product groups.
- Create or update products with
group_memberships. - Remove obsolete groups only after their replacement memberships have been sent.
A product write that references a missing group returns 422 product_group_not_found. A missing option returns 422 product_group_option_not_found.
The ProductGroup object
| Field | Type | Required | Description |
|---|---|---|---|
external_id | string | Yes | Your stable identifier. It is the upsert key and the reference used by products. |
humind_id | string | Returned only | Humind's internal 24-character ObjectId. |
name | string | Yes | Display name, maximum 500 characters. |
handle | string | No | Lowercase, hyphen-separated handle, unique per company. Humind derives api-<external_id-slug> when omitted on create. |
options | object[] | No | Up to 50 option axes. Omit on upsert to preserve current options. Send [] to remove all options. |
created_at | ISO 8601 | Returned only | Creation timestamp in UTC. |
updated_at | ISO 8601 | Returned only | Last modification timestamp in UTC. |
Each option contains:
| Field | Type | Required | Description |
|---|---|---|---|
external_id | string | Yes | Stable identifier used in product memberships, for example color. |
name | string | Yes | Display label, for example Color. It can be renamed without changing the identifier. |
Option external_id values and option names must each be unique within a group.
Create or upsert
POST /product-groups creates a group or updates the group with the same external_id.
Required scope: catalog:write
curl -X POST https://api.thehumind.com/public/v1/product-groups \
-H "Authorization: Bearer hmd_live_..." \
-H "Idempotency-Key: 96e32e41-2dac-4338-b071-150d30641eb5" \
-H "Content-Type: application/json" \
-d '{
"external_id": "sofa-model-1",
"name": "Sofa model 1",
"handle": "sofa-model-1",
"options": [
{ "external_id": "color", "name": "Color" },
{ "external_id": "material", "name": "Material" }
]
}'The response is 201 Created for a new group and 200 OK for an update.
Attach a product
Add group_memberships to any product payload accepted by POST /products, POST /products/batch, PUT /products/{id}, PATCH /products/{id}, or an NDJSON product import.
{
"external_id": "sofa-model-1-blue-velvet",
"title": "Sofa model 1, blue velvet",
"group_memberships": [
{
"group_external_id": "sofa-model-1",
"selected_options": [
{ "option_external_id": "color", "value": "Blue" },
{ "option_external_id": "material", "value": "Velvet" }
]
}
],
"variants": [
{
"external_id": "sofa-model-1-blue-velvet-default",
"price": 1290,
"currency": "EUR"
}
]
}Omitting group_memberships preserves existing public API memberships. Sending group_memberships: [] removes all public API memberships from that product. Humind preserves memberships managed by Shopify and other internal connectors.
List and retrieve
| Method | Path | Scope | Description |
|---|---|---|---|
| GET | /product-groups | catalog:read | Cursor-paginated list. Supports handle, limit, and cursor. |
| GET | /product-groups/{id} | catalog:read | Retrieve by api:<external_id> or humind_id. |
Only groups created through the public API are returned. Connector-managed groups are not exposed.
Replace and patch
| Method | Path | Scope | Description |
|---|---|---|---|
| PUT | /product-groups/{id} | catalog:write | Replace using a complete ProductGroup payload. |
| PATCH | /product-groups/{id} | catalog:write | Update only supplied fields. |
When external_id is present in a PUT or PATCH body, it must match the group identified by the URL. Removing an option also removes selections for that option from member products.
Batch upsert
POST /product-groups/batch accepts 1 to 500 groups as a bare array or { "items": [...] }. Items are processed independently and the endpoint returns 207 Multi-Status.
If an external_id appears more than once, only the first item is processed. Later duplicates return duplicate_external_id_in_batch.
Delete
DELETE /product-groups/{id} permanently deletes the public API group and removes that membership from every product. Products themselves are never deleted.
Required scope: catalog:write
The endpoint returns 204 No Content.