PinAppAI

← All docs

Reviewer access & permissions

Who can leave feedback on your project — open access vs allowlist, inviting reviewers, removing them, and what 403 errors mean.


Two questions decide who can post feedback on your project: is this project open to anyone, or invite-only? and is this email on the allowlist? This page walks through both.

Open access vs allowlist

Each project has a single toggle — Open access — that flips its access mode.

  • Open access OFF (default) — only invited reviewers + workspace members can submit. The widget’s email-OTP modal accepts a code only for emails on the project’s reviewer list.
  • Open access ON — anyone who can reach the page can verify their email and submit. The widget auto-creates a reviewer record on first OTP.

Toggle it from your project’s edit panel. The recommendation:

Off for production — keeps your dashboard signal-to-noise high. On for public beta tests — you want unsolicited feedback from real visitors.

You can flip it any time. Existing reviewer rows survive either direction; the toggle only changes who CAN newly verify.

Inviting reviewers

From the project’s reviewer list in admin: + Add reviewer → enter email → save. Repeat for each invitee. They don’t get a notification email by default — share the page URL yourself (Slack, email, project tracker).

Workspace members (anyone you’ve added to your PinAppAI workspace) are implicitly allowed without needing a per-project reviewer entry. Useful for internal teams.

Removing reviewers (two-stage)

The Remove button on a reviewer row is a two-stage action that mirrors a Trash → Empty Trash pattern:

  1. First click on an active reviewer → soft-revokes (status='revoked'). The row stays in the list with a REVOKED badge so you can see who used to have access. Already-submitted feedback survives untouched.
  2. Second click on a revoked reviewer → hard-deletes the row. The row is gone from the list entirely.

The two stages are explicit because revocation is reversible-in-spirit (audit trail of “who was once a reviewer”) whereas hard-deletion isn’t. The submitted feedback rows always survive both stages — they reference the reviewer’s user account, not the project_reviewer entry.

What 403 errors mean for reviewers

The OTP modal surfaces specific 403 messages so you can self-diagnose if a reviewer can’t get in:

Modal textWhat it meansWhat to fix
”This site isn’t on the project’s allowed-origins list…”The page’s origin (e.g., https://staging.your.site) isn’t in allowed_origins for the projectAdd the origin in admin → project edit → Allowed origins
”This email isn’t on the project’s reviewer allowlist…”The reviewer’s email isn’t on the allowlist AND open access is offEither add the email as a reviewer, or flip Open access on
Anything elseThe API returned the literal message — usually a stale data-project keyVerify the script tag matches your current project’s API key

These granular messages replaced an older “you don’t have permission, contact the project owner” generic message that left owners debugging blind.

API key vs reviewer

Two separate concepts:

  • pk_* (widget key) — embedded in your widget script tag. Public, scoped to one project, intended to be in your customer-facing HTML. Cannot post feedback by itself; it only identifies which project the widget belongs to.
  • Reviewer token (pt_*) — minted by Better Auth after OTP verification. Stored in localStorage by the widget. Required on every feedback POST. Per-reviewer, per-browser.

Revoking a reviewer doesn’t invalidate their localStorage token instantly — but the next POST that token attempts is rejected at the API gate, so the user is locked out at submit time. They’ll see the granular 403 in the modal on retry.

Workspace roles (advanced)

Workspaces have four roles: owner > admin > editor > viewer. Project access flows through workspace membership: any workspace member can submit feedback on any project in the workspace. Only owners + admins can manage API keys and project settings. Viewers and editors can submit but not configure.

Workspace member changes propagate to project access immediately — no per-project sync.