# How to manage catalog items (https://developer.godaddy.com/en/docs/api-users/commerce/manage-catalog)

***

title: How to manage catalog items
description: Create and manage SKUs and SKU groups through the Catalog GraphQL subgraph — the store-scoped endpoint for catalog operations.
agentNotes:
permissions: \[]
scopes: \["commerce.product:read", "commerce.product:write"]
rateLimit: "Read RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset on each catalog-subgraph response. On 429, wait RateLimit-Reset or Retry-After."
idempotent: false
destructive: false
failureRecovery: "Query operations are safe to retry. For mutations, check the current state before retrying to avoid duplicate creates."
related:
apis:

* title: "Catalog GraphQL reference"
  href: "/docs/references/rest/catalog"
  guides:
* title: "Manage a store"
  href: "/docs/api-users/commerce/set-up-a-store"
* title: "Process an order"
  href: "/docs/api-users/commerce/manage-orders-and-customers"
* title: "About the Commerce API"
  href: "/docs/api-users/commerce"
  concepts:
* title: "Authentication"
  href: "/docs/api-users/auth"
* title: "Rate limits"
  href: "/docs/api-users/rate-limits"
* title: "Paginate results"
  href: "/docs/api-users/pagination"

***

## 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.

Examples use `https://api.godaddy.com`. Use a [Personal Access Token](https://developer.godaddy.com/docs/api-users/auth) 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](https://developer.godaddy.com/docs/api-users/rate-limits).

The following article describes how to manage catalog items. Go to [Catalog GraphQL reference](https://developer.godaddy.com/docs/references/rest/catalog) 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)](https://developer.godaddy.com/docs/api-users/auth) with `commerce.product:read` (queries) or `commerce.product:write` (mutations)
* your `storeId`

  Sign in to your GoDaddy account and go to [About the Commerce API](https://developer.godaddy.com/docs/api-users/commerce#your-stores) 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.

1. Query SKU groups for your store:

   ```bash tab="curl"
   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 } } }"}'
   ```

   ```js tab="Node"
   const token = process.env.GODADDY_PAT;
   const storeId = process.env.STORE_ID;

   const res = await fetch(
     `https://api.godaddy.com/v2/commerce/stores/${storeId}/catalog-subgraph`,
     {
       method: "POST",
       headers: {
         Authorization: `Bearer ${token}`,
         "x-store-id": storeId,
         "Content-Type": "application/json",
       },
       body: JSON.stringify({
         query: `{
           skuGroups(first: 10) {
             edges {
               node { id label type status }
             }
             pageInfo { hasNextPage endCursor }
           }
         }`,
       }),
     }
   );
   const { data } = await res.json();
   console.log(data.skuGroups.edges.map((edge) => edge.node));
   ```

   ```python tab="Python"
   import os, requests

   token = os.environ["GODADDY_PAT"]
   store_id = os.environ["STORE_ID"]

   res = requests.post(
       f"https://api.godaddy.com/v2/commerce/stores/{store_id}/catalog-subgraph",
       headers={
           "Authorization": f"Bearer {token}",
           "x-store-id": store_id,
           "Content-Type": "application/json",
       },
       json={"query": "{ skuGroups(first: 10) { edges { node { id label type status } } pageInfo { hasNextPage endCursor } } }"},
   )
   res.raise_for_status()
   print([edge["node"] for edge in res.json()["data"]["skuGroups"]["edges"]])
   ```

   ```go tab="Go"
   package main

   import (
       "bytes"
       "encoding/json"
       "fmt"
       "net/http"
       "os"
   )

   func main() {
       token := os.Getenv("GODADDY_PAT")
       storeId := os.Getenv("STORE_ID")

       payload := map[string]any{
           "query": "{ skuGroups(first: 10) { edges { node { id label type status } } pageInfo { hasNextPage endCursor } } }",
       }
       body, _ := json.Marshal(payload)

       url := fmt.Sprintf("https://api.godaddy.com/v2/commerce/stores/%s/catalog-subgraph", storeId)
       req, _ := http.NewRequest("POST", url, bytes.NewReader(body))
       req.Header.Set("Authorization", "Bearer "+token)
       req.Header.Set("x-store-id", storeId)
       req.Header.Set("Content-Type", "application/json")

       res, err := http.DefaultClient.Do(req)
       if err != nil { panic(err) }
       defer res.Body.Close()

       var result map[string]any
       json.NewDecoder(res.Body).Decode(&result)
       fmt.Println(result)
   }
   ```

2. Review the response including SKU group IDs and the pagination cursor:

   ```json
   {
     "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>"
         }
       }
     }
   }
   ```

   To fetch the next page, pass the `endCursor` value as the `after` argument: `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`:

  ```bash tab="curl"
  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>" }
    }'
  ```

  ```js tab="Node"
  const token = process.env.GODADDY_PAT;
  const storeId = process.env.STORE_ID;
  const skuGroupId = "<SKU_GROUP_UUID>";

  const res = await fetch(
    `https://api.godaddy.com/v2/commerce/stores/${storeId}/catalog-subgraph`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "x-store-id": storeId,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        query: `query GetSkuGroup($id: String!) {
          skuGroup(id: $id) {
            id label type status
            skus { edges { node { id label code status } } }
          }
        }`,
        variables: { id: skuGroupId },
      }),
    }
  );
  const { data } = await res.json();
  console.log(data.skuGroup);
  ```

  ```python tab="Python"
  import os, requests

  token = os.environ["GODADDY_PAT"]
  store_id = os.environ["STORE_ID"]
  sku_group_id = "<SKU_GROUP_UUID>"

  res = requests.post(
      f"https://api.godaddy.com/v2/commerce/stores/{store_id}/catalog-subgraph",
      headers={
          "Authorization": f"Bearer {token}",
          "x-store-id": store_id,
          "Content-Type": "application/json",
      },
      json={
          "query": "query GetSkuGroup($id: String!) { skuGroup(id: $id) { id label type status skus { edges { node { id label code status } } } } }",
          "variables": {"id": sku_group_id},
      },
  )
  res.raise_for_status()
  print(res.json()["data"]["skuGroup"])
  ```

  ```go tab="Go"
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "net/http"
      "os"
  )

  func main() {
      token := os.Getenv("GODADDY_PAT")
      storeId := os.Getenv("STORE_ID")
      skuGroupId := "<SKU_GROUP_UUID>"

      payload := map[string]any{
          "query":     "query GetSkuGroup($id: String!) { skuGroup(id: $id) { id label type status skus { edges { node { id label code status } } } } }",
          "variables": map[string]any{"id": skuGroupId},
      }
      body, _ := json.Marshal(payload)

      url := fmt.Sprintf("https://api.godaddy.com/v2/commerce/stores/%s/catalog-subgraph", storeId)
      req, _ := http.NewRequest("POST", url, bytes.NewReader(body))
      req.Header.Set("Authorization", "Bearer "+token)
      req.Header.Set("x-store-id", storeId)
      req.Header.Set("Content-Type", "application/json")

      res, err := http.DefaultClient.Do(req)
      if err != nil { panic(err) }
      defer res.Body.Close()

      var result map[string]any
      json.NewDecoder(res.Body).Decode(&result)
      fmt.Println(result)
  }
  ```

## 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.

1. Send the create mutation:

   ```bash tab="curl"
   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"
         }
       }
     }'
   ```

   ```js tab="Node"
   const token = process.env.GODADDY_PAT;
   const storeId = process.env.STORE_ID;

   const res = await fetch(
     `https://api.godaddy.com/v2/commerce/stores/${storeId}/catalog-subgraph`,
     {
       method: "POST",
       headers: {
         Authorization: `Bearer ${token}`,
         "x-store-id": storeId,
         "Content-Type": "application/json",
       },
       body: JSON.stringify({
         query: `mutation CreateSkuGroup($input: MutationCreateSkuGroupInput!) {
           createSkuGroup(input: $input) {
             id label type status
           }
         }`,
         variables: {
           input: {
             label: "<SKU_GROUP_DISPLAY_LABEL>",
             type: "STANDARD",
           },
         },
       }),
     }
   );
   const { data } = await res.json();
   console.log(data.createSkuGroup);
   ```

   ```python tab="Python"
   import os, requests

   token = os.environ["GODADDY_PAT"]
   store_id = os.environ["STORE_ID"]

   res = requests.post(
       f"https://api.godaddy.com/v2/commerce/stores/{store_id}/catalog-subgraph",
       headers={
           "Authorization": f"Bearer {token}",
           "x-store-id": store_id,
           "Content-Type": "application/json",
       },
       json={
           "query": "mutation CreateSkuGroup($input: MutationCreateSkuGroupInput!) { createSkuGroup(input: $input) { id label type status } }",
           "variables": {"input": {"label": "<SKU_GROUP_DISPLAY_LABEL>", "type": "STANDARD"}},
       },
   )
   res.raise_for_status()
   print(res.json()["data"]["createSkuGroup"])
   ```

   ```go tab="Go"
   package main

   import (
       "bytes"
       "encoding/json"
       "fmt"
       "net/http"
       "os"
   )

   func main() {
       token := os.Getenv("GODADDY_PAT")
       storeId := os.Getenv("STORE_ID")

       payload := map[string]any{
           "query": "mutation CreateSkuGroup($input: MutationCreateSkuGroupInput!) { createSkuGroup(input: $input) { id label type status } }",
           "variables": map[string]any{
               "input": map[string]any{
                   "label": "<SKU_GROUP_DISPLAY_LABEL>",
                   "type":  "STANDARD",
               },
           },
       }
       body, _ := json.Marshal(payload)

       url := fmt.Sprintf("https://api.godaddy.com/v2/commerce/stores/%s/catalog-subgraph", storeId)
       req, _ := http.NewRequest("POST", url, bytes.NewReader(body))
       req.Header.Set("Authorization", "Bearer "+token)
       req.Header.Set("x-store-id", storeId)
       req.Header.Set("Content-Type", "application/json")

       res, err := http.DefaultClient.Do(req)
       if err != nil { panic(err) }
       defer res.Body.Close()

       var result map[string]any
       json.NewDecoder(res.Body).Decode(&result)
       fmt.Println(result)
   }
   ```

2. Review the response including the new SKU group ID:

   ```json
   {
     "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`).

`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.

1. Send the create mutation:

   ```bash tab="curl"
   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>"
         }
       }
     }'
   ```

   ```js tab="Node"
   const token = process.env.GODADDY_PAT;
   const storeId = process.env.STORE_ID;

   const res = await fetch(
     `https://api.godaddy.com/v2/commerce/stores/${storeId}/catalog-subgraph`,
     {
       method: "POST",
       headers: {
         Authorization: `Bearer ${token}`,
         "x-store-id": storeId,
         "Content-Type": "application/json",
       },
       body: JSON.stringify({
         query: `mutation CreateSku($input: CreateSKUInput!) {
           createSku(input: $input) {
             id label code status
           }
         }`,
         variables: {
           input: {
             label: "<SKU_DISPLAY_LABEL>",
             code: "<SKU_CODE>",
           },
         },
       }),
     }
   );
   const { data } = await res.json();
   console.log(data.createSku);
   ```

   ```python tab="Python"
   import os, requests

   token = os.environ["GODADDY_PAT"]
   store_id = os.environ["STORE_ID"]

   res = requests.post(
       f"https://api.godaddy.com/v2/commerce/stores/{store_id}/catalog-subgraph",
       headers={
           "Authorization": f"Bearer {token}",
           "x-store-id": store_id,
           "Content-Type": "application/json",
       },
       json={
           "query": "mutation CreateSku($input: CreateSKUInput!) { createSku(input: $input) { id label code status } }",
           "variables": {"input": {"label": "<SKU_DISPLAY_LABEL>", "code": "<SKU_CODE>"}},
       },
   )
   res.raise_for_status()
   print(res.json()["data"]["createSku"])
   ```

   ```go tab="Go"
   package main

   import (
       "bytes"
       "encoding/json"
       "fmt"
       "net/http"
       "os"
   )

   func main() {
       token := os.Getenv("GODADDY_PAT")
       storeId := os.Getenv("STORE_ID")

       payload := map[string]any{
           "query": "mutation CreateSku($input: CreateSKUInput!) { createSku(input: $input) { id label code status } }",
           "variables": map[string]any{
               "input": map[string]any{
                   "label": "<SKU_DISPLAY_LABEL>",
                   "code":  "<SKU_CODE>",
               },
           },
       }
       body, _ := json.Marshal(payload)

       url := fmt.Sprintf("https://api.godaddy.com/v2/commerce/stores/%s/catalog-subgraph", storeId)
       req, _ := http.NewRequest("POST", url, bytes.NewReader(body))
       req.Header.Set("Authorization", "Bearer "+token)
       req.Header.Set("x-store-id", storeId)
       req.Header.Set("Content-Type", "application/json")

       res, err := http.DefaultClient.Do(req)
       if err != nil { panic(err) }
       defer res.Body.Close()

       var result map[string]any
       json.NewDecoder(res.Body).Decode(&result)
       fmt.Println(result)
   }
   ```

2. Review the response including the new SKU ID:

   ```json
   {
     "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.

1. Send the update mutation:

   ```bash tab="curl"
   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>"
         }
       }
     }'
   ```

   ```js tab="Node"
   const token = process.env.GODADDY_PAT;
   const storeId = process.env.STORE_ID;

   const res = await fetch(
     `https://api.godaddy.com/v2/commerce/stores/${storeId}/catalog-subgraph`,
     {
       method: "POST",
       headers: {
         Authorization: `Bearer ${token}`,
         "x-store-id": storeId,
         "Content-Type": "application/json",
       },
       body: JSON.stringify({
         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>",
           },
         },
       }),
     }
   );
   const { data } = await res.json();
   console.log(data.updateSku);
   ```

   ```python tab="Python"
   import os, requests

   token = os.environ["GODADDY_PAT"]
   store_id = os.environ["STORE_ID"]

   res = requests.post(
       f"https://api.godaddy.com/v2/commerce/stores/{store_id}/catalog-subgraph",
       headers={
           "Authorization": f"Bearer {token}",
           "x-store-id": store_id,
           "Content-Type": "application/json",
       },
       json={
           "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>"}},
       },
   )
   res.raise_for_status()
   print(res.json()["data"]["updateSku"])
   ```

   ```go tab="Go"
   package main

   import (
       "bytes"
       "encoding/json"
       "fmt"
       "net/http"
       "os"
   )

   func main() {
       token := os.Getenv("GODADDY_PAT")
       storeId := os.Getenv("STORE_ID")

       payload := map[string]any{
           "query": "mutation UpdateSku($id: String!, $input: MutationUpdateSkuInput!) { updateSku(id: $id, input: $input) { id label code status } }",
           "variables": map[string]any{
               "id":    "<SKU_UUID>",
               "input": map[string]any{"label": "<UPDATED_SKU_DISPLAY_LABEL>"},
           },
       }
       body, _ := json.Marshal(payload)

       url := fmt.Sprintf("https://api.godaddy.com/v2/commerce/stores/%s/catalog-subgraph", storeId)
       req, _ := http.NewRequest("POST", url, bytes.NewReader(body))
       req.Header.Set("Authorization", "Bearer "+token)
       req.Header.Set("x-store-id", storeId)
       req.Header.Set("Content-Type", "application/json")

       res, err := http.DefaultClient.Do(req)
       if err != nil { panic(err) }
       defer res.Body.Close()

       var result map[string]any
       json.NewDecoder(res.Body).Decode(&result)
       fmt.Println(result)
   }
   ```

2. Review the response confirming the updated fields:

   ```json
   {
     "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`:

  ```bash tab="curl"
  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>" }
    }'
  ```

  ```js tab="Node"
  const token = process.env.GODADDY_PAT;
  const storeId = process.env.STORE_ID;

  const res = await fetch(
    `https://api.godaddy.com/v2/commerce/stores/${storeId}/catalog-subgraph`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "x-store-id": storeId,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        query: `mutation ArchiveSku($id: String!) { archiveSku(id: $id) { id status } }`,
        variables: { id: "<SKU_UUID>" },
      }),
    }
  );
  const { data } = await res.json();
  console.log(data.archiveSku);
  ```

  ```python tab="Python"
  import os, requests

  token = os.environ["GODADDY_PAT"]
  store_id = os.environ["STORE_ID"]

  res = requests.post(
      f"https://api.godaddy.com/v2/commerce/stores/{store_id}/catalog-subgraph",
      headers={
          "Authorization": f"Bearer {token}",
          "x-store-id": store_id,
          "Content-Type": "application/json",
      },
      json={
          "query": "mutation ArchiveSku($id: String!) { archiveSku(id: $id) { id status } }",
          "variables": {"id": "<SKU_UUID>"},
      },
  )
  res.raise_for_status()
  print(res.json()["data"]["archiveSku"])
  ```

  ```go tab="Go"
  package main

  import (
      "bytes"
      "encoding/json"
      "fmt"
      "net/http"
      "os"
  )

  func main() {
      token := os.Getenv("GODADDY_PAT")
      storeId := os.Getenv("STORE_ID")

      payload := map[string]any{
          "query":     "mutation ArchiveSku($id: String!) { archiveSku(id: $id) { id status } }",
          "variables": map[string]any{"id": "<SKU_UUID>"},
      }
      body, _ := json.Marshal(payload)

      url := fmt.Sprintf("https://api.godaddy.com/v2/commerce/stores/%s/catalog-subgraph", storeId)
      req, _ := http.NewRequest("POST", url, bytes.NewReader(body))
      req.Header.Set("Authorization", "Bearer "+token)
      req.Header.Set("x-store-id", storeId)
      req.Header.Set("Content-Type", "application/json")

      res, err := http.DefaultClient.Do(req)
      if err != nil { panic(err) }
      defer res.Body.Close()

      var result map[string]any
      json.NewDecoder(res.Body).Decode(&result)
      fmt.Println(result)
  }
  ```

## 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](https://developer.godaddy.com/docs/api-users/auth) 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.                                                                                                                    |

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.

```json
{
  "data": {
    "skuGroup": null
  }
}
```

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:

```graphql
# 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.
