# Feedjolt > Full English documentation for AI agents and model-training crawlers. The short index is https://www.feedjolt.com/llms.txt. Feedjolt is a public feedback and roadmap platform for B2B SaaS teams. Always written **Feedjolt** (lowercase j). Request `Accept: text/markdown` or append `.md` on any docs URL for a single page. --- # FAQ > Quick answers about Feedjolt: what it is, passwordless login, plans and admin seats, roles, posts, the public portal, integrations, billing, and privacy. ## General ### What is Feedjolt? A B2B SaaS feedback and roadmap platform. Customers vote on what they want; you triage, plan, and ship; the public roadmap and changelog stay up to date automatically. ### Who is it for? Product managers, founders, and customer success teams at SaaS companies. If you have a roadmap and customers, Feedjolt fits. ### How does Startup pricing work? Startup is $9/mo (monthly only) and application-based. Apply at **Dashboard -> Billing -> Apply for Startup pricing**: submit your product URL and what you're building. We review it and approve eligible early-stage teams. It caps at 2 admin seats; grow past that and you move up to Growth. Full details: **[Startup pricing](/en/docs/billing/startup-pricing)**. ## Account ### Why no passwords? Passwords get reused, leaked, and forgotten. We use magic links (email) and Google OAuth instead. Same security model your bank uses, less friction. ### Can I change my email? Not currently in the dashboard. Email **support@feedjolt.com** with the old and new email; we'll handle it. ### Can I have multiple workspaces? Yes. One account, multiple workspaces. Each workspace has its own billing and members. ### Can I move data between regions (EU/US)? No. The file-storage bucket is fixed when you sign up and inherited by your workspaces. See **[Data region](/en/docs/account/data-region)**. ## Workspaces and members ### Difference between OWNER, ADMIN, CONTRIBUTOR? - **OWNER** - full control, including billing and deleting the workspace. - **ADMIN** - manages members, content, integrations. - **CONTRIBUTOR** - submits posts, votes, public comments. No moderation. Full matrix: **[Roles](/en/docs/roles)**. ### How many admin seats per plan? Admin seats (OWNER + ADMIN) are capped per plan: **Startup 2**, **Growth 25**, **Scale 50**. CONTRIBUTOR seats and end-user seats are unlimited on every plan. ### Can I transfer ownership? Yes. **Settings -> Members -> Promote to OWNER**, then optionally **demote yourself**. There must always be at least one OWNER. ## Posts and feedback ### Can I edit posts after submitting? Yes - you can edit your own. ADMINs can edit any post. ### Can end users see internal notes? No. Internal notes are visible only to OWNER and ADMIN. ### What happens to votes when I merge two posts? They move to the target. Duplicates (same user voted on both) are deduped to one. ### Can I have private posts on a public board? Yes - flag the post as **internal** and it disappears from the public portal but stays in the dashboard. ## Public portal ### Do I need a custom domain? Custom domains aren't supported yet. Your portal URL is `feedjolt.com/p/{slug}`. On the [roadmap](https://www.feedjolt.com/en/portal/luodaint/roadmap). ### Can I block search engines from indexing? Yes - turn off **Allow indexing** at **Dashboard -> Portal -> Search engines**, or set the workspace to **private** at **Settings -> Visibility** (paid plans). Public portals index the hub and boards by default. Individual posts are never indexed. ### Will the widget slow down my site? The widget loader is ~5 KB gzip and async-loaded. The full UI loads only when the user clicks. Lighthouse impact should be negligible. ## Integrations ### Does Feedjolt support Slack? Yes. **[Slack integration](/en/docs/integrations/slack)**. ### Linear? Yes, with bidirectional status sync. **[Linear integration](/en/docs/integrations/linear)**. ### GitHub Issues / Jira? Not yet. Both are on the roadmap. ### Is there a public API? Yes. **[API](/en/docs/integrations/api)**. REST + Bearer token. ### Webhooks? Yes. Signed, retried, with delivery logs. **[Webhooks](/en/docs/integrations/webhooks)**. ### n8n? Yes. Install `n8n-nodes-feedjolt` from npm on self-hosted n8n (**Settings → Community nodes**). n8n Cloud's **verified** Creator Portal listing is still pending. **[n8n](/en/docs/developers/external-apps/n8n)**. ## Billing ### How does the trial work? 14 days of the Growth plan when you create a workspace. No card up front. **[Trial](/en/docs/billing/trial)**. ### What happens after the trial? Pick a plan to keep editing. Without payment, the workspace goes **read-only** - your data stays intact and the public portal stays live, but you can't moderate, change statuses, or invite members until you add a payment method. **[Trial](/en/docs/billing/trial)**. ### What payment methods do you accept? Cards at checkout (Creem for new subscriptions; Stripe if you already pay with Stripe). Bank transfer / invoice for annual plans on request. ### Can I get a refund? Within 30 days, yes - email support. After that, case by case. ### What if my card fails? You get 14 days of "past_due" with daily emails. After that, the workspace goes read-only until you reactivate. Existing data is preserved. ## Privacy and security ### Where is my data stored? Uploaded files go to an EU or US storage bucket you choose. See **[Data region](/en/docs/account/data-region)**. ### Do you have a DPA? Yes. Email **support@feedjolt.com**. ### Are you SOC 2 / ISO 27001? Not yet. Working on it. We can share a security one-pager on request. ### How do I delete my account? **Settings -> Danger zone -> Delete account**. Immediate, irreversible. **[Delete account](/en/docs/account/delete)**. ## Contact Can't find an answer here? **[/en/contact](/en/contact)** is the fastest path. --- # Welcome to Feedjolt > Feedjolt turns customer feedback into a public roadmap people can vote on. Start here to find getting started, core concepts, workflow, portal, and integrations. Feedjolt turns customer feedback into a public roadmap your customers can vote on. Less spreadsheets, fewer "did anyone hear back about that" Slack threads, more actually-shipped features. ## Where to start If you're brand new, follow the path: 1. **[Getting started](/en/docs/getting-started)** - sign up, pick a file-storage bucket, create your first workspace. 2. **[Core concepts](/en/docs/concepts)** - the model: workspaces, boards, posts, statuses, votes, comments. 3. **[Roles & permissions](/en/docs/roles)** - who can do what. If you already have a workspace and you're shipping: - **[Workflow](/en/docs/workflow)** - triage, merge duplicates, ship status changes. - **[Portal](/en/docs/portal)** - the public face customers see. Roadmap, changelog, widget. - **[Integrations](/en/docs/integrations)** - Slack, Linear, webhooks, API, n8n. If you're a customer of someone using Feedjolt: - **[For customers](/en/docs/for-customers)** - how to submit feedback and vote. ## How this site is organized Each section starts with an **overview** that explains the moving parts and links to deeper pages. Use the sidebar to jump around, or `Cmd/Ctrl + K` to search. Something missing? Open `Help -> Contact` from any Feedjolt page and tell us - that's the fastest way to get a doc written. --- # Data region > Uploaded files go to an EU or US storage bucket you choose at sign-up. Workspaces inherit that choice. It cannot be changed later. Uploaded files go to an EU or US storage bucket you choose. ## What's stored where - **EU**: uploads (logos, post attachments, image embeds) go to `feedjolt-eu-private`. - **US**: uploads go to `feedjolt-us-private`. ## How the region is set - **At user sign-up** - pick EU or US. "No preference" defaults to US. - **Inherited by your workspace** when you create one. Other members can have a different choice; the workspace uses the creator's bucket. ## Why is it immutable? The choice is set at sign-up and cannot be changed later. If you really need to switch, the path is: 1. Export your workspace data via the API. 2. Delete the workspace. 3. Sign up a new account with the other bucket choice. 4. Recreate the workspace and re-import. ## Multi-region workspaces Not supported. Each workspace has one file-storage bucket — the creator's. If you need both buckets, create two workspaces from accounts that chose differently. ## What does NOT change with the file-storage choice - Pricing (same per plan). - Feature set (no features locked to one bucket). --- # Delete your account > Delete your Feedjolt account permanently. What gets removed, what survives, transferring owned workspaces, GDPR data export, and how to recover access. You can delete your Feedjolt account at any time. The deletion is **immediate and irreversible**. ## What gets deleted - Your **user record** - email, name, avatar, sign-in methods. - All **posts**, **comments**, **votes** you authored. - Any **workspaces you own**, including everything in them: members, boards, posts, comments, votes, integrations, files. *Members of those workspaces lose access immediately.* - All **personal data**: email preferences, sessions, audit log entries naming you. What survives: - **Anonymized audit log entries** in workspaces you didn't own. (Required for compliance - we keep the timestamp and event type but not your identity.) - **Aggregated data** in our internal metrics - no PII, just counts. ## What does NOT get auto-deleted If you're a **member (not owner)** of someone else's workspace: - The workspace **continues** to exist (it's not yours to delete). - Your posts and comments **stay** but are reattributed as **"Deleted user"**. - Your votes **stay** as anonymous votes. - You're removed from the member list immediately. If you want your posts/comments removed too, do that **before** deleting your account. ## How to delete 1. **Dashboard -> Settings -> Danger zone -> Delete account**. 2. Type your email to confirm. 3. Click **Delete permanently**. You're signed out immediately. Within ~60 seconds, all listed data is gone from our database. We **do not** offer a grace period, "trash" folder, or "deactivate without deleting". If you want to take a break, just sign out. ## What if I own a workspace I want to keep? Transfer ownership first: 1. **Workspace -> Settings -> Members**. 2. Promote another member to OWNER. 3. *Then* delete your account from your personal settings. You can't delete an account that's the sole owner of any workspace. The dashboard will tell you which workspaces and ask you to transfer first. ## GDPR / data portability Before deleting, you can **export your data**: **Dashboard -> Settings -> Privacy -> Export my data**. You get a ZIP with: - A JSON file of your user record. - A JSON file of every post, comment, and vote you authored. - A folder of every file you uploaded (logos, attachments). Export takes a few seconds for small accounts; up to ~10 minutes for accounts with thousands of posts. You'll get an email when it's ready. ## Rate limits Account deletion is rate-limited to **3 per hour per IP** to prevent abuse. (You'll only ever do this once, but bots might try.) ## Trouble? If you can't sign in to delete your account (e.g., lost access to your email), email **support@feedjolt.com** with "delete my account" and the email on file. We'll verify identity another way and handle it manually. --- # Email preferences > Control which Feedjolt emails you receive. Opt out per type from Settings or any unsubscribe link, manage end-user preferences, and stop all workspace emails. Feedjolt sends emails for a few reasons. You can opt out of any of them, individually. ## Where to manage Two paths, same destination: - **Dashboard -> Settings -> Notifications** - full control with a sign-in. - **Click "Unsubscribe" in any email** - token-based, no sign-in required. Manages just the one type of email. The "no sign-in" path is RFC 8058 compliant - Gmail and Outlook show a one-click unsubscribe button in the email itself. ## What you can control | Email type | Who gets it by default | Can opt out? | | --- | --- | --- | | Sign-in magic link | Anyone signing in | ❌ (it's the auth) | | New post on a board you subscribed to | Subscribers only | ✅ | | Status change on a post you authored | Authors | ✅ | | Status change on a post you voted on | Voters (opt-in) | ✅ | | New comment on a post you participated in | Participants | ✅ | | Workspace invite | Invited members | ❌ (it's the invite) | | Weekly Jolt | Accepted owners and admins | ✅ | | Trial reminders | Accepted workspace owners | ✅ | | Receipts and billing | Workspace owners | ❌ (legal req.) | ## End-user preferences If you're not a Feedjolt member but you're an end user (you submit feedback in someone's portal): - Visit `feedjolt.com/p/{slug}/email-preferences` (also accessible via any unsubscribe link). - Sign in with your email (magic link). - Toggle preferences per workspace. End-user preferences are scoped per workspace - opting out of ACME's emails doesn't affect Globex's. ## Bulk unsubscribe Want to stop everything from a workspace? Click any unsubscribe link from a Feedjolt email and pick **Stop all emails from this workspace**. We'll honor it immediately. ## Re-subscribing Toggling a preference back on is instant. Resume points are not retroactive - you won't get yesterday's notifications. ## Trouble? - **Still getting emails after unsubscribing.** Wait 5 minutes (queued sends finish). If still happening 24 hours later, [contact us](/en/contact). - **No emails at all when there should be.** Check spam, then `Settings -> Notifications` to confirm subscriptions are on. If still nothing, your email provider may be marking us as spam - add `noreply@feedjolt.com` to contacts. --- # Google OAuth > Sign in or sign up to Feedjolt with Google. Link Google to an existing magic-link account, manage scopes, and unlink anytime from your profile settings. **Continue with Google** lets you sign in (or sign up) using a Google account. ## How it works 1. Click **Continue with Google** at **[/login](/en/login)** or **[/register](/en/register)**. 2. Pick a Google account on Google's screen. 3. Approve the requested scopes (just `email` and `profile`). 4. Google redirects back to Feedjolt; you're signed in. The OAuth flow uses Google's standard authorization-code-with-PKCE handshake. Tokens are exchanged server-side and never exposed to your browser. ## What we access Just two things: - Your **email address** - to identify you and send notifications. - Your **basic profile** - name and avatar (we don't pull your contacts, calendar, or any other data). We don't store Google access or refresh tokens. We use Google for authentication only, not for ongoing API access. ## Linking Google to an existing account If you signed up via magic link first and want to add Google as a sign-in method: 1. **Dashboard -> Settings -> Profile -> Sign-in methods**. 2. Click **Connect Google**. 3. Approve. The Google account is now linked. Either method (magic link or Google) signs you into the same account. If you click "Continue with Google" with a Google email that **already has a Feedjolt account via magic link**, the two are linked automatically. You don't need to manually connect. ## Unlinking Google **Settings -> Profile -> Sign-in methods -> Disconnect Google**. You must have at least one sign-in method active. If Google is your only one, add magic link first (i.e., have any email confirmation flow). ## Trouble? - **"This email is already in use."** It is - via magic link. Sign in with magic link first, then connect Google. - **Google says "this app isn't verified."** Feedjolt is verified. If you see this, you might be on a different domain. Make sure you're at `feedjolt.com`. - **Wrong Google account selected.** Sign out of Google in another tab and try again. ## Security notes - We use Google's `email_verified` flag - accounts with unverified emails are rejected. - Account linking by email match is a known phishing vector for poorly-implemented auth. We mitigate by only linking when Google's `email_verified=true` and only on first OAuth sign-in. --- # Account > Manage your Feedjolt account: sign-in methods, profile and locale, email preferences, EU or US file-storage bucket, active sessions, and account deletion. Your **account** is your personal Feedjolt identity. It's separate from any workspace - you can be a member of many workspaces with one account. ## Pages - **[Magic link](/en/docs/account/magic-link)** - passwordless sign-in. - **[Google OAuth](/en/docs/account/google-oauth)** - sign in with Google. - **[Email preferences](/en/docs/account/email-preferences)** - manage notifications. - **[Data region](/en/docs/account/data-region)** - EU or US file-storage bucket, chosen at sign-up, cannot be changed later. - **[Delete account](/en/docs/account/delete)** - GDPR-compliant hard delete. ## Account profile At **Dashboard -> Settings -> Profile**: - **Display name** - shown to other members and on comments you author. - **Avatar** - from Google (if connected) or upload. - **Locale** - `en`, `es`, `ca`. Determines the language of the dashboard and emails. - **Linked sign-in methods** - manage magic-link email + Google connection. ## Sessions You're signed in via httpOnly cookies (access + refresh). Sessions persist across browser restarts. To see active sessions or revoke them all (e.g., signed in on a public computer): **Dashboard -> Settings -> Security -> Active sessions**. Revoking all sessions logs you out everywhere except the current browser. --- # Magic link > How Feedjolt magic links sign you in: a one-time, 15-minute email link, no passwords. Covers single-use rules, sessions, multiple devices, and sign-out. A **magic link** is a one-time URL we email you that signs you in when clicked. No password to remember, nothing to store. ## How it works 1. Enter your email at **[/login](/en/login)** or **[/register](/en/register)**. 2. Solve the Cloudflare Turnstile challenge (usually invisible). 3. Check your inbox for an email from `noreply@feedjolt.com`. 4. Click the link in the email. 5. You're signed in. The link is valid for **15 minutes** and is **single-use**. If you click it twice, only the first click works. ## Behind the scenes - The link contains a short-lived JWT. - Clicking exchanges it for a **session pair**: a 15-minute access token + a 7-day refresh token, both as httpOnly cookies. - The frontend auto-refreshes when the access token expires; you stay signed in. ## Multiple devices Each device has its own session pair. Signing in on your laptop doesn't sign you out on your phone. ## Sign out **Dashboard -> Settings -> Profile -> Sign out**, or just clear your cookies. To sign out from **all** devices: **Settings -> Security -> Sign out everywhere**. This invalidates every refresh token; you'll need a fresh magic link to come back. ## Trouble? - **Didn't get the email.** Check spam. Add `noreply@feedjolt.com` to your address book. - **Link says "expired".** That's the 15-minute window. Request a new one. - **Link says "already used".** It's single-use. Request a new one. - **Browser blocked the redirect.** Open the link in a different browser, or copy-paste the URL. ## Security notes - We hash links server-side; the link in your email is not stored as-is. - Failed-login attempts are rate-limited per IP. - We never store passwords. There's nothing to reset. If you suspect someone else has access to your email, **Settings -> Security -> Sign out everywhere** is your friend. --- # For agents > When to use Feedjolt, how to call the REST API and MCP server, and where the machine-readable files live. This page is for AI agents and the humans who wire them up. Humans who want a walkthrough should start at [Quickstart](/en/docs/developers/quickstart). ## When to use Feedjolt Use Feedjolt when a product team needs a **customer-facing** feedback portal: - Collect feature requests, bugs, and ideas from a hosted portal, embeddable widget, REST API, or MCP server. - Let customers upvote and follow requests so the team can prioritize by demand. Admin boards weight workspace admins and gym-marked users at 1.5×; the public portal stays a raw vote count. There is no ARR, plan, or segment matrix. - Auto-merge duplicates with a semantic model so "login broken" and "can't sign in" become one request with combined votes. - Publish a public roadmap and a changelog that notifies voters when something ships. - AI-draft one changelog entry from a connected GitHub repo (commits and merged PRs). A human still publishes. The full capability list — what customers and staff can do, plus what is **not** shipped — is in [llms.txt](https://www.feedjolt.com/llms.txt). Do **not** use Feedjolt as a general helpdesk, an NPS/survey tool, or an internal-only issue tracker. It is not a Linear or Jira replacement. ## How to call Feedjolt | Surface | URL | | --- | --- | | Agent index | [https://www.feedjolt.com/llms.txt](https://www.feedjolt.com/llms.txt) | | Full docs | [https://www.feedjolt.com/llms-full.txt](https://www.feedjolt.com/llms-full.txt) | | OpenAPI JSON | [https://www.feedjolt.com/openapi.json](https://www.feedjolt.com/openapi.json) | | OpenAPI YAML | [https://www.feedjolt.com/api/openapi.yaml](https://www.feedjolt.com/api/openapi.yaml) | | API host OpenAPI | [https://api.feedjolt.com/openapi.json](https://api.feedjolt.com/openapi.json) | | MCP Reader | `https://api.feedjolt.com/mcp/reader/` | | MCP Writer | `https://api.feedjolt.com/mcp/writer/` | | MCP Combined (legacy OAuth resource) | `https://api.feedjolt.com/mcp/` | | MCP server card | [https://www.feedjolt.com/.well-known/mcp.json](https://www.feedjolt.com/.well-known/mcp.json) | | n8n (`n8n-nodes-feedjolt` on npm) | [https://www.feedjolt.com/en/docs/developers/external-apps/n8n](https://www.feedjolt.com/en/docs/developers/external-apps/n8n) | | Sitemap | [https://www.feedjolt.com/sitemap.xml](https://www.feedjolt.com/sitemap.xml) | Marketing and docs URLs negotiate markdown: send `Accept: text/markdown` (the `Vary` header includes `Accept`). Docs also accept a `.md` suffix. ## Auth - Humans: passwordless (magic link or Google). No password to store. - REST (n8n, scripts, HTTP clients): `Authorization: Bearer fjk_…` API keys, minted in the dashboard on **Startup and Scale**. See [Connect external apps](/en/docs/developers/external-apps). - MCP (Cursor, Claude, other agents): OAuth 2.1 on `/mcp/reader/` and `/mcp/writer/`. Do **not** put a Feedjolt API key or `FEEDJOLT_API_KEY` into Cursor plugin settings. Gated on the same `rest_api` plan feature as the REST API. There is no "contact sales" form to get a key. Create an account, pick Startup or Scale, open **Settings → API keys**. The 14-day Growth trial (no card) covers the **product UI**. It does not include REST/MCP — those are Startup and Scale. See [Sandbox](/en/docs/developers/sandbox). ## Rate limits REST and MCP return rate-limit headers so you can throttle yourself. See [Rate limits](/en/docs/developers/api/rate-limits). ## Local verification (contributors) Agents and contributors proving UI or API changes should use the repo-local skill at [`.cursor/skills/verify-feedjolt/SKILL.md`](https://github.com/luodaint/feedjolt/blob/development/.cursor/skills/verify-feedjolt/SKILL.md): 1. `.cursor/skills/verify-feedjolt/scripts/launch.sh` — starts owned dev stack (refuses if port 3000 is already in use). 2. `.cursor/skills/verify-feedjolt/scripts/doctor.sh` — health checks on API + web. 3. Drive the UI with browser automation; hit the API with `curl`. 4. `.cursor/skills/verify-feedjolt/scripts/cleanup.sh` when done. Magic-link login needs the Celery worker running; links appear in worker logs locally, not a real inbox. --- # Developers > Integrate Feedjolt into your app with the embeddable widget, signed webhooks, and the REST API. Quickstart, references, and the bug-reporting workflow. This section is for engineers. If you're configuring Feedjolt as an admin (turning Slack on, inviting members), the **[Integrations](/en/docs/integrations)** section is friendlier. If you're writing code that talks to Feedjolt, you're in the right place. ## What you can build - **Embed feedback inside your app** - drop in the widget. - **React to events** - webhooks deliver signed JSON to your endpoint when feedback moves. - **Read and write programmatically** - the REST API covers most of what the dashboard does. - **Wire an automation tool** - start with [n8n](/en/docs/developers/external-apps/n8n). Cursor uses [MCP OAuth](/en/docs/developers/mcp), not an API key in plugins. ## Where to start - **[Quickstart](/en/docs/developers/quickstart)** - a 10-minute integration: widget on your site, an API key in your hand, a webhook hitting your dev server. - **[For agents](/en/docs/developers/for-agents)** - when to use Feedjolt, OpenAPI, MCP, markdown. - **[Widget](/en/docs/developers/widget)** - installation, configuration, customization, CSP. - **[Webhooks](/en/docs/developers/webhooks)** - payload reference, signature verification, retry behavior. - **[API](/en/docs/developers/api)** - authentication, rate limits, errors, pagination, links to the full OpenAPI reference. - **[MCP](/en/docs/developers/mcp)** - Streamable HTTP server for Claude, Cursor, and other agents. - **[Connect external apps](/en/docs/developers/external-apps)** - n8n and other automation tools. API key for REST; OAuth for Cursor. - **[Sandbox](/en/docs/developers/sandbox)** - self-serve signup, trial, and API keys. ## API reference The interactive endpoint reference is at **[https://api.feedjolt.com/docs](https://api.feedjolt.com/docs)** (Swagger UI, with try-it). OpenAPI JSON: **[https://www.feedjolt.com/openapi.json](https://www.feedjolt.com/openapi.json)** (also at **[https://api.feedjolt.com/openapi.json](https://api.feedjolt.com/openapi.json)**). YAML: **[https://www.feedjolt.com/api/openapi.yaml](https://www.feedjolt.com/api/openapi.yaml)**. MCP server card: **[https://www.feedjolt.com/.well-known/mcp.json](https://www.feedjolt.com/.well-known/mcp.json)**. The pages in this section cover cross-cutting behavior (auth, errors, pagination, webhook contract) - the OpenAPI ref is canonical for per-endpoint shape. ## What's coming A few things on the [roadmap](https://www.feedjolt.com/en/portal/luodaint/roadmap) we know developers ask for: - Automatic webhook retries with exponential backoff. - Signed-timestamp webhook signatures (Stripe-style replay protection). - A `window.feedjolt.open()` JS API for custom widget triggers. - Official TypeScript and Python SDKs. Vote on what would unblock you. ## Reporting bugs If something behaves weirdly: 1. **Reproduce in a fresh dev workspace** so we can see the same data. 2. **File at [/en/contact](/en/contact)** with the request ID from `X-Request-ID` (every API response carries one). 3. **For widget bugs**, paste your install snippet and any CSP errors from the console. --- # JWT SSO > Sign your logged-in users into the Feedjolt portal and widget with a short-lived JWT your backend mints. No second login. Configure claims, secrets, rotation. If your app already knows who the user is, you shouldn't make them log in again to leave feedback. With JWT SSO your backend signs a short-lived token identifying the user; Feedjolt verifies it server-side and transparently signs them into the portal and the in-app widget. JWT SSO is available on every plan. ## How it works 1. You configure a signing secret and algorithm at **Dashboard -> Developers -> JWT SSO**. 2. When a signed-in user opens feedback, your backend mints a JWT with their claims, signed with that secret. 3. You hand the token to Feedjolt - either on the widget via `data-sso-token`, or by POSTing it to the identify endpoint. 4. Feedjolt verifies the signature, creates or updates the matching end user, and sets a server-side session cookie. No magic-link, no extra login. The secret lives only on your server and on Feedjolt's. The browser only ever sees the resulting token - never the secret. ## Apply with a coding agent 1. Set the secret, algorithm, issuer, and audience at **Dashboard -> Developers -> JWT SSO**. Use the dice to generate a 64-character hex secret. 2. Save. 3. Copy the prompt in the right column. 4. Paste it into your coding agent so it can add the mint-and-redirect code to your app. The prompt includes your secret. Paste it only into a tool you trust. Manual snippets stay collapsed under **Do it yourself**. ## Configuration JWT SSO is configured per workspace (owner only) at **Dashboard -> Developers -> JWT SSO**: | Field | Notes | | --- | --- | | `secret_key` | Your shared signing secret. 16-512 characters. Store it server-side only. | | `algorithm` | One of `HS256` (default), `HS384`, `HS512`. HMAC shared-secret signing. | | `issuer` | Optional. If set, the token's `iss` claim must match. | | `audience` | Optional. If set, the token's `aud` claim must match. | | `sync_mode` | `UPSERT` (default) auto-creates unknown users; `UPDATE_ONLY` rejects tokens for users that don't exist yet. | Only HMAC algorithms are supported - there is no public-key (asymmetric) mode. Both sides hold the same secret. ## Token claims Mint a standard JWT signed with your secret. These claims are **required** - a token missing any of them is rejected: | Claim | Meaning | | --- | --- | | `sub` | Your stable user ID. Used as the end user's external ID. | | `email` | The user's email. | | `name` | Display name. | | `iat` | Issued-at (standard JWT). | | `exp` | Expiry (standard JWT). Keep it short - minutes, not days. | Optional claims enrich the synced profile: | Claim | Meaning | | --- | --- | | `avatar_url` | Profile image URL. | | `custom_fields` | Object of arbitrary key/values stored on the end user. | | `company` | Object identifying the user's company - see below. | If you configured an `issuer` or `audience`, also include the matching `iss` / `aud` claims; they're only verified when configured. ### Company claim Pass `company` as an object to attach the user to a company record (created or updated on the fly). `companies` (an array) is also accepted - the first entry is used. ```json { "company": { "id": "org_123", "name": "Acme Inc", "plan": "enterprise", "mrr": 2400, "industry": "fintech", "employee_count": 120 } } ``` Only `id` and `name` are required for a company; the rest are optional. ## Minting the token Mint the JWT on your backend, where the secret is safe. Keep `exp` short. The token stays valid until `exp` — Feedjolt does not treat it as single-use, so a leaked token can be reused until it expires. ```js // Node.js - npm i jsonwebtoken import jwt from "jsonwebtoken"; const token = jwt.sign( { sub: user.id, email: user.email, name: user.fullName, avatar_url: user.avatarUrl, company: { id: user.orgId, name: user.orgName }, }, process.env.FEEDJOLT_JWT_SECRET, { algorithm: "HS256", expiresIn: "5m" }, ); ``` ```python # Python - pip install pyjwt import datetime, jwt now = datetime.datetime.now(datetime.timezone.utc) token = jwt.encode( { "sub": user.id, "email": user.email, "name": user.full_name, "avatar_url": user.avatar_url, "company": {"id": user.org_id, "name": user.org_name}, "iat": now, "exp": now + datetime.timedelta(minutes=5), }, FEEDJOLT_JWT_SECRET, algorithm="HS256", ) ``` ## Handing the token to Feedjolt **Widget:** pass the token on the loader's `data-sso-token` attribute (see [Widget configuration](/developers/widget/configuration)). The widget forwards it as an iframe `ssoToken` query param and the user is signed in inside the panel. **Portal (redirect):** send the user to your portal with `?ssoToken=` on the query string: ``` https://www.feedjolt.com/{locale}/portal/{slug}?ssoToken={jwt} ``` The portal reads `ssoToken`, POSTs it to the identify endpoint, then strips the param from the URL. The token itself is still valid until `exp`. **Portal / direct:** POST the token to the identify endpoint for your workspace: ```bash curl -X POST https://api.feedjolt.com/api/workspaces/{workspace}/identify \ -H "Content-Type: application/json" \ -d '{"token": "YOUR_JWT_HERE"}' ``` On success Feedjolt returns the synced end user and sets a server-side session cookie (`httpOnly`, `secure`, `SameSite=Lax`). That cookie - not your JWT - keeps the user signed in afterward, so you mint a fresh short-lived JWT only at sign-in. ## Key rotation Rotating the signing secret is zero-downtime. When you save a new secret, Feedjolt keeps the previous one valid so tokens already in flight still verify. Up to the **last 5** secrets stay accepted during rollover; older ones drop off automatically. To rotate: set the new secret in the dashboard, deploy it to your backend, and let any in-flight tokens drain. No coordinated cutover needed. ## Security notes - **Verification is server-side.** Feedjolt validates the signature, expiry, and (if set) issuer/audience on its own servers. Never trust identity asserted by the browser. - **The secret never reaches the browser.** Mint tokens on your backend only. Treat the secret like a password. - **Keep `exp` short.** The JWT only needs to live long enough to bootstrap the session cookie - minutes is plenty. - **`UPDATE_ONLY` for closed systems.** If you provision users out of band and never want SSO to create new ones, set `sync_mode` to `UPDATE_ONLY`. --- # Quickstart > Install the Feedjolt widget, create an API key, and receive your first webhook on a local tunnel. A 10-minute developer quickstart - skip what you don't need. End state: feedback button on your site, a working API call from your terminal, and a webhook arriving at a localhost tunnel. Skip the parts you don't need. ## Prerequisites - A Feedjolt workspace. **[Sign up](/en/register)** if you don't have one. - Your **workspace slug** - the URL part. Find it at **Dashboard -> Settings -> General**. - 10 minutes. ## 1. Install the widget (2 min) Paste this before `` on any page of your site: ```html ``` Reload the page. You should see a floating "Feedback" button. Click it; the widget opens. Submit a test post. It should appear in your dashboard at **Dashboard -> Boards -> [your default board]** within seconds. ## 2. Get an API key (3 min) **Dashboard -> Settings -> API keys -> New key**. - **Name** it something honest: `local-dev-marc`, not `key`. - **Scopes**: pick read-only scopes to start. - **Copy** the key when shown. It starts with `fjk_`. **You won't see it again.** Test it (replace `YOUR_BOARD_SLUG` with one of your boards): ```bash curl -H "Authorization: Bearer fjk_YOUR_KEY" \ "https://api.feedjolt.com/api/v1/boards/YOUR_BOARD_SLUG/posts?limit=5" ``` You should get JSON with up to 5 posts. If you get `401`, the key is wrong or revoked. If `403`, the scope is too narrow. The full endpoint reference is at **[https://api.feedjolt.com/docs](https://api.feedjolt.com/docs)**. ## 3. Receive a webhook (5 min) For local dev, you'll need a tunnel. We recommend [ngrok](https://ngrok.com) or [Cloudflare Tunnel](https://www.cloudflare.com/products/tunnel/). ```bash ngrok http 3000 # -> https://abc123.ngrok-free.app ``` In your code, accept POST requests: ```ts // Node + Express import express from "express"; const app = express(); app.use(express.json()); app.post("/feedjolt-webhook", (req, res) => { console.log("event:", req.headers["x-feedjolt-event"]); console.log("body:", req.body); res.status(200).send("ok"); }); app.listen(3000); ``` In Feedjolt: **Dashboard -> Settings -> Webhooks -> New endpoint**. - **URL**: `https://abc123.ngrok-free.app/feedjolt-webhook` - **Events**: pick a few (e.g., `post.created`, `status.changed`). - Click **Save**. Copy the **signing secret**. Trigger an event by **submitting a feedback post** (use the widget you just installed). Within ~5 seconds, your endpoint should receive a POST. > **Sign verification** is essential before going to production. See **[Webhooks: signing](/en/docs/developers/webhooks/signing)**. ## 4. Cleanup - Revoke the API key when done testing: **Settings -> API keys -> Revoke**. - Delete the test webhook endpoint: **Settings -> Webhooks -> Delete**. - Delete test posts: open the post -> **Delete**, or use the API. ## What next - **[Widget config](/en/docs/developers/widget/configuration)** - the five `data-*` attributes. - **[Webhook signing](/en/docs/developers/webhooks/signing)** - verify the requests are really from us. - **[API reference](https://api.feedjolt.com/docs)** - every endpoint, with try-it. If anything in this guide didn't work, **[file a bug](/en/contact)** - we want this guide to be friction-free. **Agents proving UI changes locally?** See [For agents → Local verification](/en/docs/developers/for-agents#local-verification-contributors). --- # Sandbox and trial > How agents and developers try Feedjolt without a sales call: self-serve signup, the Growth trial, and Startup API keys. There is **no separate sandbox cluster**. You try Feedjolt against a real workspace you own. ## Product UI trial Every new workspace gets a **14-day Growth trial**. No credit card. That trial is for the dashboard, portal, and roadmap — not for the developer API. See [Trial](/en/docs/billing/trial). ## Developer access (REST + MCP) REST API keys and the MCP server are a **Startup and Scale** feature (the barbell: Growth trades those developer tools away for higher seat/AI limits). They are **self-serve**: 1. Create an account (magic link or Google) at [https://www.feedjolt.com](https://www.feedjolt.com). 2. Create a workspace. Choose an EU or US file-storage bucket (cannot be changed later). 3. Choose **Startup** (or Scale) in **Settings → Billing**. Startup is the cheapest plan that includes the API. 4. Open **Settings → API keys → New key**. The full key (`fjk_…`) is shown once. 5. Call `https://api.feedjolt.com/api/v1/…` with `Authorization: Bearer fjk_…`, or add Reader (`https://api.feedjolt.com/mcp/reader/`) and Writer (`https://api.feedjolt.com/mcp/writer/`) as separate MCP servers. Combined `https://api.feedjolt.com/mcp/` is legacy. No sales form. No waitlist. ## Inspect without a key These files are public: - OpenAPI: [https://www.feedjolt.com/openapi.json](https://www.feedjolt.com/openapi.json) - MCP server card: [https://www.feedjolt.com/.well-known/mcp.json](https://www.feedjolt.com/.well-known/mcp.json) - Agent index: [https://www.feedjolt.com/llms.txt](https://www.feedjolt.com/llms.txt) - Full docs: [https://www.feedjolt.com/llms-full.txt](https://www.feedjolt.com/llms-full.txt) - Interactive API docs: [https://api.feedjolt.com/docs](https://api.feedjolt.com/docs) ## What we do not offer - A hosted shared sandbox with dummy data. - API keys on the Growth trial. - "Contact sales to enable the API." --- # Billing > How billing works in Feedjolt: per-workspace plans, the 14-day Growth trial, Creem and Stripe payments, invoices, role access, payment failures, refunds and cancellation. Billing is per workspace. One Feedjolt account can own multiple workspaces, each with its own plan and payment method. ## Pages - **[Plans](/en/docs/billing/plans)** - Startup, Growth, Scale, and what's included. - **[Startup pricing](/en/docs/billing/startup-pricing)** - how to apply for the $9 plan. - **[Trial](/en/docs/billing/trial)** - every new workspace gets one. ## Quick facts - **Three paid plans** - Startup ($9/mo), Growth ($19/mo), Scale ($49/mo). There is no self-serve free tier (see **Free license** below for admin-granted exceptions). - **Trial** - every new workspace gets a 14-day trial of **Growth**, no card up front. - **Startup** - application-based; apply from Billing. See **[Startup pricing](/en/docs/billing/startup-pricing)**. - **Payments** - new subscriptions check out through Creem (Merchant of Record). Existing Stripe customers stay on Stripe. We never see your card. - **Currencies** - USD by default. EUR available on request. - **Tax** - collected at checkout from your billing address. - **Invoices** - emailed to the OWNER on each charge. Downloadable from the dashboard. ## Where to manage **Dashboard -> Settings -> Billing** (OWNER only). From here you can: - See current plan and usage. - Upgrade / downgrade. - Update payment method. - Cancel. - Download past invoices. - Open the billing portal (Stripe or Creem, matching how you pay). ## Free license Some workspaces run on a **free license** instead of a paid plan - granted by a Feedjolt admin, not something you can self-serve. A free-license workspace: - Shows a **Free license** badge on **Settings -> Billing** instead of a plan price. - Gets **full access to its assigned tier** - the same seats, quotas, and features as a paying workspace on that plan. - Has **no billing and no card on file** - nothing to add, nothing to be charged. Workspaces created by a Feedjolt admin are automatically placed on a free Scale license. ## Who can do what - **OWNER** - full access. Sees billing, can change plan, can update card. - **ADMIN** - can **see** billing (usage, current plan) but cannot change it. - **CONTRIBUTOR** - no billing access at all. ## Payment failures If a card payment fails, we retry for 14 days. During this period: - The product keeps working. - The OWNER gets daily emails. - After 14 days without a successful charge, the workspace goes **read-only**. Your data stays intact and the public portal stays live - end-users can still submit - but admins can't make changes until payment is restored. To recover: update your payment method, then click **Retry payment**. ## Refunds We handle refunds case by case via support - email **support@feedjolt.com** within 30 days of charge. For annual plans, pro-rated refunds are negotiable. ## Cancellation Cancel anytime from the billing portal. Stripe customers stay active until the end of the current billing period. If you pay through Creem, canceling in the hosted portal may end access immediately. After that - or if a subscription lapses - the workspace goes **read-only** until you reactivate it from Billing. A read-only workspace keeps all its data, and its public portal stays live so end-users can keep submitting. You can re-subscribe at any time; data is preserved indefinitely. ## Reactivating a canceled subscription A workspace goes read-only when its subscription is canceled - typically because a trial ended without a card on file, or a subscription lapsed after cancellation. The dashboard shows a read-only banner and admins can't make changes until you reactivate. To reactivate: the OWNER opens **Settings -> Billing** and clicks the **Reactivate** button (it names your previous plan, e.g. "Reactivate Growth"). This restarts the subscription at the plan you were previously on. Returning Stripe customers reuse Stripe Checkout (saved card + promo codes). Everyone else checks out through Creem. The workspace becomes active again as soon as payment completes. --- # Plans > Compare Feedjolt plans: Startup, Growth, and Scale. See seats, AI quotas, premium features, trial behavior, and how annual versus monthly billing works. Three plans. Pick the smallest one that fits. ## At a glance | | **Startup** | **Growth** | **Scale** | | --- | :---: | :---: | :---: | | Price | $9 / month | $19 / month (or $15 billed yearly) | $49 / month (or $39 billed yearly) | | Admin seats | 2 | 25 | 50 | | CONTRIBUTOR seats | unlimited | unlimited | unlimited | | End-user seats | unlimited | unlimited | unlimited | | Boards | unlimited | unlimited | unlimited | | Posts per month | unlimited | unlimited | unlimited | | Public portal | ✅ | ✅ | ✅ | | Roadmap | ✅ | ✅ | ✅ | | Changelog | ✅ | ✅ | ✅ | | Embed widget | ✅ | ✅ | ✅ | | Linear integration | ✅ | ✅ | ✅ | | Webhooks | ✅ | ❌ | ✅ | | Public API (REST & MCP) | ✅ | ❌ | ✅ | | Email intake | ✅ | ✅ | ✅ | | AI features (auto-tagging, summarization) | 1,000 / month | 5,000 / month | 15,000 / month | | Slack integration | ✅ | ❌ | ✅ | | GitHub changelog drafts | ✅ | ❌ | ✅ | | Saved views | ✅ | ❌ | ✅ | | Audit logs | ✅ | ❌ | ✅ | | Advanced permissions | ✅ | ❌ | ✅ | | Retention controls | ✅ | ❌ | ✅ | | Custom email domain | ✅ | ❌ | ✅ | | Advanced AI (sentiment) | ✅ | ❌ | ✅ | The plans are a **barbell**. Ten premium features - Slack integration, GitHub changelog drafts, webhooks, the public REST & MCP API, saved views, audit logs, advanced permissions, retention controls, custom email domain, and advanced AI (sentiment) - ship on **Startup and Scale**, and are the one thing **Growth** trades away. Startup is the super-offer: every feature Scale has, capped only by small limits (2 admin seats, 1,000 AI ops, monthly-only). Growth drops that premium set in exchange for a lower per-feature price and much higher capacity - 25 admin seats and 5,000 AI ops. Scale has everything plus the top limits. Every other (floor) feature is on all three plans. **Startup** is monthly-only - no annual option. **Growth** and **Scale** offer a lower price when billed yearly. ## How limits work - **Admin seats** - counted as `OWNER + ADMIN` total. Hitting the limit blocks new ADMIN invites; existing members keep working. CONTRIBUTOR seats and end-user seats are **unlimited** on every plan. - **Posts per month** - **unlimited** on every plan. - **AI quota** - counts AI operations (auto-tagging, post-summarization, semantic search). Counts hard-stop at the limit: 1,000 on Startup, 5,000 on Growth, 15,000 on Scale per month. ## Startup is application-based Startup at $9/month is reserved for genuine early-stage teams. You apply from **Dashboard → Billing**, submit your product URL and what you're building, and a reviewer decides. As you grow past the 2 admin-seat limit you move up to Growth. Full walkthrough: **[Startup pricing](/en/docs/billing/startup-pricing)**. ## Trial Every new workspace starts on a **14-day trial of Growth** by default. No card required. After trial: - **You added a card** → you're charged for the plan you picked. - **You didn't** → the workspace goes **read-only**. Your data stays intact, the public portal stays live, and end-users can still submit. Reactivate any time by adding payment from **Settings → Billing**. Read more: **[Trial](/en/docs/billing/trial)**. ## Annual vs monthly Growth and Scale are cheaper billed yearly ($15/mo and $39/mo respectively, versus $19 and $49 monthly). Startup is monthly-only. Pick at upgrade time. ## Upgrading and downgrading - **Upgrades** apply immediately. You get pro-rated credit for the unused portion of your current plan; the new plan kicks in. - **Downgrades** apply at the end of the current billing period. Until then, you keep paid features. If you downgrade and you're over the new plan's admin-seat limit (e.g., you have 30 admins on Growth's 25-cap), incoming admins are blocked but existing ones aren't kicked out. You'll see a warning in the dashboard until you reduce seats or upgrade back. ## Custom enterprise For workspaces that need: - Custom contracts / DPA / security review. - A custom invoice flow. - Volume beyond Scale's limits. Email **enterprise@feedjolt.com**. --- # Startup pricing > How the $9 Startup plan works on Feedjolt: apply with your product details, get reviewed by a human, and subscribe with Scale features at startup limits. The **Startup** plan is application-based: it's reserved for genuine early-stage startups, solo founders, and very small teams. An approved Startup workspace gets the **full feature set - the same features as Scale**: Slack, GitHub changelog drafts, audit logs, advanced permissions, retention controls, email intake, advanced AI (sentiment), and everything else. Feature parity is the headline perk of the super-offer. The only ceilings are **2 admin seats** and **1,000 AI ops per month** (and monthly-only billing). You're not on a stripped-down tier - you're on Scale's feature set with startup-sized limits. ## How to apply 1. Open **Dashboard → Billing**. 2. On the **Startup** plan, click **Apply for Startup pricing**. 3. Tell us your **product URL** and a sentence on **what you're building** (optional extra links help). 4. Submit. Your application goes to review. While your application is pending, your **trial keeps running** - you don't lose access. ## Review Each application is reviewed by our team (an AI assists by scoring how early-stage the product looks, but a human makes every decision). You'll get an email when it's decided: - **Approved** - you can subscribe to Startup at the discounted price right from Billing. - **Not approved** - you can edit your application and re-apply, or continue on a higher plan. ## Growing out of Startup Startup is for small teams. As your team grows past the Startup seat limit, you'll move up to the next plan - the discount is for getting started, and it grows with you. --- # Trial > Every new Feedjolt workspace gets a 14-day Growth trial with no card required. See what is included, the reminders, and what happens when the trial ends. Every new workspace gets a **14-day trial of the Growth plan**. No card required up front. ## What's included The full Growth plan: every integration, unlimited boards, 25 admin seats, the Growth AI quota - everything Growth ships. The trial is unrestricted. ## When it starts The moment you create the workspace. The clock starts immediately, even if you don't actually use the workspace until day 5. ## Reminders - **Day 3** - "Trial ending in 11 days" email. We name a couple of high-leverage features you might not have tried yet. - **Day 13** - "Last day" email with a clear "what happens at midnight" rundown. If you already converted to a paid plan, both emails read more like "you're about to be charged on day 14" - same calendar, different framing. New trials do not create a card or a billing customer until you convert. ## What happens at the end - **You added a card** → you're charged for the plan you selected (change it in **Settings -> Billing -> Plan** before the trial ends). - **You didn't add a card** → the workspace goes **read-only**. Paid features stop: - Slack stops posting. - Webhooks pause delivery. - The dashboard becomes view-only for admins - no new edits. - Existing data is **preserved**. Nothing is deleted. - The public portal stays live; end-users can still submit feedback. Reactivate any time by adding payment from **Settings -> Billing**. ## Converting mid-trial **Settings -> Billing** → pick a plan (or keep Growth). That opens checkout. You are charged when you convert, not at the end of an unused trial. You can also start an annual plan during trial; billing starts at checkout. ## Extending a trial Trials can be extended by support in unusual cases (security review delays, procurement holds). Email **support@feedjolt.com** before day 13. We don't routinely extend trials for "I'm still evaluating" - use the trial to *fully* stress-test the paid features before your card is charged. If you're a genuine early-stage team, you can also [apply for Startup pricing](/en/docs/billing/startup-pricing) at $9/month. ## Re-trialing A workspace gets one trial in its lifetime. Recreating the workspace doesn't reset the trial counter (we track it on your account). If you're piloting Feedjolt across multiple companies as a consultant, contact us - we'll find a sensible arrangement. --- # Pick a data region > Uploaded files go to an EU or US storage bucket you choose. The choice is per-user, permanent, and inherited by your workspaces. Uploaded files go to an EU or US storage bucket you choose. You pick at sign-up. The choice is per-user and **cannot be changed later**. ## What's the difference? - **EU**: uploads go to the `feedjolt-eu-private` bucket. - **US**: uploads go to the `feedjolt-us-private` bucket. If you select "no preference", the choice defaults to US. ## What about workspaces? When you create a workspace, it inherits **your** choice. Files uploaded to that workspace go to that workspace's bucket. If you join a workspace someone else created, uploads to that workspace use the creator's bucket, not yours. ## Why is it permanent? The choice is set at sign-up and cannot be changed later. If you need the other bucket, the path is: export your data, delete the workspace, recreate it under an account that chose the other option. --- # Getting started > Go from zero to your first Feedjolt feedback post in five minutes: sign up, pick a file-storage bucket, create a workspace and board, and invite your team (optional). The shortest path from zero to your customers voting on your roadmap. ## The five-minute setup 1. **[Sign up](/en/docs/getting-started/sign-up)** - magic link or Google. No password. 2. **[Pick a data region](/en/docs/getting-started/data-region)** - EU or US file-storage bucket. Decide once; it's permanent. 3. **[Create your workspace](/en/docs/getting-started/workspace)** - pick a slug; that's your portal URL. 4. **[Create your first board](/en/docs/concepts/boards#creating-a-board)** - one is enough to start. 5. **[Invite teammates](/en/docs/getting-started/invite-team)** _(optional)_ - they'll triage with you. Flying solo? Skip it. That's it. Send your portal URL (`feedjolt.com/p/your-slug`) to a customer and they can submit feedback. ## What you should know before you start - **You start on a 14-day Growth trial.** No credit card. All core features while it runs; pick a plan before it ends to keep editing. - **The file-storage bucket you pick is permanent.** Read [data region](/en/docs/getting-started/data-region) first. - **Slugs are URL-visible.** `acme-corp` is fine; `my-cool-feedback-board-final-v2` will follow you forever. --- # Invite your team > Invite teammates to your Feedjolt workspace as OWNER, ADMIN, or CONTRIBUTOR. Send invites, pick the right role, manage seat limits, and handle pending invites. Invite teammates so they can triage feedback, change statuses, and reply to customers - without needing your password (you don't have one anyway). **Flying solo?** Inviting teammates is optional. In the **Quick Setup** checklist you can **Skip** this step and your setup still reaches 100% - add people later whenever you're ready. ## Send an invite 1. **Dashboard -> Settings -> Members**. 2. Click **Invite member**. 3. Enter their email and pick a role. 4. They receive an invite email with a one-click acceptance link. Invite tokens are valid for **7 days**. Re-send if it expires. ## Pick the right role - **OWNER** - full control, including billing and deleting the workspace. Usually one person; sometimes two. **Only an existing OWNER can invite another OWNER.** - **ADMIN** - manages content, members (except other admins/owners), integrations, settings. Most of your triage team should be here. Admins can invite ADMIN and CONTRIBUTOR, not OWNER. - **CONTRIBUTOR** - can submit posts and vote. Good for engineers or designers who want to log their own ideas without seeing internal notes. Full matrix: **[Roles & permissions](/en/docs/roles)**. ## Seat limits Only **admin seats** (OWNER + ADMIN) are capped, and the cap depends on your plan: **Startup 2**, **Growth 25**, **Scale 50**. CONTRIBUTOR seats and end-user seats are unlimited on every plan. Grow past your admin cap and you move up a plan. See **[plans](/en/docs/billing/plans)**. ## Removing or changing roles - **Promote/demote**: Members list -> click a member -> change role. - **Remove**: Members list -> click a member -> Remove. Their posts and comments stay; they lose access immediately. You can't demote yourself if you're the only OWNER. Promote someone else first. ## Pending invites The Members page shows pending invites separately. You can resend or revoke before they're accepted. **Pending is not a member yet.** Until the invitee clicks the acceptance link: - They **cannot open the dashboard** for that workspace (API returns "Not a member"). - The workspace **does not appear** in their workspace picker. - They **do not receive** Weekly Jolt, trial reminders, startup-pricing mail, or the daily admin digest — even if you invited them as OWNER or ADMIN. Only the invite email goes out while pending. Everything else starts after acceptance. --- # Sign up > Sign up for Feedjolt without a password, using a magic link or your Google account. Covers the sign-up steps, linked accounts, sessions, and troubleshooting. Feedjolt is passwordless. You sign up the same way you sign in: a one-time link in your inbox or your Google account. ## Magic link 1. Go to **[feedjolt.com/en/register](/en/register)**. 2. Enter your email. 3. Solve the Cloudflare Turnstile challenge (it's quick - usually invisible). 4. Check your inbox. Click the link. Done. The link is valid for **15 minutes**. If you don't click in time, just request a new one. ## Google 1. Go to **[feedjolt.com/en/register](/en/register)** and click **Continue with Google**. 2. Pick the Google account you want to use. 3. You're in. If your Google email matches an existing magic-link account, the two are linked automatically - same user, two ways to sign in. ## Why no passwords? Passwords get reused, leaked, and forgotten. We don't want to be in the password storage business, and you don't want to remember another one. Magic links are short-lived JWTs over httpOnly cookies - same security model your bank uses, minus the friction. ## Sessions After sign-in, an access token (15 minutes) and a refresh token (7 days) live in httpOnly cookies. The frontend automatically refreshes when the access token expires; you stay signed in across browser restarts until the refresh token expires. To sign out from all sessions, see [account settings](/en/docs/account). ## Trouble? - **Didn't get the email.** Check spam. Add `noreply@feedjolt.com` to contacts. Try again. - **Link says "expired".** That's the 15-minute window. Request a fresh one. - **Google says "this email is already in use".** It is, via magic link. Sign in with magic link first, then link Google in account settings. --- # Create your workspace > Create your Feedjolt workspace: pick a name, a URL slug and inherit your file-storage bucket. Slug rules, the 14-day Growth trial, defaults you get, and multiple workspaces. A **workspace** is a Feedjolt account. Each workspace has its own boards, members, branding, and public portal URL. ## Create one After signing in, you'll be prompted to create your first workspace. You can also create a new one later from **Dashboard -> Switch workspace -> Create new**. You'll need: - **Name** - what your team calls it. Shown in the dashboard, in emails, in Slack messages. Editable later. - **Slug** - URL-safe identifier. Becomes part of your public portal URL: `feedjolt.com/p/{slug}`. Must be unique across all of Feedjolt. **Editable, but URL changes break old links.** - **File-storage bucket** - inherited from your user account. Not changeable. A 14-day Growth trial starts automatically. No credit card. Pick a plan before it ends to keep editing - without payment the workspace goes read-only (data intact, public portal stays live) until you add a plan. See [billing](/en/docs/billing). ## Naming things Slug rules: - Lowercase letters, numbers, hyphens. - 3–40 characters. - No leading/trailing hyphens. - Reserved words (`api`, `admin`, `dashboard`, `auth`, etc.) are blocked. Pick something short. `acme` beats `acme-customer-feedback-platform-v2`. You'll see this slug in URLs every day. ## What you get A fresh workspace ships with: - A **default board** (you can rename or delete). - A **default set of statuses**: `Under review`, `Planned`, `In progress`, `Shipped`. Customize anytime. - A **default tag** or two. Add your own. - A trial subscription. See [billing](/en/docs/billing). ## Multiple workspaces You can be a member of as many workspaces as you want. Switch between them via the workspace picker in the top-left of the dashboard. A user owning multiple workspaces means: your account is the OWNER of each. Each workspace has independent billing, members, and data. ## Next: invite your team Triage works better with two pairs of eyes. **[Invite teammates](/en/docs/getting-started/invite-team)**. --- # Boards > What boards are in Feedjolt: collections of posts that separate audiences, products, or stages. Covers visibility levels, moderation, voting, and deletion. A **board** is where posts live. Most workspaces have a few - one per product, or one per audience (customers vs. internal). ## When to use multiple boards - **Different audiences.** "Customer feedback" (public) vs. "Engineering ideas" (internal). - **Different products.** "Mobile app" vs. "Web dashboard". - **Different stages.** "Discovery" (raw ideas) vs. "Planned" (committed). When in doubt, start with one board. Splitting later is easy; merging is harder. ## Visibility Each board has a visibility setting: | Visibility | Who can see it | Who can submit | | --- | --- | --- | | **Public** | Anyone with the link | Anyone (no auth) | | **Authenticated** | Anyone signed in | Anyone signed in | | **Invite-only** | Workspace members + invited end users | Members + invited end users | | **Internal** | Workspace members only | Members only | Use **Internal** for engineering ideas you don't want customers reading. Use **Invite-only** for beta groups. A few behaviors worth knowing: - **Authenticated** boards show up on the portal for signed-out visitors as locked cards (name and description only) with a "Sign in to view" prompt. Posts stay hidden until sign-in. - **Invite-only** boards never appear to anyone who isn't on the invite list. Invite emails (Board settings → Invites) contain a sign-in link that's valid for 7 days — the recipient lands on the board already signed in, no code needed. Removing an invite immediately revokes its emailed link. - **Internal** boards are never published to the portal at all. ## Creating a board **Dashboard -> Boards -> New board**. You'll set: - **Name** - shown to end users. - **Slug** - URL segment in the portal. - **Visibility** - see above. - **Moderation** - if on, new posts start as **drafts** and need an admin to approve. Off by default. - **Voting** - on/off per board. Off makes it a pure submission inbox. ## Board settings Edit at **Dashboard -> Boards -> [board] -> Settings**. - **Pinned post** - appears at the top. - **Featured flag** - surfaces the board on the portal homepage. - **Sort order** - newest, top-voted, recent activity. - **Allowed post types** (if your workspace defines categories). > See [Notifications](/en/docs/workflow/notifications#daily-admin-digest) for details on the per-board digest toggle. ## Moderation When **moderation** is on, end-user submissions land in a queue. An ADMIN reviews, edits if needed, and publishes - or rejects with a reason. Members' own posts skip the queue. So do edits to existing posts. ## Deleting a board Deletion cascades - every post, comment, and vote in the board is removed. Owners get a confirmation prompt with the post count. Consider **archiving** (Settings -> Archive) instead. Archived boards are hidden from the portal but stay in the dashboard for audit and search. --- # Comments > Public discussion and private internal notes on the same Feedjolt post. Markdown, mentions, threading, pinned and incognito comments, moderation and edits. Every post has two parallel comment threads: - **Public comments** - visible in the portal. End users and members both write here. - **Internal comments** - visible only to ADMIN and OWNER. Useful for triage notes, ACME-signed-the-contract context, "let's bundle this with #142". ## Posting a comment You must be signed in. End users sign in via magic link or OAuth (same flow as members). Posting requires: - A non-empty body. - The board's visibility allows the user. Comments support Markdown and `@mentions`. Mentioning a member sends them a notification. ## Threading Comments can have one level of replies (parent -> child). We chose not to support deep threading because public feedback discussions tend to spiral. One level is enough to acknowledge "good point" without hiding the original topic three levels deep. ## Internal comments When writing a comment, ADMINs see a checkbox **Internal note**. Tick it and the comment is invisible to end users. The post's public thread shows no indication that internal notes exist. Internal comments are useful for: - Linking to internal docs or design files. - Capturing context from sales/support conversations. - "Let's not promise this until we ship X first." ## Pinned comments ADMINs can pin one comment per post. Pinned comments appear above all others. Use this for canonical "here's what we decided" responses to avoid burying them under newer chatter. ## Incognito comments When commenting on a public board, end users can choose to post **incognito** - their name is hidden from the public view. We still record their identity internally for moderation; they can edit/delete their own comments. ## Editing and deleting Authors can edit and delete their own comments. ADMINs can delete any comment (including end-user ones). Edited comments show an "edited" indicator with a timestamp. ## Moderation If a comment is flagged as spam (manually by an ADMIN or by future auto-moderation), it's hidden from the public view but kept in the database for audit. ADMINs can recover it. ## Notifications Subscribe to `comment.created` events at **Settings -> Notifications -> Subscriptions** to get pinged on new comments - per-board or workspace-wide. --- # Core concepts > The Feedjolt mental model: workspaces hold boards, boards hold posts, and posts have votes, comments, statuses, and tags. The model fits on a napkin. The model is small enough to fit on a napkin. ``` Workspace └── Board └── Post ├── Votes ├── Comments (public + internal) ├── Status └── Tags ``` A few extras live alongside: - **Members** belong to the workspace and have a role. - **End users** are your customers; they vote and submit feedback. - **Statuses** are workspace-scoped and customizable. - **Tags** are workspace-scoped. - **Subscriptions** route notifications to email or Slack channels. - **Integrations** sit at the workspace level. ## The pages - **[Workspaces](/en/docs/concepts/workspaces)** - the top-level container. - **[Boards](/en/docs/concepts/boards)** - collections of posts. - **[Posts](/en/docs/concepts/posts)** - feedback items. - **[Statuses](/en/docs/concepts/statuses)** - where a post is in your workflow. - **[Voting](/en/docs/concepts/voting)** - how prioritization works. - **[Comments](/en/docs/concepts/comments)** - public + internal threads. - **[Tags](/en/docs/concepts/tags)** - labels for filtering. If you understand workspaces, boards, and posts you can skip ahead to **[Workflow](/en/docs/workflow)**. Everything else is detail. --- # Posts > A post is a single piece of feedback in Feedjolt: title, body, status, tags, votes, and comments. Learn how posts are submitted, edited, merged, and moved. A **post** is one feedback item. "Add dark mode", "Sign-up form is broken on Safari", "What if we supported SAML SSO". ## Anatomy Every post has: - **Title** (required, short). - **Body** (Markdown - links, lists, code blocks). - **Status** - one of your workspace's [statuses](/en/docs/concepts/statuses). Defaults to "Under review". - **Tags** - zero or more [tags](/en/docs/concepts/tags). - **Author** - either an admin (you) or an end user (your customer). - **Votes** - count + the list of voters. - **Comments** - public thread + internal-only thread. - **Attachments** - images and files (paid plans). Plus internal flags: - **Draft** - not published yet (used when board moderation is on). - **Internal** - hidden from the public portal. - **Incognito** - author hidden from the public view. - **Spam** - flagged but not auto-deleted. ## Submitting End users submit via the public portal or the [embedded widget](/en/docs/portal/widget). Members submit from the dashboard. For **public boards**, submission requires nothing - name + email is asked but optional. For **invite-only** or **authenticated** boards, the submitter must sign in. ## Editing Authors can edit their own posts. ADMINs can edit any post. Edit history isn't shown in the public portal but is recorded. ## Merging duplicates If two posts are the same idea, an ADMIN can merge them. The workspace OWNER can also turn on opt-in auto-merge. The source post redirects to the target; votes and comments transfer. See **[Merging duplicates](/en/docs/workflow/merging)**. ## Visibility flags - **Internal** - hide from public portal but visible to members. Useful for raw triage notes. - **Incognito** - author hidden. Use when a customer wants to stay anonymous. - **Spam** - marks the post but doesn't delete. ADMINs can still see and recover. ## Moving a post between boards Filed a post on the wrong board? Owners and Admins can move it. Open the post, click the **⋯** menu, and choose **Move to board…**. Pick the destination board and confirm. The post keeps its status, tags, votes, comments, and subscribers — only the board changes. If the destination board has different visibility (for example moving a public post to an **Internal** board), Feedjolt warns you first, because it changes who can see the post. ## Voting One vote per user per post. Toggling adds or removes. Anonymous voting is allowed on public boards (rate-limited by IP). See **[Voting](/en/docs/concepts/voting)**. ## Comments Public comments appear in the portal. Internal comments are member-only. See **[Comments](/en/docs/concepts/comments)**. ## Notifications When a post's status changes, the author and all subscribers are notified - by email and (if connected) in the workspace's Slack channel mappings. See **[Notifications](/en/docs/workflow/notifications)**. --- # Statuses > Statuses track where a post sits in your workflow. Rename, recolor, and reorder them, and map your statuses to the three public roadmap buckets in Feedjolt. A **status** is the state a post is in: "Under review", "Planned", "Shipped", whatever your team uses. ## Defaults A new workspace ships with five statuses: - **Open** - the default for new submissions. Not on the roadmap. - **Under Review** - being triaged. Not on the roadmap. - **Planned** - committed, on the roadmap, not started yet. - **In Progress** - actively being built. - **Complete** - done. You can rename, recolor, reorder, or delete any of these. ## Custom statuses **Dashboard -> Settings -> Statuses**. For each status: - **Name** - short, action-oriented. "Researching" beats "TBD". - **Color** - used in the dashboard and portal. - **Sort order** - controls the column order on the dashboard [roadmap](/en/docs/portal/roadmap). - **Show on roadmap** - toggle. Only statuses with this on appear as columns on the **dashboard** roadmap. - **Public bucket** - `Planned`, `In Progress`, `Done`, or `Hidden`. Controls which column (if any) the status maps to on the **public** portal roadmap. - **Default** - exactly one status is the default for new posts. ## Dashboard roadmap vs public roadmap Two views, two controls: - The **dashboard roadmap** has one column per status with `Show on roadmap` on, ordered by sort order. Optimised for member triage. - The **public roadmap** always has exactly three columns - **Planned**, **In Progress**, **Done** - and groups your statuses into those buckets via the `Public bucket` field. A status with no bucket assigned never appears on the public roadmap. That separation lets you keep a fine-grained internal workflow (`Researching`, `Up next`, `Beta`, `GA`) while showing customers a simple three-step story. Configure the mapping at **Dashboard -> Portal -> Public roadmap**. ## Workflow rules We don't enforce status transitions. You can move a post from "Shipped" back to "Under review" if you need to. Power-tool, sharp edges; we trust you. If you want guardrails, a future "workflow rules" feature is on the [roadmap](https://www.feedjolt.com/en/portal/luodaint/roadmap). Until then, train your triage team. ## What changing a status does Changing a status: 1. **Records a status change event** with who, when, from -> to. 2. **Triggers notifications**: email to the post author and subscribers; Slack message if the workspace has a channel mapping for `status.changed`. 3. **Moves the post** on the dashboard roadmap (if "Show on roadmap" is on for both old and new status) and on the public roadmap (if both statuses have a public bucket assigned). 4. **Optionally publishes a changelog entry** - for status changes to a "Done"-bucket status, you can promote the post to a [changelog](/en/docs/portal/changelog) entry in one click. ## Status history Every status change is logged. Open a post in the dashboard and click **History** to see the full timeline (post created -> status changed -> ...). This data is API-accessible via [the public API](/en/docs/integrations/api). --- # Tags > How tags work in Feedjolt: workspace-wide labels for grouping and filtering posts. Covers automatic tagging, colors, filtering, and renaming or deleting tags. **Tags** are short labels you stick on posts to group them. `bug`, `mobile`, `api`, `vip-customer`, `q3-priority` - whatever helps your team. ## Workspace-scoped Tags are defined at the workspace level, not per board. A tag exists once and can be applied across all boards in the workspace. The list is shared. ## Creating tags Tags are created on-the-fly when you tag a post. Type a new label in the tag picker and it gets added to the workspace tag list. You can also pre-create tags at **Dashboard -> Settings -> Tags**. ## Automatic tagging Every new submission is categorized the moment it comes in. When someone posts feedback, Feedjolt reads the title and body and applies the most relevant tags automatically - so your team can filter, search, and prioritize without any manual setup. How it works: - **Reuses your tags first.** It picks from the tags you already have whenever one fits. - **Creates new tags when nothing fits** - capped so the list can't sprawl (it stops inventing new tags once the workspace has built up a healthy set of auto-created ones). - **Never removes your tags.** Auto-tagging only adds; tags you applied by hand always stay. - **Runs in the background.** Tagging happens just after the post is created, not while the submitter waits. Automatic tagging is available on **Startup and up**. It's on by default - turn it off any time at **Dashboard -> Tags**, at the top of the page. ## Tagging posts In the dashboard, open any post and use the tag picker. Multiple tags per post are fine. Members of any role can tag posts (CONTRIBUTOR included), unless you've restricted it. End users don't see the tag picker on the portal; only members tag. ## Filtering In the dashboard: - **Boards list** -> filter by tag(s) to narrow the view. - **Reports** -> tag-based aggregations (e.g., "votes per tag"). In the public portal: - Tags appear on posts. Clicking a tag filters the board's post list. ## Tag colors Each tag has a color. Default colors are auto-assigned; override at **Settings -> Tags**. ## Renaming and deleting - **Rename** - updates the label everywhere instantly. - **Delete** - removes the tag from all posts. The posts themselves stay. ## When tags get out of hand Tag systems erode. Three rules to keep them useful: 1. **Audit quarterly.** Delete tags you stopped using; merge near-duplicates (`mobile` and `mobile-app`). 2. **Keep the list small.** Under 30. If you have 100, you're using tags as a project management tool - that's a job for a status, a label per board, or a separate tool. 3. **Decide tag names ahead of time.** Don't let everyone invent. Tag drift is real. --- # Voting > How voting works in Feedjolt: one vote per user per post, admin + gym-weight 1.5× scoring on admin boards, raw counts on the public portal. Voting is how customers tell you what matters most. - **One vote per user per post.** Click again to remove it. - **Base weight is 1.0.** Workspace admins and users you mark with the gym-weight icon count **1.5×**. - **Admin boards and the roadmap sort by weighted score.** The public portal still shows raw vote counts. - **The gym-weight icon is admin-only.** Customers and non-admins never see it. ## Who can vote Per board: - **Public board** - anyone, including unauthenticated visitors. Anonymous votes are tracked by browser cookie + IP rate-limited. - **Authenticated board** - anyone signed in. - **Invite-only / Internal** - only members (and invited end users for invite-only). ## Weighted votes (admin) A vote is still one click. Weighting only changes how the dashboard ranks posts: | Voter | Weight | | --- | --- | | Workspace OWNER or ADMIN | 1.5 | | User marked with the gym-weight icon | 1.5 | | Everyone else | 1.0 | Mark a user from **Dashboard → Users**. The control is a gym-weight icon. It never appears on the public portal, and contributors do not see it. Admin boards and the roadmap sort by that weighted score. The portal stays an honest raw tally so customers see the same number they clicked. There is no ARR, plan, or segment matrix. Those attributes do not change vote weight. ## Vote on behalf ADMINs can cast votes on behalf of a customer (e.g., when you take feedback over a sales call). This is logged: the vote shows the end user as the voter, but `voted_on_behalf_by` records the admin who did it. ## Vote thresholds and notifications You can subscribe to a `vote.threshold` event - get a Slack/email ping when a post crosses 10, 50, 100, or a custom number of votes. Set it up at **Dashboard -> Settings -> Notifications -> Subscriptions**. ## Anonymous voting On public boards, visitors can vote without an account. We assign a long-lived browser cookie so they can change their vote later. Same person, two devices = two votes. We're aware. Trade-off vs. forcing sign-up: removing friction wins for early-stage products. If anonymity is causing you pain, switch the board to **authenticated**. --- # Workspaces > A Feedjolt workspace is the top-level container for boards, posts, members, integrations, branding, and billing. Learn its identity, settings, and deletion. A **workspace** holds everything: boards, posts, members, integrations, branding, billing. ## Identity Each workspace has: - **Name** - display name, editable. - **Slug** - URL-safe ID. Used in `feedjolt.com/p/{slug}`. Editable, but old URLs 404 after a change. - **Logo** - uploaded to the workspace's storage bucket. Shown in dashboard, portal, emails. - **File-storage bucket** - inherited from the creator. Cannot be changed later. ## Members Members have one of three roles: **OWNER**, **ADMIN**, **CONTRIBUTOR**. See **[Roles & permissions](/en/docs/roles)** for the full matrix. A workspace must have at least one OWNER. The first one is whoever created it. ## Boards A workspace can have many boards. Boards isolate feedback by audience: e.g. one for customers, one for internal-only ideas. See **[Boards](/en/docs/concepts/boards)**. ## Settings Workspace settings live at **Dashboard -> Settings**. Common things you'll set: - Logo and brand color (used in the public portal and the widget). - Default board (which board the widget opens to first). - Notification defaults (email, Slack channel mappings). - Integrations (Slack, Linear, webhooks, API keys). - Billing. ## Public portal URL Every workspace gets a public portal at `feedjolt.com/p/{slug}` (also reachable as `feedjolt.com/{locale}/portal/{slug}`). That's where end users land when they click a link in a notification email. See **[Portal](/en/docs/portal)**. ## Multiple workspaces You can own or join more than one workspace. Each is independent - separate billing, separate members, separate data. Switch between them in the top-left of the dashboard. ## Deletion Owners can delete a workspace from **Settings -> Danger zone**. Deletion cascades: every board, post, comment, vote, integration, and uploaded file is removed. There is no soft-delete and no recovery. You'll be prompted to type the slug to confirm. --- # Following posts > Follow a Feedjolt post to get email updates when its status changes, new comments arrive, or it's merged. Follow without voting and unsubscribe anytime. When you submit a post, vote on a post, or comment on a post, you're automatically **following** it. You'll get notified when: - The **status** changes (e.g., "Planned" -> "In progress" -> "Shipped"). - A **new comment** is posted (including the team's responses). - The post is **merged** into another (with a link to the merged target). ## Following without voting Sometimes you want updates on a post without voting (it's already at high counts; you just want to track it). Click **Follow** on the post. Same notifications, no vote added. ## Unfollowing Three ways: - Open the post, click **Unfollow**. - Click **unsubscribe** in any notification email about that post. - Manage everything at `feedjolt.com/p/{slug}/email-preferences`. ## What you'll see Notifications come by **email** by default. The email contains: - The post title and a link. - What changed (status, new comment, etc.). - A one-click unsubscribe link. The team running the portal can configure email frequency per their needs. Most portals send instantly; a few batch into a daily digest. ## In-app notifications Currently email-only. In-app notifications (a bell icon on the portal) are on the [roadmap](https://www.feedjolt.com/en/portal/luodaint/roadmap). ## When you stop getting emails We stop sending status emails when the post moves to a **terminal status** (usually "Shipped" or "Won't fix"), unless you've explicitly subscribed to "all changes including post-shipped". This keeps "Shipped" notifications from being followed by months of edits to the changelog entry. If you really want every change forever, set up a webhook (if you're a developer) - see **[Webhooks](/en/docs/integrations/webhooks)**. --- # For customers > Using a product that runs on Feedjolt? Learn how to submit feedback, vote on requests, follow posts for updates, and what happens with your email and privacy. If you're reading this, you're probably submitting feedback to a company that uses Feedjolt to run its public roadmap. These pages are for **you** - the customer - not the team running the product. ## What you can do - **[Submit feedback](/en/docs/for-customers/submit)** - file a request, report a bug, ask a question. - **[Vote](/en/docs/for-customers/voting)** - tell the team what you want most. - **[Follow posts](/en/docs/for-customers/following)** - get notified when something changes. ## Quick orientation The team you're giving feedback to has a **portal** - a public page that looks something like `feedjolt.com/p/their-slug`. On that portal you'll find: - **Boards** - sections for different kinds of feedback (e.g., "Customer feedback", "Bug reports", "Feature requests"). - A **roadmap** - what's planned, in progress, or shipped. - A **changelog** - a feed of what's recently changed. - A search box. You don't need a Feedjolt account to read or vote on most portals. Submitting a post or commenting will ask for your email - that's so the team can follow up with you. ## Privacy - Your email is **only** used to notify you about your own posts and votes. It's not shared with the team in a marketing context. - You can unsubscribe from any email with one click. - You can delete your end-user account at any time at `feedjolt.com/p/{slug}/account`. ## Reaching the team Each portal has a "Contact" link in the footer (or it should). If you can't find one, check the company's main website. For Feedjolt-the-platform itself (this docs site, the way the portal works in general), contact us at **[/en/contact](/en/contact)**. --- # Submit feedback > How to submit feedback on Feedjolt, on the portal or through the embedded widget. Covers writing a good post, editing or deleting it, and anonymous submissions. There are two ways to submit feedback: **directly on the portal**, or **through the embedded widget** on the company's site. ## On the portal 1. Open the portal - it'll look like `feedjolt.com/p/{slug}` or be linked from the company's website. 2. Pick a **board**. The default is usually fine if you're not sure. 3. Click **Submit feedback** (or whatever the team's renamed it). 4. Fill in: - **Title** - short and specific. "Sign-up form rejects valid emails on Safari" beats "Bug". - **Body** - Markdown supported. Include screenshots, steps to reproduce, links. - Your **email** - required for some boards, optional for others. If you provide it, you'll get notified when the team replies or changes the status. 5. Click **Submit**. You'll see your post appear immediately. If the board has **moderation** on, your post will read "Under review" and appear after an admin approves. ## Through the widget Some companies embed a small "Feedback" button on their app. Click it; the same submission form opens in an overlay. The widget can search existing feedback before you submit, so if your idea has been requested already, you can vote on it instead of creating a duplicate. ## What makes a good post - **One idea per post.** "Add dark mode and also fix sign-up" is two posts, vote-fragmented. - **What, then why.** "Add CSV export" + "I need to email reports to my boss every Friday." - **Screenshots for bugs.** A 30-second screen recording is better than a paragraph of "it doesn't work". - **Search before posting.** If a similar post exists, vote and comment on it instead. ## After submitting You'll receive: - An **email confirmation** that your post was created. - **Notifications** when the status changes ("Planned", "In progress", "Shipped"). - **Notifications** when someone comments on your post. You can opt out of any of these in **email preferences** (link in any notification email). ## If you need to edit or delete You can edit your own posts. Open the post you submitted; you'll see an **Edit** button. Deleting your own post is also supported. The post is marked deleted; votes and comments are removed. ## If you submit anonymously Some boards allow anonymous submission (no email). In that case: - You won't get notifications. - You can't edit or delete (we have no way to verify you're the original author). - The post still appears publicly. If you need to be anonymous to the public but identifiable to the team, use the **incognito** option (when available) - your name is hidden from public view but the team sees you. --- # Voting > How to vote on Feedjolt posts: click upvote, click again to remove. One vote per post, anonymous voting on public boards, and what your vote means to the team. Voting tells the team which posts matter most to you. The more votes a post gets, the more visible it is on the roadmap. ## How to vote On any post: - Click the **upvote** button (usually a number next to a triangle/arrow). - The number goes up. Yours is counted. - Click again to **remove** your vote. You can vote on as many posts as you want. There's no quota. ## One vote per person, per post You can't vote twice on the same post. If you cared about it twice as much, leave a comment explaining why; that's actionable in a way that "vote weight" isn't. ## Anonymous voting On **public boards**, you can vote without signing in. Your vote is tracked by a browser cookie - clear cookies and you'll lose your vote (the count, the post will keep). On **authenticated boards**, voting requires sign-in (magic link to your email). ## What your vote does A vote increments the post's count. The team sees: - The total vote count. - The list of voters (with email if you signed in, or "Anonymous" if you didn't). - Optional **vote thresholds** - the team can set up alerts when a post crosses 10, 50, or any number of votes. Your email is **not** shared with the team beyond this internal list. They can email you (if your post receives a comment or status change) but they can't pull your data into a CRM. ## Why votes matter - Posts with more votes appear higher in default sorting. - The team's roadmap discussions usually start with "what's getting the most votes". - If a feature you want is at 3 votes, recruiting a few colleagues who also want it is a real signal. ## What votes don't mean - The team is not **obligated** to build the most-voted post. Some popular requests are bad ideas; some unpopular requests are critical bugs. Votes are one signal among many. - A "Won't fix" status doesn't mean "we hate you" - it usually means "we considered this carefully and it doesn't fit our direction". Comments on the post should explain why. ## Vote-on-behalf If you've talked to the team directly (sales call, support ticket), they can record your vote on the relevant post on your behalf. You'll see it on the post under your email/name. Removing it works the same way as a vote you cast yourself - open the post, click the button. --- # Branding > Make your Feedjolt portal feel like your product: set the logo, favicon, primary color, name, and custom labels, hide the badge, and inherit branding in emails. Your portal can - and should - look like part of your product. ## What you can customize - **Logo** - uploaded image, shown in the portal header and emails. Free for all plans. - **Favicon** - the icon in the browser tab when visitors are on your portal. Free for all plans. - **Primary color** - used for buttons, links, vote pills, status accents on the public portal. Free for all plans. - **Workspace name** - shown in the portal header. - **Description** - a one-liner under the workspace name on the portal homepage. - **"Powered by Feedjolt" badge** - hide the footer link to Feedjolt. Available on every plan. - **Custom domain** - *not yet supported*. On the [roadmap](https://www.feedjolt.com/en/portal/luodaint/roadmap). For now, your URL is `feedjolt.com/p/{slug}`. Configure at **Dashboard -> Portal** — Logo, Favicon, Primary color, and Badge cards. ## Logo Upload at **Dashboard -> Portal -> Logo**. Square or wide formats both work. PNG with transparent background is best. Max 2 MB. Drag-and-drop or click "Upload logo". The logo is stored in the workspace's storage bucket and served via a presigned URL. It's used: - On the portal header. - In notification emails (header + footer). - In Slack messages (workspace icon). ## Favicon The 32×32 (or larger) icon that shows in the browser tab. Drop a PNG, ICO, or SVG up to 256 KB. Falls back to the Feedjolt icon if you don't set one. ## Primary color Pick a hex color (color picker or paste a hex). The portal applies it as a CSS custom property scoped to the portal subtree - your dashboard purple stays untouched. Used for: - Vote buttons and pills. - Status filter chips and post-card hover. - Pagination buttons. - Active-state accents. A live preview button on the right shows how the color reads against white text. We **block colors that fail WCAG AA contrast** for white-on-color (ratio < 4.5) - the picker rejects "this color won't meet contrast requirements" with a hint to try a darker shade. White or very pale colors get rejected; mid-to-dark tones pass. ## "Powered by Feedjolt" badge By default the portal shows a small "Powered by Feedjolt" link in the footer. Every plan can hide it: flip the toggle in the Badge card on the Portal page. ## Voice (informal) The portal copy has a few editable strings: - **Submit button label** - defaults to "Submit feedback". Could be "Suggest a feature". - **Vote button label** - defaults to "Upvote". Could be "👍" or "I want this". - **Empty board message** - what shows when a board has no posts yet. Make it inviting. **Settings -> Portal -> Custom labels** to override. ## Email branding Outgoing notification emails inherit your logo and brand color automatically. The "from" address is `noreply@feedjolt.com` by default. Custom-domain "from" addresses are on Startup and Scale (not Growth) and need DNS verification (TXT record). See [email branding setup](/en/docs/account/email-preferences). ## Custom CSS in the widget The widget supports arbitrary CSS overrides. See **[Widget](/en/docs/portal/widget#custom-css)**. ## Don't get carried away A clean white-with-brand-accent portal is faster, more accessible, and more trusted than a heavy themed one. Resist the urge to add a custom font or background image - it usually subtracts from the credibility you're trying to build. --- # Changelog > Use the Feedjolt changelog to publish a public what's-new feed. Write and schedule entries, promote shipped posts in one click, and share updates over RSS. The changelog is your public "what's new" feed. Each entry is short, dated, and (optionally) linked to the original feedback post. ## When to use the changelog - **Every release.** Make it routine. Customers love being told what changed. - **Big features only.** If your release notes are usually internal-detail-heavy, the changelog is for the user-facing summary. - **Don't overuse.** "Fixed a typo" doesn't need a changelog entry. Bundle small fixes weekly. ## Writing an entry **Dashboard -> Changelog -> New entry**. Each entry has: - **Title** - short and active. "Dark mode" beats "We've added a new theme option". - **Body** - Markdown. Include screenshots; they make the page scannable. Flip **Preview** to see it the way customers will. - **Version** (optional) - `v2.4`, `2026-04-29`, whatever you use. - **Status** - `Draft`, `Published`, `Scheduled`. - **Linked posts** - pick the original feedback posts this entry resolves. Linked posts can be auto-marked **Shipped**. ## Draft from GitHub If the week's work already lives in git, skip the blank page. GitHub drafts are on **Startup and Scale (not Growth)**. 1. Connect a repo at **Dashboard -> Integrations** (`/en/dashboard/integrations`) -> **GitHub**. 2. Open **Dashboard -> Changelog -> Draft from GitHub**. 3. Pick **since last published changelog** or a date range. 4. Stay on the page. Drafting can take a minute or two. Feedjolt opens **one draft** - title plus customer-facing bullets, not a commit dump. 5. Flip **Preview**, edit, then **Publish**. Emails and webhooks wait until you publish. Feedjolt does **not** watch the repo. There is no timer and no merge webhook. You click **Draft from GitHub** when you want a draft - usually after a release or once a week. **Since last published** covers everything merged since the last public entry. To use another repo, pick it on **Integrations -> GitHub** and save. Disconnect only if you need a different GitHub account. Staff see which commits and pull requests were used. The public changelog does not. Feedjolt does not auto-publish. This is not GitHub Issues sync. See [GitHub changelog drafts](/en/docs/integrations/github). ## Promote a post to a changelog entry When a post moves to "Shipped": 1. **Promote to changelog** appears on the post detail page. 2. Click it. 3. The title, body, and link are pre-filled. Edit, save, publish. This is the fastest path: customer gets the "Your post shipped!" notification AND your changelog stays current. ## Drafts and scheduling Save as draft to come back later. Schedule for a future date if your release is on Tuesday but you're writing the entry on Friday. Drafts and scheduled entries are not visible on the public changelog. ## RSS The changelog has an RSS feed at `feedjolt.com/p/{slug}/changelog/rss`. Customers can subscribe. ## In-app notifications When a customer who's voted on a linked post sees the changelog, they get a small "1 new" badge on the page. Optional email: configure at **Settings -> Notifications -> changelog.published**. --- # Public portal > Your Feedjolt portal is the public face of your workspace: feed, boards, roadmap, changelog and widget. Visibility rules, sign-in, URLs, SEO and turning it off. Your **portal** is what your customers see. It lives at `feedjolt.com/p/{your-slug}`. A typical portal has: - A **homepage** with the full feedback feed — filter by board, sort by votes or date, vote inline — plus a submit call-to-action, search, and trending posts in the sidebar. - One or more **boards** - collections of posts. - A **roadmap** - posts grouped by status. - A **changelog** - what you've shipped. - An **embedded widget** - a "Feedback" button you can put on your own site. ## The pages - **[Roadmap](/en/docs/portal/roadmap)** - the columns customers love. - **[Changelog](/en/docs/portal/changelog)** - your "what's new" page. - **[Widget](/en/docs/portal/widget)** - embed on your app or site. - **[Branding](/en/docs/portal/branding)** - logo, colors, voice. ## What's public, what's hidden - **Public boards** - visible to anyone with the link. - **Authenticated boards** - visible after sign-in (magic link). - **Invite-only boards** - visible to invited end users only. - **Internal boards** - never on the portal. Members only. Within a board: - **Public posts** - shown. - **Internal posts** - hidden, even on a public board. - **Drafts** (when moderation is on) - hidden until approved. - **Spam** - hidden. ## Signing in to a portal Visitors don't need an account to browse a portal — boards, the roadmap, and the changelog are public. To vote, comment, or post under their own name, they sign in with just an email: 1. Click **Sign in** in the portal header (or just try to vote or comment). 2. Enter a name and email — no password, ever. 3. Type the 6-digit code from the email. Done: the vote or comment they were casting goes through automatically. Sessions last 60 days. Anonymous feedback submission still works without signing in — those posts arrive as drafts for your team to review, without a public author name. If your workspace uses **JWT SSO** with **Require SSO** enabled, email sign-in is disabled — your own app remains the only door. ## URL structure - `feedjolt.com/p/{slug}` - homepage. - `feedjolt.com/p/{slug}/boards/{board}` - board detail. - `feedjolt.com/p/{slug}/posts/{id}` - single post. - `feedjolt.com/p/{slug}/roadmap` - roadmap view. - `feedjolt.com/p/{slug}/changelog` - changelog view. These are the canonical URLs. The redundant longer forms (`/{locale}/portal/{slug}/...`) work too but redirect to the short form. ## Turning the portal off The whole public portal can be switched off in one click: **Dashboard -> Portal -> Public portal**. While off, every URL under `feedjolt.com/p/{slug}/...` returns 404 - boards, roadmap, changelog, posts, the lot. The embedded [widget](/en/docs/portal/widget) keeps working when the portal is off - so customers can still submit feedback from your own site while the public hub stays hidden. Handy for stealth-mode products, internal-only feedback collection, or temporarily winding down a product line. Independent of that master switch, you can hide just the roadmap or just the changelog tab via the same Portal settings page. ## SEO Public portal hubs, boards, changelog, and roadmap pages are indexed by search engines and listed in `feedjolt.com/sitemap.xml`. Individual post pages are not. They send `noindex` so Google does not list each task. You don't need to do anything for this to work - it's on by default. To stop indexing the whole portal, turn indexing off in **Dashboard -> Portal -> Search engines**, or flip the master portal switch off (above). --- # Roadmap > The public Feedjolt roadmap groups posts into Planned, In Progress, and Done. Map your statuses to buckets, control visibility, filter by tags, and share the URL. The public roadmap shows posts grouped into three columns: **Planned**, **In Progress**, **Done**. Customers can scan, vote, and comment without diving into individual boards. ## Why three buckets Customers don't care about your internal pipeline. They want to know: is it on the list, is it being built, is it shipped. The public roadmap collapses your fine-grained workflow into those three answers. You can keep as many internal statuses as you want (`Researching`, `Up next`, `Beta`, `GA`, …) - each one maps to a bucket (or to none) via its **Public bucket** setting. See [statuses](/en/docs/concepts/statuses) for the field. ## What appears on the roadmap A post is on the public roadmap if **all** of: - Its status has a **Public bucket** assigned (`Planned`, `In Progress`, or `Done`). - It is **not internal**. - It is **not a draft** (or it's been approved). - The board it lives in is **public** or **authenticated**. Statuses with no public bucket (e.g. `Open`, `Under Review`) never appear on the public roadmap, regardless of their `Show on roadmap` setting - that flag controls the *dashboard* roadmap only. ## Mapping statuses to buckets **Dashboard -> Portal -> Public roadmap**. Each status has a dropdown: `Planned`, `In Progress`, `Done`, or `Hidden`. A typical mapping: | Public bucket | Statuses | | --- | --- | | Hidden | Open, Under Review | | Planned | Planned, Up next | | In Progress | In Progress, Beta | | Done | Complete, Shipped | The dashboard surfaces a warning if a bucket is empty - an empty bucket renders as an empty column on the portal. ## Roadmap visibility Two independent toggles: - **Master portal switch** - `Dashboard -> Portal -> Public portal` flips the whole portal off. Every public URL under `/p/{slug}/...` returns 404. Use it for stealth-mode launches or wind-downs. - **Roadmap-only switch** - `Dashboard -> Portal -> Public roadmap` hides just the roadmap tab while leaving boards, changelog, and the widget public. Useful for early-stage products that don't have a coherent plan yet, or for B2B teams that want feedback collection but not public commitment. ## Filtering End users can filter the roadmap by **tags**. The tag pill row lives above the columns; if your workspace has more than ten tags it collapses into a dropdown. The filter is URL-driven - selected tags appear as `?tags=tag-a,tag-b` in the address bar, so a filtered view is bookmarkable and shareable. Members in the dashboard see the same roadmap with extra filters (author, vote threshold) and the option to **export to CSV**. ## Dashboard roadmap Members get a different view inside `Dashboard -> Roadmap`: one column per status with `Show on roadmap` enabled, ordered by sort order. Use this for triage; use the public version for customer-facing communication. ## Linking and embedding The roadmap has a stable URL: `feedjolt.com/p/{slug}/roadmap`. Bookmark it, share it, embed it. (For embedding on your own page, the [widget](/en/docs/portal/widget) is usually a better fit.) ## SEO Roadmap pages are indexed by search engines. Opening a post from the roadmap goes to a detail page that is not indexed. --- # Embeddable widget > Add a Feedjolt feedback button to your site with one script tag. Customers search posts, vote, and submit without leaving your app. Configure look, SSO, and CSP. The widget is a single ` ``` That's it. Refresh your site; you should see a floating button in the configured position. ## Configuration At **Dashboard -> Developers -> Widget**, you can set: - **Launcher text** - "Feedback", "Got an idea?", "Help us improve". - **Position** - bottom-right or bottom-left. - **Theme** - light, dark, auto (matches the user's OS preference). - **Primary color** - defaults to your brand color. - **Active toggle** - kill switch; turn the widget off without changing your install snippet. For per-page overrides (theme, default board), see the developer reference at **[Developers -> Widget](/en/docs/developers/widget)**. ## Single sign-on (SSO) If your customers are already signed in to your app, pass a JWT on the script tag's `data-sso-token` attribute. The loader forwards it as `ssoToken` into the widget iframe. Claims, signing, and examples are in **[JWT SSO](/en/docs/developers/jwt-sso)**. See **[Developers -> Widget -> Configuration](/en/docs/developers/widget/configuration)** for the attribute list. ## Privacy The widget sets a single first-party cookie (`fj_widget`) for state (open/closed) and a same-domain session cookie when the user submits feedback. No third-party trackers. ## CSP If your site has a strict CSP, allow: - `script-src https://www.feedjolt.com` - `connect-src https://www.feedjolt.com` - `frame-src https://www.feedjolt.com` - `img-src https://cdn.feedjolt.com data: blob:` ## Removing Delete the ` ``` | Attribute | Required | Notes | | --- | :---: | --- | | `data-workspace` | yes | Your workspace slug. Without this the loader logs an error and exits. | | `data-board` | no | Slug of a default board to deep-link to when the widget opens. The picker still shows other boards. | | `data-theme` | no | `light`, `dark`, or `auto`. Override of the workspace default. | | `data-sso-token` | no | A JWT identifying the signed-in user - see SSO below. | | `data-api-url` | no | Override of the inferred API base URL. Useful for self-hosted or staged installs. | If your needs aren't covered by these five attributes, configure the rest at **Developers -> Widget**. ## Per-workspace settings (dashboard) The config loaded at runtime contains: - `launcher_text` - the button label. - `launcher_position` - `bottom-right` or `bottom-left`. - `primary_color` - used as the launcher background. - `is_active` - kill switch. If `false`, the loader returns early; nothing is rendered. These propagate to every install of the widget for that workspace, no script change required. ## SSO via `data-sso-token` Pass a JWT on `data-sso-token` to authenticate the user inside the widget. The token is forwarded as a `ssoToken` query parameter to the portal iframe, which then signs the user into a Feedjolt session. The token is a short-lived JWT your backend mints. Claims, secret, and examples live in [JWT SSO](/developers/jwt-sso). Leave `data-sso-token` empty if you have not set JWT SSO yet. Users can still sign in with a magic link inside the widget. ## Locale The widget reads the locale from `` - `en`, `es`, or `ca`. If unrecognised, it defaults to `en`. There's no `data-locale` attribute today - set the page's `lang` attribute instead. ## Programmatic control Programmatic open / close / `window.feedjolt.open()` are not exposed today. The launcher button is the entry point. If you want a custom button, file feedback - depending on demand we can ship a small JS API. --- # Widget Content Security Policy > The exact Content Security Policy directives the Feedjolt widget needs to load: script, connect, frame, img, style, and font sources, plus a strict CSP example. If your site has a strict Content Security Policy, the widget needs explicit allowances. Without them, the loader script, the iframe, and asset fetches will all be blocked. ## Minimum directives ``` script-src https://www.feedjolt.com connect-src https://www.feedjolt.com frame-src https://www.feedjolt.com img-src https://cdn.feedjolt.com data: blob: style-src 'unsafe-inline' font-src https://www.feedjolt.com data: ``` If you already use `default-src 'self'`, the directives above are **additions** - they don't replace your existing ones. ## Per-directive notes ### `script-src` The widget loader is fetched from `feedjolt.com`. It's a single small script; the iframe's JS is inside the iframe and uses its own CSP. If you require **nonces** for inline scripts (no `'unsafe-inline'`), the loader is external - no nonce needed. **You don't need to nonce-tag the loader.** ### `connect-src` The loader posts a few telemetry pings (open/close events for our anti-abuse logging) to `feedjolt.com`. Iframe API calls happen *inside the iframe* and use the iframe's own CSP, not yours. ### `frame-src` The iframe is `