{"openapi":"3.1.0","info":{"title":"Cove Wishlist developer API","version":"1.0.0","summary":"Server-to-server access to a shop’s wishlists.","description":"Read a customer’s wishlists, save and remove items, and list the most-saved products. Authenticate with an API key created in the app (Developers page). Server to server only: no CORS, keys must never reach a browser. Customers are identified by Shopify customer ID only; the API never accepts or returns emails or other customer details. Every response is JSON with Cache-Control: no-store.","contact":{"url":"https://covewishlist.com/developers"}},"servers":[{"url":"https://covewishlist.com/api/v1"}],"security":[{"apiKey":[]}],"paths":{"/me":{"get":{"operationId":"getMe","summary":"The shop and scope of this API key","responses":{"200":{"description":"The key’s shop and scope.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Paused"}}}},"/customers/{customerId}/wishlist":{"get":{"operationId":"getCustomerWishlist","summary":"A customer’s lists and saved items","description":"Every list with its live items, newest first. A customer who never saved anything gets `lists: []` (never a 404); reading creates nothing.","parameters":[{"name":"customerId","in":"path","required":true,"description":"Numeric Shopify customer ID (not the GID, never an email).","schema":{"type":"string","pattern":"^[1-9][0-9]{0,18}$"}}],"responses":{"200":{"description":"The customer’s wishlist.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Wishlist"}}}},"400":{"description":"`invalid_customer_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Paused"}}}},"/customers/{customerId}/items":{"post":{"operationId":"addCustomerItem","summary":"Save an item for a customer","description":"Needs a read+write key. Without `listId` the item goes to the customer’s default list (created on first use); with it, to that list, which must be theirs. Idempotent: saving an item already in the list answers 200 with `added: false`. A new save counts as one wishlist action toward the shop’s monthly quota.","parameters":[{"name":"customerId","in":"path","required":true,"description":"Numeric Shopify customer ID (not the GID, never an email).","schema":{"type":"string","pattern":"^[1-9][0-9]{0,18}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddItem"}}}},"responses":{"200":{"description":"Already saved; nothing changed.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddResult"}}}},"201":{"description":"Saved.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddResult"}}}},"400":{"description":"`invalid_request`, `invalid_json`, `invalid_customer_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"`list_not_found`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`list_full`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"`body_too_large`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"`rate_limited` or `quota_reached`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"$ref":"#/components/responses/Paused"}}}},"/customers/{customerId}/items/{productId}":{"delete":{"operationId":"removeCustomerItem","summary":"Remove an item for a customer","description":"Needs a read+write key. Without `listId` the item leaves every list (like the storefront heart). Without `variantId` it removes the product-level save. Idempotent: `removed: 0` when nothing was saved.","parameters":[{"name":"customerId","in":"path","required":true,"description":"Numeric Shopify customer ID (not the GID, never an email).","schema":{"type":"string","pattern":"^[1-9][0-9]{0,18}$"}},{"name":"productId","in":"path","required":true,"description":"Numeric Shopify product ID.","schema":{"type":"string","pattern":"^[1-9][0-9]{0,18}$"}},{"name":"variantId","in":"query","required":false,"description":"Remove the save of this variant (numeric ID or GID).","schema":{"type":"string"}},{"name":"listId","in":"query","required":false,"description":"Only from this list.","schema":{"$ref":"#/components/schemas/ListId"}}],"responses":{"200":{"description":"Removed (or nothing to remove).","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveResult"}}}},"400":{"description":"`invalid_request`, `invalid_customer_id`, `invalid_product_id`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"`list_not_found`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Paused"}}}},"/products/most-saved":{"get":{"operationId":"getMostSavedProducts","summary":"The shop’s most-saved products","description":"Products by how many shoppers have them saved now (a shopper counts once however many lists hold it). Counts only.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":250,"default":50}}],"responses":{"200":{"description":"Most-saved first.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MostSaved"}}}},"400":{"description":"`invalid_limit`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/Paused"}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from the app’s Developers page (`cove_live_` + 32 characters). Read keys can call the GET operations; read+write keys all of them."}},"headers":{"X-RateLimit-Limit":{"description":"Requests this key may make per minute.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the window resets (Unix seconds).","schema":{"type":"integer"}}},"responses":{"Unauthorized":{"description":"`missing_api_key` or `invalid_api_key`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"`plan_required` or `insufficient_scope`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"TooManyRequests":{"description":"`rate_limited`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer"}}}},"Paused":{"description":"`paused`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["invalid_request","invalid_json","invalid_customer_id","invalid_product_id","invalid_limit","missing_api_key","invalid_api_key","plan_required","insufficient_scope","list_not_found","not_found","method_not_allowed","list_full","body_too_large","rate_limited","quota_reached","internal_error","paused"]},"feature":{"type":"string","description":"With `plan_required`."},"plan":{"type":"string","description":"With `plan_required`: the lowest plan that includes it."}}},"ListId":{"type":"string","pattern":"^[a-z0-9]{20,32}$"},"Me":{"type":"object","required":["shop","scope"],"properties":{"shop":{"type":"string","examples":["example.myshopify.com"]},"scope":{"type":"string","enum":["READ","READ_WRITE"]}}},"Item":{"type":"object","required":["productId","variantId","quantity","addedAt"],"properties":{"productId":{"type":"string"},"variantId":{"type":["string","null"],"description":"Null = saved at product level."},"quantity":{"type":"integer"},"addedAt":{"type":"string","format":"date-time"}}},"List":{"type":"object","required":["id","name","isDefault","shared","createdAt","count","items"],"properties":{"id":{"$ref":"#/components/schemas/ListId"},"name":{"type":"string","description":"Shopper text: render it as text, never as HTML."},"isDefault":{"type":"boolean","description":"Where one-tap storefront saves go."},"shared":{"type":"boolean","description":"Has a live share link (the link itself is never returned)."},"createdAt":{"type":"string","format":"date-time"},"count":{"type":"integer"},"items":{"type":"array","items":{"$ref":"#/components/schemas/Item"}}}},"Wishlist":{"type":"object","required":["customerId","count","lists"],"properties":{"customerId":{"type":"string"},"count":{"type":"integer","description":"Distinct saved products/variants across all lists."},"lists":{"type":"array","items":{"$ref":"#/components/schemas/List"}}}},"AddItem":{"type":"object","required":["productId"],"additionalProperties":false,"properties":{"productId":{"oneOf":[{"type":"string","pattern":"^[1-9][0-9]{0,18}$"},{"type":"string","pattern":"^gid://shopify/Product/[1-9][0-9]{0,18}$"},{"type":"integer","minimum":1,"maximum":9007199254740991}]},"variantId":{"oneOf":[{"type":"string","pattern":"^[1-9][0-9]{0,18}$"},{"type":"string","pattern":"^gid://shopify/ProductVariant/[1-9][0-9]{0,18}$"},{"type":"integer","minimum":1,"maximum":9007199254740991}],"description":"Omit or null for a product-level save."},"listId":{"$ref":"#/components/schemas/ListId"}}},"AddResult":{"type":"object","required":["added","wishlist"],"properties":{"added":{"type":"boolean"},"wishlist":{"$ref":"#/components/schemas/Wishlist"}}},"RemoveResult":{"type":"object","required":["removed","wishlist"],"properties":{"removed":{"type":"integer","description":"Saved rows removed (an item can sit in several lists)."},"wishlist":{"$ref":"#/components/schemas/Wishlist"}}},"MostSaved":{"type":"object","required":["products"],"properties":{"products":{"type":"array","items":{"type":"object","required":["productId","shoppers","saves"],"properties":{"productId":{"type":"string"},"shoppers":{"type":"integer","description":"Shoppers with it saved now."},"saves":{"type":"integer","description":"Live saved rows (variants and lists counted separately)."}}}}}}}}}