Create a new Shopping List only in response to a meaningful user action, rather than preemptively. Recommended scenarios:
- When a user adds their first item to a new wishlist or shopping list.
 - When a user explicitly requests to create a new list (for example, setting up a new gift registry).
 
It's crucial to avoid unnecessary Shopping List creation to prevent database clutter and potential performance issues. Best practice dictates checking if a suitable list already exists for the user before creating a new one.
If no suitable list exists, you create one using a 
ShoppingListDraft object.The ShoppingListDraft object
This object contains all the initial information required for the new Shopping List.
Essential 
ShoppingListDraft Fields:name(LocalizedString): A user-friendly name for the list, supporting multiple languages.customerId(String) ORanonymousId(String): Crucial for associating the list with either a logged-in customer or an anonymous session. You must provide one, but not both.lineItems(Array ofShoppingListLineItemDraft) ORtextLineItems(Array ofTextLineItemDraft): You must provide at least one initial item (either a product or a text note) when creating the list.
Optional but Recommended 
ShoppingListDraft Fields:key(String): Assign a unique, user-defined key for business purposes, allowing retrieval without the list ID.store(StoreResourceIdentifier): Associate the list with a specific store. Note: This is used for the general endpoint; it should be omitted when using the in-store endpoint.slug(LocalizedString): Define a human-readable, URL-friendly identifier for the list.description(LocalizedString): Provide a description for the list.deleteDaysAfterLastModification(Number): Override the default period (if configured) after which the list is automatically deleted due to inactivity.custom(CustomFieldsDraft): Add custom fields for storing additional structured data specific to your project needs.businessUnit(BusinessUnitResourceIdentifier): Associate the list with a specific Business Unit.
Refer to the ShoppingListDraft Documentation for the complete list of fields and details.
TypeScript example: Building the ShoppingListDraft
This example demonstrates constructing a 
ShoppingListDraft for a logged-in customer, including various optional fields. import {
   ShoppingListDraft,
   LocalizedString,
   StoreResourceIdentifier, // Corrected import assumption
   ShoppingListLineItemDraft,
   TextLineItemDraft,
   CustomFieldsDraft,
   TypeResourceIdentifier,
   CustomerResourceIdentifier,
 } from '@commercetools/platform-sdk'; // Assuming imports are handled correctly
 /**
 * Draft object containing the data for the new shopping list.
 * @type {ShoppingListDraft}
 */
 const shoppingListDraft: ShoppingListDraft = {
  /**
   * The name of the shopping list (required).
   * Provide translations for different locales as needed.
   * @type {LocalizedString}
   */
  name: {
    'en': "My 100th Birthday Wishlist",
  },
   /**
   * Optional: A user-defined unique key for this shopping list.
   * Useful for retrieving the list later without knowing its ID.
   * @type {string | undefined}
   */
  key: 'birthday-wishlist-2025-john-doe',
   /**
   * Link this shopping list to a specific customer (required if no anonymousId).
   * Use either 'id' or 'key' to identify the customer.
   * Cannot be used simultaneously with 'anonymousId'.
   * @type {CustomerResourceIdentifier | undefined}
   */
  customer: {
    typeId: 'customer',
    id: 'eaf18adc-c61e-4f2c-9d04-b6b8ad51d998', // Replace with actual customer ID
  },
   /**
   * Optional: Link this shopping list to a specific store (used for general endpoint).
   * Use either 'id' or 'key' to identify the store.
   * Omit this field when using the in-store creation endpoint.
   * @type {StoreResourceIdentifier | undefined}
   */
  store: {
    typeId: 'store',
    key: 'dach', // <-- Replace with actual Store Key
  },
   /**
   * Optional: A description for the shopping list.
   * @type {LocalizedString | undefined}
   */
  description: {
    'en': 'Things I would love to receive for my birthday!',
  },
   /**
   * Optional: Add initial product line items (required if no textLineItems).
   * Identify products by 'productId' or 'sku'.
   * @type {ShoppingListLineItemDraft[] | undefined}
   */
  lineItems: [
    {
      productId: 'cc93fbab-d329-4000-93a0-cf6757ff89ea', // Replace with actual Product ID
      quantity: 1,
      variantId: 1, // Specify product variant
    },
    {
      sku: 'M0E20000000EG1V', // Replace with actual SKU
      quantity: 2,
    },
  ],
   /**
   * Optional: Add initial text line items (like notes) (required if no lineItems).
   * @type {TextLineItemDraft[] | undefined}
   */
  textLineItems: [
    {
      name: { 'en': 'Gift wrapping needed for item 1' },
      quantity: 1,
      // description: { 'en': 'Use the blue wrapping paper.' }, // Optional description
    },
  ],
   /**
   * Optional: If this list is for an anonymous user instead of a logged-in customer.
   * Provide this *instead* of the 'customer' field.
   * Cannot be used simultaneously with 'customer'.
   * @type {string | undefined}
   */
  // anonymousId: "replace-with-anonymous-session-id", // <-- Use this OR customer, not both
   /**
   * Optional: Set days until auto-deletion after last modification.
   * @type {number | undefined}
   */
  // deleteDaysAfterLastModification: 30,
   /**
   * Optional: Add Custom Fields if configured for ShoppingLists.
   * @type {CustomFieldsDraft | undefined}
   */
  // custom: {
  //   type: {
  //     typeId: "type",
  //     key: "my-shopping-list-custom-type-key" // <-- Replace with your custom type key
  //   },
  //   fields: {
  //     myCustomTextField: "Custom value example", // <-- Replace with your field names/values
  //     myCustomBooleanField: true
  //   }
  // }
 };
