Comment, or reply with parentId (a top-level comment only). uploadIds from createFeedbackUpload. 10/minute. Returns the thread.
OptionalparentOptionaluploadFollow: get notified when it changes status, ships, or gets an official answer.
Mark notifications read: the given ids, or all of them when omitted.
Optionalids?: string[]Post an idea / request. The author votes and follows it automatically. 5 per hour. uploadIds from createFeedbackUpload.
Optionalbody?: stringOptionaltagOptionaluploadReact to a post. Answers the post's reactions. reactions_off (404) when the switch is off.
Upload one image (field image: png, jpeg, webp or gif, up to 8 MB). It comes back as webp, at most
2000px, with its metadata (GPS, camera) removed. Put url in the markdown as  and send
uploadId in uploadIds when saving the post or comment; unattached uploads are deleted after 24h.
20 per day. Refusals: uploads_off, image_too_large, unsupported_image, invalid_image, upload_quota.
Vote. Voting also follows the post, unless the user unfollowed it before. 30 per minute.
Delete your own comment (its replies stay). Returns the thread.
Unfollow. Sticks: voting again later does not re-follow.
Delete your own post - only while nobody else has voted on it (ask_staff otherwise).
Boards the viewer may see, with visible-post counts per status.
Optionalauth?: stringA comment's edit history, as getFeedbackPostRevisions (no title). A deleted comment's history is staff only.
Optionalauth?: stringThe thread: the official staff answer first, then comments oldest first with their replies (one level).
Staff notes (internal) only reach staff. A deleted comment shows as deleted: true with no body while it
still has replies.
Optionalauth?: stringPosts staff featured for the top of the feedback page (up to 10, in their order).
Optionalauth?: stringThe bell's number. Counts up to 100 (capped then true - show "99+").
The inbox (the bell): newest first. Visibility is checked when you read it, so a post that has gone
private is simply not there. Page with before = the previous page's next.
Optionalbefore?: stringOptionallimit?: numberOne post. A merged post answers { post: null, viewer: null, mergedInto }: send the user to
mergedInto (its old number keeps working this way).
Optionalauth?: stringA post's edit history ("View history"): newest first, the current version included, at most 50. Same visibility as the post (404 otherwise). After a staff / developer edit, non-staff see that version and later ones only.
Optionalauth?: stringThe list. board / tag take a slug or id; sort is top (default, pinned first inside a board),
new or trending (votes in the last 14 days). limit up to 50. Searching logged out is rate limited.
Optionalauth?: stringOptionalboard?: stringOptionallimit?: numberOptionaloffset?: numberOptionalq?: stringOptionalsort?: FeedbackSortOptionalstatus?: Optionaltag?: stringThe roadmap: planned, in progress, and shipped in the last 30 days (older ones are on the timeline).
Optionalauth?: stringDM settings. dmBlocked: Discord refused a DM (closed DMs) - switching DMs on again clears it. dmsAvailable false = DMs are off for everyone.
Optionalauth?: stringShipped posts, newest first, each with the public changelog entry it shipped in (if staff linked one).
Optionalauth?: stringOptionallimit?: numberOptionaloffset?: numberThe "my feedback" page: my posts, what I voted on, what I follow (100 each, newest first).
My KLIPY customer_id for the GIF picker: stable per user, not the Discord id. The dashboard calls KLIPY itself
(their terms: API requests come from the user's browser) and sends this on search, trending and share.
Up to 5 visible posts whose titles look like q - the "is this already asked?" hint while typing a title.
Optionalauth?: stringEdit your own comment. Returns the thread.
Edit your own post. Only while it is open / under review and has 10 or fewer votes (viewer.canEdit).
Optionalbody?: stringOptionaltagOptionaltitle?: stringOptionaluploadTurn the update digest DM on or off (off by default; at most one DM per 15 minutes, 10 a day).
The feedback board - ideas and private requests, votes, follows (replaces Fider at feedback.noti.bot).
── WHO SEES WHAT ────────────────────────────────────────────────────────── Reads work logged out: pass
authONLY when the user is logged in. With a session the server answers for that user (premium-only boards, their own hidden posts, staff view) and marks the responseprivate, no-store; without one it answers the public view and lets it be cached. Never cache a logged-in response on the page side as if it were public.Behind the
feedbacklaunch flag: while it is hidden for the caller every method 404s. A post the viewer may not see is 404 too, never 403 - do not show "forbidden", show "not found".── REFUSALS ─────────────────────────────────────────────────────────────── A refused write is
{ status, error: { code } },codefromFeedbackErrorCode.voteRefusal/commentRefusalon a post'sviewertell you up front why the buttons are off (banned, new account, archived board, locked post), so the page can say so instead of letting the click fail.── TEXT ───────────────────────────────────────────────────────────────────
titleis plain text.bodyis MARKDOWN, stored raw: render it with an allowlist (no raw HTML, images only from Noti's own host, linksrel="nofollow ugc noopener"). The server does not sanitise HTML for you.