> For the complete documentation index, see [llms.txt](https://the-wishlist-documentation.gitbook.io/the-wishlist-documentation-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://the-wishlist-documentation.gitbook.io/the-wishlist-documentation-docs/developer-reference/best-practices.md).

# Best Practices for Developers

## Customer data

* **Customer email address and mobile** fields must be unique.
* **customerRef** is your company's internal identifier. For **Shopify customers** it's the Shopify customer identifier. *Please ensure that your customerRef field has a consistent data type - if there is no customerRef, then don't just populate this with the customer's email address. Leave it blank.*
* **alternativeCustomerRef** is available if you have a **Secondary identifier** for customer's in your business. For example, if you're using a mix of platforms such as ERP, Marketing, ecommerce, or POS. However, we recommend you use the TWC CustomerID, customerRef or email to identify customers via our APIs.
* There are **2 customer marketing subscription statuses**, email optin/optout, and SMS optin/out. These are usually maintained in separate applications and imported via Shopify or your master company database via API integration. There are two exceptions:

1. If using our **inbuilt email engine**, opt-outs are captured by TWC and made available to your customer system of record via either API push from TWC or via webhook.
2. If using our **storePOS in-store application**, your staff can create and update customers. Usually we'll push to your customer system of record (eg Shopify) via direct API immediately after receiving the update.

* We display **Customer profile information in our StorePOS application** such as joined store. annual spend, loyalty status. We calculate some of these values based on sales history; most are loaded directly from your customer system of record. Please **contact us to discuss what you need so we make sure data is retrieved/calculated/displayed in storePOS**.

## Wishlists

* When **creating a wishlist** we recommend the following approach:

1. Check the customer exists using GET and the customer's email.
2. If you get a **404**, create the customer using the email, and then create the wishlist.
3. If the customer exists, use the customerID to create the wishlist

(For Shopify users, although TWC syncs customer details automatically, per Shopify's recommendations, there is a small chance that their webhook will not always fire, meaning TWC may not have the absolute latest data. For this reason we recommend checking by email, and if not successful, create the customer using a TWC API call)

[create-wishlist.png](https://github.com/The-Wishlist-Co/twc-api-specs/blob/main/docs/developer/assets/images/create-wishlist.png)

* **Wishlist name is an optional field, but recommended**. TWC doesn't default this value, so you may wish to do this in your code as it is displayed in reports.
* To **allow customers multiple wishlists**, set the default wishlist flag when saving a wishlist to identify a default wishlist. TWC doesn't set this flag automatically. We we also recommend selecting 'the least recent wishlist' as the default when retrieving and displaying wishlist items. This is particularly important if you're planning to integrate with a third-party app (eg legacy POS) that doesn't support multiple wishlists. If your POS only supports one wishlist, either set 'default wishlist' or 'display oldest wishlist in POS'.
* Items can only be added to an already created wishlist. Create the wishlist before adding items.
* **Always add items to wishlists at the VARIANT level, not the parent product level.**
* **Added from cart** Use this optional flag if an items is added from a shopping cart (eg as a save cart behaviour).
* When **adding an item in-store/POS**, include the ‘addedByStaff’ flag, the locationRef (storeID) and staffRef (staff ID) in the wishlist item record. Together, these 3 items are used to enable staff attribution and in reporting. (Note, there is an additional flag, noPostStore which disables the standard post-store visit notification for this item if the post store notification is enabled at a company level).
* For **sharing wishlists**, we recommend using the TWC WishlistID, and adding to the end of a share URL, eg <https://yourdomain.com/share-id/wishlistID>.
* We can **load wishlists from older systems** if you provide them in CSV (please contact us).
* There is generally no need to use wishlistItemRef. Use wishlistItemId as the primary means to identify wishlist items.

## Sales/orders and quotes

* Only **load sales that are identified with a customer record** (**Shopify customers**, this happens automatically unless disabled during setup). We don't need to store unidentified sales in TWC.
* Contact us if you're planning to **import sales via API**. We can advise which fields should be mapped, so your sales conversions are recorded and your reports are accurate.
* Also contact us if you wish to **manage quotes**; notifications are slightly different between quotes and quote lines when compared to orders and order lines.

## Products and variants

* *All products are expected to have a VARIANT structure, with a parent product identifier for each variant product.* The behaviour of our storePOS application is highly dependent on **clean product data**. We assume **colours and sizes are consistently mapped** across your product range.
* If you are using product bundling, this could impact our reporting. Please contact us if you wish to use bundling.
* Product notifications such as low stock and price drop will process whenever products are imported.
* Please reach out to us if you are planning to **import products via API**. We can advise which fields should be mapped, to ensure notifications payloads are correct and that product searching works correctly in our front-ends.
* For **Shopify customers** the product/variant updates are automatic unless specifically disabled.

## Locations and staff

* For **reporting**, we recommend loading your location file and staff files. Contact us for more details.
* For **Shopify customers** this happens automatically unless specifically disabled.

## General tips

* We suggest using **API endpoints** that allow either **Ref** or **ID** as variables when available. They're more recent and may perform better.
* Products don't need to exist in TWC to be saved to a wishlist.

### Data fields required to facilitate accurate reporting

The Wishlist Company provides KPI dashboard(s) and reports in the Store Console. We also provide some limited store-based reporting in our Wishlist InStore module. To ensure we can provide accurate reporting, we request that developers and those integrating data to our platform take the following into account:

* Please include your location and staff identifiers with wishlist, wishlist item, order and store transactions (we do this automatically for Shopify, Infinity and NewStore)
* All order headers should include a field for 'totalItems' to enable our average purchase size KPIs to work; total amount of order; processed time; (and location and staff identifiers); your customer identifier (customerRef) and ideally the customer's email
* Orderlines must have quantity, unit price and subtotal
* Returns and refunds are considered 'negative orders' with negative quantity and amounts
* Wishlist items should include the current price
* Products and variants must include your product and variant identifiers consistent with your website. All products and variants must have a description. Please include your variant upc in the 'barcode' field

Please contact us before uploading your data so that we can validate your data field mapping.

## Pagination

Where a Wishlist API is returning a list of items, we use pagination to limit the size of the return data set. Developers can set a page size parameter to adjust this value from the default of 20 items to up to 50 items, however if a list is longer than 50 items, additional GET(s) must be performed to get the remaining records. The Wishlist will always return records by ascending ID. For the 2nd and subsequent GET(s), developers need to pass the received "lastEvaluatedItemId" so that The Wishlist knows to return the next highest item as the first record in the next set.

To clarify, send the 'lastEvaluatedItemId' value as the value for the parameter 'lastItemId'.

This is a sample response:

```
    "id": "d12521d6-f202-4b4e-a2e4-c9dc5208df4f",
    "name": "Pink dress",
    "customerId": "6eb552bf-30fa-48d5-bf11-ed806af7969e",
    "customerRef": "9178080805174",
    "deleted": false,
    "createdTime": "2025-06-11T05:24:34.929889Z",
    "modifiedTime": "2025-06-12T13:24:52.247986Z",
    "lastEvaluatedItemId": "64730cd9-f234-41ba-9976-e4f8fda2925b",
    "itemCount": 23,
    "wishlistItems": [ ...
```
