Feature wishlist

Build better apps with customer feedback. The wishlist is a public feature-request board: users suggest ideas, upvote the ones they want most, and comment. You moderate — new ideas are hidden until you approve them, and you move each through a status lifecycle and reply in the comments.

It runs everywhere the other flows do: a hosted board at appmate.cloud/wishlist/{appSlug}, an embeddable widget, the iOS SDK (a drop-in screen and a raw data API), and MCP tools for AI agents.

How it works

  1. Create a wishlist flow for your app and publish it.
  2. Users submit ideas. By default a new idea is pending — invisible to everyone until you approve it. (Turn on moderation.autoApprove to skip the queue.)
  3. You approve an idea to open; it now appears on the board and collects upvotes and comments.
  4. As you work on it, move it through the lifecycle: open → planned → in_progress → done, or declined to reject it while keeping the decision visible.

Identity & anti-abuse

Each idea allows one vote per person. How a “person” is identified depends on the flow's identity.mode:

  • anonymous (default) — no login. Votes are deduped by an anonymous cookie combined with a hashed IP, or by your host-app userId when the SDK passes one. Lowest friction; best-effort (clearing cookies and changing IP can defeat it).
  • email— require an email to submit, vote, and/or comment (toggle each). Votes dedupe on the email's hash — the strong-dedup option for high-traffic boards.
In the iOS SDK, pass your real userId whenever you have one — votes and comments then dedupe per user across devices, which is stronger than the anonymous cookie.

Embed on your site

Drop the board into any page with one <iframe>. Upvotes and comments work inside the frame.

html
<iframe
  src="https://appmate.cloud/embed/wishlist/my-app"
  loading="lazy"
  style="border:0; width:100%; height:640px;">
</iframe>

Append ?compact=1 to hide the title block, or ?p={token}(from the editor's “Preview draft” button) to preview an unpublished board.

iOS SDK (present it natively)

Inside an iOS app, show the board natively— don't link the hosted web page above. It renders in-app, dedupes by userId, and avoids a Safari bounce. One call presents it:

swift
import AppMate

// Drop-in: present the board as a sheet from a button or menu.
RetentionFlow.presentWishlist(userId: currentUser?.id)

Or place the ready-made screen in your own hierarchy — sheet, tab, or pushed on a stack:

swift
NavigationStack {
    WishlistView(userId: currentUser?.id)
}

…or build your own UI on top of the typed data API:

swift
let page = try await RetentionFlow.wishlistIdeas(sort: .votes)
for idea in page.items {
    print(idea.title, idea.voteCount)
}

// Vote / comment (identity follows the userId you pass, else an anon id).
try await RetentionFlow.voteWishlistIdea(ideaId: idea.id, userId: user.id)
try await RetentionFlow.postWishlistComment(
    ideaId: idea.id, body: "Yes please!", userId: user.id
)

See the iOS SDK reference for setup.

Public API

No auth — these power the board, the embed, and the SDK:

  • GET /api/public/wishlist/list — public ideas, paginated (sort=votes|new, status, category).
  • POST /api/public/wishlist/submit — submit an idea (lands pending unless auto-approve is on).
  • POST / DELETE /api/public/wishlist/vote — add / remove a vote (idempotent).
  • GET / POST /api/public/wishlist/comments — list / add comments.

Owner (v1) API

Bearer-token endpoints for moderation (used by the dashboard and MCP):

  • GET/PUT /api/v1/apps/{app}/flows/wishlist + /publish — read / edit / publish the config.
  • GET /api/v1/apps/{app}/wishlist/ideas — all statuses; PATCH/DELETE …/ideas/{id} to set status or delete.
  • …/ideas/{id}/comments (owner reply) and …/wishlist/ideas.csv (export).

For AI agents (MCP)

The AppMate MCP server exposes wishlist tools: get_wishlist_flow, update_wishlist_draft, publish_wishlist_flow, list_wishlist_ideas, set_wishlist_idea_status, post_wishlist_comment, list_wishlist_comments, delete_wishlist_idea, delete_wishlist_comment, and export_wishlist_csv.

delete_wishlist_idea removes the idea andits votes and comments — it's irreversible. To reject an idea while keeping it (and the decision) visible, set its status to declined.