How to manage catalog items
View as MarkdownCreate and manage SKUs and SKU groups through the Catalog GraphQL subgraph — the store-scoped endpoint for catalog operations.
Overview
The Catalog subgraph manages SKUs and SKU groups (there's no Product type). A SKU is a single purchasable variant. A SKU group is a collection of related SKUs (for example, a shirt available in multiple sizes). All catalog operations go through one GraphQL endpoint: POST /v2/commerce/stores/{storeId}/catalog-subgraph. Send the same store ID in the {storeId} path and the x-store-id header. The header is required. If they differ, the subgraph uses the header — the path does not override it.
API host
Examples use https://api.godaddy.com. Use a Personal Access Token issued for the API host you call.
Catalog scopes use commerce.product:* naming for historical reasons. Request commerce.product:read to query data and commerce.product:write for mutations. Read RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset on every catalog-subgraph response. On HTTP 429, wait for RateLimit-Reset or Retry-After. See Handle rate limits.
The following article describes how to manage catalog items. Go to Catalog GraphQL reference for more information about the Catalog subgraph.
Prerequisites
The following prerequisites are required before you can manage catalog items:
- a GoDaddy account with an active commerce store
- a Personal Access Token (PAT) with
commerce.product:read(queries) orcommerce.product:write(mutations) - your
storeIdFind your store ID
Sign in to your GoDaddy account and go to About the Commerce API to retrieve your
storeId.
List SKU groups
skuGroups returns a paginated list of SKU groups for your store. Use first and after to page through results.
The following procedure retrieves the first page of SKU groups.
-
Query SKU groups for your store:
curl -s -X POST "https://api.godaddy.com/v2/commerce/stores/${STORE_ID}/catalog-subgraph" \ -H "Authorization: Bearer $GODADDY_PAT" \ -H "x-store-id: ${STORE_ID}" \ -H "Content-Type: application/json" \ -d '{"query": "{ skuGroups(first: 10) { edges { node { id label type status } } pageInfo { hasNextPage endCursor } } }"}' -
Review the response including SKU group IDs and the pagination cursor:
{ "data": { "skuGroups": { "edges": [ { "node": { "id": "<SKU_GROUP_UUID>", "label": "<SKU_GROUP_DISPLAY_LABEL>", "type": "<SKU_GROUP_TYPE>", "status": "<LIFECYCLE_STATUS>" } } ], "pageInfo": { "hasNextPage": true, "endCursor": "<PAGINATION_CURSOR>" } } } }Fetch the next page
To fetch the next page, pass the
endCursorvalue as theafterargument:skuGroups(first: 10, after: "<PAGINATION_CURSOR>").
Get a SKU group
skuGroup(id) retrieves a single SKU group and its associated SKUs.
-
Retrieve a SKU group by its
id:SKU_GROUP_ID="<SKU_GROUP_UUID>" curl -s -X POST "https://api.godaddy.com/v2/commerce/stores/${STORE_ID}/catalog-subgraph" \ -H "Authorization: Bearer $GODADDY_PAT" \ -H "x-store-id: ${STORE_ID}" \ -H "Content-Type: application/json" \ -d '{ "query": "query GetSkuGroup($id: String!) { skuGroup(id: $id) { id label type status skus { edges { node { id label code status } } } } }", "variables": { "id": "<SKU_GROUP_UUID>" } }'
Create a SKU group
createSkuGroup creates a new SKU group. The label and type fields are required. Live accepts PHYSICAL, DIGITAL, and PRODUCT for type. Metafield type must be lowercase (string, not STRING).
The following procedure creates a SKU group.
-
Send the create mutation:
curl -s -X POST "https://api.godaddy.com/v2/commerce/stores/${STORE_ID}/catalog-subgraph" \ -H "Authorization: Bearer $GODADDY_PAT" \ -H "x-store-id: ${STORE_ID}" \ -H "Content-Type: application/json" \ -d '{ "query": "mutation CreateSkuGroup($input: MutationCreateSkuGroupInput!) { createSkuGroup(input: $input) { id label type status } }", "variables": { "input": { "label": "<SKU_GROUP_DISPLAY_LABEL>", "type": "STANDARD" } } }' -
Review the response including the new SKU group ID:
{ "data": { "createSkuGroup": { "id": "<SKU_GROUP_UUID>", "label": "<SKU_GROUP_DISPLAY_LABEL>", "type": "STANDARD", "status": "<LIFECYCLE_STATUS>" } } }
Create a SKU
createSku creates a new SKU. The label field is required. Pass skuGroupId to attach it to a product (SKU group) in the same call, or use addSkusToSkuGroup afterwards. You can also create SKUs inline on createSkuGroup via skus.
When you set prices or unitCost, for SimpleMoneyInput.value send 1999 for $19.99 USD, not 19.99. Metafield type must be lowercase (string, not STRING).
SKU label is not the product title
createSku.label is the variant label. The Commerce products UI uses the SKU group label as the product title. Changing a SKU label does not rename the product — use updateSkuGroup for that. To change an existing SKU price, use updateSkuPrice; createSkuPrice fails if the SKU already has a price.
The following procedure creates a SKU.
-
Send the create mutation:
curl -s -X POST "https://api.godaddy.com/v2/commerce/stores/${STORE_ID}/catalog-subgraph" \ -H "Authorization: Bearer $GODADDY_PAT" \ -H "x-store-id: ${STORE_ID}" \ -H "Content-Type: application/json" \ -d '{ "query": "mutation CreateSku($input: CreateSKUInput!) { createSku(input: $input) { id label code status } }", "variables": { "input": { "label": "<SKU_DISPLAY_LABEL>", "code": "<SKU_CODE>" } } }' -
Review the response including the new SKU ID:
{ "data": { "createSku": { "id": "<SKU_UUID>", "label": "<SKU_DISPLAY_LABEL>", "code": "<SKU_CODE>", "status": "<LIFECYCLE_STATUS>" } } }
Update a SKU
updateSku updates one or more fields on an existing SKU. All input fields are optional. Only include the fields you want to change.
The following procedure updates the label of a SKU.
-
Send the update mutation:
curl -s -X POST "https://api.godaddy.com/v2/commerce/stores/${STORE_ID}/catalog-subgraph" \ -H "Authorization: Bearer $GODADDY_PAT" \ -H "x-store-id: ${STORE_ID}" \ -H "Content-Type: application/json" \ -d '{ "query": "mutation UpdateSku($id: String!, $input: MutationUpdateSkuInput!) { updateSku(id: $id, input: $input) { id label code status } }", "variables": { "id": "<SKU_UUID>", "input": { "label": "<UPDATED_SKU_DISPLAY_LABEL>" } } }' -
Review the response confirming the updated fields:
{ "data": { "updateSku": { "id": "<SKU_UUID>", "label": "<UPDATED_SKU_DISPLAY_LABEL>", "code": "<SKU_CODE>", "status": "<LIFECYCLE_STATUS>" } } }
Archive a SKU
archiveSku marks a SKU as archived (there's no delete mutation). Archived SKUs are excluded from active queries unless you filter by status: ARCHIVED.
-
Archive a SKU by its
id:curl -s -X POST "https://api.godaddy.com/v2/commerce/stores/${STORE_ID}/catalog-subgraph" \ -H "Authorization: Bearer $GODADDY_PAT" \ -H "x-store-id: ${STORE_ID}" \ -H "Content-Type: application/json" \ -d '{ "query": "mutation ArchiveSku($id: String!) { archiveSku(id: $id) { id status } }", "variables": { "id": "<SKU_UUID>" } }'
Common errors
| Status | Most likely cause |
|---|---|
400 | x-store-id header is missing, or the GraphQL selection is invalid (for example selecting id on the Option union without ... on ListOption). A path {storeId} that doesn't match the header is not a 400 — the subgraph still uses x-store-id. |
401 | PAT is missing or expired. Go to Authentication to generate a new token. |
403 | Token doesn't include commerce.product:read or commerce.product:write. |
404 | SKU or SKU group ID doesn't exist or isn't accessible with the provided token. |
429 | Rate limit exceeded (RateLimit-Remaining: 0). Wait RateLimit-Reset seconds, or Retry-After if present. Do not assume 60 req/min. |
HTTP 200 doesn't mean success
GraphQL requests may return HTTP 200 even when there are errors. Always check the errors array in the response body. Schema validation errors (unknown fields, missing variables) return HTTP 400, but runtime errors (invalid UUIDs, business rule violations) return HTTP 200 with an errors array alongside data.
GraphQL behavior notes
Non-existent IDs return null
When you query an entity by ID (for example skuGroup(id: "...") or sku(id: "...")), a non-existent or inaccessible ID returns null with no error. This is standard GraphQL behavior, not a failure.
{
"data": {
"skuGroup": null
}
}Placeholder UUIDs in documentation
Code examples in the API reference use placeholder UUIDs like ID_VALUE or 497f6eca-6276-4993-bfeb-53cbbbba6f08. These are documentation placeholders — replace them with real IDs from your store. Querying a placeholder UUID returns null.
References are read via parent objects
There is no top-level reference(id: ...) query. References follow a HATEOAS pattern — you read them through the parent object they're attached to:
# Read references on a SKU group
query {
skuGroup(id: "your-sku-group-id") {
references {
edges {
node {
id
type
value
}
}
}
}
}To manage references, use mutations like addReferencesToSkuGroup, removeReferencesFromSkuGroup, addReferencesToSku, etc.
Agent & Automation Notes
commerce.product:read, commerce.product:writeRelated
Last updated on
How is this guide?