Permissions
| Key | Grants |
|---|---|
surveys | See the Surveys tab and read everything in it. |
surveys_create | Add surveys. |
surveys_update | Edit existing ones. |
surveys_delete | Remove them. |
surveys_publish | Publish and archive — the only one that reaches users. |
The retired app_ratings_report permission granted reading and full catalog
editing from one key. Upgrading carries each holder’s grant forward to the first four above,
so nobody loses access. Publish is new and is not granted automatically — hand it out
deliberately. (Since 1.6.0, which apps exist and can be rated is managed in the
App Library under the Applications module’s own permissions — the
in-module catalog editor is gone.)
Two surfaces, two audiences
This module has an admin half and an end-user half, and they are gated in opposite directions on purpose.
| Surveys tab | The prompt | |
|---|---|---|
| Who | Platform operators | Every user inside a tenant workspace |
| Database | Main only — tenant sessions are refused | Tenant sessions (or any session on a single-tenant install) |
| Permission | surveys required | None required |
Targeting
Two optional filters on each survey. Leave either blank to mean “everyone”.
- User types — e.g. staff only, or client-portal users only.
- Tenants — pick one or more tenants from the list, by company key
(the same key they sign in with, e.g.
ahm). Useful for piloting a wording change on one customer before rolling it out. Platform surveys only — inside a tenant workspace a survey reaches that tenant’s own users by definition, so the control is not shown.
A start and end date can also bound the window. Outside it, nobody is prompted.
When prompts are deliberately suppressed
Even with a published, perfectly targeted survey, no prompt is shown:
- to anyone working on the main platform database, when multi-tenancy is enabled. Those users are running the fleet rather than using the product, so their consent belongs to no tenant — and the operator publishing a survey should not be interrupted by their own prompt. (On a single-tenant install every user is on the main database, so this rule does not apply there.)
- on the sign-in, forbidden or maintenance pages;
- during a support-access session — while an operator is signed in as a tenant admin, recording “their” consent would attribute one person’s decision to another;
- on background requests, or on public pages outside the app;
- more than once per page load — and a required prompt always outranks an optional one.
What gets audited
| Action | Audit log | Ledger |
|---|---|---|
| Create / edit / delete a survey | Yes | — |
| Publish or archive | Yes (warning) | — |
| Agree / decline a required survey | Yes (warning) | Yes |
| Answer an optional survey | No | Yes |
Optional answers stay out of the audit log on purpose. The ledger is the evidence record; mirroring every star rating into the audit trail would bury the entries that matter.
Where the data lives
All survey data is stored in the main database, never per-tenant. A user answering from inside a tenant workspace still writes their response to the main database, because that is where the survey they are answering lives.
Each response also stores the responder’s name and email as they stood at that moment. Two reasons: consent evidence must not change when someone edits their profile later, and it lets the Responses list render without reaching into every tenant database to look people up.
The mobile endpoints
This module owns GET /v1/api/me/apps and POST /v1/api/me/app-rating.
Both keep their original URLs. Both now return 404 module_unavailable when the module
is switched off — so treat the toggle as a live switch on your mobile clients, not just a UI
preference.
Since 1.1.0 it also owns the mobile survey prompt queue:
GET /v1/api/me/surveys (the signed-in employee’s pending prompts) and
POST /v1/api/me/surveys/respond (answer / agree / decline / snooze / opt out) —
what the Syntry app’s survey popup runs on. This surface has its own policy
switch, Send survey prompts to the mobile app (Survey Settings → Tenant
Policy), independent of the rating switch and off by default. With it off, both
endpoints answer the same 404 module_unavailable.
One operational nuance: fetching the queue counts one “ask” against the first survey’s prompt limit — the same counting the web prompt does when it renders. The Syntry app therefore fetches only when it is about to show the popup, never on a timer.