#Wishlists
These endpoints are called from a shopper's browser, so they take your publishable key rather than a secret one. Anything specific to one customer also takes a signed email and timestamp: see Identifying the customer for how to produce the signature.
GET /widgets/wishlists/for-product
List the current customer's wishlists plus whether each contains a product. The customer parameters are optional here: with the publishable key alone it returns the store's wishlist settings and an empty list, which is how the widget renders for a shopper who is not signed in
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)The signed-in shopper's address. Leave it out for a shopper who is not signed in.
timestampstringThe Unix seconds the signature was made at. Required with customerEmail.
signaturestringThe HMAC of the email and timestamp. Required with customerEmail.
productSlugstringrequiredSlug of the product. On Shopify this is the product handle.
curl \
"https://api.cascade.dev/widgets/wishlists/for-product?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&productSlug=string"import { client } from "@cascade-commerce/api/widget/client"
import { getWidgetsWishlistsForProduct } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await getWidgetsWishlistsForProduct({
query: { apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY", productSlug: "string" },
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists/for-product?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&productSlug=string")
req = Net::HTTP::Get.new(uri)
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
req = Request(
"https://api.cascade.dev/widgets/wishlists/for-product?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&productSlug=string",
)
with urlopen(req) as res:
print(json.load(res)){
"productSlug": "string",
"productFound": true,
"wishlists": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"itemsCount": 0,
"shared": true,
"shareUrl": "https://example.com",
"shareToken": "string",
"isDefault": true,
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"hasProduct": true,
"productItemId": "550e8400-e29b-41d4-a716-446655440000"
}
],
"sharingEnabled": true,
"multipleWishlists": true,
"itemImagesEnabled": true,
"defaultWishlistName": "string"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"productSlug": {
"type": "string"
},
"productFound": {
"type": "boolean"
},
"wishlists": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"itemsCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"shared": {
"type": "boolean",
"description": "Whether anyone with the share link can view the wishlist."
},
"shareUrl": {
"type": "string",
"format": "uri",
"description": "The public link to the wishlist. It only works while the wishlist is shared."
},
"shareToken": {
"type": "string",
"description": "The token in the share link, for building a product link that opens with the shopper's photo and note: `?cascadeWishlist=<shareToken>&cascadeItem=<itemId>`. Only meaningful while the wishlist is shared."
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the customer's default wishlist, the one one-click saves go to."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"hasProduct": {
"type": "boolean"
},
"productItemId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"name",
"itemsCount",
"shared",
"shareUrl",
"shareToken",
"isDefault",
"createdAt",
"updatedAt",
"hasProduct",
"productItemId"
],
"additionalProperties": false
}
},
"sharingEnabled": {
"type": "boolean",
"description": "Whether this store allows wishlist sharing at all. When false, hide every share control."
},
"multipleWishlists": {
"type": "boolean",
"description": "Whether this store lets a customer keep several wishlists. When false, everything they save goes on one list, so hide the controls for creating or naming another. Lists a customer already holds keep working either way."
},
"itemImagesEnabled": {
"type": "boolean",
"description": "Whether this store lets a signed-in customer attach their own photo to a saved item. When false, hide the photo picker; any photo already on an item comes back as null."
},
"defaultWishlistName": {
"type": "string",
"description": "The name this store gives a customer's first wishlist. A customer with no lists yet is shown one empty list under this name; nothing is saved until they use it."
}
},
"required": [
"productSlug",
"productFound",
"wishlists",
"sharingEnabled",
"multipleWishlists",
"itemImagesEnabled",
"defaultWishlistName"
],
"additionalProperties": false
}POST /widgets/wishlists/claim
Move the lists a shopper saved in their browser before signing in onto their customer record. When the store allows several lists, each browser list becomes a new wishlist and a name that is already taken gets a numbered suffix. When it keeps one list per customer, everything flattens into the default list. An item already on the target list is left exactly as it is. The whole claim succeeds or fails together, so the browser can keep its copy until the response confirms the merge
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)requiredEmail address of the customer the storefront signed in.
timestampstringrequiredUnix time in seconds when the signature was generated. It is accepted for 24 hours.
signaturestringrequiredHex HMAC-SHA256 of customerEmail followed by timestamp, keyed with your widget signing secret. See the widgets guide for the recipe.
Body Parameters
listsobject[]requiredThe lists the shopper built in their browser before signing in.
curl \
-X POST \
"https://api.cascade.dev/widgets/wishlists/claim?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081..." \
-H "Content-Type: application/json" \
-d '{
"lists": [
{
"name": "string",
"items": [
"..."
]
}
]
}'import { client } from "@cascade-commerce/api/widget/client"
import { postWidgetsWishlistsClaim } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await postWidgetsWishlistsClaim({
query: {
apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY",
customerEmail: "shopper@example.com",
timestamp: "1735689600",
signature: "9f86d081...",
},
body: {
lists: [
{
name: "string",
items: ["..."],
},
],
},
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists/claim?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...")
req = Net::HTTP::Post.new(uri)
req["Content-Type"] = "application/json"
req.body = <<~JSON
{
"lists": [
{
"name": "string",
"items": [
"..."
]
}
]
}
JSON
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
body = """{
"lists": [
{
"name": "string",
"items": [
"..."
]
}
]
}"""
req = Request(
"https://api.cascade.dev/widgets/wishlists/claim?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...",
data=body.encode(),
headers={"Content-Type": "application/json"},
)
with urlopen(req) as res:
print(json.load(res)){
"wishlists": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"itemsCount": 0,
"shared": true,
"shareUrl": "https://example.com",
"shareToken": "string",
"isDefault": true,
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
}
],
"sharingEnabled": true,
"multipleWishlists": true,
"itemImagesEnabled": true,
"claimedLists": 0,
"claimedItems": 0,
"skippedItems": 0
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"wishlists": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"itemsCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"shared": {
"type": "boolean",
"description": "Whether anyone with the share link can view the wishlist."
},
"shareUrl": {
"type": "string",
"format": "uri",
"description": "The public link to the wishlist. It only works while the wishlist is shared."
},
"shareToken": {
"type": "string",
"description": "The token in the share link, for building a product link that opens with the shopper's photo and note: `?cascadeWishlist=<shareToken>&cascadeItem=<itemId>`. Only meaningful while the wishlist is shared."
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the customer's default wishlist, the one one-click saves go to."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
}
},
"required": [
"id",
"name",
"itemsCount",
"shared",
"shareUrl",
"shareToken",
"isDefault",
"createdAt",
"updatedAt"
],
"additionalProperties": false
},
"description": "Every wishlist the customer holds after the claim."
},
"sharingEnabled": {
"type": "boolean",
"description": "Whether this store allows wishlist sharing at all. When false, hide every share control."
},
"multipleWishlists": {
"type": "boolean",
"description": "Whether this store lets a customer keep several wishlists. When false, everything they save goes on one list, so hide the controls for creating or naming another. Lists a customer already holds keep working either way."
},
"itemImagesEnabled": {
"type": "boolean",
"description": "Whether this store lets a signed-in customer attach their own photo to a saved item. When false, hide the photo picker; any photo already on an item comes back as null."
},
"claimedLists": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many new wishlists the claim created."
},
"claimedItems": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many items the claim added."
},
"skippedItems": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Items that were not added: already on the target list, repeated in the payload, or naming a product this store no longer has."
}
},
"required": [
"wishlists",
"sharingEnabled",
"multipleWishlists",
"itemImagesEnabled",
"claimedLists",
"claimedItems",
"skippedItems"
],
"additionalProperties": false
}POST /widgets/wishlists/upload-url
Get a link to upload a customer's own photo of a saved item. PUT the file's bytes to uploadUrl, then send key as imageKey when updating the item. Photos only, at most 5 MB, checked again once the bytes land. Refused while the store has photos on saved items switched off. Rate limited per address
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)requiredEmail address of the customer the storefront signed in.
timestampstringrequiredUnix time in seconds when the signature was generated. It is accepted for 24 hours.
signaturestringrequiredHex HMAC-SHA256 of customerEmail followed by timestamp, keyed with your widget signing secret. See the widgets guide for the recipe.
Body Parameters
fileNamestringrequiredThe file's name, kept for the dashboard.
contentTypeimage/jpeg | image/png | image/webp | image/gifrequiredThe file's MIME type. Photos only: JPEG, PNG, WebP or GIF.
sizeBytesnumberrequiredThe file's size in bytes. Photos can be at most 5 MB.
curl \
-X POST \
"https://api.cascade.dev/widgets/wishlists/upload-url?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081..." \
-H "Content-Type: application/json" \
-d '{
"fileName": "string",
"contentType": "image/jpeg",
"sizeBytes": 0
}'import { client } from "@cascade-commerce/api/widget/client"
import { postWidgetsWishlistsUploadUrl } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await postWidgetsWishlistsUploadUrl({
query: {
apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY",
customerEmail: "shopper@example.com",
timestamp: "1735689600",
signature: "9f86d081...",
},
body: {
fileName: "string",
contentType: "image/jpeg",
sizeBytes: 0,
},
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists/upload-url?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...")
req = Net::HTTP::Post.new(uri)
req["Content-Type"] = "application/json"
req.body = <<~JSON
{
"fileName": "string",
"contentType": "image/jpeg",
"sizeBytes": 0
}
JSON
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
body = """{
"fileName": "string",
"contentType": "image/jpeg",
"sizeBytes": 0
}"""
req = Request(
"https://api.cascade.dev/widgets/wishlists/upload-url?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...",
data=body.encode(),
headers={"Content-Type": "application/json"},
)
with urlopen(req) as res:
print(json.load(res)){
"key": "string",
"uploadUrl": "string",
"expiresAt": "2025-01-15T09:30:00Z"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Send this back as `imageKey` when you update the item. Nothing is shown until you do."
},
"uploadUrl": {
"type": "string",
"description": "PUT the file's bytes here. The link is good for five minutes."
},
"expiresAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the upload link stops working."
}
},
"required": ["key", "uploadUrl", "expiresAt"],
"additionalProperties": false
}GET /widgets/wishlists/banner
What a product page shows when somebody arrives from a shared wishlist link carrying cascadeWishlist and cascadeItem: the shopper's photo and note for that item, whose list it is, and a link to the whole list. No customer signature is needed. The answer is null whenever there is nothing to show: the list is private or sharing is off, the item is not this product, or it carries neither a photo nor a note
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
shareTokenstringrequiredThe cascadeWishlist value from the link the shopper arrived on.
itemIdstring (uuid)requiredThe cascadeItem value from the same link.
productSlugstringrequiredSlug of the product the page is showing. The banner only answers for a match.
curl \
"https://api.cascade.dev/widgets/wishlists/banner?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&shareToken=string&itemId=550e8400-e29b-41d4-a716-446655440000&productSlug=string"import { client } from "@cascade-commerce/api/widget/client"
import { getWidgetsWishlistsBanner } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await getWidgetsWishlistsBanner({
query: {
apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY",
shareToken: "string",
itemId: "550e8400-e29b-41d4-a716-446655440000",
productSlug: "string",
},
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists/banner?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&shareToken=string&itemId=550e8400-e29b-41d4-a716-446655440000&productSlug=string")
req = Net::HTTP::Get.new(uri)
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
req = Request(
"https://api.cascade.dev/widgets/wishlists/banner?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&shareToken=string&itemId=550e8400-e29b-41d4-a716-446655440000&productSlug=string",
)
with urlopen(req) as res:
print(json.load(res)){
"banner": {
"imageUrl": "string",
"note": "string",
"ownerFirstName": "string",
"wishlistName": "string",
"shareUrl": "https://example.com"
}
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"banner": {
"anyOf": [
{
"type": "object",
"properties": {
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The shopper's own photo of the item, or null if they added none or photos are off."
},
"note": {
"type": "string",
"description": "The shopper's note about the item, or an empty string."
},
"ownerFirstName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The list owner's first name for display, or null if they have none on file."
},
"wishlistName": {
"type": "string",
"description": "The wishlist's name, as the shopper typed it."
},
"shareUrl": {
"type": "string",
"format": "uri",
"description": "The public link to the whole list."
}
},
"required": ["imageUrl", "note", "ownerFirstName", "wishlistName", "shareUrl"],
"additionalProperties": false
},
{
"type": "null"
}
],
"description": "What to show, or null when there is nothing to show: the list is private, the item is not this product, or it carries neither a photo nor a note."
}
},
"required": ["banner"],
"additionalProperties": false
}POST /widgets/wishlists/default/toggle-item
Toggle a product on the customer's default wishlist, creating the default list on first use
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)requiredEmail address of the customer the storefront signed in.
timestampstringrequiredUnix time in seconds when the signature was generated. It is accepted for 24 hours.
signaturestringrequiredHex HMAC-SHA256 of customerEmail followed by timestamp, keyed with your widget signing secret. See the widgets guide for the recipe.
Body Parameters
productSlugstringrequiredSlug of the product. On Shopify this is the product handle.
curl \
-X POST \
"https://api.cascade.dev/widgets/wishlists/default/toggle-item?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081..." \
-H "Content-Type: application/json" \
-d '{
"productSlug": "string"
}'import { client } from "@cascade-commerce/api/widget/client"
import { postWidgetsWishlistsDefaultToggleItem } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await postWidgetsWishlistsDefaultToggleItem({
query: {
apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY",
customerEmail: "shopper@example.com",
timestamp: "1735689600",
signature: "9f86d081...",
},
body: {
productSlug: "string",
},
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists/default/toggle-item?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...")
req = Net::HTTP::Post.new(uri)
req["Content-Type"] = "application/json"
req.body = <<~JSON
{
"productSlug": "string"
}
JSON
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
body = """{
"productSlug": "string"
}"""
req = Request(
"https://api.cascade.dev/widgets/wishlists/default/toggle-item?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...",
data=body.encode(),
headers={"Content-Type": "application/json"},
)
with urlopen(req) as res:
print(json.load(res)){
"wishlist": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"itemsCount": 0,
"shared": true,
"shareUrl": "https://example.com",
"shareToken": "string",
"isDefault": true,
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"items": [
{
"id": "...",
"productId": "...",
"productVariantId": "...",
"quantity": "...",
"note": "...",
"imageUrl": "...",
"purchasedQuantity": "...",
"createdAt": "...",
"product": "...",
"variant": "..."
}
]
},
"added": true,
"sharingEnabled": true,
"multipleWishlists": true,
"itemImagesEnabled": true
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"wishlist": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"itemsCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"shared": {
"type": "boolean",
"description": "Whether anyone with the share link can view the wishlist."
},
"shareUrl": {
"type": "string",
"format": "uri",
"description": "The public link to the wishlist. It only works while the wishlist is shared."
},
"shareToken": {
"type": "string",
"description": "The token in the share link, for building a product link that opens with the shopper's photo and note: `?cascadeWishlist=<shareToken>&cascadeItem=<itemId>`. Only meaningful while the wishlist is shared."
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the customer's default wishlist, the one one-click saves go to."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productVariantId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"quantity": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "How many of this item the customer wants, or null if they did not say."
},
"note": {
"type": "string",
"description": "The customer's note about this item, such as a size or color preference."
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's own photo of the item, to show in place of the product image, or null if they added none or the store has photos switched off."
},
"purchasedQuantity": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many of this item the customer has bought themselves."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"product": {
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"title": {
"type": "string"
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "URL of the product's page on the storefront, or null if it is not known."
}
},
"required": ["slug", "title", "imageUrl", "url"],
"additionalProperties": false
},
"variant": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"slug": {
"type": "string"
},
"title": {
"type": "string"
}
},
"required": ["id", "slug", "title"],
"additionalProperties": false
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"productId",
"productVariantId",
"quantity",
"note",
"imageUrl",
"purchasedQuantity",
"createdAt",
"product",
"variant"
],
"additionalProperties": false
}
}
},
"required": [
"id",
"name",
"itemsCount",
"shared",
"shareUrl",
"shareToken",
"isDefault",
"createdAt",
"updatedAt",
"items"
],
"additionalProperties": false
},
"added": {
"type": "boolean",
"description": "True when the toggle put the product on the list, false when it took it off."
},
"sharingEnabled": {
"type": "boolean",
"description": "Whether this store allows wishlist sharing at all. When false, hide every share control."
},
"multipleWishlists": {
"type": "boolean",
"description": "Whether this store lets a customer keep several wishlists. When false, everything they save goes on one list, so hide the controls for creating or naming another. Lists a customer already holds keep working either way."
},
"itemImagesEnabled": {
"type": "boolean",
"description": "Whether this store lets a signed-in customer attach their own photo to a saved item. When false, hide the photo picker; any photo already on an item comes back as null."
}
},
"required": ["wishlist", "added", "sharingEnabled", "multipleWishlists", "itemImagesEnabled"],
"additionalProperties": false
}GET /widgets/wishlists
List the current customer's wishlists. The customer parameters are optional here: with the publishable key alone it returns the store's wishlist settings and an empty list, which is how the widget renders for a shopper who is not signed in
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)The signed-in shopper's address. Leave it out for a shopper who is not signed in.
timestampstringThe Unix seconds the signature was made at. Required with customerEmail.
signaturestringThe HMAC of the email and timestamp. Required with customerEmail.
curl \
"https://api.cascade.dev/widgets/wishlists?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY"import { client } from "@cascade-commerce/api/widget/client"
import { getWidgetsWishlists } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await getWidgetsWishlists({
query: { apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY" },
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY")
req = Net::HTTP::Get.new(uri)
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
req = Request(
"https://api.cascade.dev/widgets/wishlists?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY",
)
with urlopen(req) as res:
print(json.load(res)){
"wishlists": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"itemsCount": 0,
"shared": true,
"shareUrl": "https://example.com",
"shareToken": "string",
"isDefault": true,
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
}
],
"sharingEnabled": true,
"multipleWishlists": true,
"itemImagesEnabled": true,
"defaultWishlistName": "string"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"wishlists": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"itemsCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"shared": {
"type": "boolean",
"description": "Whether anyone with the share link can view the wishlist."
},
"shareUrl": {
"type": "string",
"format": "uri",
"description": "The public link to the wishlist. It only works while the wishlist is shared."
},
"shareToken": {
"type": "string",
"description": "The token in the share link, for building a product link that opens with the shopper's photo and note: `?cascadeWishlist=<shareToken>&cascadeItem=<itemId>`. Only meaningful while the wishlist is shared."
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the customer's default wishlist, the one one-click saves go to."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
}
},
"required": [
"id",
"name",
"itemsCount",
"shared",
"shareUrl",
"shareToken",
"isDefault",
"createdAt",
"updatedAt"
],
"additionalProperties": false
}
},
"sharingEnabled": {
"type": "boolean",
"description": "Whether this store allows wishlist sharing at all. When false, hide every share control."
},
"multipleWishlists": {
"type": "boolean",
"description": "Whether this store lets a customer keep several wishlists. When false, everything they save goes on one list, so hide the controls for creating or naming another. Lists a customer already holds keep working either way."
},
"itemImagesEnabled": {
"type": "boolean",
"description": "Whether this store lets a signed-in customer attach their own photo to a saved item. When false, hide the photo picker; any photo already on an item comes back as null."
},
"defaultWishlistName": {
"type": "string",
"description": "The name this store gives a customer's first wishlist. A customer with no lists yet is shown one empty list under this name; nothing is saved until they use it."
}
},
"required": [
"wishlists",
"sharingEnabled",
"multipleWishlists",
"itemImagesEnabled",
"defaultWishlistName"
],
"additionalProperties": false
}POST /widgets/wishlists
Create a new wishlist
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)requiredEmail address of the customer the storefront signed in.
timestampstringrequiredUnix time in seconds when the signature was generated. It is accepted for 24 hours.
signaturestringrequiredHex HMAC-SHA256 of customerEmail followed by timestamp, keyed with your widget signing secret. See the widgets guide for the recipe.
Body Parameters
namestringrequiredWhat the customer called the wishlist.
curl \
-X POST \
"https://api.cascade.dev/widgets/wishlists?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081..." \
-H "Content-Type: application/json" \
-d '{
"name": "string"
}'import { client } from "@cascade-commerce/api/widget/client"
import { postWidgetsWishlists } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await postWidgetsWishlists({
query: {
apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY",
customerEmail: "shopper@example.com",
timestamp: "1735689600",
signature: "9f86d081...",
},
body: {
name: "string",
},
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...")
req = Net::HTTP::Post.new(uri)
req["Content-Type"] = "application/json"
req.body = <<~JSON
{
"name": "string"
}
JSON
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
body = """{
"name": "string"
}"""
req = Request(
"https://api.cascade.dev/widgets/wishlists?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...",
data=body.encode(),
headers={"Content-Type": "application/json"},
)
with urlopen(req) as res:
print(json.load(res)){
"wishlist": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"itemsCount": 0,
"shared": true,
"shareUrl": "https://example.com",
"shareToken": "string",
"isDefault": true,
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"items": [
{
"id": "...",
"productId": "...",
"productVariantId": "...",
"quantity": "...",
"note": "...",
"imageUrl": "...",
"purchasedQuantity": "...",
"createdAt": "...",
"product": "...",
"variant": "..."
}
]
},
"sharingEnabled": true,
"multipleWishlists": true,
"itemImagesEnabled": true
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"wishlist": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"itemsCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"shared": {
"type": "boolean",
"description": "Whether anyone with the share link can view the wishlist."
},
"shareUrl": {
"type": "string",
"format": "uri",
"description": "The public link to the wishlist. It only works while the wishlist is shared."
},
"shareToken": {
"type": "string",
"description": "The token in the share link, for building a product link that opens with the shopper's photo and note: `?cascadeWishlist=<shareToken>&cascadeItem=<itemId>`. Only meaningful while the wishlist is shared."
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the customer's default wishlist, the one one-click saves go to."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productVariantId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"quantity": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "How many of this item the customer wants, or null if they did not say."
},
"note": {
"type": "string",
"description": "The customer's note about this item, such as a size or color preference."
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's own photo of the item, to show in place of the product image, or null if they added none or the store has photos switched off."
},
"purchasedQuantity": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many of this item the customer has bought themselves."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"product": {
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"title": {
"type": "string"
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "URL of the product's page on the storefront, or null if it is not known."
}
},
"required": ["slug", "title", "imageUrl", "url"],
"additionalProperties": false
},
"variant": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"slug": {
"type": "string"
},
"title": {
"type": "string"
}
},
"required": ["id", "slug", "title"],
"additionalProperties": false
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"productId",
"productVariantId",
"quantity",
"note",
"imageUrl",
"purchasedQuantity",
"createdAt",
"product",
"variant"
],
"additionalProperties": false
}
}
},
"required": [
"id",
"name",
"itemsCount",
"shared",
"shareUrl",
"shareToken",
"isDefault",
"createdAt",
"updatedAt",
"items"
],
"additionalProperties": false
},
"sharingEnabled": {
"type": "boolean",
"description": "Whether this store allows wishlist sharing at all. When false, hide every share control."
},
"multipleWishlists": {
"type": "boolean",
"description": "Whether this store lets a customer keep several wishlists. When false, everything they save goes on one list, so hide the controls for creating or naming another. Lists a customer already holds keep working either way."
},
"itemImagesEnabled": {
"type": "boolean",
"description": "Whether this store lets a signed-in customer attach their own photo to a saved item. When false, hide the photo picker; any photo already on an item comes back as null."
}
},
"required": ["wishlist", "sharingEnabled", "multipleWishlists", "itemImagesEnabled"],
"additionalProperties": false
}GET /widgets/wishlists/{id}
Get a wishlist with its items
Path Parameters
idstring (uuid)requiredThe ID of the wishlist.
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)requiredEmail address of the customer the storefront signed in.
timestampstringrequiredUnix time in seconds when the signature was generated. It is accepted for 24 hours.
signaturestringrequiredHex HMAC-SHA256 of customerEmail followed by timestamp, keyed with your widget signing secret. See the widgets guide for the recipe.
curl \
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081..."import { client } from "@cascade-commerce/api/widget/client"
import { getWidgetsWishlistsById } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await getWidgetsWishlistsById({
path: { id: "550e8400-e29b-41d4-a716-446655440000" },
query: {
apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY",
customerEmail: "shopper@example.com",
timestamp: "1735689600",
signature: "9f86d081...",
},
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...")
req = Net::HTTP::Get.new(uri)
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
req = Request(
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...",
)
with urlopen(req) as res:
print(json.load(res)){
"wishlist": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"itemsCount": 0,
"shared": true,
"shareUrl": "https://example.com",
"shareToken": "string",
"isDefault": true,
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"items": [
{
"id": "...",
"productId": "...",
"productVariantId": "...",
"quantity": "...",
"note": "...",
"imageUrl": "...",
"purchasedQuantity": "...",
"createdAt": "...",
"product": "...",
"variant": "..."
}
]
},
"sharingEnabled": true,
"multipleWishlists": true,
"itemImagesEnabled": true
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"wishlist": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"itemsCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"shared": {
"type": "boolean",
"description": "Whether anyone with the share link can view the wishlist."
},
"shareUrl": {
"type": "string",
"format": "uri",
"description": "The public link to the wishlist. It only works while the wishlist is shared."
},
"shareToken": {
"type": "string",
"description": "The token in the share link, for building a product link that opens with the shopper's photo and note: `?cascadeWishlist=<shareToken>&cascadeItem=<itemId>`. Only meaningful while the wishlist is shared."
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the customer's default wishlist, the one one-click saves go to."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productVariantId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"quantity": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "How many of this item the customer wants, or null if they did not say."
},
"note": {
"type": "string",
"description": "The customer's note about this item, such as a size or color preference."
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's own photo of the item, to show in place of the product image, or null if they added none or the store has photos switched off."
},
"purchasedQuantity": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many of this item the customer has bought themselves."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"product": {
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"title": {
"type": "string"
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "URL of the product's page on the storefront, or null if it is not known."
}
},
"required": ["slug", "title", "imageUrl", "url"],
"additionalProperties": false
},
"variant": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"slug": {
"type": "string"
},
"title": {
"type": "string"
}
},
"required": ["id", "slug", "title"],
"additionalProperties": false
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"productId",
"productVariantId",
"quantity",
"note",
"imageUrl",
"purchasedQuantity",
"createdAt",
"product",
"variant"
],
"additionalProperties": false
}
}
},
"required": [
"id",
"name",
"itemsCount",
"shared",
"shareUrl",
"shareToken",
"isDefault",
"createdAt",
"updatedAt",
"items"
],
"additionalProperties": false
},
"sharingEnabled": {
"type": "boolean",
"description": "Whether this store allows wishlist sharing at all. When false, hide every share control."
},
"multipleWishlists": {
"type": "boolean",
"description": "Whether this store lets a customer keep several wishlists. When false, everything they save goes on one list, so hide the controls for creating or naming another. Lists a customer already holds keep working either way."
},
"itemImagesEnabled": {
"type": "boolean",
"description": "Whether this store lets a signed-in customer attach their own photo to a saved item. When false, hide the photo picker; any photo already on an item comes back as null."
}
},
"required": ["wishlist", "sharingEnabled", "multipleWishlists", "itemImagesEnabled"],
"additionalProperties": false
}PATCH /widgets/wishlists/{id}
Update a wishlist's settings: its name or whether it is shared
Path Parameters
idstring (uuid)requiredThe ID of the wishlist.
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)requiredEmail address of the customer the storefront signed in.
timestampstringrequiredUnix time in seconds when the signature was generated. It is accepted for 24 hours.
signaturestringrequiredHex HMAC-SHA256 of customerEmail followed by timestamp, keyed with your widget signing secret. See the widgets guide for the recipe.
Body Parameters
namestringA new name for the wishlist.
sharedbooleanTurns the wishlist's share link on or off.
isDefaultbooleanMakes this wishlist the customer's default for one-click saves. Send false to leave the customer without a default.
curl \
-X PATCH \
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081..." \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"shared": true,
"isDefault": true
}'import { client } from "@cascade-commerce/api/widget/client"
import { patchWidgetsWishlistsById } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await patchWidgetsWishlistsById({
path: { id: "550e8400-e29b-41d4-a716-446655440000" },
query: {
apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY",
customerEmail: "shopper@example.com",
timestamp: "1735689600",
signature: "9f86d081...",
},
body: {
name: "string",
shared: true,
isDefault: true,
},
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...")
req = Net::HTTP::Patch.new(uri)
req["Content-Type"] = "application/json"
req.body = <<~JSON
{
"name": "string",
"shared": true,
"isDefault": true
}
JSON
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
body = """{
"name": "string",
"shared": true,
"isDefault": true
}"""
req = Request(
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...",
data=body.encode(),
method="PATCH",
headers={"Content-Type": "application/json"},
)
with urlopen(req) as res:
print(json.load(res)){
"wishlist": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"itemsCount": 0,
"shared": true,
"shareUrl": "https://example.com",
"shareToken": "string",
"isDefault": true,
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"items": [
{
"id": "...",
"productId": "...",
"productVariantId": "...",
"quantity": "...",
"note": "...",
"imageUrl": "...",
"purchasedQuantity": "...",
"createdAt": "...",
"product": "...",
"variant": "..."
}
]
},
"sharingEnabled": true,
"multipleWishlists": true,
"itemImagesEnabled": true
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"wishlist": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"itemsCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"shared": {
"type": "boolean",
"description": "Whether anyone with the share link can view the wishlist."
},
"shareUrl": {
"type": "string",
"format": "uri",
"description": "The public link to the wishlist. It only works while the wishlist is shared."
},
"shareToken": {
"type": "string",
"description": "The token in the share link, for building a product link that opens with the shopper's photo and note: `?cascadeWishlist=<shareToken>&cascadeItem=<itemId>`. Only meaningful while the wishlist is shared."
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the customer's default wishlist, the one one-click saves go to."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productVariantId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"quantity": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "How many of this item the customer wants, or null if they did not say."
},
"note": {
"type": "string",
"description": "The customer's note about this item, such as a size or color preference."
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's own photo of the item, to show in place of the product image, or null if they added none or the store has photos switched off."
},
"purchasedQuantity": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many of this item the customer has bought themselves."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"product": {
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"title": {
"type": "string"
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "URL of the product's page on the storefront, or null if it is not known."
}
},
"required": ["slug", "title", "imageUrl", "url"],
"additionalProperties": false
},
"variant": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"slug": {
"type": "string"
},
"title": {
"type": "string"
}
},
"required": ["id", "slug", "title"],
"additionalProperties": false
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"productId",
"productVariantId",
"quantity",
"note",
"imageUrl",
"purchasedQuantity",
"createdAt",
"product",
"variant"
],
"additionalProperties": false
}
}
},
"required": [
"id",
"name",
"itemsCount",
"shared",
"shareUrl",
"shareToken",
"isDefault",
"createdAt",
"updatedAt",
"items"
],
"additionalProperties": false
},
"sharingEnabled": {
"type": "boolean",
"description": "Whether this store allows wishlist sharing at all. When false, hide every share control."
},
"multipleWishlists": {
"type": "boolean",
"description": "Whether this store lets a customer keep several wishlists. When false, everything they save goes on one list, so hide the controls for creating or naming another. Lists a customer already holds keep working either way."
},
"itemImagesEnabled": {
"type": "boolean",
"description": "Whether this store lets a signed-in customer attach their own photo to a saved item. When false, hide the photo picker; any photo already on an item comes back as null."
}
},
"required": ["wishlist", "sharingEnabled", "multipleWishlists", "itemImagesEnabled"],
"additionalProperties": false
}DELETE /widgets/wishlists/{id}
Delete a wishlist
Path Parameters
idstring (uuid)requiredThe ID of the wishlist.
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)requiredEmail address of the customer the storefront signed in.
timestampstringrequiredUnix time in seconds when the signature was generated. It is accepted for 24 hours.
signaturestringrequiredHex HMAC-SHA256 of customerEmail followed by timestamp, keyed with your widget signing secret. See the widgets guide for the recipe.
curl \
-X DELETE \
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081..."import { client } from "@cascade-commerce/api/widget/client"
import { deleteWidgetsWishlistsById } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await deleteWidgetsWishlistsById({
path: { id: "550e8400-e29b-41d4-a716-446655440000" },
query: {
apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY",
customerEmail: "shopper@example.com",
timestamp: "1735689600",
signature: "9f86d081...",
},
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...")
req = Net::HTTP::Delete.new(uri)
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
req = Request(
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...",
method="DELETE",
)
with urlopen(req) as res:
print(json.load(res)){
"id": "550e8400-e29b-41d4-a716-446655440000"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
},
"required": ["id"],
"additionalProperties": false
}POST /widgets/wishlists/{id}/share-token
Generate a new share token for a wishlist, invalidating the old share link
Path Parameters
idstring (uuid)requiredThe ID of the wishlist.
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)requiredEmail address of the customer the storefront signed in.
timestampstringrequiredUnix time in seconds when the signature was generated. It is accepted for 24 hours.
signaturestringrequiredHex HMAC-SHA256 of customerEmail followed by timestamp, keyed with your widget signing secret. See the widgets guide for the recipe.
curl \
-X POST \
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000/share-token?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081..."import { client } from "@cascade-commerce/api/widget/client"
import { postWidgetsWishlistsByIdShareToken } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await postWidgetsWishlistsByIdShareToken({
path: { id: "550e8400-e29b-41d4-a716-446655440000" },
query: {
apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY",
customerEmail: "shopper@example.com",
timestamp: "1735689600",
signature: "9f86d081...",
},
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000/share-token?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...")
req = Net::HTTP::Post.new(uri)
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
req = Request(
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000/share-token?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...",
method="POST",
)
with urlopen(req) as res:
print(json.load(res)){
"wishlist": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"itemsCount": 0,
"shared": true,
"shareUrl": "https://example.com",
"shareToken": "string",
"isDefault": true,
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"items": [
{
"id": "...",
"productId": "...",
"productVariantId": "...",
"quantity": "...",
"note": "...",
"imageUrl": "...",
"purchasedQuantity": "...",
"createdAt": "...",
"product": "...",
"variant": "..."
}
]
},
"sharingEnabled": true,
"multipleWishlists": true,
"itemImagesEnabled": true
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"wishlist": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"itemsCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"shared": {
"type": "boolean",
"description": "Whether anyone with the share link can view the wishlist."
},
"shareUrl": {
"type": "string",
"format": "uri",
"description": "The public link to the wishlist. It only works while the wishlist is shared."
},
"shareToken": {
"type": "string",
"description": "The token in the share link, for building a product link that opens with the shopper's photo and note: `?cascadeWishlist=<shareToken>&cascadeItem=<itemId>`. Only meaningful while the wishlist is shared."
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the customer's default wishlist, the one one-click saves go to."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productVariantId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"quantity": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "How many of this item the customer wants, or null if they did not say."
},
"note": {
"type": "string",
"description": "The customer's note about this item, such as a size or color preference."
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's own photo of the item, to show in place of the product image, or null if they added none or the store has photos switched off."
},
"purchasedQuantity": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many of this item the customer has bought themselves."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"product": {
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"title": {
"type": "string"
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "URL of the product's page on the storefront, or null if it is not known."
}
},
"required": ["slug", "title", "imageUrl", "url"],
"additionalProperties": false
},
"variant": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"slug": {
"type": "string"
},
"title": {
"type": "string"
}
},
"required": ["id", "slug", "title"],
"additionalProperties": false
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"productId",
"productVariantId",
"quantity",
"note",
"imageUrl",
"purchasedQuantity",
"createdAt",
"product",
"variant"
],
"additionalProperties": false
}
}
},
"required": [
"id",
"name",
"itemsCount",
"shared",
"shareUrl",
"shareToken",
"isDefault",
"createdAt",
"updatedAt",
"items"
],
"additionalProperties": false
},
"sharingEnabled": {
"type": "boolean",
"description": "Whether this store allows wishlist sharing at all. When false, hide every share control."
},
"multipleWishlists": {
"type": "boolean",
"description": "Whether this store lets a customer keep several wishlists. When false, everything they save goes on one list, so hide the controls for creating or naming another. Lists a customer already holds keep working either way."
},
"itemImagesEnabled": {
"type": "boolean",
"description": "Whether this store lets a signed-in customer attach their own photo to a saved item. When false, hide the photo picker; any photo already on an item comes back as null."
}
},
"required": ["wishlist", "sharingEnabled", "multipleWishlists", "itemImagesEnabled"],
"additionalProperties": false
}POST /widgets/wishlists/{id}/items
Add an item to a wishlist
Path Parameters
idstring (uuid)requiredThe ID of the wishlist.
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)requiredEmail address of the customer the storefront signed in.
timestampstringrequiredUnix time in seconds when the signature was generated. It is accepted for 24 hours.
signaturestringrequiredHex HMAC-SHA256 of customerEmail followed by timestamp, keyed with your widget signing secret. See the widgets guide for the recipe.
Body Parameters
productSlugstringrequiredSlug of the product. On Shopify this is the product handle.
productVariantIdstring (uuid) | nullThe variant the customer chose, or null to save the product as a whole.
quantityinteger | nullHow many of this item the customer wants. Leave it out if they did not say.
notestringA short note about this item, such as a size or color preference.
curl \
-X POST \
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000/items?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081..." \
-H "Content-Type: application/json" \
-d '{
"productSlug": "string",
"productVariantId": "550e8400-e29b-41d4-a716-446655440000",
"quantity": 0,
"note": "string"
}'import { client } from "@cascade-commerce/api/widget/client"
import { postWidgetsWishlistsByIdItems } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await postWidgetsWishlistsByIdItems({
path: { id: "550e8400-e29b-41d4-a716-446655440000" },
query: {
apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY",
customerEmail: "shopper@example.com",
timestamp: "1735689600",
signature: "9f86d081...",
},
body: {
productSlug: "string",
productVariantId: "550e8400-e29b-41d4-a716-446655440000",
quantity: 0,
note: "string",
},
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000/items?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...")
req = Net::HTTP::Post.new(uri)
req["Content-Type"] = "application/json"
req.body = <<~JSON
{
"productSlug": "string",
"productVariantId": "550e8400-e29b-41d4-a716-446655440000",
"quantity": 0,
"note": "string"
}
JSON
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
body = """{
"productSlug": "string",
"productVariantId": "550e8400-e29b-41d4-a716-446655440000",
"quantity": 0,
"note": "string"
}"""
req = Request(
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000/items?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...",
data=body.encode(),
headers={"Content-Type": "application/json"},
)
with urlopen(req) as res:
print(json.load(res)){
"wishlist": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"itemsCount": 0,
"shared": true,
"shareUrl": "https://example.com",
"shareToken": "string",
"isDefault": true,
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"items": [
{
"id": "...",
"productId": "...",
"productVariantId": "...",
"quantity": "...",
"note": "...",
"imageUrl": "...",
"purchasedQuantity": "...",
"createdAt": "...",
"product": "...",
"variant": "..."
}
]
},
"sharingEnabled": true,
"multipleWishlists": true,
"itemImagesEnabled": true
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"wishlist": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"itemsCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"shared": {
"type": "boolean",
"description": "Whether anyone with the share link can view the wishlist."
},
"shareUrl": {
"type": "string",
"format": "uri",
"description": "The public link to the wishlist. It only works while the wishlist is shared."
},
"shareToken": {
"type": "string",
"description": "The token in the share link, for building a product link that opens with the shopper's photo and note: `?cascadeWishlist=<shareToken>&cascadeItem=<itemId>`. Only meaningful while the wishlist is shared."
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the customer's default wishlist, the one one-click saves go to."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productVariantId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"quantity": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "How many of this item the customer wants, or null if they did not say."
},
"note": {
"type": "string",
"description": "The customer's note about this item, such as a size or color preference."
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's own photo of the item, to show in place of the product image, or null if they added none or the store has photos switched off."
},
"purchasedQuantity": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many of this item the customer has bought themselves."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"product": {
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"title": {
"type": "string"
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "URL of the product's page on the storefront, or null if it is not known."
}
},
"required": ["slug", "title", "imageUrl", "url"],
"additionalProperties": false
},
"variant": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"slug": {
"type": "string"
},
"title": {
"type": "string"
}
},
"required": ["id", "slug", "title"],
"additionalProperties": false
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"productId",
"productVariantId",
"quantity",
"note",
"imageUrl",
"purchasedQuantity",
"createdAt",
"product",
"variant"
],
"additionalProperties": false
}
}
},
"required": [
"id",
"name",
"itemsCount",
"shared",
"shareUrl",
"shareToken",
"isDefault",
"createdAt",
"updatedAt",
"items"
],
"additionalProperties": false
},
"sharingEnabled": {
"type": "boolean",
"description": "Whether this store allows wishlist sharing at all. When false, hide every share control."
},
"multipleWishlists": {
"type": "boolean",
"description": "Whether this store lets a customer keep several wishlists. When false, everything they save goes on one list, so hide the controls for creating or naming another. Lists a customer already holds keep working either way."
},
"itemImagesEnabled": {
"type": "boolean",
"description": "Whether this store lets a signed-in customer attach their own photo to a saved item. When false, hide the photo picker; any photo already on an item comes back as null."
}
},
"required": ["wishlist", "sharingEnabled", "multipleWishlists", "itemImagesEnabled"],
"additionalProperties": false
}PATCH /widgets/wishlists/{id}/items/{itemId}
Update an item's quantity, note or photo, or move it to another of the customer's wishlists
Path Parameters
idstring (uuid)requiredThe ID of the wishlist the item is on.
itemIdstring (uuid)requiredThe ID of the wishlist item.
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)requiredEmail address of the customer the storefront signed in.
timestampstringrequiredUnix time in seconds when the signature was generated. It is accepted for 24 hours.
signaturestringrequiredHex HMAC-SHA256 of customerEmail followed by timestamp, keyed with your widget signing secret. See the widgets guide for the recipe.
Body Parameters
quantityinteger | nullHow many of this item the customer wants. Send null to clear it.
notestringA short note about this item, such as a size or color preference. Send an empty string to clear it.
imageKeystring | nullThe key from POST /widgets/wishlists/upload-url, to attach the customer's own photo to the item. It replaces any photo already there. Send null to take the photo off. Refused while the store has photos on saved items switched off.
wishlistIdstring (uuid)Moves the item to this wishlist, which must belong to the same customer. Any quantity or note edits in the same request are applied first. If the target list already has the same product and variant, the two entries merge: the target entry stays, keeps its quantity, and the moved item's note is appended to its note.
curl \
-X PATCH \
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000/items/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081..." \
-H "Content-Type: application/json" \
-d '{
"quantity": 0,
"note": "string",
"imageKey": "string",
"wishlistId": "550e8400-e29b-41d4-a716-446655440000"
}'import { client } from "@cascade-commerce/api/widget/client"
import { patchWidgetsWishlistsByIdItemsByItemId } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await patchWidgetsWishlistsByIdItemsByItemId({
path: {
id: "550e8400-e29b-41d4-a716-446655440000",
itemId: "550e8400-e29b-41d4-a716-446655440000",
},
query: {
apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY",
customerEmail: "shopper@example.com",
timestamp: "1735689600",
signature: "9f86d081...",
},
body: {
quantity: 0,
note: "string",
imageKey: "string",
wishlistId: "550e8400-e29b-41d4-a716-446655440000",
},
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000/items/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...")
req = Net::HTTP::Patch.new(uri)
req["Content-Type"] = "application/json"
req.body = <<~JSON
{
"quantity": 0,
"note": "string",
"imageKey": "string",
"wishlistId": "550e8400-e29b-41d4-a716-446655440000"
}
JSON
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
body = """{
"quantity": 0,
"note": "string",
"imageKey": "string",
"wishlistId": "550e8400-e29b-41d4-a716-446655440000"
}"""
req = Request(
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000/items/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...",
data=body.encode(),
method="PATCH",
headers={"Content-Type": "application/json"},
)
with urlopen(req) as res:
print(json.load(res)){
"wishlist": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"itemsCount": 0,
"shared": true,
"shareUrl": "https://example.com",
"shareToken": "string",
"isDefault": true,
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"items": [
{
"id": "...",
"productId": "...",
"productVariantId": "...",
"quantity": "...",
"note": "...",
"imageUrl": "...",
"purchasedQuantity": "...",
"createdAt": "...",
"product": "...",
"variant": "..."
}
]
},
"sharingEnabled": true,
"multipleWishlists": true,
"itemImagesEnabled": true
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"wishlist": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"itemsCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"shared": {
"type": "boolean",
"description": "Whether anyone with the share link can view the wishlist."
},
"shareUrl": {
"type": "string",
"format": "uri",
"description": "The public link to the wishlist. It only works while the wishlist is shared."
},
"shareToken": {
"type": "string",
"description": "The token in the share link, for building a product link that opens with the shopper's photo and note: `?cascadeWishlist=<shareToken>&cascadeItem=<itemId>`. Only meaningful while the wishlist is shared."
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the customer's default wishlist, the one one-click saves go to."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productVariantId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"quantity": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "How many of this item the customer wants, or null if they did not say."
},
"note": {
"type": "string",
"description": "The customer's note about this item, such as a size or color preference."
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's own photo of the item, to show in place of the product image, or null if they added none or the store has photos switched off."
},
"purchasedQuantity": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many of this item the customer has bought themselves."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"product": {
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"title": {
"type": "string"
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "URL of the product's page on the storefront, or null if it is not known."
}
},
"required": ["slug", "title", "imageUrl", "url"],
"additionalProperties": false
},
"variant": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"slug": {
"type": "string"
},
"title": {
"type": "string"
}
},
"required": ["id", "slug", "title"],
"additionalProperties": false
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"productId",
"productVariantId",
"quantity",
"note",
"imageUrl",
"purchasedQuantity",
"createdAt",
"product",
"variant"
],
"additionalProperties": false
}
}
},
"required": [
"id",
"name",
"itemsCount",
"shared",
"shareUrl",
"shareToken",
"isDefault",
"createdAt",
"updatedAt",
"items"
],
"additionalProperties": false
},
"sharingEnabled": {
"type": "boolean",
"description": "Whether this store allows wishlist sharing at all. When false, hide every share control."
},
"multipleWishlists": {
"type": "boolean",
"description": "Whether this store lets a customer keep several wishlists. When false, everything they save goes on one list, so hide the controls for creating or naming another. Lists a customer already holds keep working either way."
},
"itemImagesEnabled": {
"type": "boolean",
"description": "Whether this store lets a signed-in customer attach their own photo to a saved item. When false, hide the photo picker; any photo already on an item comes back as null."
}
},
"required": ["wishlist", "sharingEnabled", "multipleWishlists", "itemImagesEnabled"],
"additionalProperties": false
}DELETE /widgets/wishlists/{id}/items/{itemId}
Remove an item from a wishlist
Path Parameters
idstring (uuid)requiredThe ID of the wishlist the item is on.
itemIdstring (uuid)requiredThe ID of the wishlist item.
Query Parameters
apiPublishableKeystringrequiredYour organization's publishable key, from Settings, API keys.
customerEmailstring (email)requiredEmail address of the customer the storefront signed in.
timestampstringrequiredUnix time in seconds when the signature was generated. It is accepted for 24 hours.
signaturestringrequiredHex HMAC-SHA256 of customerEmail followed by timestamp, keyed with your widget signing secret. See the widgets guide for the recipe.
curl \
-X DELETE \
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000/items/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081..."import { client } from "@cascade-commerce/api/widget/client"
import { deleteWidgetsWishlistsByIdItemsByItemId } from "@cascade-commerce/api/widget"
client.setConfig({
baseUrl: "https://api.cascade.dev",
})
const { data, error } = await deleteWidgetsWishlistsByIdItemsByItemId({
path: {
id: "550e8400-e29b-41d4-a716-446655440000",
itemId: "550e8400-e29b-41d4-a716-446655440000",
},
query: {
apiPublishableKey: "pk_YOUR_PUBLISHABLE_KEY",
customerEmail: "shopper@example.com",
timestamp: "1735689600",
signature: "9f86d081...",
},
})require "net/http"
uri = URI("https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000/items/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...")
req = Net::HTTP::Delete.new(uri)
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyimport json
from urllib.request import Request, urlopen
req = Request(
"https://api.cascade.dev/widgets/wishlists/550e8400-e29b-41d4-a716-446655440000/items/550e8400-e29b-41d4-a716-446655440000?apiPublishableKey=pk_YOUR_PUBLISHABLE_KEY&customerEmail=shopper%40example.com×tamp=1735689600&signature=9f86d081...",
method="DELETE",
)
with urlopen(req) as res:
print(json.load(res)){
"wishlist": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "string",
"itemsCount": 0,
"shared": true,
"shareUrl": "https://example.com",
"shareToken": "string",
"isDefault": true,
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"items": [
{
"id": "...",
"productId": "...",
"productVariantId": "...",
"quantity": "...",
"note": "...",
"imageUrl": "...",
"purchasedQuantity": "...",
"createdAt": "...",
"product": "...",
"variant": "..."
}
]
},
"sharingEnabled": true,
"multipleWishlists": true,
"itemImagesEnabled": true
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"wishlist": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"itemsCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"shared": {
"type": "boolean",
"description": "Whether anyone with the share link can view the wishlist."
},
"shareUrl": {
"type": "string",
"format": "uri",
"description": "The public link to the wishlist. It only works while the wishlist is shared."
},
"shareToken": {
"type": "string",
"description": "The token in the share link, for building a product link that opens with the shopper's photo and note: `?cascadeWishlist=<shareToken>&cascadeItem=<itemId>`. Only meaningful while the wishlist is shared."
},
"isDefault": {
"type": "boolean",
"description": "Whether this is the customer's default wishlist, the one one-click saves go to."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"productVariantId": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"quantity": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "How many of this item the customer wants, or null if they did not say."
},
"note": {
"type": "string",
"description": "The customer's note about this item, such as a size or color preference."
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's own photo of the item, to show in place of the product image, or null if they added none or the store has photos switched off."
},
"purchasedQuantity": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many of this item the customer has bought themselves."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"product": {
"type": "object",
"properties": {
"slug": {
"type": "string"
},
"title": {
"type": "string"
},
"imageUrl": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "URL of the product's page on the storefront, or null if it is not known."
}
},
"required": ["slug", "title", "imageUrl", "url"],
"additionalProperties": false
},
"variant": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"slug": {
"type": "string"
},
"title": {
"type": "string"
}
},
"required": ["id", "slug", "title"],
"additionalProperties": false
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"productId",
"productVariantId",
"quantity",
"note",
"imageUrl",
"purchasedQuantity",
"createdAt",
"product",
"variant"
],
"additionalProperties": false
}
}
},
"required": [
"id",
"name",
"itemsCount",
"shared",
"shareUrl",
"shareToken",
"isDefault",
"createdAt",
"updatedAt",
"items"
],
"additionalProperties": false
},
"sharingEnabled": {
"type": "boolean",
"description": "Whether this store allows wishlist sharing at all. When false, hide every share control."
},
"multipleWishlists": {
"type": "boolean",
"description": "Whether this store lets a customer keep several wishlists. When false, everything they save goes on one list, so hide the controls for creating or naming another. Lists a customer already holds keep working either way."
},
"itemImagesEnabled": {
"type": "boolean",
"description": "Whether this store lets a signed-in customer attach their own photo to a saved item. When false, hide the photo picker; any photo already on an item comes back as null."
}
},
"required": ["wishlist", "sharingEnabled", "multipleWishlists", "itemImagesEnabled"],
"additionalProperties": false
}