mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-21 19:39:28 -05:00
255 lines
10 KiB
YAML
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 }
|