Creating the Shopping List via API
You can create the Shopping List using either the general API endpoint or a store-specific endpoint.
TypeScript example: Creating the Shopping List via general endpoint
Use this method when you're not using a store-specific context, or when explicitly setting the 
store field in the draft. // Assuming 'apiRoot' is your configured API client instance
 // Assuming 'shoppingListDraft' holds the draft object from the previous step
 apiRoot
 .shoppingLists()
 .post({
 /**
  * The data for the new shopping list.
  * @type {ShoppingListDraft}
  */
 body: shoppingListDraft,
 })
 .execute()
 .then((response) => {
 // On success, the response body contains the newly created ShoppingList object
 console.log('Successfully created shopping list:');
 console.log(JSON.stringify(response.body, null, 2)); // Pretty print the result
 })
 .catch((error) => {
 // Handle potential errors (for example, validation errors, duplicate key)
 console.error('Error creating shopping list:');
 // The error object often contains detailed information in error.body.errors
 console.error(JSON.stringify(error, null, 2));
 });
TypeScript example: Creating via in-store endpoint
Using the 
/in-store/key={storeKey}/shopping-lists endpoint automatically associates the list with the specified store.- Modification: Remove the 
storefield from theShoppingListDraftobject itself, as the store context is provided in the endpoint path. - API Call: Use the 
.inStoreKeyWithStoreKeyValue()method in your SDK call. 
First, ensure the 
store field is not present in your shoppingListDraft if you intend to use this endpoint. // Remove or comment out the 'store' field in your shoppingListDraft:
 /*
  store: {
    typeId: 'store',
    key: 'dach',
  },
 */
 // Assuming 'apiRoot' is your configured API client instance
 // Assuming 'shoppingListDraft' holds the draft object (without the 'store' field)
 const storeKey = 'dach'; // Replace with the actual Store Key
 apiRoot
 .inStoreKeyWithStoreKeyValue({ storeKey: storeKey }) // Specify the store context here
 .shoppingLists()
 .post({
   /**
    * The data for the new shopping list (without the 'store' field).
    * @type {ShoppingListDraft}
    */
   body: shoppingListDraft,
 })
 .execute()
 .then((response) => {
   console.log(
     `Successfully created shopping list in store '${storeKey}':`,
   );
   // The response body contains the created ShoppingList, now associated with the store.
   console.log(JSON.stringify(response.body, null, 2));
 })
 .catch((error) => {
   console.error(
     `Error creating shopping list in store '${storeKey}':`,
   );
   console.error(JSON.stringify(error, null, 2));
 });
Main steps for creation (using in-store endpoint)
- Input Validation: Ensure 
shoppingListDraftandstoreKeyare provided. - Build 
ShoppingListDraft: Construct the draft object, omitting thestorefield but including eithercustomerIdoranonymousId. - Perform API Call (In-Store): Send a 
POSTrequest using.inStoreKeyWithStoreKeyValue({ storeKey: storeKey })and the draft in the body. - Process Response: Parse the API response to get the created 
ShoppingListobject. - Error Handling: Implement 
try...catchto manage potential API errors. 
Creating a Shopping List for an anonymous user
When a user is not logged in, you can still create a Shopping List for them by providing an 
anonymousId instead of a customerId in the ShoppingListDraft. The anonymousId should be a unique identifier for the user's session (for example, generated using a UUID library and potentially stored in local storage or a cookie).The creation process using the API (either general or in-store endpoint) remains the same as shown above; just ensure the 
shoppingListDraft contains the anonymousId field and not the customer field.Example response: Created Shopping List (JSON)
Upon successful creation, the API returns the complete 
ShoppingList object. Here's an example structure: {
   "id": "generated-shopping-list-id",
   "version": 1,
   "name": {
     "en": "My 100th Birthday Wishlist"
   },
   "customer": { // Or "anonymousId": "session-id" if created anonymously
     "typeId": "customer",
     "id": "eaf18adc-c61e-4f2c-9d04-b6b8ad51d998"
   },
   "store": { // Present if created via general endpoint with store, or via in-store endpoint
     "typeId": "store",
     "key": "dach"
   },
   "key": "birthday-wishlist-2025-john-doe",
   "slug": { /* ... */ },
   "description": {
     "en": "Things I would love to receive for my birthday!"
   },
   "lineItems": [
     {
       "id": "generated-line-item-id-1",
       "productId": "cc93fbab-d329-4000-93a0-cf6757ff89ea",
       "name": { "en": "Product Name A" },
       "variantId": 1,
       "quantity": 1,
       "addedAt": "2025-05-01T10:35:58.000Z",
       "productType": { "typeId": "product-type", "id": "..." },
       "variant": { /* ... variant details ... */ }
       // ... other line item fields
     },
     {
       "id": "generated-line-item-id-2",
       "productId": "...", // Inferred from SKU during creation
       "name": { "en": "Product Name B" },
       "productSlug": { "en": "product-name-b" },
       "variantId": 1, // Inferred from SKU during creation
       "quantity": 2,
       "addedAt": "2025-05-01T10:35:58.000Z",
       "productType": { "typeId": "product-type", "id": "..." },
       "variant": { "id": 1, "sku": "M0E20000000EG1V", /* ... */ }
       // ... other line item fields
     }
   ],
   "textLineItems": [
     {
       "id": "generated-text-line-item-id",
       "name": { "en": "Gift wrapping needed for item 1" },
       "quantity": 1,
       "addedAt": "2025-05-01T10:35:58.000Z"
       // ... other text line item fields
     }
   ],
   "deleteDaysAfterLastModification": null, // Or the number set
   "custom": null, // Or custom fields object
   "createdAt": "2025-05-01T10:35:58.123Z",
   "lastModifiedAt": "2025-05-01T10:35:58.123Z"
 }