REST API

Use the REST API to read and change wishlists from your own systems, such as a CRM, an ERP or a headless storefront.

Authentication

Create an API key in the app under Developers → API keys. The key is shown once; store it somewhere safe. Send it in the Authorization header:

GET /api/v1/products/top HTTP/1.1
Host: <edge base URL>
Authorization: Bearer wl_live_…

The edge base URL is shown on the Developers page.

Each key has one or both scopes:

ScopeAllows
readReading lists, items, product stats and analytics
writeAdding and removing items

You can have up to 10 keys. Revoking a key takes effect within a few minutes.

Endpoints

MethodPathScopeDescription
GET/api/v1/customers/{id}/listsreadA customer's lists. Requires protected customer data access.
GET/api/v1/lists/{id}/itemsreadItems of a list.
POST/api/v1/lists/{id}/itemswriteAdds an item: { "productId": "123", "variantId": "456" }.
DELETE/api/v1/lists/{id}/itemswriteRemoves an item: { "productId": "123", "variantId": "456" }.
GET/api/v1/products/{id}/statsreadSaves, add-to-cart and orders for one product.
GET/api/v1/products/topreadMost saved products.
GET/api/v1/analytics/summaryreadTotals for a date range (?from=YYYY-MM-DD&to=YYYY-MM-DD).

Ids are numeric Shopify ids as strings, not GIDs. Leave variantId out, or send "", for a product-level item.

Responses

  • GET /customers/{id}/lists returns { "customerId", "lists": [...] }. Each list has id, name, isDefault, kind, itemCount, shared and updatedAt.
  • GET /lists/{id}/items returns a page of items with productId, variantId, listId, quantity, addedAt, addedBy and priceAtAdd.
  • POST and DELETE on items return { "changed": true }, or false when nothing changed (the item was already saved, or was not in the list). A new item answers 201.
  • GET /products/top returns a page of products with productId, count (current saves), adds, removes, addToCart, orders and revenue.
  • GET /products/{id}/stats returns the same fields for one product plus a daily series.
  • GET /analytics/summary returns from, to, adds, removes, addToCart, orders, revenue, customers and guests.

Times are Unix milliseconds. Prices and revenue are integers in the minor unit of the shop currency (cents for USD).

Pagination

List endpoints use cursor pagination. Pass limit (1–250, default 50) and the nextCursor from the previous response as cursor.

GET /api/v1/products/top?limit=100&cursor=eyJ… HTTP/1.1
{
  "items": [],
  "nextCursor": null
}

nextCursor is null on the last page.

Errors

Every error uses the same shape, with an HTTP status that matches the code:

{
  "error": {
    "code": "not_found",
    "message": "List not found"
  }
}
CodeStatusMeaning
bad_request400The request body or query is invalid.
unauthorized401The key is missing, invalid or revoked.
forbidden403The key doesn't have the required scope.
not_found404The resource doesn't exist.
conflict409The change conflicts with the current state.
limit_reached422A limit was reached, such as 500 items per list.
rate_limited429Too many requests (about 100 per 10 seconds per key). Retry after the number of seconds in the Retry-After header.
internal500Something went wrong on our side.

Versioning

The version is part of the path (/v1). Breaking changes ship as a new version.