Use vendors as wishlist items
A member’s wishlist holds listings by default, but it can also hold vendors: a “Follow
this shop” button on a vendor page, a “My favourite makers” screen in an app. Both kinds of
item live in the same wishlist and go through the same four
Front API endpoints; the type parameter tells them apart.
| Action | Request |
|---|---|
| Add | POST /front_api/v1/wishlists with {"item_id": …, "type": "vendor"} |
| Check | GET /front_api/v1/wishlists/{item_id}/check?type=vendor |
| List | GET /front_api/v1/wishlists?type=vendor |
| Remove | DELETE /front_api/v1/wishlists/{item_id}?type=vendor |
item_id is the vendor’s user id. Every call needs a signed-in member: a Bearer token in an
app, or the storefront session in a theme. See
Authentication.
Build a follow button
Section titled “Build a follow button”-
Show the current state. When the vendor page loads, ask whether the member already follows the vendor:
Terminal window curl "https://acme.mykreezalid.com/front_api/v1/wishlists/4242/check?type=vendor" \-H "Authorization: Bearer $TOKEN"{ "success": true, "vendor_id": 4242, "exists": true }For a visitor who is not signed in, the answer is
{"success": false, "code": "X001", "error": "No authenticated user"}: show the button in its “follow” state and send them to the login page on click. -
Follow on click:
Terminal window curl -X POST https://acme.mykreezalid.com/front_api/v1/wishlists \-H "Authorization: Bearer $TOKEN" \-H "Content-Type: application/json" \-d '{"item_id": 4242, "type": "vendor"}'{ "success": true, "message": "Vendor added successfully" } -
Unfollow on the second click:
Terminal window curl -X DELETE "https://acme.mykreezalid.com/front_api/v1/wishlists/4242?type=vendor" \-H "Authorization: Bearer $TOKEN"{ "success": true, "message": "vendor deleted successfully from wishlist" }
In a theme, the same calls run from the page’s JavaScript with the member’s session, no token needed:
const API = '/front_api/v1/wishlists';
async function call(url, init = {}) { const res = await fetch(url, { credentials: 'same-origin', headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, ...init, }); if (res.status === 403) return { success: false, needsLogin: true }; return res.json();}
export async function initFollowButton(button) { const vendorId = button.dataset.vendorId; const state = await call(`${API}/${vendorId}/check?type=vendor`); let following = state.success && state.exists; button.setAttribute('aria-pressed', String(following));
button.addEventListener('click', async () => { const result = following ? await call(`${API}/${vendorId}?type=vendor`, { method: 'DELETE' }) : await call(API, { method: 'POST', body: JSON.stringify({ item_id: Number(vendorId), type: 'vendor' }) });
if (result.needsLogin || state.code === 'X001') { window.location.href = '/login'; return; } if (result.success) { following = !following; button.setAttribute('aria-pressed', String(following)); } });}Responses and messages
Section titled “Responses and messages”The add and remove calls answer 200 with success and a message. Branch on success, and
use message to tell the cases apart:
message |
Meaning |
|---|---|
Vendor added successfully |
The vendor is now in the wishlist. |
vendor_already_in_user_wishlist |
Nothing changed: the member already follows this vendor. Treat it as a success in a toggle. |
vendor_not_found |
No user has this id on the marketplace. |
vendor deleted successfully from wishlist |
The vendor was removed. |
vendor_not_in_your_wishlist |
Nothing to remove. |
No authenticated user |
Status 403: no member is signed in. |
The listing equivalents read Listing added successfully, listing_already_in_user_wishlist,
listing_not_found and so on.
Show the followed vendors
Section titled “Show the followed vendors”GET /front_api/v1/wishlists?type=vendor returns the member’s followed vendors, 20 per page,
with pagination. Each entry carries vendor_id and the
vendor’s public profile in user:
{ "wishlists": [ { "vendor_id": 4242, "user": { "id": 4242, "url_key": "atelier-lune", "business_name": "Atelier Lune", "image": "https://…", "average_rating": 4.8, "review_count": 37, "listing_count": 52 } } ], "pagination": { "currentPage": 1, "nextPage": false, "…": "…" }}Vendors whose account is deactivated, banned or deleted drop out of the list on their own;
the entry is not removed from the wishlist, so the check endpoint still answers
"exists": true for them.
Link each entry to the vendor’s public page, and load its listings or reviews with
GET /front_api/v1/directories/{user_id} and GET /front_api/v1/reviews/user/{user_id}.
Things to know
Section titled “Things to know”- The item is any user. Adding checks only that a user with this id exists on the marketplace, not that they are a vendor. Show the button on vendor pages only.
- One entry per vendor. Adding a vendor twice does not duplicate it.
- Listings and vendors are separate. Following a vendor does not add their listings, and
GET /wishlistswithouttypelists only listings, limited to those that are published and approved.