curl --request PATCH \
--url https://app.formbricks.com/api/v3/surveys/{surveyId} \
--header 'Content-Type: application/json' \
--cookie next-auth.session-token= \
--data '
{
"name": "Updated Product Feedback"
}
'{
"data": {
"id": "<string>",
"workspaceId": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z",
"archivedAt": "2023-11-07T05:31:56Z",
"name": "<string>",
"type": "link",
"status": "draft",
"metadata": {
"title": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"description": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
}
},
"defaultLanguage": "<string>",
"languages": [
{
"code": "en-US",
"default": true,
"enabled": true,
"alias": "english"
}
],
"showLanguageSwitch": true,
"autoSelectLanguage": true,
"welcomeCard": {
"enabled": true,
"headline": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"subheader": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"buttonLabel": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"fileUrl": "<string>",
"videoUrl": "<string>",
"timeToFinish": true,
"showResponseCount": true
},
"blocks": [
{
"id": "<string>",
"name": "<string>",
"elements": [
{
"id": "<string>",
"type": "openText",
"headline": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"required": true,
"subheader": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"imageUrl": "<string>",
"imageAltText": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"videoUrl": "<string>",
"isDraft": true,
"placeholder": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"longAnswer": true,
"inputType": "text",
"insightsEnabled": false,
"charLimit": {
"enabled": false,
"min": 123,
"max": 123
},
"validation": {
"rules": [
{
"id": "<string>",
"type": "minLength",
"params": {},
"field": "addressLine1"
}
],
"logic": "and"
}
}
],
"logic": [
{
"id": "<string>",
"conditions": {
"id": "<string>",
"connector": "and",
"conditions": [
{
"id": "<string>",
"leftOperand": {
"type": "element",
"value": "<string>",
"meta": {}
},
"operator": "equals",
"rightOperand": {
"type": "static",
"value": "<string>"
}
}
]
},
"actions": [
{
"id": "<string>",
"objective": "calculate",
"variableId": "<string>",
"operator": "assign",
"value": {
"type": "static",
"value": "<string>"
}
}
]
}
],
"logicFallback": "<string>",
"buttonLabel": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"backButtonLabel": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
}
}
],
"endings": [
{
"id": "<string>",
"type": "endScreen",
"headline": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"subheader": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"buttonLabel": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"buttonLink": "<string>",
"imageUrl": "<string>",
"imageAltText": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"videoUrl": "<string>",
"hideDefaultIcon": true
}
],
"hiddenFields": {
"enabled": true,
"fieldIds": [
"<string>"
]
},
"variables": [
{
"id": "<string>",
"name": "<string>",
"type": "number",
"value": 123
}
],
"customCss": {
"light": "<string>",
"dark": "<string>"
},
"visibility": "restricted",
"owner": {
"name": "<string>"
},
"access": {
"via": "workspace",
"canManageVisibility": true
},
"distribution": {
"displayOption": "displaySome",
"displayLimit": 3,
"displayPercentage": null,
"recontactDays": 7,
"autoClose": null,
"autoComplete": null,
"delay": 0,
"triggers": [
{
"actionClassId": "clyy1234567890123456789012"
}
]
},
"targeting": {
"filters": [
{
"id": "<string>",
"connector": "and",
"resource": {
"id": "<string>",
"root": {
"type": "attribute",
"contactAttributeKey": "<string>"
},
"qualifier": {
"operator": "lessThan"
},
"value": "<string>"
}
}
]
}
},
"warnings": [
{
"code": "import_removed",
"scope": "workspace",
"appearance": "light",
"line": 2,
"column": 2,
"reason": "<string>"
}
]
}Update a survey
Updates a survey through a strict top-level partial document. Omitted top-level fields are preserved. Provided top-level objects and arrays replace that whole subtree; this endpoint does not deep-merge nested objects and does not implement JSON Patch.
This write endpoint accepts the canonical multilingual authoring document only. Translatable
fields must be locale-code maps, not strings. PATCH ?lang=... and ?version=... are not
supported in Scope 1.
For MCP and AI-agent workflows, fetch the current survey first, modify only the intended
top-level fields, call /api/v3/surveys/validate with operation: patch for preflight, then
submit the same patch here. Missing ids in replaced arrays are treated as deletions. Variable
name renames are allowed but may be destructive for downstream exports or integrations.
Element id changes are rejected once the survey and element are no longer drafts.
Server-owned fields that GET returns (id, workspaceId, type, createdAt, archivedAt, defaultLanguage, languages[].alias) are accepted and verified, so the output of a GET can be sent straight back. Echoing the value you were given is a no-op; changing one is a 422 read_only_field.
A round-tripped updatedAt acts as an optimistic-concurrency precondition: the write is applied only if the survey has not changed since your read, and is otherwise rejected with 409. Omit it and overlapping writes remain last-write-wins. Header-based preconditions (ETag / If-Match) are still future work.
curl --request PATCH \
--url https://app.formbricks.com/api/v3/surveys/{surveyId} \
--header 'Content-Type: application/json' \
--cookie next-auth.session-token= \
--data '
{
"name": "Updated Product Feedback"
}
'{
"data": {
"id": "<string>",
"workspaceId": "<string>",
"createdAt": "2023-11-07T05:31:56Z",
"updatedAt": "2023-11-07T05:31:56Z",
"archivedAt": "2023-11-07T05:31:56Z",
"name": "<string>",
"type": "link",
"status": "draft",
"metadata": {
"title": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"description": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
}
},
"defaultLanguage": "<string>",
"languages": [
{
"code": "en-US",
"default": true,
"enabled": true,
"alias": "english"
}
],
"showLanguageSwitch": true,
"autoSelectLanguage": true,
"welcomeCard": {
"enabled": true,
"headline": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"subheader": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"buttonLabel": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"fileUrl": "<string>",
"videoUrl": "<string>",
"timeToFinish": true,
"showResponseCount": true
},
"blocks": [
{
"id": "<string>",
"name": "<string>",
"elements": [
{
"id": "<string>",
"type": "openText",
"headline": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"required": true,
"subheader": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"imageUrl": "<string>",
"imageAltText": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"videoUrl": "<string>",
"isDraft": true,
"placeholder": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"longAnswer": true,
"inputType": "text",
"insightsEnabled": false,
"charLimit": {
"enabled": false,
"min": 123,
"max": 123
},
"validation": {
"rules": [
{
"id": "<string>",
"type": "minLength",
"params": {},
"field": "addressLine1"
}
],
"logic": "and"
}
}
],
"logic": [
{
"id": "<string>",
"conditions": {
"id": "<string>",
"connector": "and",
"conditions": [
{
"id": "<string>",
"leftOperand": {
"type": "element",
"value": "<string>",
"meta": {}
},
"operator": "equals",
"rightOperand": {
"type": "static",
"value": "<string>"
}
}
]
},
"actions": [
{
"id": "<string>",
"objective": "calculate",
"variableId": "<string>",
"operator": "assign",
"value": {
"type": "static",
"value": "<string>"
}
}
]
}
],
"logicFallback": "<string>",
"buttonLabel": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"backButtonLabel": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
}
}
],
"endings": [
{
"id": "<string>",
"type": "endScreen",
"headline": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"subheader": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"buttonLabel": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"buttonLink": "<string>",
"imageUrl": "<string>",
"imageAltText": {
"en-US": "What should we improve?",
"de-DE": "Was sollten wir verbessern?"
},
"videoUrl": "<string>",
"hideDefaultIcon": true
}
],
"hiddenFields": {
"enabled": true,
"fieldIds": [
"<string>"
]
},
"variables": [
{
"id": "<string>",
"name": "<string>",
"type": "number",
"value": 123
}
],
"customCss": {
"light": "<string>",
"dark": "<string>"
},
"visibility": "restricted",
"owner": {
"name": "<string>"
},
"access": {
"via": "workspace",
"canManageVisibility": true
},
"distribution": {
"displayOption": "displaySome",
"displayLimit": 3,
"displayPercentage": null,
"recontactDays": 7,
"autoClose": null,
"autoComplete": null,
"delay": 0,
"triggers": [
{
"actionClassId": "clyy1234567890123456789012"
}
]
},
"targeting": {
"filters": [
{
"id": "<string>",
"connector": "and",
"resource": {
"id": "<string>",
"root": {
"type": "attribute",
"contactAttributeKey": "<string>"
},
"qualifier": {
"operator": "lessThan"
},
"value": "<string>"
}
}
]
}
},
"warnings": [
{
"code": "import_removed",
"scope": "workspace",
"appearance": "light",
"line": 2,
"column": 2,
"reason": "<string>"
}
]
}Authorizations
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.
Path Parameters
Survey identifier.
Body
Patch payload shape. Top-level fields are partial; any provided nested object or array fully replaces that subtree. Omitted top-level fields are preserved.
The server-owned fields GET returns — id, workspaceId, type, createdAt, updatedAt, archivedAt, defaultLanguage and languages[].alias — are accepted and verified, so a survey fetched with GET can be sent straight back. Echoing the value you were given is a no-op; changing one is a 422 read_only_field. visibility, owner and access are accepted the same way, but a changed value is a 422 unsupported_field: visibility changes go through POST /api/v3/surveys/{surveyId}/visibility. A round-tripped updatedAt additionally acts as an optimistic-concurrency precondition, and a stale one is rejected with 409. questions, analytics, styling and scripts remain rejected outright. App surveys (stored type: app) additionally accept distribution and targeting; both are rejected for link surveys, and changing targeting filters requires the Contacts entitlement.
metadata, languages, welcomeCard, blocks, endings, hiddenFields, and variables
replace their full top-level value when provided. Missing ids in replaced arrays are deletions.
Non-default locale keys in translatable maps must be declared in languages; undeclared locale
keys are rejected with unsupported_locale. To remove a language, remove it from both
languages and every translatable map that contains that locale key.
Use /api/v3/surveys/validate with operation: patch before committing automated or agentic
changes.
Read-only echo. Must match the survey being patched.
Read-only echo. A survey cannot be moved between workspaces.
Read-only echo. Immutable after creation.
link, app Read-only echo of the creation timestamp.
Read-only echo, and an optimistic-concurrency precondition: the write is applied only if the survey has not changed since the read this value came from, and is otherwise a 409.
Read-only echo. Use /archive and /restore to change it.
Read-only echo. Accepted only unchanged, so a survey fetched with GET can be sent back; any other value is a 422 unsupported_field. Change it with POST /api/v3/surveys/{surveyId}/visibility.
restricted, workspace Read-only echo, accepted only unchanged (otherwise 422 unsupported_field).
Show child attributes
Show child attributes
Read-only echo, accepted only unchanged (otherwise 422 unsupported_field).
Show child attributes
Show child attributes
Read-only echo of the survey default language, in whatever shape GET returned — legacy surveys carry language-only codes, so this is not constrained to LocaleCode.
1draft, inProgress, paused, completed Arbitrary JSON survey context for customer- or operation-specific metadata. v3 preserves
arbitrary metadata values as-is. If present, title and description are treated as
translatable text maps and returned with real locale-code keys.
Show child attributes
Show child attributes
Replaces the survey language configuration. The default language cannot be changed through
PATCH; any default: true entry must match the existing default language. Languages referenced
by metadata, welcomeCard, blocks, or endings translatable maps must be explicitly
declared here, so remove the locale key from those maps as well when intentionally removing
a language.
50Show child attributes
Show child attributes
Show respondents a language switch on multi-language surveys. null and false both mean off. Omit to keep the stored value.
Open link and app surveys in the respondent's browser language when it matches an enabled survey language; otherwise the default language is used. null and false both mean off. Omit to keep the stored value.
Optional card shown before the first survey block.
Show child attributes
Show child attributes
1 - 1000 elementsShow child attributes
Show child attributes
100Ending reached after the last block or a jump action. type selects the allowed shape;
unsupported fields are rejected instead of ignored.
- Option 1
- Option 2
Show child attributes
Show child attributes
Hidden fields, sometimes called embedded data in other survey products. Field ids are stable public identifiers and may be referenced by logic, recall, quotas, integrations, and response data.
Naming rule for new field ids — the same rule the survey editor applies (ENG-2539): a new id must start with a lowercase letter and then contain only lowercase letters, numbers and underscores (^[a-z][a-z0-9_]*$), and must not take a reserved name. Reserved are the link-survey system params and internal ids — userId, source, suid, end, start, welcomeCard, hidden, verifiedEmail, multiLanguage, embed, verify, suToken, lang, preview, startAt, skipPrefilled, offlineSupport (matched case-insensitively) — and the names of auto-captured system fields, which every survey can already read without declaring them: source, url, country, action, browser, os, deviceType, ipAddress, finished, language, locale, responseId, surveyId, durationSeconds, startedAt, finishedAt, pagePath, pageReferrer, utmSource, utmMedium, utmCampaign, utmTerm, utmContent, screenWidth, screenHeight, viewportWidth, viewportHeight, timezone.
Ids a survey already declares are grandfathered: they always load, and re-sending the survey unchanged never fails validation — only adding such a name as a new field is refused. Deleting a grandfathered field spends the reprieve: once it is gone from the saved survey, the name can no longer be re-added. Note this means re-creating a survey from an exported document can fail with a 400 when the export declares a name the rule refuses; rename the field in the payload before importing. The pattern below describes what stored surveys may hold (the pre-existing lenient charset), not what a new id may look like.
Show child attributes
Show child attributes
100Survey variable. Variable ids are stable references used by logic and calculation actions. Variable names are human-readable labels and must be unique within the survey.
- Option 1
- Option 2
Show child attributes
Show child attributes
App-survey runtime/display settings. Only valid for stored type: app. Replaces the full distribution; omitted scalars reset to their defaults.
Show child attributes
Show child attributes
{
"displayOption": "displaySome",
"displayLimit": 3,
"displayPercentage": null,
"recontactDays": 7,
"autoClose": null,
"autoComplete": null,
"delay": 0,
"triggers": [
{
"actionClassId": "clyy1234567890123456789012"
}
]
}
App-survey contact targeting. Only valid for stored app surveys.
Show child attributes
Show child attributes
Survey custom CSS source. Omitted: unchanged. null: clears both fields. An object replaces both fields and needs both keys. Change is judged on normalized source, so echoing the value GET returned is a no-op that needs no plan. Adding or editing needs the Scale plan on Formbricks Cloud (403 custom_css_plan_required); clearing never does. A failed write keeps the saved CSS. Only an addition or edit is processed, so only it counts against the custom CSS budget of 60 per minute per user or API key, shared with custom CSS validation; beyond it the patch is a 429.
Show child attributes
Show child attributes
Response
Survey updated successfully
The three fields every SurveyListItem and SurveyResource carries, merged into both via allOf. All required, always present.
Show child attributes
Show child attributes
Processing warnings for this write: constructs the processor removed. Additive, returned beside data (never inside it, so data can be sent back unchanged); present only when the write processed custom CSS.
50Show child attributes
Show child attributes
Was this page helpful?