Files
formbricks/docs/api-v3-reference/openapi-surveys.yml
T
2026-03-17 15:50:22 +00:00

255 lines
10 KiB
YAML

# V3 API — GET Surveys (hand-maintained; not generated by generate-api-specs).
# Implementation: apps/web/app/api/v3/surveys/route.ts
# See apps/web/app/api/v3/README.md and docs/Survey-Server-Actions.md (Part III) for full context.
openapi: 3.1.0
info:
title: Formbricks API v3 (Surveys)
description: |
**GET /api/v3/surveys** — authenticate with **session cookie** or **`x-api-key`** (management key with access to the workspace environment).
**Spec location:** `docs/api-v3-reference/openapi-surveys.yml` (alongside v2 at `docs/api-v2-reference/openapi.yml`).
**workspaceId (today)**
Query param `workspaceId` is the **environment id** (survey container in the DB). The API uses the name *workspace* because the product is moving toward **Workspace** as the default container; until that exists, resolution is implemented in `workspace-context.ts` (single place to change when Environment is deprecated).
**Auth order**
Session is tried first, then API key. Unauthenticated callers get **401** before query validation. **`createdBy` is session-only** (API key + `createdBy` → **400**).
**Pagination**
**limit** + **offset** (not cursor). Suited to page-based UIs (page 1/2/3, previous/next). Cursor-based pagination is intentionally **not** offered here (one-directional “next” only); revisit only for a high-volume feed-style endpoint.
**Filtering**
Filters and sort are **flat query parameters** (`name`, `status`, `type`, `createdBy`, `sortBy`). Arrays use repeated keys or comma-separated values (e.g. `status=draft&status=inProgress`).
**Security**
Missing/forbidden workspace returns **403** with a generic message (not **404**) so resource existence is not leaked. List responses use `private, no-store`.
**OpenAPI**
This YAML is **not** produced by `pnpm generate-api-specs` (that script only builds v2 → `docs/api-v2-reference/openapi.yml`). Update this file when the route contract changes.
**Next steps (out of scope for this spec)**
Additional v3 survey endpoints (single survey, CRUD), frontend cutover from `getSurveysAction`, optional ETag/304, field selection — see Survey-Server-Actions.md Part III.
version: 0.1.0
x-implementation-notes:
route: apps/web/app/api/v3/surveys/route.ts
query-parser: apps/web/app/api/v3/surveys/parse-v3-surveys-list-query.ts
auth: apps/web/app/api/v3/lib/auth.ts
workspace-resolution: apps/web/app/api/v3/lib/workspace-context.ts
openapi-generated: false
pagination-model: offset
cursor-pagination: not-supported
paths:
/api/v3/surveys:
get:
operationId: getSurveysV3
summary: List surveys
description: Returns surveys for the workspace. Session cookie or x-api-key.
tags:
- V3 Surveys
parameters:
- in: query
name: workspaceId
required: true
schema:
type: string
format: cuid2
description: |
Workspace identifier. **Today:** pass the **environment id** (the environment that contains the surveys). When Workspace replaces Environment in the data model, clients may pass workspace ids instead; resolution is centralized in workspace-context.
- in: query
name: limit
schema:
type: integer
minimum: 1
maximum: 100
default: 20
description: Page size (max 100)
- in: query
name: offset
schema:
type: integer
minimum: 0
default: 0
description: Pagination offset (0-based). No cursor/`after` token — see API info for rationale.
- in: query
name: name
schema:
type: string
maxLength: 512
description: Case-insensitive substring match on survey name (same as in-app list filters).
- in: query
name: status
schema:
type: array
items:
type: string
enum: [draft, inProgress, paused, completed]
style: form
explode: true
description: |
Survey status filter. Repeat the parameter (`status=draft&status=inProgress`) or use comma-separated values (`status=draft,inProgress`). Invalid values → **400**.
- in: query
name: type
schema:
type: array
items:
type: string
enum: [link, app]
style: form
explode: true
description: Survey type filter (`link` / `app`). Same repeat-or-comma rules as `status`.
- in: query
name: createdBy
schema:
type: array
items:
type: string
enum: [you, others]
style: form
explode: true
description: |
**Session only:** creator scope (`you` / `others`); server applies the signed-in user. **Not supported with API keys** (400).
- in: query
name: sortBy
schema:
type: string
enum: [createdAt, updatedAt, name, relevance]
description: Sort order. Default is service-defined when omitted.
responses:
"200":
description: Surveys retrieved successfully
headers:
X-Request-Id:
schema: { type: string }
description: Request correlation ID
Cache-Control:
schema: { type: string }
example: "private, no-store"
content:
application/json:
schema:
type: object
required: [data, meta]
properties:
data:
type: array
items:
$ref: "#/components/schemas/SurveyListItem"
meta:
type: object
required: [limit, offset, total]
properties:
limit: { type: integer }
offset: { type: integer }
total:
type: integer
description: Count of surveys matching the same filters as this list request
"400":
description: Bad Request
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
"401":
description: Not authenticated (no valid session or API key)
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
"403":
description: Forbidden — no access, or workspace/environment does not exist (404 not used; avoids existence leak)
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
"429":
description: |
Rate limit exceeded (wrapper). Uses the **legacy v1 JSON** shape from `responses.tooManyRequestsResponse`.
content:
application/json:
schema:
$ref: "#/components/schemas/LegacyTooManyRequests"
"500":
description: |
Handler errors return RFC 9457 Problem Details. Uncaught errors from the API wrapper may return legacy v1 JSON (`code` / `message` / `details`).
content:
application/problem+json:
schema:
$ref: "#/components/schemas/Problem"
application/json:
schema:
$ref: "#/components/schemas/LegacyInternalError"
security:
- sessionAuth: []
- apiKeyAuth: []
components:
securitySchemes:
sessionAuth:
type: apiKey
in: cookie
name: next-auth.session-token
description: |
NextAuth session JWT cookie. **Development:** often `next-auth.session-token`.
**Production (HTTPS):** often `__Secure-next-auth.session-token`. Send the cookie your browser receives after sign-in.
apiKeyAuth:
type: apiKey
in: header
name: x-api-key
description: |
Management API key; must include **workspaceId** as an allowed environment with read, write, or manage permission.
schemas:
SurveyListItem:
type: object
description: |
Shape from `getSurveys` (`surveySelect` + `responseCount`). Serialized dates are ISO 8601 strings.
Legacy DB rows may include survey **type** values `website` or `web` (see Prisma); filter **type** only accepts `link` | `app`.
properties:
id: { type: string }
name: { type: string }
environmentId: { type: string }
type: { type: string, enum: [link, app, website, web] }
status:
type: string
enum: [draft, inProgress, paused, completed]
createdAt: { type: string, format: date-time }
updatedAt: { type: string, format: date-time }
responseCount: { type: integer }
creator: { type: object, nullable: true, properties: { name: { type: string } } }
Problem:
type: object
description: RFC 9457 Problem Details for HTTP APIs (`application/problem+json`). Responses typically include a machine-readable `code` field alongside `title`, `status`, `detail`, and `requestId`.
required: [title, status, detail, requestId]
properties:
type: { type: string, format: uri }
title: { type: string }
status: { type: integer }
detail: { type: string }
instance: { type: string }
code:
type: string
enum: [bad_request, not_authenticated, forbidden, internal_server_error]
requestId: { type: string }
details: { type: object }
invalid_params:
type: array
items:
type: object
properties:
name: { type: string }
reason: { type: string }
LegacyTooManyRequests:
type: object
required: [code, message, details]
properties:
code: { type: string, enum: [too_many_requests] }
message: { type: string }
details: { type: object }
LegacyInternalError:
type: object
required: [code, message, details]
properties:
code: { type: string, enum: [internal_server_error] }
message: { type: string }
details: { type: object }