---
title: "Read a survey's visibility and the impact of changing it"
method: GET
path: "/api/v3/surveys/{surveyId}/visibility"
tags: ["V3 Surveys"]
---

# Read a survey's visibility and the impact of changing it

`GET /api/v3/surveys/{surveyId}/visibility`

## Request

- Base URL: `https://app.formbricks.com`
- URL: `https://app.formbricks.com/api/v3/surveys/{surveyId}/visibility`
- Auth: one of:
  - API key in cookie `next-auth.session-token`
  - API key in header `x-api-key`
  - HTTP bearer

Returns the survey's enforced visibility, its owner, the caller's access, and what a change would do: `blockers[]` lists the outbound connections that currently make `restricted` refusable (webhooks, integrations, active feedback sources, draft or enabled workflows, and non-archived creatives that open it), `impact` carries the numbers the confirmation dialogues show, `allowedTargets[]` the values a `POST` would act on right now, and `pending` / `version` describe a change still in flight. Read this before offering "Make restricted"; the `POST` answers **409** while `blockers[]` is non-empty.

Requires `survey.change_visibility`, the same permission as the `POST`: the survey's owner while they still hold read access to the workspace, or an organisation owner/manager, with the feature enabled. Everyone else — read or write members, team-level managers, every API key, and anyone who cannot see the survey at all — answers **403** with the same body as an unknown id. Connection names and ids are configuration, not survey content, and only the people who may act on them get to read them.

While `pending` is non-null the survey is restricted for everyone but its owner (within their workspace access: read to view, write to edit) and the organisation's owners and managers, whichever direction is queued — the application fails closed until the graph acknowledges the change — so `visibility` reads `restricted` in that state and `allowedTargets` includes the value that cancels the pending change.

## Path parameters

- `surveyId` string, cuid2, required

## Response `200`

Visibility state retrieved

- object
  - `data` SurveyVisibilityState, required: The three fields every `SurveyListItem` and `SurveyResource` carries, merged into both via `allOf`. All required, always present.
    - `id` string, required: Survey identifier.
    - `visibility` 'restricted' | 'workspace', required: `restricted`: readable by the owner and the organisation's owners and managers only. The owner's access is conditional on their workspace access, level for level: they read the survey only while they can read the workspace, and edit it only while they can write to it — being the owner grants nothing the workspace does not. `workspace`: readable by everyone with access to the workspace — today's behaviour.
    - `owner` SurveyOwner, required: The authorization owner — the person whose restricted surveys these are. Distinct from `creator`, which is attribution only and is never rewritten. Display only, like `creator`: no user id is exposed, because `access.via === "owner"` already answers "is this mine" and `filter[owner][in]=me` filters server-side. Ownership transfer can add an identifier later, additively. Durable source: `Survey.ownerId` in PostgreSQL, projected to `survey#owner@user`; the graph never holds ownership alone, so a rebuild from an empty graph restores it.
      - `name` string, required
    - `access` SurveyAccess, required: Why **this caller** can see the survey, and whether they may change its visibility. Derived by the server per request; a rendering hint only — every mutation is re-authorised on the server.
      - `via` string, required: Why this caller can see the survey. Known values today: `workspace` (the survey is workspace-visible and the caller has workspace read — always the value for API keys), `owner` (restricted, the caller owns it), `organizationRole` (restricted, the caller reaches it only as an organisation owner or manager — the case that shows the admin banner). **Open set, deliberately not an enum**: named person and team sharing will add values, so clients treat an unknown string as "some other access path" and never branch exhaustively. Explanatory metadata, not authorization truth — the server re-authorises every call.
      - `canManageVisibility` boolean, required: Permission only: `true` when this caller holds `survey.change_visibility` — owner or organisation owner/manager, feature enabled for the organisation and deployment. It can be `true` while `allowedTargets` is empty (blockers, or no owner): it answers "may this person manage visibility at all", which is what shows or hides the controls; `allowedTargets` on `GET …/visibility` answers which transitions would succeed now. Stays `true` for an organisation manager on an ownerless restricted survey.
    - `blockers` SurveyVisibilityBlocker[], required: Connections that make `restricted` refusable right now. Empty when being restricted is allowed, and always empty for the `workspace` direction.
      - `type` 'webhook' | 'integration' | 'feedbackSource' | 'dashboard' | 'workflow' | 'creative', required
      - `id` string, required
      - `name` string, required: Display name of the connection, for the UI to list. Never empty; falls back to the type.
    - `impact` SurveyVisibilityImpact, required: The numbers the confirmation dialogues show.
      - `memberCount` integer, required: People other than the owner and the organisation's owners/managers who can see the survey now (if workspace-visible) or would gain access (if restricted).
      - `responseCount` integer, required: Responses on the survey, partial ones included.
    - `pending` 'restricted' | 'workspace', required: `restricted`: readable by the owner and the organisation's owners and managers only. The owner's access is conditional on their workspace access, level for level: they read the survey only while they can read the workspace, and edit it only while they can write to it — being the owner grants nothing the workspace does not. `workspace`: readable by everyone with access to the workspace — today's behaviour.
    - `version` integer, required: Monotonic per survey; incremented by every accepted `POST`, including cancellations. Projection work is fenced on it: a projector holding an older version never writes. `0` for a survey whose visibility was never changed through this endpoint.
    - `allowedTargets` SurveyVisibility[], required: Values a `POST …/visibility` by this caller would act on right now. Never the enforced value — **except** when a different value is pending, in which case the enforced value is listed because requesting it cancels the pending change. Never `restricted` while `blockers[]` is non-empty or `owner` is `null`. Empty when nothing would happen. Drives the row menu and the editor control.

## Other responses

- `400`: Bad Request — malformed JSON, invalid query/body/params, duplicate name, or unsupported field.
- `401`: Not authenticated (no valid session or API key).
- `403`: Forbidden, one of two codes. `forbidden`: the caller cannot see the survey, **or** sees it but may not change its visibility — workspace members without ownership, team-level managers, and every API key — with the same body as any unreadable survey. `visibility_not_enabled`: the organisation lacks the RBAC / access-control entitlement, or the deployment's readiness marker for survey visibility is not set; this answer does not depend on the survey.
- `429`: Rate limit exceeded.
- `500`: Internal Server Error.

## Changes

- **2026-10-28** `84820a01e550`: 15 warning
  - added the new `chart_in_use` enum value to the `code` response property for the response status `400`
  - added the new `chart_in_use` enum value to the `code` response property for the response status `401`
  - added the new `chart_in_use` enum value to the `code` response property for the response status `403`
  - added the new `chart_in_use` enum value to the `code` response property for the response status `429`
  - …11 more
- **2026-10-27** `aad5dc1d8236`: 11 warning
  - added the new `creative` enum value to the `data/allOf[subschema #3]/blockers/items/type` response property for the response status `200`
  - added the new `creatives_not_entitled` enum value to the `code` response property for the response status `400`
  - added the new `creatives_not_entitled` enum value to the `code` response property for the response status `401`
  - added the new `creatives_not_entitled` enum value to the `code` response property for the response status `403`
  - …7 more
- …earlier changes not shown

[Operation history](https://skmtc.dev/formbricks/apis/formbricks-api-v3/changes/api/v3/surveys/:surveyId/visibility/get.md)

---

[API](https://skmtc.dev/formbricks/apis/formbricks-api-v3.md) - [All operations](https://skmtc.dev/formbricks/apis/formbricks-api-v3/llms.txt) - [OpenAPI document](https://skmtc.dev/formbricks/apis/formbricks-api-v3/revisions/25335c959a13?raw)
