Returns workflow run summaries for a workspace, newest first (createdAt descending). Use
workflowId to narrow the list to one workflow, or responseId to find the runs a specific
survey response produced.
List items are summaries without triggerPayload, data, or logs; fetch
GET /api/v3/workflows/runs/{runId} for the full debug-oriented payload. This keeps
response-level data out of list reads by default.
GET
/
api
/
v3
/
workflows
/
runs
List workflow runs
curl --request GET \ --url https://app.formbricks.com/api/v3/workflows/runs \ --cookie next-auth.session-token=
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.
Page size (max 100). The workflows endpoints have not yet moved to the v3-wide maximum of 250 — their bound lives in the shared packages/workflows contracts, which are owned alongside the workflows feature rather than by this spec. Documented at the value actually enforced rather than at the platform norm; tracked separately.
Run lifecycle-state filter. Repeat the parameter or use comma-separated values
(filter[status][in]=failed,canceled). Invalid values → 400.
Workflow run lifecycle state. completed, failed, and canceled are terminal. Valid
transitions: queued → running, running → queued (retry/backoff), queued →
canceled, and running → completed/failed/canceled. Retries do not introduce a
separate status; retry state is exposed via attempt and nextAttemptAt.
A list meta carrying pagination and nothing else — the shape for collections that do not report a total and have no domain context to echo.
Adds nothing to ListPaginationMeta; the allOf wrapper is what closes it. Each composing operation bounds its own requests through its limit query parameter, which is why this shape states no cap of its own.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Documentation - Formbricks","colors":{"primary":"#00C4B8","light":"#00C4B8","dark":"#00C4B8"},"logo":{"light":"https://mintcdn.com/formbricks/wqEbm3FT1QK_6-vL/images/logo-light.svg?fit=max\u0026auto=format\u0026n=wqEbm3FT1QK_6-vL\u0026q=85\u0026s=365e5fb767b72b4fbbb2016860fd92ba","dark":"https://mintcdn.com/formbricks/wqEbm3FT1QK_6-vL/images/logo-dark.svg?fit=max\u0026auto=format\u0026n=wqEbm3FT1QK_6-vL\u0026q=85\u0026s=763690d005584ee5f4b4014615c3b98c"},"favicon":"https://mintcdn.com/formbricks/wqEbm3FT1QK_6-vL/images/favicon.svg?fit=max\u0026auto=format\u0026n=wqEbm3FT1QK_6-vL\u0026q=85\u0026s=01910ab43e3a3acc0aca5471235b90c5","navbar":{"links":[{"href":"https://github.com/formbricks/formbricks/discussions","label":"Support"}],"primary":{"type":"button","label":"Go to app","href":"https://app.formbricks.com"}},"footer":{"socials":{"github":"https://github.com/formbricks/formbricks","linkedin":"https://linkedin.com/company/formbricks","x":"https://x.com/formbricks"}},"integrations":{"posthog":{"apiKey":"phc_zJO1n3rjHlhqKiJ0gqLDwT4qvfWF1wzHDq2gfl0moQm","apiHost":"https://eu.i.posthog.com"}},"errors":{"404":{"redirect":true}},"contextual":{"options":["copy","view","chatgpt","claude","perplexity"],"display":"header"},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"formbricks","hasAudioNarration":false,"actualSubdomain":"formbricks","customDomains":["formbricks.com"],"gitSource":{"type":"github","owner":"formbricks","repo":"formbricks","deployBranch":"release/6.1","contentDirectory":"docs","isPrivate":false,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ad8c05da69b8ab3962ea10d","collectionId":"cbc1ed51-3c6a-4b1f-8507-84eb7d51eb9b","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ad8c05da69b8ab3962ea10d"},"feedback":{"thumbs":true,"issues":true,"edits":true,"agentFeedback":false},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6ad8c05da69b8ab3962ea10d","clientVersion":"0.0.3971","searchFilterCounts":[{"language":"default","tag":"Surveys (Ask)","count":87},{"language":"default","tag":"Survey Features","count":71},{"language":"default","tag":"Self Hosting","count":53},{"language":"default","tag":"API v2 Reference (Beta)","count":41},{"language":"default","tag":"API v1 Reference","count":35},{"language":"default","tag":"Platform","count":28},{"language":"default","tag":"Configuration","count":28},{"language":"default","tag":"Platform Features","count":23},{"language":"default","tag":"Integrations","count":22},{"language":"default","tag":"Development","count":21}]},"assistantConfig":{},"basePath":"/docs","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-v7-file-tree","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"pause-universal-search-reconcile","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"per-site-search-delta","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-private-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-nav-generations","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-agent-model-picker","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"isAtlas":false,"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"api-v3-reference/v3-workflows/list-workflow-runs","slug":"/api-v3-reference/v3-workflows/list-workflow-runs","pageMetadata":{"title":"List workflow runs","description":"Returns workflow run summaries for a workspace, newest first (`createdAt` descending). Use\n`workflowId` to narrow the list to one workflow, or `responseId` to find the runs a specific\nsurvey response produced.\n\nList items are summaries without `triggerPayload`, `data`, or `logs`; fetch\n`GET /api/v3/workflows/runs/{runId}` for the full debug-oriented payload. This keeps\nresponse-level data out of list reads by default.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/workflows/runs","href":"/api-v3-reference/v3-workflows/list-workflow-runs","autogeneratedByOpenApi":true,"hidden":true},"description":{"compiledSource":"\"use strict\";\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsxs(_components.p, {\n children: [\"Returns workflow run summaries for a workspace, newest first (\", _jsx(_components.code, {\n children: \"createdAt\"\n }), \" descending). Use\\n\", _jsx(_components.code, {\n children: \"workflowId\"\n }), \" to narrow the list to one workflow, or \", _jsx(_components.code, {\n children: \"responseId\"\n }), \" to find the runs a specific\\nsurvey response produced.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"List items are summaries without \", _jsx(_components.code, {\n children: \"triggerPayload\"\n }), \", \", _jsx(_components.code, {\n children: \"data\"\n }), \", or \", _jsx(_components.code, {\n children: \"logs\"\n }), \"; fetch\\n\", _jsx(_components.code, {\n children: \"GET /api/v3/workflows/runs/{runId}\"\n }), \" for the full debug-oriented payload. This keeps\\nresponse-level data out of list reads by default.\"]\n })]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"List workflow runs","description":"Returns workflow run summaries for a workspace, newest first (`createdAt` descending). Use\n`workflowId` to narrow the list to one workflow, or `responseId` to find the runs a specific\nsurvey response produced.\n\nList items are summaries without `triggerPayload`, `data`, or `logs`; fetch\n`GET /api/v3/workflows/runs/{runId}` for the full debug-oriented payload. This keeps\nresponse-level data out of list reads by default.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/workflows/runs","href":"/api-v3-reference/v3-workflows/list-workflow-runs","autogeneratedByOpenApi":true,"hidden":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":["/docs/_mintlify/custom/formbricks/fd84136b00b6b9ed/formbricks.js"],"openApiReferenceData":{"operation":{"operationId":"listWorkflowRunsV3","summary":"List workflow runs","description":"Returns workflow run summaries for a workspace, newest first (`createdAt` descending). Use\n`workflowId` to narrow the list to one workflow, or `responseId` to find the runs a specific\nsurvey response produced.\n\nList items are summaries without `triggerPayload`, `data`, or `logs`; fetch\n`GET /api/v3/workflows/runs/{runId}` for the full debug-oriented payload. This keeps\nresponse-level data out of list reads by default.\n","tags":["V3 Workflows"],"parameters":["f1cf0d62-a558-478b-9a4a-2879ef4cf040","18b36a68-0017-4d8e-bafe-0207ed1fec2f","b0cd2417-d9fa-437f-8b52-ea71fede3112","a7072d1f-4e86-47cf-a215-5be8cda616b8","ec431406-07c9-4b3e-825e-564705075f44","41ad3fae-d15a-4763-bc02-4bf4c955d13a","114aafbf-e854-4e16-a93f-db9eaf5fac73"],"responses":{"200":"0da959ea-a64f-40de-ba53-506657cfbe35","400":"5cb4ae4c-9efd-4be5-95bd-25ae5ee31f07","401":"ee616c63-d888-443b-9ca7-fabba75e5dce","403":"a411f6ff-3b72-440a-abfd-65666ad49ed0","429":"b32548bc-8796-42c9-81cb-c053806cb770","500":"27c24838-f6a8-42b5-a8ec-8321729a29d7"},"security":["47363168-ea5b-42ef-b12c-0d280fa19a38","d09b63f3-5c41-482c-b5c7-5087342bc502","c472c642-651b-48c0-be46-1341abc8ceb8"],"method":"get","type":"path","servers":["5a1d53ae-163d-4303-ac56-7a378a4d43bc"],"path":"/api/v3/workflows/runs","baseUrlOptions":["https://app.formbricks.com"],"title":"List workflow runs","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{"f1cf0d62-a558-478b-9a4a-2879ef4cf040":{"in":"query","name":"workspaceId","required":true,"schema":{"type":"string","format":"cuid2","isRequired":true,"description":"Workspace identifier. This is the canonical container ID for v3 APIs.","uniqueKey":"","typeLabel":"string\u003ccuid2>"},"description":"Workspace identifier. This is the canonical container ID for v3 APIs."},"18b36a68-0017-4d8e-bafe-0207ed1fec2f":{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":20,"description":"Page size (max 100). The workflows endpoints have not yet moved to the v3-wide maximum of 250 — their bound lives in the shared `packages/workflows` contracts, which are owned alongside the workflows feature rather than by this spec. Documented at the value actually enforced rather than at the platform norm; tracked separately.","uniqueKey":"","typeLabel":"integer"},"description":"Page size (max 100). The workflows endpoints have not yet moved to the v3-wide maximum of 250 — their bound lives in the shared `packages/workflows` contracts, which are owned alongside the workflows feature rather than by this spec. Documented at the value actually enforced rather than at the platform norm; tracked separately."},"b0cd2417-d9fa-437f-8b52-ea71fede3112":{"in":"query","name":"cursor","schema":{"type":"string","description":"Opaque cursor returned as `meta.nextCursor` from the previous page. Omit on the first request.","uniqueKey":"","typeLabel":"string"},"description":"Opaque cursor returned as `meta.nextCursor` from the previous page. Omit on the first request."},"a7072d1f-4e86-47cf-a215-5be8cda616b8":{"in":"query","name":"workflowId","schema":{"type":"string","format":"cuid2","description":"Optional workflow scoping. Returns only runs of this workflow.","uniqueKey":"","typeLabel":"string\u003ccuid2>"},"description":"Optional workflow scoping. Returns only runs of this workflow."},"ec431406-07c9-4b3e-825e-564705075f44":{"in":"query","name":"responseId","schema":{"type":"string","format":"cuid2","description":"Optional response scoping. Returns only runs triggered by this survey response.","uniqueKey":"","typeLabel":"string\u003ccuid2>"},"description":"Optional response scoping. Returns only runs triggered by this survey response."},"41ad3fae-d15a-4763-bc02-4bf4c955d13a":{"in":"query","name":"filter[status][in]","schema":{"type":"array","items":{"type":"string","enum":["queued","running","completed","failed","canceled"],"description":"Workflow run lifecycle state. `completed`, `failed`, and `canceled` are terminal. Valid\ntransitions: `queued` → `running`, `running` → `queued` (retry/backoff), `queued` →\n`canceled`, and `running` → `completed`/`failed`/`canceled`. Retries do not introduce a\nseparate status; retry state is exposed via `attempt` and `nextAttemptAt`.\n","uniqueKey":"items.[INDEX]","typeLabel":"enum\u003cstring>"},"description":"Run lifecycle-state filter. Repeat the parameter or use comma-separated values\n(`filter[status][in]=failed,canceled`). Invalid values → **400**.\n","uniqueKey":"","typeLabel":"enum\u003cstring>[]"},"style":"form","explode":true,"description":"Run lifecycle-state filter. Repeat the parameter or use comma-separated values\n(`filter[status][in]=failed,canceled`). Invalid values → **400**.\n"},"114aafbf-e854-4e16-a93f-db9eaf5fac73":{"in":"query","name":"filter[isDryRun][eq]","schema":{"type":"boolean","description":"Filter for dry runs created by `POST /api/v3/workflows/{workflowId}/test` (`true`) or\nfor real trigger-initiated runs only (`false`). Omit to return both.\n","uniqueKey":"","typeLabel":"boolean"},"description":"Filter for dry runs created by `POST /api/v3/workflows/{workflowId}/test` (`true`) or\nfor real trigger-initiated runs only (`false`). Omit to return both.\n"}},"responses":{"0da959ea-a64f-40de-ba53-506657cfbe35":{"description":"Workflow runs 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":{"type":"object","description":"Run-list row returned by `GET /api/v3/workflows/runs`: the slim run summary plus the resolved\n`workflowName`, joined so the workspace-wide runs table can label each row. Distinct from the\n`lastRun` summary embedded in workflow resources, which omits the name (the parent workflow\nalready carries it). Excludes `triggerPayload`, `data`, and `logs`.\n","required":["workflowName","id","workflowId","workspaceId","workflowVersionId","status","isDryRun","triggerType","surveyId","responseId","error","attempt","createdAt","updatedAt","startedAt","finishedAt"],"properties":{"id":{"type":"string","format":"cuid2","isRequired":true,"uniqueKey":"data.items.[INDEX].id","typeLabel":"string\u003ccuid2>"},"workflowId":{"type":"string","format":"cuid2","isRequired":true,"uniqueKey":"data.items.[INDEX].workflowId","typeLabel":"string\u003ccuid2>"},"workspaceId":{"type":"string","format":"cuid2","isRequired":true,"uniqueKey":"data.items.[INDEX].workspaceId","typeLabel":"string\u003ccuid2>"},"workflowVersionId":{"oneOf":[{"type":"string","format":"cuid2","description":"Immutable workflow version snapshot the run executes against. `null` for dry runs of\nworkflows that have never been enabled. Version contents are not readable through the\nv3 API in Scope 1.\n","isRequired":true,"uniqueKey":"data.items.[INDEX].workflowVersionId.oneOf.0","typeLabel":"string\u003ccuid2>"},{"type":"null","format":"cuid2","description":"Immutable workflow version snapshot the run executes against. `null` for dry runs of\nworkflows that have never been enabled. Version contents are not readable through the\nv3 API in Scope 1.\n","isRequired":true,"uniqueKey":"data.items.[INDEX].workflowVersionId.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.items.[INDEX].workflowVersionId","typeLabel":"string\u003ccuid2> | null"},"status":{"type":"string","enum":["queued","running","completed","failed","canceled"],"description":"Workflow run lifecycle state. `completed`, `failed`, and `canceled` are terminal. Valid\ntransitions: `queued` → `running`, `running` → `queued` (retry/backoff), `queued` →\n`canceled`, and `running` → `completed`/`failed`/`canceled`. Retries do not introduce a\nseparate status; retry state is exposed via `attempt` and `nextAttemptAt`.\n","isRequired":true,"uniqueKey":"data.items.[INDEX].status","typeLabel":"enum\u003cstring>"},"isDryRun":{"type":"boolean","description":"`true` for runs created by `POST /api/v3/workflows/{workflowId}/test`.","isRequired":true,"uniqueKey":"data.items.[INDEX].isDryRun","typeLabel":"boolean"},"triggerType":{"type":"string","enum":["response.completed"],"isRequired":true,"uniqueKey":"data.items.[INDEX].triggerType","typeLabel":"enum\u003cstring>"},"surveyId":{"oneOf":[{"type":"string","format":"cuid2","isRequired":true,"uniqueKey":"data.items.[INDEX].surveyId.oneOf.0","typeLabel":"string\u003ccuid2>"},{"type":"null","format":"cuid2","isRequired":true,"uniqueKey":"data.items.[INDEX].surveyId.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.items.[INDEX].surveyId","typeLabel":"string\u003ccuid2> | null"},"responseId":{"oneOf":[{"type":"string","format":"cuid2","description":"Survey response that triggered the run. `null` for synthesized dry-run data or when the response was deleted.","isRequired":true,"uniqueKey":"data.items.[INDEX].responseId.oneOf.0","typeLabel":"string\u003ccuid2>"},{"type":"null","format":"cuid2","description":"Survey response that triggered the run. `null` for synthesized dry-run data or when the response was deleted.","isRequired":true,"uniqueKey":"data.items.[INDEX].responseId.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.items.[INDEX].responseId","typeLabel":"string\u003ccuid2> | null"},"error":{"oneOf":[{"type":"string","description":"Terminal or most recent failure reason. `null` while the run is healthy.","isRequired":true,"uniqueKey":"data.items.[INDEX].error.oneOf.0","typeLabel":"string"},{"type":"null","description":"Terminal or most recent failure reason. `null` while the run is healthy.","isRequired":true,"uniqueKey":"data.items.[INDEX].error.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.items.[INDEX].error","typeLabel":"string | null"},"attempt":{"type":"integer","minimum":0,"description":"Retry attempt counter. `0` on the first execution; retries increment it without changing `status`.","isRequired":true,"uniqueKey":"data.items.[INDEX].attempt","typeLabel":"integer"},"createdAt":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"data.items.[INDEX].createdAt","typeLabel":"string\u003cdate-time>"},"updatedAt":{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"data.items.[INDEX].updatedAt","typeLabel":"string\u003cdate-time>"},"startedAt":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"data.items.[INDEX].startedAt.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"data.items.[INDEX].startedAt.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.items.[INDEX].startedAt","typeLabel":"string\u003cdate-time> | null"},"finishedAt":{"oneOf":[{"type":"string","format":"date-time","isRequired":true,"uniqueKey":"data.items.[INDEX].finishedAt.oneOf.0","typeLabel":"string\u003cdate-time>"},{"type":"null","format":"date-time","isRequired":true,"uniqueKey":"data.items.[INDEX].finishedAt.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"data.items.[INDEX].finishedAt","typeLabel":"string\u003cdate-time> | null"},"workflowName":{"type":"string","description":"Name of the workflow this run belongs to, joined for the runs-list display.","isRequired":true,"uniqueKey":"data.items.[INDEX].workflowName","typeLabel":"string"}},"uniqueKey":"data.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"data","typeLabel":"object[]"},"meta":{"type":"object","description":"A list `meta` carrying pagination and nothing else — the shape for collections that do not report a total and have no domain context to echo.\n\nAdds nothing to `ListPaginationMeta`; the `allOf` wrapper is what closes it. Each composing operation bounds its own requests through its `limit` query parameter, which is why this shape states no cap of its own.","required":["limit","nextCursor"],"properties":{"limit":{"type":"integer","minimum":1,"description":"The page size actually applied. Carries no `maximum`: it echoes what the server used, it does not bound what may be asked for. The request-side bound is the `limit` query parameter on the operation itself and differs per collection — read it there. A shared description cannot state it without being wrong for some of the operations that compose this base.","isRequired":true,"uniqueKey":"meta.limit","typeLabel":"integer"},"nextCursor":{"oneOf":[{"type":"string","description":"Opaque cursor for the next page. `null` when there are no more results — the only reliable end-of-collection signal, since the server may return fewer items than `limit` without the collection being exhausted. Pass it back verbatim: the encoding is deliberately unspecified and may change without notice, so a client that decodes or constructs one is relying on something this contract does not promise.","isRequired":true,"uniqueKey":"meta.nextCursor.oneOf.0","typeLabel":"string"},{"type":"null","description":"Opaque cursor for the next page. `null` when there are no more results — the only reliable end-of-collection signal, since the server may return fewer items than `limit` without the collection being exhausted. Pass it back verbatim: the encoding is deliberately unspecified and may change without notice, so a client that decodes or constructs one is relying on something this contract does not promise.","isRequired":true,"uniqueKey":"meta.nextCursor.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"meta.nextCursor","typeLabel":"string | null"}},"isRequired":true,"uniqueKey":"meta","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"data":[{"id":"\u003cstring>","workflowId":"\u003cstring>","workspaceId":"\u003cstring>","workflowVersionId":"\u003cstring>","status":"queued","isDryRun":true,"triggerType":"response.completed","surveyId":"\u003cstring>","responseId":"\u003cstring>","error":"\u003cstring>","attempt":1,"createdAt":"2023-11-07T05:31:56Z","updatedAt":"2023-11-07T05:31:56Z","startedAt":"2023-11-07T05:31:56Z","finishedAt":"2023-11-07T05:31:56Z","workflowName":"\u003cstring>"}],"meta":{"limit":2,"nextCursor":"\u003cstring>"}}}},"exampleType":"generated"}},"exampleType":"generated"},"5cb4ae4c-9efd-4be5-95bd-25ae5ee31f07":{"description":"Bad Request — malformed JSON, invalid query/body/params, duplicate name, or unsupported field.","headers":{"X-Request-Id":{"schema":{"type":"string"},"description":"Request correlation ID"},"Cache-Control":{"schema":{"type":"string"},"example":"private, no-store"}},"content":{"application/problem+json":{"schema":{"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`.\n\nBranch on `code`, not on `detail` or `title`: `code` is stable and locale-independent, whereas `detail` is prose that may be reworded. No problem sets `type`, so per RFC 9457 §4.2.1 `title` is always the HTTP reason phrase for `status` and carries no information of its own.\n\nMember naming is frozen as published, mixed conventions included (`requestId` alongside `invalid_params` and `details.resource_type`): renaming any of them would break every client that reads them.","required":["title","status","detail","requestId"],"properties":{"title":{"type":"string","isRequired":true,"uniqueKey":"title","typeLabel":"string"},"status":{"type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"detail":{"type":"string","isRequired":true,"uniqueKey":"detail","typeLabel":"string"},"requestId":{"type":"string","isRequired":true,"uniqueKey":"requestId","typeLabel":"string"},"type":{"type":"string","format":"uri","uniqueKey":"type","typeLabel":"string\u003curi>"},"instance":{"type":"string","uniqueKey":"instance","typeLabel":"string"},"code":{"type":"string","enum":["ai_features_not_enabled","ai_generated_payload_invalid","ai_instance_not_configured","ai_output_too_long","ai_provider_auth_failed","ai_smart_tools_disabled","bad_gateway","bad_request","conflict","custom_css_plan_required","forbidden","internal_server_error","invalid_workflow_state","not_authenticated","not_found","payload_too_large","projection_pending","service_unavailable","stored_survey_invalid","survey_not_workspace_visible","too_many_requests","unprocessable_content","visibility_blocked_by_connections","visibility_change_not_allowed","visibility_not_enabled","workflow_not_executable","workspace_survey_limit_reached"],"uniqueKey":"code","typeLabel":"enum\u003cstring>"},"details":{"type":"object","uniqueKey":"details","typeLabel":"object"},"invalid_params":{"type":"array","items":{"type":"object","description":"Field-level validation error. `name` and `reason` are always intended for humans.\nOptional machine-readable fields are included when the API can identify the semantic error,\nespecially for survey locale, identifier, and reference validation used by MCP and agent clients.\n","required":["name","reason"],"properties":{"name":{"type":"string","description":"Dot-path to the invalid request field.","isRequired":true,"uniqueKey":"invalid_params.items.[INDEX].name","typeLabel":"string"},"reason":{"type":"string","description":"Human-readable repair guidance.","isRequired":true,"uniqueKey":"invalid_params.items.[INDEX].reason","typeLabel":"string"},"code":{"type":"string","enum":["dangling_reference","duplicate_identifier","duplicate_locale","forbidden_identifier","immutable_identifier","invalid_locale","invalid_reference","missing_required_field","misordered_reference","missing_translation","qsf_limit_exceeded","qsf_not_recognized","read_only_field","unsupported_field","unsupported_locale"],"description":"Machine-readable validation category, when available.\n\nThis is the shared error shape every v3 operation returns, so it lists what the API can emit today and nothing more — `INVALID_PARAM_CODES` in `app/api/v3/lib/response.ts` is the registry, and a code absent from it is dropped before the response is built. Categories for operations that do not exist yet are added with the code that emits them, not ahead of it.\n\n`qsf_not_recognized` and `qsf_limit_exceeded` come from the Qualtrics import (an internal, session-only route sharing this shape): the file is not a Qualtrics export it can read, or it is one past an import limit, which `identifier` names.\n","uniqueKey":"invalid_params.items.[INDEX].code","typeLabel":"enum\u003cstring>"},"identifier":{"type":"string","description":"Identifier involved in the validation failure, when available. For language errors, this can be the normalized language code.","uniqueKey":"invalid_params.items.[INDEX].identifier","typeLabel":"string"},"referenceType":{"type":"string","enum":["block","element","ending","hiddenField","language","variable","variableName","recall"],"description":"Identifier namespace involved in the validation failure. Same rule as `code`: these are the namespaces the API emits today, and more arrive with the operations that emit them.","uniqueKey":"invalid_params.items.[INDEX].referenceType","typeLabel":"enum\u003cstring>"},"missingId":{"type":"string","description":"Referenced id that does not exist in the submitted survey document.","uniqueKey":"invalid_params.items.[INDEX].missingId","typeLabel":"string"},"firstUsedAt":{"type":"string","description":"Dot-path where a duplicate identifier was first used.","uniqueKey":"invalid_params.items.[INDEX].firstUsedAt","typeLabel":"string"},"conflictsWith":{"type":"string","description":"Dot-path to the existing identifier that conflicts with this field.","uniqueKey":"invalid_params.items.[INDEX].conflictsWith","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"invalid_params.items.[INDEX]","typeLabel":"object"},"uniqueKey":"invalid_params","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"title":"\u003cstring>","status":123,"detail":"\u003cstring>","requestId":"\u003cstring>","type":"\u003cstring>","instance":"\u003cstring>","code":"ai_features_not_enabled","details":{},"invalid_params":[{"name":"\u003cstring>","reason":"\u003cstring>","code":"dangling_reference","identifier":"\u003cstring>","referenceType":"block","missingId":"\u003cstring>","firstUsedAt":"\u003cstring>","conflictsWith":"\u003cstring>"}]}}},"exampleType":"generated"}},"exampleType":"generated"},"ee616c63-d888-443b-9ca7-fabba75e5dce":{"description":"Not authenticated (no valid session or API key).","headers":{"WWW-Authenticate":{"schema":{"type":"string"},"example":"Bearer realm=\"formbricks\"","description":"Authentication scheme challenge. RFC 9110 §15.5.2 asks a 401 for a challenge \"applicable to the target resource\", and Bearer is applicable here because these operations accept the API key as `Authorization: Bearer \u003ckey>` as well as `x-api-key`. Session-cookie-only operations send no challenge — see `V3UnauthorizedSession`. The MCP endpoints send a richer OAuth challenge carrying `resource_metadata` and `scope`."},"X-Request-Id":{"schema":{"type":"string"},"description":"Request correlation ID"},"Cache-Control":{"schema":{"type":"string"},"example":"private, no-store"}},"content":{"application/problem+json":{"schema":{"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`.\n\nBranch on `code`, not on `detail` or `title`: `code` is stable and locale-independent, whereas `detail` is prose that may be reworded. No problem sets `type`, so per RFC 9457 §4.2.1 `title` is always the HTTP reason phrase for `status` and carries no information of its own.\n\nMember naming is frozen as published, mixed conventions included (`requestId` alongside `invalid_params` and `details.resource_type`): renaming any of them would break every client that reads them.","required":["title","status","detail","requestId"],"properties":{"title":{"type":"string","isRequired":true,"uniqueKey":"title","typeLabel":"string"},"status":{"type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"detail":{"type":"string","isRequired":true,"uniqueKey":"detail","typeLabel":"string"},"requestId":{"type":"string","isRequired":true,"uniqueKey":"requestId","typeLabel":"string"},"type":{"type":"string","format":"uri","uniqueKey":"type","typeLabel":"string\u003curi>"},"instance":{"type":"string","uniqueKey":"instance","typeLabel":"string"},"code":{"type":"string","enum":["ai_features_not_enabled","ai_generated_payload_invalid","ai_instance_not_configured","ai_output_too_long","ai_provider_auth_failed","ai_smart_tools_disabled","bad_gateway","bad_request","conflict","custom_css_plan_required","forbidden","internal_server_error","invalid_workflow_state","not_authenticated","not_found","payload_too_large","projection_pending","service_unavailable","stored_survey_invalid","survey_not_workspace_visible","too_many_requests","unprocessable_content","visibility_blocked_by_connections","visibility_change_not_allowed","visibility_not_enabled","workflow_not_executable","workspace_survey_limit_reached"],"uniqueKey":"code","typeLabel":"enum\u003cstring>"},"details":{"type":"object","uniqueKey":"details","typeLabel":"object"},"invalid_params":{"type":"array","items":{"type":"object","description":"Field-level validation error. `name` and `reason` are always intended for humans.\nOptional machine-readable fields are included when the API can identify the semantic error,\nespecially for survey locale, identifier, and reference validation used by MCP and agent clients.\n","required":["name","reason"],"properties":{"name":{"type":"string","description":"Dot-path to the invalid request field.","isRequired":true,"uniqueKey":"invalid_params.items.[INDEX].name","typeLabel":"string"},"reason":{"type":"string","description":"Human-readable repair guidance.","isRequired":true,"uniqueKey":"invalid_params.items.[INDEX].reason","typeLabel":"string"},"code":{"type":"string","enum":["dangling_reference","duplicate_identifier","duplicate_locale","forbidden_identifier","immutable_identifier","invalid_locale","invalid_reference","missing_required_field","misordered_reference","missing_translation","qsf_limit_exceeded","qsf_not_recognized","read_only_field","unsupported_field","unsupported_locale"],"description":"Machine-readable validation category, when available.\n\nThis is the shared error shape every v3 operation returns, so it lists what the API can emit today and nothing more — `INVALID_PARAM_CODES` in `app/api/v3/lib/response.ts` is the registry, and a code absent from it is dropped before the response is built. Categories for operations that do not exist yet are added with the code that emits them, not ahead of it.\n\n`qsf_not_recognized` and `qsf_limit_exceeded` come from the Qualtrics import (an internal, session-only route sharing this shape): the file is not a Qualtrics export it can read, or it is one past an import limit, which `identifier` names.\n","uniqueKey":"invalid_params.items.[INDEX].code","typeLabel":"enum\u003cstring>"},"identifier":{"type":"string","description":"Identifier involved in the validation failure, when available. For language errors, this can be the normalized language code.","uniqueKey":"invalid_params.items.[INDEX].identifier","typeLabel":"string"},"referenceType":{"type":"string","enum":["block","element","ending","hiddenField","language","variable","variableName","recall"],"description":"Identifier namespace involved in the validation failure. Same rule as `code`: these are the namespaces the API emits today, and more arrive with the operations that emit them.","uniqueKey":"invalid_params.items.[INDEX].referenceType","typeLabel":"enum\u003cstring>"},"missingId":{"type":"string","description":"Referenced id that does not exist in the submitted survey document.","uniqueKey":"invalid_params.items.[INDEX].missingId","typeLabel":"string"},"firstUsedAt":{"type":"string","description":"Dot-path where a duplicate identifier was first used.","uniqueKey":"invalid_params.items.[INDEX].firstUsedAt","typeLabel":"string"},"conflictsWith":{"type":"string","description":"Dot-path to the existing identifier that conflicts with this field.","uniqueKey":"invalid_params.items.[INDEX].conflictsWith","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"invalid_params.items.[INDEX]","typeLabel":"object"},"uniqueKey":"invalid_params","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"title":"\u003cstring>","status":123,"detail":"\u003cstring>","requestId":"\u003cstring>","type":"\u003cstring>","instance":"\u003cstring>","code":"ai_features_not_enabled","details":{},"invalid_params":[{"name":"\u003cstring>","reason":"\u003cstring>","code":"dangling_reference","identifier":"\u003cstring>","referenceType":"block","missingId":"\u003cstring>","firstUsedAt":"\u003cstring>","conflictsWith":"\u003cstring>"}]}}},"exampleType":"generated"}},"exampleType":"generated"},"a411f6ff-3b72-440a-abfd-65666ad49ed0":{"description":"Forbidden — no workspace access, or resource does not exist (404 not used; avoids existence leak).","headers":{"X-Request-Id":{"schema":{"type":"string"},"description":"Request correlation ID"},"Cache-Control":{"schema":{"type":"string"},"example":"private, no-store"}},"content":{"application/problem+json":{"schema":{"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`.\n\nBranch on `code`, not on `detail` or `title`: `code` is stable and locale-independent, whereas `detail` is prose that may be reworded. No problem sets `type`, so per RFC 9457 §4.2.1 `title` is always the HTTP reason phrase for `status` and carries no information of its own.\n\nMember naming is frozen as published, mixed conventions included (`requestId` alongside `invalid_params` and `details.resource_type`): renaming any of them would break every client that reads them.","required":["title","status","detail","requestId"],"properties":{"title":{"type":"string","isRequired":true,"uniqueKey":"title","typeLabel":"string"},"status":{"type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"detail":{"type":"string","isRequired":true,"uniqueKey":"detail","typeLabel":"string"},"requestId":{"type":"string","isRequired":true,"uniqueKey":"requestId","typeLabel":"string"},"type":{"type":"string","format":"uri","uniqueKey":"type","typeLabel":"string\u003curi>"},"instance":{"type":"string","uniqueKey":"instance","typeLabel":"string"},"code":{"type":"string","enum":["ai_features_not_enabled","ai_generated_payload_invalid","ai_instance_not_configured","ai_output_too_long","ai_provider_auth_failed","ai_smart_tools_disabled","bad_gateway","bad_request","conflict","custom_css_plan_required","forbidden","internal_server_error","invalid_workflow_state","not_authenticated","not_found","payload_too_large","projection_pending","service_unavailable","stored_survey_invalid","survey_not_workspace_visible","too_many_requests","unprocessable_content","visibility_blocked_by_connections","visibility_change_not_allowed","visibility_not_enabled","workflow_not_executable","workspace_survey_limit_reached"],"uniqueKey":"code","typeLabel":"enum\u003cstring>"},"details":{"type":"object","uniqueKey":"details","typeLabel":"object"},"invalid_params":{"type":"array","items":{"type":"object","description":"Field-level validation error. `name` and `reason` are always intended for humans.\nOptional machine-readable fields are included when the API can identify the semantic error,\nespecially for survey locale, identifier, and reference validation used by MCP and agent clients.\n","required":["name","reason"],"properties":{"name":{"type":"string","description":"Dot-path to the invalid request field.","isRequired":true,"uniqueKey":"invalid_params.items.[INDEX].name","typeLabel":"string"},"reason":{"type":"string","description":"Human-readable repair guidance.","isRequired":true,"uniqueKey":"invalid_params.items.[INDEX].reason","typeLabel":"string"},"code":{"type":"string","enum":["dangling_reference","duplicate_identifier","duplicate_locale","forbidden_identifier","immutable_identifier","invalid_locale","invalid_reference","missing_required_field","misordered_reference","missing_translation","qsf_limit_exceeded","qsf_not_recognized","read_only_field","unsupported_field","unsupported_locale"],"description":"Machine-readable validation category, when available.\n\nThis is the shared error shape every v3 operation returns, so it lists what the API can emit today and nothing more — `INVALID_PARAM_CODES` in `app/api/v3/lib/response.ts` is the registry, and a code absent from it is dropped before the response is built. Categories for operations that do not exist yet are added with the code that emits them, not ahead of it.\n\n`qsf_not_recognized` and `qsf_limit_exceeded` come from the Qualtrics import (an internal, session-only route sharing this shape): the file is not a Qualtrics export it can read, or it is one past an import limit, which `identifier` names.\n","uniqueKey":"invalid_params.items.[INDEX].code","typeLabel":"enum\u003cstring>"},"identifier":{"type":"string","description":"Identifier involved in the validation failure, when available. For language errors, this can be the normalized language code.","uniqueKey":"invalid_params.items.[INDEX].identifier","typeLabel":"string"},"referenceType":{"type":"string","enum":["block","element","ending","hiddenField","language","variable","variableName","recall"],"description":"Identifier namespace involved in the validation failure. Same rule as `code`: these are the namespaces the API emits today, and more arrive with the operations that emit them.","uniqueKey":"invalid_params.items.[INDEX].referenceType","typeLabel":"enum\u003cstring>"},"missingId":{"type":"string","description":"Referenced id that does not exist in the submitted survey document.","uniqueKey":"invalid_params.items.[INDEX].missingId","typeLabel":"string"},"firstUsedAt":{"type":"string","description":"Dot-path where a duplicate identifier was first used.","uniqueKey":"invalid_params.items.[INDEX].firstUsedAt","typeLabel":"string"},"conflictsWith":{"type":"string","description":"Dot-path to the existing identifier that conflicts with this field.","uniqueKey":"invalid_params.items.[INDEX].conflictsWith","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"invalid_params.items.[INDEX]","typeLabel":"object"},"uniqueKey":"invalid_params","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"title":"\u003cstring>","status":123,"detail":"\u003cstring>","requestId":"\u003cstring>","type":"\u003cstring>","instance":"\u003cstring>","code":"ai_features_not_enabled","details":{},"invalid_params":[{"name":"\u003cstring>","reason":"\u003cstring>","code":"dangling_reference","identifier":"\u003cstring>","referenceType":"block","missingId":"\u003cstring>","firstUsedAt":"\u003cstring>","conflictsWith":"\u003cstring>"}]}}},"exampleType":"generated"}},"exampleType":"generated"},"b32548bc-8796-42c9-81cb-c053806cb770":{"description":"Rate limit exceeded.","headers":{"X-Request-Id":{"schema":{"type":"string"},"description":"Request correlation ID"},"Cache-Control":{"schema":{"type":"string"},"example":"private, no-store"},"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until the current rate-limit window resets."}},"content":{"application/problem+json":{"schema":{"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`.\n\nBranch on `code`, not on `detail` or `title`: `code` is stable and locale-independent, whereas `detail` is prose that may be reworded. No problem sets `type`, so per RFC 9457 §4.2.1 `title` is always the HTTP reason phrase for `status` and carries no information of its own.\n\nMember naming is frozen as published, mixed conventions included (`requestId` alongside `invalid_params` and `details.resource_type`): renaming any of them would break every client that reads them.","required":["title","status","detail","requestId"],"properties":{"title":{"type":"string","isRequired":true,"uniqueKey":"title","typeLabel":"string"},"status":{"type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"detail":{"type":"string","isRequired":true,"uniqueKey":"detail","typeLabel":"string"},"requestId":{"type":"string","isRequired":true,"uniqueKey":"requestId","typeLabel":"string"},"type":{"type":"string","format":"uri","uniqueKey":"type","typeLabel":"string\u003curi>"},"instance":{"type":"string","uniqueKey":"instance","typeLabel":"string"},"code":{"type":"string","enum":["ai_features_not_enabled","ai_generated_payload_invalid","ai_instance_not_configured","ai_output_too_long","ai_provider_auth_failed","ai_smart_tools_disabled","bad_gateway","bad_request","conflict","custom_css_plan_required","forbidden","internal_server_error","invalid_workflow_state","not_authenticated","not_found","payload_too_large","projection_pending","service_unavailable","stored_survey_invalid","survey_not_workspace_visible","too_many_requests","unprocessable_content","visibility_blocked_by_connections","visibility_change_not_allowed","visibility_not_enabled","workflow_not_executable","workspace_survey_limit_reached"],"uniqueKey":"code","typeLabel":"enum\u003cstring>"},"details":{"type":"object","uniqueKey":"details","typeLabel":"object"},"invalid_params":{"type":"array","items":{"type":"object","description":"Field-level validation error. `name` and `reason` are always intended for humans.\nOptional machine-readable fields are included when the API can identify the semantic error,\nespecially for survey locale, identifier, and reference validation used by MCP and agent clients.\n","required":["name","reason"],"properties":{"name":{"type":"string","description":"Dot-path to the invalid request field.","isRequired":true,"uniqueKey":"invalid_params.items.[INDEX].name","typeLabel":"string"},"reason":{"type":"string","description":"Human-readable repair guidance.","isRequired":true,"uniqueKey":"invalid_params.items.[INDEX].reason","typeLabel":"string"},"code":{"type":"string","enum":["dangling_reference","duplicate_identifier","duplicate_locale","forbidden_identifier","immutable_identifier","invalid_locale","invalid_reference","missing_required_field","misordered_reference","missing_translation","qsf_limit_exceeded","qsf_not_recognized","read_only_field","unsupported_field","unsupported_locale"],"description":"Machine-readable validation category, when available.\n\nThis is the shared error shape every v3 operation returns, so it lists what the API can emit today and nothing more — `INVALID_PARAM_CODES` in `app/api/v3/lib/response.ts` is the registry, and a code absent from it is dropped before the response is built. Categories for operations that do not exist yet are added with the code that emits them, not ahead of it.\n\n`qsf_not_recognized` and `qsf_limit_exceeded` come from the Qualtrics import (an internal, session-only route sharing this shape): the file is not a Qualtrics export it can read, or it is one past an import limit, which `identifier` names.\n","uniqueKey":"invalid_params.items.[INDEX].code","typeLabel":"enum\u003cstring>"},"identifier":{"type":"string","description":"Identifier involved in the validation failure, when available. For language errors, this can be the normalized language code.","uniqueKey":"invalid_params.items.[INDEX].identifier","typeLabel":"string"},"referenceType":{"type":"string","enum":["block","element","ending","hiddenField","language","variable","variableName","recall"],"description":"Identifier namespace involved in the validation failure. Same rule as `code`: these are the namespaces the API emits today, and more arrive with the operations that emit them.","uniqueKey":"invalid_params.items.[INDEX].referenceType","typeLabel":"enum\u003cstring>"},"missingId":{"type":"string","description":"Referenced id that does not exist in the submitted survey document.","uniqueKey":"invalid_params.items.[INDEX].missingId","typeLabel":"string"},"firstUsedAt":{"type":"string","description":"Dot-path where a duplicate identifier was first used.","uniqueKey":"invalid_params.items.[INDEX].firstUsedAt","typeLabel":"string"},"conflictsWith":{"type":"string","description":"Dot-path to the existing identifier that conflicts with this field.","uniqueKey":"invalid_params.items.[INDEX].conflictsWith","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"invalid_params.items.[INDEX]","typeLabel":"object"},"uniqueKey":"invalid_params","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"title":"\u003cstring>","status":123,"detail":"\u003cstring>","requestId":"\u003cstring>","type":"\u003cstring>","instance":"\u003cstring>","code":"ai_features_not_enabled","details":{},"invalid_params":[{"name":"\u003cstring>","reason":"\u003cstring>","code":"dangling_reference","identifier":"\u003cstring>","referenceType":"block","missingId":"\u003cstring>","firstUsedAt":"\u003cstring>","conflictsWith":"\u003cstring>"}]}}},"exampleType":"generated"}},"exampleType":"generated"},"27c24838-f6a8-42b5-a8ec-8321729a29d7":{"description":"Internal Server Error.","headers":{"X-Request-Id":{"schema":{"type":"string"},"description":"Request correlation ID"},"Cache-Control":{"schema":{"type":"string"},"example":"private, no-store"}},"content":{"application/problem+json":{"schema":{"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`.\n\nBranch on `code`, not on `detail` or `title`: `code` is stable and locale-independent, whereas `detail` is prose that may be reworded. No problem sets `type`, so per RFC 9457 §4.2.1 `title` is always the HTTP reason phrase for `status` and carries no information of its own.\n\nMember naming is frozen as published, mixed conventions included (`requestId` alongside `invalid_params` and `details.resource_type`): renaming any of them would break every client that reads them.","required":["title","status","detail","requestId"],"properties":{"title":{"type":"string","isRequired":true,"uniqueKey":"title","typeLabel":"string"},"status":{"type":"integer","isRequired":true,"uniqueKey":"status","typeLabel":"integer"},"detail":{"type":"string","isRequired":true,"uniqueKey":"detail","typeLabel":"string"},"requestId":{"type":"string","isRequired":true,"uniqueKey":"requestId","typeLabel":"string"},"type":{"type":"string","format":"uri","uniqueKey":"type","typeLabel":"string\u003curi>"},"instance":{"type":"string","uniqueKey":"instance","typeLabel":"string"},"code":{"type":"string","enum":["ai_features_not_enabled","ai_generated_payload_invalid","ai_instance_not_configured","ai_output_too_long","ai_provider_auth_failed","ai_smart_tools_disabled","bad_gateway","bad_request","conflict","custom_css_plan_required","forbidden","internal_server_error","invalid_workflow_state","not_authenticated","not_found","payload_too_large","projection_pending","service_unavailable","stored_survey_invalid","survey_not_workspace_visible","too_many_requests","unprocessable_content","visibility_blocked_by_connections","visibility_change_not_allowed","visibility_not_enabled","workflow_not_executable","workspace_survey_limit_reached"],"uniqueKey":"code","typeLabel":"enum\u003cstring>"},"details":{"type":"object","uniqueKey":"details","typeLabel":"object"},"invalid_params":{"type":"array","items":{"type":"object","description":"Field-level validation error. `name` and `reason` are always intended for humans.\nOptional machine-readable fields are included when the API can identify the semantic error,\nespecially for survey locale, identifier, and reference validation used by MCP and agent clients.\n","required":["name","reason"],"properties":{"name":{"type":"string","description":"Dot-path to the invalid request field.","isRequired":true,"uniqueKey":"invalid_params.items.[INDEX].name","typeLabel":"string"},"reason":{"type":"string","description":"Human-readable repair guidance.","isRequired":true,"uniqueKey":"invalid_params.items.[INDEX].reason","typeLabel":"string"},"code":{"type":"string","enum":["dangling_reference","duplicate_identifier","duplicate_locale","forbidden_identifier","immutable_identifier","invalid_locale","invalid_reference","missing_required_field","misordered_reference","missing_translation","qsf_limit_exceeded","qsf_not_recognized","read_only_field","unsupported_field","unsupported_locale"],"description":"Machine-readable validation category, when available.\n\nThis is the shared error shape every v3 operation returns, so it lists what the API can emit today and nothing more — `INVALID_PARAM_CODES` in `app/api/v3/lib/response.ts` is the registry, and a code absent from it is dropped before the response is built. Categories for operations that do not exist yet are added with the code that emits them, not ahead of it.\n\n`qsf_not_recognized` and `qsf_limit_exceeded` come from the Qualtrics import (an internal, session-only route sharing this shape): the file is not a Qualtrics export it can read, or it is one past an import limit, which `identifier` names.\n","uniqueKey":"invalid_params.items.[INDEX].code","typeLabel":"enum\u003cstring>"},"identifier":{"type":"string","description":"Identifier involved in the validation failure, when available. For language errors, this can be the normalized language code.","uniqueKey":"invalid_params.items.[INDEX].identifier","typeLabel":"string"},"referenceType":{"type":"string","enum":["block","element","ending","hiddenField","language","variable","variableName","recall"],"description":"Identifier namespace involved in the validation failure. Same rule as `code`: these are the namespaces the API emits today, and more arrive with the operations that emit them.","uniqueKey":"invalid_params.items.[INDEX].referenceType","typeLabel":"enum\u003cstring>"},"missingId":{"type":"string","description":"Referenced id that does not exist in the submitted survey document.","uniqueKey":"invalid_params.items.[INDEX].missingId","typeLabel":"string"},"firstUsedAt":{"type":"string","description":"Dot-path where a duplicate identifier was first used.","uniqueKey":"invalid_params.items.[INDEX].firstUsedAt","typeLabel":"string"},"conflictsWith":{"type":"string","description":"Dot-path to the existing identifier that conflicts with this field.","uniqueKey":"invalid_params.items.[INDEX].conflictsWith","typeLabel":"string"}},"additionalProperties":false,"uniqueKey":"invalid_params.items.[INDEX]","typeLabel":"object"},"uniqueKey":"invalid_params","typeLabel":"object[]"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"title":"\u003cstring>","status":123,"detail":"\u003cstring>","requestId":"\u003cstring>","type":"\u003cstring>","instance":"\u003cstring>","code":"ai_features_not_enabled","details":{},"invalid_params":[{"name":"\u003cstring>","reason":"\u003cstring>","code":"dangling_reference","identifier":"\u003cstring>","referenceType":"block","missingId":"\u003cstring>","firstUsedAt":"\u003cstring>","conflictsWith":"\u003cstring>"}]}}},"exampleType":"generated"}},"exampleType":"generated"}},"security":{"47363168-ea5b-42ef-b12c-0d280fa19a38":{"sessionAuth":{"type":"apiKey","in":"cookie","name":"next-auth.session-token","description":"NextAuth session JWT cookie. **Development:** often `next-auth.session-token`.\n**Production (HTTPS):** often `__Secure-next-auth.session-token`. Send the cookie your browser receives after sign-in.\n","scopes":[],"schemeName":"sessionAuth"}},"d09b63f3-5c41-482c-b5c7-5087342bc502":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Management API key; must include **workspaceId** as an allowed workspace with read, write, or manage permission.\n","scopes":[],"schemeName":"apiKeyAuth"}},"c472c642-651b-48c0-be46-1341abc8ceb8":{"bearerAuth":{"type":"http","scheme":"bearer","description":"The same management API key, presented as `Authorization: Bearer \u003ckey>` instead of `x-api-key`. Equivalent in every way — same key, same workspace permissions — and offered because it is what most HTTP clients and SDK generators reach for by default.\nA **401** from any operation that accepts it carries `WWW-Authenticate: Bearer realm=\"formbricks\"`. Session-only operations accept neither this nor `x-api-key`.\n","scopes":[],"schemeName":"bearerAuth"}}},"servers":{"5a1d53ae-163d-4303-ac56-7a378a4d43bc":{"url":"https://app.formbricks.com","description":"Formbricks Cloud. Paths in this spec already include the `/api/v3` prefix; self-hosted instances substitute their own origin."}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"apiKey","in":"cookie","name":"next-auth.session-token","description":"NextAuth session JWT cookie. **Development:** often `next-auth.session-token`.\n**Production (HTTPS):** often `__Secure-next-auth.session-token`. Send the cookie your browser receives after sign-in.\n","scopes":[],"schemeName":"sessionAuth"},"schema":{"title":"next-auth.session-token","type":"string","description":"NextAuth session JWT cookie. **Development:** often `next-auth.session-token`.\n**Production (HTTPS):** often `__Secure-next-auth.session-token`. Send the cookie your browser receives after sign-in.\n","isRequired":true,"typeLabel":"string","deprecated":false},"schemeName":"sessionAuth","name":"next-auth.session-token"}],"title":"sessionAuth"},{"schemes":[{"scheme":{"type":"apiKey","in":"header","name":"x-api-key","description":"Management API key; must include **workspaceId** as an allowed workspace with read, write, or manage permission.\n","scopes":[],"schemeName":"apiKeyAuth"},"schema":{"title":"x-api-key","type":"string","description":"Management API key; must include **workspaceId** as an allowed workspace with read, write, or manage permission.\n","isRequired":true,"typeLabel":"string","deprecated":false},"schemeName":"apiKeyAuth","name":"x-api-key"}],"title":"apiKeyAuth"},{"schemes":[{"scheme":{"type":"http","scheme":"bearer","description":"The same management API key, presented as `Authorization: Bearer \u003ckey>` instead of `x-api-key`. Equivalent in every way — same key, same workspace permissions — and offered because it is what most HTTP clients and SDK generators reach for by default.\nA **401** from any operation that accepts it carries `WWW-Authenticate: Bearer realm=\"formbricks\"`. Session-only operations accept neither this nor `x-api-key`.\n","scopes":[],"schemeName":"bearerAuth"},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"The same management API key, presented as `Authorization: Bearer \u003ckey>` instead of `x-api-key`. Equivalent in every way — same key, same workspace permissions — and offered because it is what most HTTP clients and SDK generators reach for by default.\nA **401** from any operation that accepts it carries `WWW-Authenticate: Bearer realm=\"formbricks\"`. Session-only operations accept neither this nor `x-api-key`.\n","format":"bearer","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"bearerAuth","name":"Authorization"}],"title":"bearerAuth"}]},"originalFileLocation":"api-v3-reference/openapi.yml"},"subdomain":"formbricks","siteName":"Documentation - Formbricks","title":"List workflow runs - Documentation - Formbricks","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-20T07:04:41.618Z","originalFileLocation":"api-v3-reference/v3-workflows/list-workflow-runs.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Returns workflow run summaries for a workspace, newest first (createdAt descending). Use workflowId to narrow the list to one workflow, or responseId to find the runs a specific survey response produced. List items are summaries without triggerPayload, data, or logs; fetch GET /api/v3/workflows/runs/{runId} for the full debug-oriented payload. This keeps response-level data out of list reads by default.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Documentation - Formbricks\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003cmeta data-mint-head name=\"robots\" content=\"noindex\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/formbricks/GlZ4IqkvkQlhFmAc/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/docs/mintlify-assets/_mintlify/favicons/formbricks/GlZ4IqkvkQlhFmAc/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/formbricks/GlZ4IqkvkQlhFmAc/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/formbricks/GlZ4IqkvkQlhFmAc/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/formbricks/GlZ4IqkvkQlhFmAc/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/docs/mintlify-assets/_mintlify/favicons/formbricks/GlZ4IqkvkQlhFmAc/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/docs/mintlify-assets/_mintlify/favicons/formbricks/GlZ4IqkvkQlhFmAc/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/docs/mintlify-assets/_mintlify/favicons/formbricks/GlZ4IqkvkQlhFmAc/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/docs/mintlify-assets/_mintlify/favicons/formbricks/GlZ4IqkvkQlhFmAc/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"List workflow runs - Documentation - Formbricks\">\u003cmeta data-mint-head property=\"og:description\" content=\"Returns workflow run summaries for a workspace, newest first (createdAt descending). Use workflowId to narrow the list to one workflow, or responseId to find the runs a specific survey response produced. List items are summaries without triggerPayload, data, or logs; fetch GET /api/v3/workflows/runs/{runId} for the full debug-oriented payload. This keeps response-level data out of list reads by default.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Documentation - Formbricks\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://formbricks.com/docs/api-v3-reference/v3-workflows/list-workflow-runs\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://formbricks.mintlify.app/_mintlify/api/og/v2?division=V3+Workflows\u0026amp;title=List+workflow+runs\u0026amp;description=Returns+workflow+run+summaries+for+a+workspace%2C+newest+first+%28%60createdAt%60+descending%29.+Use%0A%60workflowId%60+to+narrow+the+list+to+one+workflow%2C+or+%60responseId%60+to+f\u0026amp;theme=5f66c2cdb60ad4d135e6b4e5\u0026amp;signature=968ce5c089d3c089043c0a63122202c49c4b6d9bdc684b5a86dbdc13950edfc3\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"List workflow runs - Documentation - Formbricks\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Returns workflow run summaries for a workspace, newest first (createdAt descending). Use workflowId to narrow the list to one workflow, or responseId to find the runs a specific survey response produced. List items are summaries without triggerPayload, data, or logs; fetch GET /api/v3/workflows/runs/{runId} for the full debug-oriented payload. This keeps response-level data out of list reads by default.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://formbricks.mintlify.app/_mintlify/api/og/v2?division=V3+Workflows\u0026amp;title=List+workflow+runs\u0026amp;description=Returns+workflow+run+summaries+for+a+workspace%2C+newest+first+%28%60createdAt%60+descending%29.+Use%0A%60workflowId%60+to+narrow+the+list+to+one+workflow%2C+or+%60responseId%60+to+f\u0026amp;theme=5f66c2cdb60ad4d135e6b4e5\u0026amp;signature=968ce5c089d3c089043c0a63122202c49c4b6d9bdc684b5a86dbdc13950edfc3\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/docs/mintlify-assets/_mintlify/favicons/formbricks/GlZ4IqkvkQlhFmAc/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Documentation - Formbricks\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#00C4B8\">\u003clink data-mint-head rel=\"canonical\" href=\"https://formbricks.com/docs/api-v3-reference/v3-workflows/list-workflow-runs\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/docs/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/docs/api-v3-reference/v3-workflows/list-workflow-runs.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://formbricks.com/#organization\",\"name\":\"Documentation - Formbricks\",\"url\":\"https://formbricks.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/formbricks/wqEbm3FT1QK_6-vL/images/logo-light.svg?fit=max\u0026auto=format\u0026n=wqEbm3FT1QK_6-vL\u0026q=85\u0026s=365e5fb767b72b4fbbb2016860fd92ba\"}},{\"@type\":\"WebSite\",\"@id\":\"https://formbricks.com/docs#website\",\"name\":\"Documentation - Formbricks\",\"url\":\"https://formbricks.com/docs\",\"publisher\":{\"@id\":\"https://formbricks.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://formbricks.com/docs/api-v3-reference/v3-workflows/list-workflow-runs#webpage\",\"url\":\"https://formbricks.com/docs/api-v3-reference/v3-workflows/list-workflow-runs\",\"name\":\"List workflow runs\",\"description\":\"Returns workflow run summaries for a workspace, newest first (createdAt descending). Use workflowId to narrow the list to one workflow, or responseId to find the runs a specific survey response produced. List items are summaries without triggerPayload, data, or logs; fetch GET /api/v3/workflows/runs/{runId} for the full debug-oriented payload. This keeps response-level data out of list reads by default.\",\"dateModified\":\"2026-10-20T07:04:41.618Z\",\"isPartOf\":{\"@id\":\"https://formbricks.com/docs#website\"},\"breadcrumb\":{\"@id\":\"https://formbricks.com/docs/api-v3-reference/v3-workflows/list-workflow-runs#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://formbricks.com/docs/api-v3-reference/v3-workflows/list-workflow-runs#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"V3 Workflows\",\"item\":\"https://formbricks.com/docs/api-v3-reference/v3-workflows/list-workflows\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"List workflow runs\",\"item\":\"https://formbricks.com/docs/api-v3-reference/v3-workflows/list-workflow-runs\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://formbricks.com/docs/api-v3-reference/v3-workflows/list-workflow-runs#apireference\",\"headline\":\"List workflow runs\",\"name\":\"List workflow runs\",\"description\":\"Returns workflow run summaries for a workspace, newest first (createdAt descending). Use workflowId to narrow the list to one workflow, or responseId to find the runs a specific survey response produced. List items are summaries without triggerPayload, data, or logs; fetch GET /api/v3/workflows/runs/{runId} for the full debug-oriented payload. This keeps response-level data out of list reads by default.\",\"url\":\"https://formbricks.com/docs/api-v3-reference/v3-workflows/list-workflow-runs\",\"mainEntityOfPage\":{\"@id\":\"https://formbricks.com/docs/api-v3-reference/v3-workflows/list-workflow-runs#webpage\"},\"dateModified\":\"2026-10-20T07:04:41.618Z\",\"publisher\":{\"@id\":\"https://formbricks.com/#organization\"},\"isPartOf\":{\"@id\":\"https://formbricks.com/docs#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Documentation - Formbricks\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Documentation - Formbricks","nav":{"global":null,"tabs":[{"tab":"Platform","pages":[{"title":"Platform","href":"/platform/introduction"}]},{"tab":"Surveys (Ask)","pages":[{"title":"Surveys (Ask)","href":"/surveys/overview"}]},{"tab":"Unify Feedback (Analyze)","pages":[{"title":"Unify Feedback (Analyze)","href":"/unify-feedback/overview"}]},{"tab":"Workflows (Act)","pages":[{"title":"Workflows (Act)","href":"/workflows/overview"}]},{"tab":"Self Hosting","pages":[{"title":"Self Hosting","href":"/self-hosting/overview"}]},{"tab":"Development","pages":[{"title":"Development","href":"/development/overview"}]},{"tab":"MCP","pages":[{"title":"MCP","href":"/platform/mcp/overview"}]},{"tab":"API v1 Reference","pages":[{"title":"API v1 Reference","href":"/api-reference/rest-api"}]},{"tab":"API v2 Reference (Beta)","pages":[{"title":"API v2 Reference (Beta)","href":"/api-v2-reference/introduction"}]},{"tab":"API v3 Reference (Private Beta)","hidden":true,"groups":[{"group":"API v3 Documentation (Private Beta)","pages":[{"title":"API v3 Reference (Private Beta)","description":"The next generation of the Formbricks management API, including the Feedback Records API","icon":"code-compare","href":"/api-v3-reference/introduction"}]},{"group":"V3 Surveys","pages":[{"title":"List surveys","description":"Returns the surveys in the workspace **that the caller may read**. A restricted survey is listed only\nto its owner and to the organisation's owners and managers; to everyone else, API keys included, it\ndoes not exist here. `meta.totalCount` and `meta.workspaceSurveyCount` count that same readable set,\nso neither number reveals a restricted survey to someone who cannot see it. The visibility predicate\nis applied in the query and the cursor, never after the fact: `limit` keeps its meaning and\n`meta.nextCursor` being `null` remains the only end-of-collection signal.\n\nSession cookie, `x-api-key`, or a Bearer token.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/surveys","href":"/api-v3-reference/v3-surveys/list-surveys"},{"title":"Create a survey","description":"Creates a block-based survey template from one strict survey document. The endpoint accepts\nmultilingual authoring maps keyed by real locale codes and converts them to Formbricks'\ninternal default-language representation. Non-default locale keys in translated content\nmust be declared in `languages`; undeclared locale keys return `unsupported_locale` in\n`invalid_params` instead of silently mutating workspace languages.\n\n`blocks[].id` and `variables[].id` are stable public identifiers. They may be omitted on\ncreate, in which case the server generates cuid2 ids. If the same create request needs to\nreference a block or variable from logic, provide explicit valid ids and use those references\nconsistently.\n\nFor normal sequential surveys, omit `logic` and `logicFallback`. `logicFallback` is only valid\nwhen the same block has at least one `logic` rule; otherwise the API returns\n`invalid_reference`.\n\n`type` may be omitted or set to `link` or `app`. App surveys additionally accept the `distribution` (display options + triggers) and `targeting` (contact segment filters) objects; both are rejected for link surveys. Trigger ids must reference existing workspace action classes (discover them via `GET /api/v3/action-classes`), and `targeting.filters` references (contact-attribute keys and segments) must exist in the workspace. Unsupported fields are rejected instead of ignored.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/surveys","href":"/api-v3-reference/v3-surveys/create-a-survey"},{"title":"Create a survey draft payload with AI","description":"Creates a strict v3 `POST /api/v3/surveys` create payload from a creator prompt and returns\nvalidation metadata. This endpoint is single-purpose: it does **not** persist the survey.\nClients should validate the returned payload with `/api/v3/surveys/validate` or use the\nembedded validation metadata, then create the draft through `POST /api/v3/surveys`.\n\nThe generated payload always sets `status: draft`. Both `type: link` and `type: app` are\nsupported; for `app`, the payload includes a default `distribution` (display once, no triggers,\nno targeting) that you finish configuring in the editor or via the create request.\n\nPrompt privacy: prompt text is sent to the configured AI provider to create the payload, but\nthis endpoint does not store prompts and server logs should use request ids and failure\ncategories instead of raw prompt content.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/surveys/generate","href":"/api-v3-reference/v3-surveys/create-a-survey-draft-payload-with-ai"},{"title":"Validate a survey document","description":"Validates a future create or patch survey payload without writing data, creating languages,\nor creating survey versions. Invalid survey documents return `200` with `data.valid=false`\nso agents and MCP clients can repair payloads from structured `invalid_params`.\n\nUse `400` only for malformed validation envelopes, unsupported operations, invalid `surveyId`,\nor unsupported query parameters.\n\n**Custom CSS.** A create or patch payload that carries `customCss` is also run through the custom CSS processor; the result adds the compiled `customCss` and `warnings`, or `errors` and `valid=false`. `operation: customCss` validates CSS alone for a live preview — with `scope: workspace | survey` and, optionally, an existing `surveyId` in `workspaceId` — and returns the compiled CSS and warnings. Validation never saves, versions, touches timestamps or invalidates caches, needs only read access, and grants nothing: the write itself checks permissions and the plan again. Requests that process custom CSS also count against a separate budget of 60 per minute per user or API key, shared with the workspace custom CSS endpoint, with survey creates and updates that add or edit custom CSS, and with the MCP tools; beyond it they return **429**.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/surveys/validate","href":"/api-v3-reference/v3-surveys/validate-a-survey-document"},{"title":"Retrieve a survey","description":"Returns the public v3 survey management resource for one survey. By default, translatable\nfields are returned as stable multilingual maps keyed by the language codes emitted in\n`languages[].code`. Use `lang` to filter those maps to one or more requested language selectors.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/surveys/{surveyId}","href":"/api-v3-reference/v3-surveys/retrieve-a-survey"},{"title":"Delete a survey","description":"Deletes a survey by id. Session cookie, `x-api-key`, or a Bearer token.","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml delete /api/v3/surveys/{surveyId}","href":"/api-v3-reference/v3-surveys/delete-a-survey"},{"title":"Update a survey","description":"Updates a survey through a strict top-level partial document. Omitted top-level fields are\npreserved. Provided top-level objects and arrays replace that whole subtree; this endpoint\ndoes not deep-merge nested objects and does not implement JSON Patch.\n\nThis write endpoint accepts the canonical multilingual authoring document only. Translatable\nfields must be locale-code maps, not strings. `PATCH ?lang=...` and `?version=...` are not\nsupported in Scope 1.\n\nFor MCP and AI-agent workflows, fetch the current survey first, modify only the intended\ntop-level fields, call `/api/v3/surveys/validate` with `operation: patch` for preflight, then\nsubmit the same patch here. Missing ids in replaced arrays are treated as deletions. Variable\nname renames are allowed but may be destructive for downstream exports or integrations.\nElement id changes are rejected once the survey and element are no longer drafts.\n\nServer-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`.\n\nA 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.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml patch /api/v3/surveys/{surveyId}","href":"/api-v3-reference/v3-surveys/update-a-survey"},{"title":"Edit survey blocks","description":"Edits a survey's blocks in place — update, insert or remove whole blocks without resending the ones you are not changing. Operations apply in order against a single snapshot and are applied atomically: either all of them land or none do.\n\nBlocks are addressed by id, never by position, so a concurrent edit cannot silently redirect an operation onto a different block. An `update` replaces the target block entirely, the same whole-subtree rule `PATCH /api/v3/surveys/{surveyId}` uses, and the replacement must carry every language the survey has configured.\n\nPass `expectedUpdatedAt` (the `updatedAt` from your last read) to make the write conditional; see the **409** response. Session cookie or x-api-key.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml patch /api/v3/surveys/{surveyId}/blocks","href":"/api-v3-reference/v3-surveys/edit-survey-blocks"},{"title":"Set survey block order","description":"Replaces the order of a survey's blocks. The body lists every current block id exactly once, in the order you want; block content is untouched.\n\nIdempotent: the same `order` always yields the same survey, and an order that already matches performs no write at all, so `updatedAt` does not move and other callers' preconditions stay valid. A stale `expectedUpdatedAt` is still rejected with **409** on that path — the precondition is evaluated before the method, so a no-op outcome never reports success to a stale caller. Because the list must be a permutation, a dropped or duplicated block is rejected rather than silently applied — the failure mode that resending the whole `blocks` array cannot catch.\n\nPass `expectedUpdatedAt` (the `updatedAt` from your last read) to make the write conditional; see the **409** response. Session cookie or x-api-key.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml put /api/v3/surveys/{surveyId}/blocks/order","href":"/api-v3-reference/v3-surveys/set-survey-block-order"},{"title":"Archive a survey","description":"Archives (soft-deletes) a survey by id. Archived surveys are hidden from the default list, stop collecting responses, and become read-only until restored — a subsequent `PATCH` returns **422**. Works on any survey, including legacy question-based surveys, so this endpoint returns a minimal lifecycle acknowledgement rather than the full survey resource. Session cookie, `x-api-key`, or a Bearer token.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/surveys/{surveyId}/archive","href":"/api-v3-reference/v3-surveys/archive-a-survey"},{"title":"Restore a survey","description":"Restores a previously archived (soft-deleted) survey by id, clearing its archive marker so it reappears in the default list and becomes editable again. Works on any survey, including legacy question-based surveys, so this endpoint returns a minimal lifecycle acknowledgement rather than the full survey resource. Session cookie, `x-api-key`, or a Bearer token.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/surveys/{surveyId}/restore","href":"/api-v3-reference/v3-surveys/restore-a-survey"},{"title":"Read a survey's visibility and the impact of changing it","description":"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, and draft or enabled workflows), `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.\n\nRequires `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.\n\nWhile `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.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/surveys/{surveyId}/visibility","href":"/api-v3-reference/v3-surveys/read-a-surveys-visibility-and-the-impact-of-changing-it"},{"title":"Change a survey's visibility","description":"Sets the survey to `restricted` or `workspace`.\n\n**Restrictions take effect at once.** A `workspace → restricted` request stores the flag, a new `version` and a pending marker in one transaction. From that instant the survey is restricted on every path — single reads, lists and counts, responses, exports — for everyone but the owner and the organisation's owners and managers, whether or not the graph has caught up (fail closed). The owner keeps only the access their workspace role gives them — read to view, write to edit; an owner who loses workspace access loses the survey too. The relationships are then projected; the answer is **200** either way, with `pending: null` when the graph acknowledged this `version` inside the request and `pending: \"restricted\"` when the outbox will finish it.\n\n**Grants take effect when enforced.** A `restricted → workspace` request answers **200** only once the graph has acknowledged this exact `version`; until then the survey stays restricted. If the in-request projection fails, the answer is **503** `projection_pending`: the change is stored and queued, `GET …/visibility` shows `pending: \"workspace\"`, and retrying is safe.\n\n**Fencing.** Every accepted change increments the survey's `version`. Projection work carries the version it was issued for, and a projector holding an older version never writes, so a worker leased before a newer change cannot overtake it — including one that crashed before its verification pass. A **200** for a grant means the graph holds this exact version.\n\n**No-ops and cancellation.** Requesting the value the survey already enforces, with nothing pending, is a **200** no-op: nothing is written or audited and `changedAt` / `changedBy` are unchanged. Requesting the enforced value while the *opposite* is pending **cancels** the pending change: a new version is stored, the queued work is superseded, and the answer is **200** with `pending: null`. Requesting the pending value again re-attempts the projection (200 or 503).\n\nWhen `restricted` is refused for two reasons at once — no owner **and** outbound connections — the **422** wins: the missing owner cannot be fixed, so listing connections to remove would send the caller down a dead end.\n\nAllowed for the survey's owner (while they still hold read access to the workspace) and for the organisation's owners and managers. **Not** for workspace members with write or team-level manage rights, and never for API keys. Every successful change is audit-logged with the actor.\n\nGoing `workspace → restricted` is refused with **409** while any outbound connection depends on the survey; resolve them first. It is refused with **422** when the survey has no owner, because \"restricted\" would then mean \"administrators only\" — duplicate the survey for a restricted copy. Going `restricted → workspace` has no preconditions.\n\nThis is the only way to change visibility: `PATCH /api/v3/surveys/{surveyId}` accepts `visibility`, `owner` and `access` only as the exact values `GET` returned (so a fetched survey round-trips), and rejects any other value as an unsupported field. Publishing does not change visibility; the publish dialogue chains this call before the status change.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/surveys/{surveyId}/visibility","href":"/api-v3-reference/v3-surveys/change-a-surveys-visibility"}]},{"group":"V3 Responses","pages":[{"title":"List responses","description":"Returns responses for a workspace, newest first. Session cookie, `x-api-key`, or a Bearer token, with read access.\n\n**Scoping.** `workspaceId` is required, as on every v3 collection read. Add `surveyId` to narrow to one survey — the common case, and the one the storage layer is indexed for (`(surveyId, createdAt)`). A workspace-wide list has to reach responses through their surveys and is correspondingly slower, so pass `surveyId` whenever you know it. `contactId` narrows to one respondent.\n\n**Pagination is keyset**, on `(createdAt, id)`. The `cursor` is opaque and bound to the sort order and the filter set it was issued for; changing either invalidates it. `meta.nextCursor` being `null` is the only end-of-collection signal — do not infer the end from a short page.\n\n`id` is there purely as a tie-breaker, and it makes the order **total**, so no row is ever skipped or repeated across pages. What it is not is a finer-grained clock: `createdAt` is stored to millisecond precision, so responses sharing a millisecond — everything written in one bulk insert, for instance — come back in an order that is stable and repeatable but is not their true creation order. Do not read the sequence within a millisecond as meaningful.\n\n**Filters are allow-listed**, and each one on its own is either served by an index or bounded by one. `filter[finished][eq]` and `filter[language][in]` additionally require `surveyId` or `contactId`, because both are heap residuals that are only bounded when the scan is anchored to one survey or one contact; sending either without such a scope returns **400**.\n\nBe aware that **combining** a `filter[createdAt]` bound with `filter[finished][eq]` is the one case no single index covers: the ordered scan uses `(surveyId, createdAt)` and `finished` stays a heap residual, so a page whose matches are sparse reads far more rows than it returns. Prefer narrowing by `surveyId` and a tight `createdAt` window, and treat that combination as the slow path until a covering index exists.\n\n**What this endpoint deliberately does not filter on:** individual answers, hidden-field values, submission metadata (`source`, `url`, `country`, `browser`, `os`, `deviceType`), contact attributes, quotas, and tags. Each is a JSON path or an unindexed join on the largest table in the database, where the honest outcome is a timeout rather than a slow query. The in-app dashboard does offer these, so this endpoint is knowingly behind it; closing the gap needs index work and is tracked separately rather than quietly omitted.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/responses","href":"/api-v3-reference/v3-responses/list-responses"},{"title":"Create a response","description":"Records a survey response. Requires read-write access to the workspace, which is resolved from `surveyId` rather than supplied by the caller.\n\n**This performs a real submission.** It runs the full response pipeline — webhooks, integrations, follow-ups, quota evaluation, and Hub ingestion once the response is finished — and it consumes one metered monthly response. That is the same power a v1/v2 management create has today, and the same power an API key with write access already carries; it is called out because an agent holding that key can create genuine submissions. Use `POST /api/v3/responses/validate` to check a payload without any of that happening.\n\n`createdAt` cannot be supplied. Bulk historical loading is therefore not what this endpoint is for — see `ResponseListItem.createdAt` for why, and use v2 while a dedicated import path is outstanding.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/responses","href":"/api-v3-reference/v3-responses/create-a-response"},{"title":"Count responses","description":"Returns how many responses match a scope and filter set, without fetching any of them.\n\nThis exists as its own operation because \"how many match this?\" is the question asked most often and it should not require paging through data to answer — particularly for agent clients, where a page of payloads to obtain a single integer is pure waste. It takes the same scope and filter parameters as `GET /api/v3/responses`, minus pagination and sorting, so a count and a page are always answering the same question.\n\nThe list endpoint's `meta.totalCount` covers the other case: a caller already paging that also wants the total. That one is opt-in; this one is the direct route.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/responses/count","href":"/api-v3-reference/v3-responses/count-responses"},{"title":"Validate a response payload","description":"Checks a create or patch payload and reports what a real write would do — **without writing anything**. Never has side effects: no response is created, no pipeline fires, nothing is metered.\n\nDeliberately the same shape as `POST /api/v3/surveys/validate`: same dual auth, a request discriminated on `operation` carrying the body the real call would take, and a result of `valid`, `operation` and `invalid_params` with document-relative paths. The value is that the two endpoints behave alike, so a client can validate uniformly. Answers are checked against the survey's own validation rules, so a payload this endpoint accepts is one the real write accepts.\n\n**It reports effects, not just a verdict.** When `valid` is `true`, `effects` names the language that would be stamped, the contact and display that would be linked, the quotas that would count, whether the pipeline would fire, and whether the write would be metered. The language is the field that motivated this endpoint: an importer can see that a payload produces language-less responses *before* writing thousands of them.\n\nAuthorization is the same as the operation being validated — read-write for `create` and `patch` — so this cannot be used as a cheaper cross-tenant existence probe than the write itself. An inaccessible `responseId` on a patch validation answers **403**, as the patch would.\n\n**What it does not do:** an endpoint lets a caller check; it cannot stop a caller writing a bad record anyway. Consistency across the write paths comes from all of them calling the same validator — this endpoint is that validator's public face, not a gate in front of it.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/responses/validate","href":"/api-v3-reference/v3-responses/validate-a-response-payload"},{"title":"Delete responses in bulk","description":"Deletes up to 100 responses in one transaction. Requires `manage` access to the workspace.\n\n**A POST custom method, not a `DELETE` on the collection.** A collection-level `DELETE` that loses its filters — through a client bug, a proxy stripping a query string, a copied curl command — degrades into erasing every response in scope. A distinct path cannot be reached by accident. AIP-165 blesses `batchDelete` for exactly this reason.\n\n**It scope-filters rather than rejecting.** Ids belonging to another workspace, and ids that no longer exist, are ignored; the ids in the caller's own workspace are deleted and `deleted` reports how many that was. Rejecting the whole call on a foreign id would do two bad things at once: leak that the id exists somewhere, and break retries — after a partially-applied call, an already-deleted id is indistinguishable from a foreign one. Scope-filtering is idempotent and leaks nothing, so a client can safely retry the same batch.\n\nBecause `deleted` can therefore be lower than the number of ids sent — or zero — do not treat a shortfall as an error. Deletion cascades to uploaded files exactly as the single-response delete does — and, exactly as it does, leaves the Hub copy in place. See that operation for why.\n\n**`workspaceId` is the scope, and it is required.** Unlike the single-response delete — which resolves the workspace *from* the response so a caller cannot pair someone else's id with a scope it happens to hold — a batch has no single response to resolve from, and scope-filtering is only meaningful against a known workspace. Supplying it is safe here because the same value is both what `manage` is checked against and what the delete is filtered by: the two cannot diverge, so a foreign id matches nothing rather than being deleted under a scope the caller does hold.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/responses/batch-delete","href":"/api-v3-reference/v3-responses/delete-responses-in-bulk"},{"title":"Get a response","description":"Returns one response in the detailed view — everything the list view carries, plus `contact`, `displayId`, `singleUseId`, and the stored answer map `data`.\n\nThe workspace is resolved from the response itself, so the caller cannot choose which scope it is authorized against and no `workspaceId` parameter is accepted. An unknown or inaccessible `responseId` answers **403**, not **404**, so response ids cannot be probed for existence.\n\n**Round-tripping.** This read returns `data` in the stored, write-shaped form, so the simplest correction is to take it, change one entry and `PATCH` it back. Embedded Data round-trips through `embeddedData[]` instead: the `key` you read is the `key` a write accepts. `answers[]` is the typed view of the same information, offered alongside. Independently of that, a client working from a *list* row — which omits the maps — can still rebuild the write-shaped payload: `answers[]`, `embeddedData[]` and `unresolved[]` together carry every stored key and value **verbatim**, with no need to refetch the survey. Two rules make that guarantee hold, and both are contractual:\n\n`rawKey`, `rawValue`, `valueText`, `valueDate`, `fileUrls` and composite slot values are always the stored bytes, never resolved or reformatted — the resolved forms live in the separate `elementLabel`, `optionId`, `optionLabel`, `rowId` and `columnId` fields. And **empty-but-present values are returned, not omitted**: the `\"\"` of an unchecked consent, the `\"\"` of a selected but unfilled Other, a blank composite slot. That second rule matters because `PATCH` replaces `data` wholesale, so an omitted key is a deleted answer rather than an unchanged one.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/responses/{responseId}","href":"/api-v3-reference/v3-responses/get-a-response"},{"title":"Delete a response","description":"Permanently deletes a response. Requires `manage` access; the workspace is resolved from the response, and an unknown or inaccessible `responseId` answers **403**.\n\nDeletion cascades to any files uploaded with the response, which are removed from storage after the row is committed. No `responseDeleted` webhook is emitted — no such trigger exists.\n\n**The Hub copy is not removed.** A submission forwarded to the Hub stays there and stays searchable through the feedback-record endpoints after this returns 204. That cascade is ENG-2855 and lands after the Hub release; until then, an erasure workflow has to delete the feedback record itself. Stated because a caller cannot cheaply verify deletion semantics on a destructive endpoint.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml delete /api/v3/responses/{responseId}","href":"/api-v3-reference/v3-responses/delete-a-response"},{"title":"Update a response","description":"Partially updates a response. Requires read-write access; the workspace is resolved from the response. An unknown or inaccessible `responseId` answers **403**.\n\n`PATCH` is the only update verb — there is no `PUT`. Within it, `data` is replaced wholesale rather than deep-merged, so send the complete answer map; `embeddedData` merges by field name. Unknown top-level keys are rejected with **400** rather than ignored.\n\nEvery patch emits `responseUpdated` and runs the response pipeline, including Hub ingestion. Transitioning `finished` to `true` additionally emits `responseFinished`; patching a response that is already finished does not re-emit it.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml patch /api/v3/responses/{responseId}","href":"/api-v3-reference/v3-responses/update-a-response"}]},{"group":"V3 Workflows","pages":[{"title":"List workflows","description":"Returns workflow list items for a workspace, sorted by `sortBy` (default `updatedAt`,\nnewest first). Workflows are workspace-scoped and exposed through the same v3\nsession-or-API-key authorization model as surveys.\n\nList items are intentionally slim: they include the derived `triggerType` and `surveyId`\nplus a `lastRun` summary, but not the full `definition`. Use\n`GET /api/v3/workflows/{workflowId}` to read the definition.\n\n`archived` workflows are excluded unless explicitly requested with\n`filter[status][in]=archived`.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/workflows","href":"/api-v3-reference/v3-workflows/list-workflows"},{"title":"Create a workflow","description":"Creates a `draft` workflow. The workflow definition is the public source of truth used by\nthe dashboard and external clients, following the document-first pattern established by the\nv3 Survey API. Runtime persistence, revision creation, and version snapshotting are\nimplementation details behind this contract.\n\nWorkflows are always created as drafts; use `POST /api/v3/workflows/{workflowId}/enable` to\nmake them respond to trigger events. Graph reference failures (duplicate node ids, edges\npointing at missing nodes, `entryNodeId` not referencing the trigger, unknown `surveyId` or\n`endingCardIds` in the workspace) are rejected with **400** and structured `invalid_params`.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/workflows","href":"/api-v3-reference/v3-workflows/create-a-workflow"},{"title":"List workflow runs","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/workflows/runs","href":"/api-v3-reference/v3-workflows/list-workflow-runs"},{"title":"Retrieve a workflow run","description":"Returns one workflow run by globally unique run id, including the full debug payload: the\ncaptured `triggerPayload`, the run `data` (per-step results), the persisted `logs` trace,\nand retry metadata (`attempt`, `nextAttemptAt`, `lastErrorAt`). Scope 1 deliberately exposes\nthese as JSON dumps so users and agents can understand exactly what happened in a run.\n\nPoll this endpoint after `POST /api/v3/workflows/{workflowId}/test`: runs execute\nasynchronously and transition `queued` → `running` → `completed`/`failed`/`canceled`.\n\nUnknown or inaccessible run ids return `403` rather than `404` to avoid leaking\ncross-workspace resource existence.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/workflows/runs/{runId}","href":"/api-v3-reference/v3-workflows/retrieve-a-workflow-run"},{"title":"Retrieve a workflow","description":"Returns one workflow definition by id. Unknown or inaccessible workflow ids return `403`\nrather than `404` to avoid leaking cross-workspace resource existence.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/workflows/{workflowId}","href":"/api-v3-reference/v3-workflows/retrieve-a-workflow"},{"title":"Delete a workflow","description":"Permanently deletes a workflow by id. Deletion cascades to the workflow's versions, runs,\nand run logs so no response-derived data is left behind (GDPR requirement). This is\nirreversible; use `POST /api/v3/workflows/{workflowId}/archive` for a reversible\nsoft-delete that keeps history. Returns `204 No Content`.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml delete /api/v3/workflows/{workflowId}","href":"/api-v3-reference/v3-workflows/delete-a-workflow"},{"title":"Update a workflow","description":"Updates human-facing workflow metadata and/or the workflow definition. Status changes are\nhandled by lifecycle endpoints (`enable`, `disable`, `archive`, `unarchive`) so the state\nmachine remains explicit. Provided fields replace the corresponding stored fields; this\nendpoint does not implement JSON Patch.\n\n`name` and `description` can be updated in any state except `archived`. The `definition`\ncan only be updated while the workflow is `draft` or `disabled`: the live version of an\n`enabled` workflow is an immutable snapshot, so definition changes require disabling (or\nmoving to draft) first and re-enabling afterwards. Violations return **422** with code\n`invalid_workflow_state`. A structurally invalid definition returns **400** with structured `invalid_params`; the referenced survey and ending cards are not verified here — that existence check runs when the workflow is enabled.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml patch /api/v3/workflows/{workflowId}","href":"/api-v3-reference/v3-workflows/update-a-workflow"},{"title":"Duplicate a workflow","description":"Creates a new `draft` workflow by copying an existing workflow's definition, name (or the\nprovided override), and description. The duplicate receives its own id and timestamps and\nstarts with empty run and version history; the source workflow is unchanged. Archived\nworkflows can be duplicated (the copy starts as a normal draft).\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/workflows/{workflowId}/duplicate","href":"/api-v3-reference/v3-workflows/duplicate-a-workflow"},{"title":"Enable a workflow","description":"Moves a workflow from `draft` or `disabled` to `enabled`. Only enabled workflows respond to\ntrigger events.\n\nEnabling validates that the definition is executable — the trigger has exactly one outgoing\nedge (trigger-only drafts cannot be enabled), the graph is acyclic, every node is\nreachable from the trigger, only Scope 1 node types are present, the referenced survey\nand ending cards still exist, and every `send_email` action addressing a *literal* email address\ntargets someone who can access this workspace (an element-id `to` resolves to the respondent's own\naddress and is exempt) — and then snapshots an immutable workflow version. Runs\nreference that snapshot via `workflowVersionId`, so later draft edits never change what an\nenabled workflow executes. Validation failures return **422** with code\n`workflow_not_executable` and structured `invalid_params`; calling enable in a state other\nthan `draft` or `disabled` returns **422** with code `invalid_workflow_state`. Two concurrent enable requests race to publish the next version; the loser is rejected with **409** code `conflict` and can safely retry.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/workflows/{workflowId}/enable","href":"/api-v3-reference/v3-workflows/enable-a-workflow"},{"title":"Disable a workflow","description":"Moves an `enabled` workflow to `disabled`. Disabled workflows keep their configuration but\ndo not respond to trigger events; runs that are already queued or running are not canceled.\nCalling disable in any other state returns **422** with code `invalid_workflow_state`.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/workflows/{workflowId}/disable","href":"/api-v3-reference/v3-workflows/disable-a-workflow"},{"title":"Archive a workflow","description":"Soft-deletes a workflow by moving it from any non-archived state to `archived`. Archived\nworkflows stop responding to trigger events immediately, become read-only, and are excluded\nfrom list responses unless requested with `filter[status][in]=archived`. Their runs, version\nhistory, and definition are preserved, and the workflow can be restored with\n`POST /api/v3/workflows/{workflowId}/unarchive`. Archiving an already archived workflow\nreturns **422** with code `invalid_workflow_state`.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/workflows/{workflowId}/archive","href":"/api-v3-reference/v3-workflows/archive-a-workflow"},{"title":"Unarchive a workflow","description":"Restores an `archived` workflow to `draft`. Unarchiving never re-enables a workflow\nautomatically: re-enable explicitly with `POST /api/v3/workflows/{workflowId}/enable`, which\nre-validates the definition (the referenced survey or ending cards may have changed while\nthe workflow was archived). Calling unarchive on a non-archived workflow returns **422**\nwith code `invalid_workflow_state`.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/workflows/{workflowId}/unarchive","href":"/api-v3-reference/v3-workflows/unarchive-a-workflow"},{"title":"Dry-run (validate) a workflow","description":"Validates a workflow without running it or causing any side effect. It checks that the workflow's current definition is executable, that the trigger's referenced survey and ending cards still exist in the workspace, and that every `send_email` action addressing a *literal* email address targets someone who can access this workspace. **No** workflow run is created and **no** email or webhook is sent.\n\nThe response is always `200` with `{ data: { workflowId, ok, problems } }`. `data.ok` is `true` when the workflow would execute; otherwise `data.problems` lists every issue found — each with a machine-readable `code` and the offending `field` — so they can be fixed in a single pass.\n\nDrafts are testable — validating the setup before going live is the point of a dry run. Only an `archived` workflow is rejected, with **422** and code `invalid_workflow_state`.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/workflows/{workflowId}/test","href":"/api-v3-reference/v3-workflows/dry-run-validate-a-workflow"}]},{"group":"V3 Action Classes","pages":[{"title":"List action classes","description":"Returns the action classes (user actions that can trigger an app survey) for a workspace. Use\nthe returned ids as `distribution.triggers[].actionClassId` when creating or updating app\nsurveys. Read-only: this v3 endpoint lists action classes but does not create them — action\nclasses are managed in the Formbricks app (Actions settings) or via the v1/v2 management API.\n\nAn empty `data` array means the workspace has no action classes yet. Triggers are optional, so\nyou can still create an app survey with `distribution.triggers: []` (or omit `distribution`\nentirely) and attach triggers later via `PATCH` once an action class exists. Session cookie, `x-api-key`, or a Bearer token.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/action-classes","href":"/api-v3-reference/v3-action-classes/list-action-classes"}]},{"group":"V3 Contact Attribute Keys","pages":[{"title":"List contact attribute keys","description":"Returns the contact attribute keys for a workspace. Use the returned `key` values as\n`targeting.filters[].root.contactAttributeKey` when targeting app surveys; `dataType` hints which\noperators apply. Session cookie, `x-api-key`, or a Bearer token. (Applying targeting filters requires the Contacts\nentitlement; this discovery endpoint does not.)\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/contact-attribute-keys","href":"/api-v3-reference/v3-contact-attribute-keys/list-contact-attribute-keys"}]},{"group":"V3 Workspaces","pages":[{"title":"Read workspace custom CSS","description":"Returns the workspace's shared survey CSS as editable **source** (light and dark), the one recoverable previous revision, whether the stored CSS is being delivered to respondents (`status`), and whether this caller may change it (`canEdit`, `planAllowed`). Compiled output is never returned here. Requires read access to the workspace. Session cookie, `x-api-key`, or a Bearer token.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/workspaces/{workspaceId}/custom-css","href":"/api-v3-reference/v3-workspaces/read-workspace-custom-css"},{"title":"Save or clear workspace custom CSS","description":"Saves or clears the workspace's shared survey CSS. `customCss` replaces both fields; `null` clears all of it. The source is processed by the same processor every save path uses: constructs it removes come back as top-level `warnings`, and CSS it rejects is a **422** that leaves the saved CSS in effect. The replaced value becomes `previous`, the one recoverable revision — restore it by sending its source back. Unchanged source writes nothing.\n\nWorkspace CSS reaches every survey in the workspace, so writing it is narrower than writing a survey: **organization owners and managers** for signed-in users (session or OAuth), and a **`manage`** grant on this workspace for API keys — a Read \u0026 write grant is refused with **403**. On Formbricks Cloud, adding or editing needs the Scale plan (**403** `custom_css_plan_required`); clearing never does. Successful changes refresh the cached configuration the SDKs receive (they pick it up on their next configuration fetch). Saves that add or edit CSS count against a custom CSS budget of 60 per minute per user or API key, shared with custom CSS validation and with survey writes that add or edit custom CSS; beyond it they return **429**. Re-saving the same CSS and clearing it are never counted.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml patch /api/v3/workspaces/{workspaceId}/custom-css","href":"/api-v3-reference/v3-workspaces/save-or-clear-workspace-custom-css"}]},{"group":"V3 Feedback Records","pages":[{"title":"List feedback records","description":"Lists the feedback records of one dataset, newest first, with optional filters and keyset\npagination. Served by the API gateway, which authorizes the call against `tenant_id` and\nforwards it to the feedback store — see the introduction for how the two layers answer.\n\nRequires an API key with **read** permission (or higher) on a workspace the dataset is assigned\nto. The organization must hold the Unify Feedback entitlement.\n\nMulti-value filters are OR-ed within a parameter and AND-ed across parameters. Repeat the\nparameter to pass several values (`?field_type=text\u0026field_type=rating`); comma-separated values\nare **not** split. Filters on enrichment members (`sentiment`, `emotions`, `sentiment_score_*`)\nnever match records that have not been enriched — use `has_sentiment=false` / `has_emotions=false`\nto find those.\n\n**Incremental extraction.** To keep a copy of a dataset in sync, filter on `updated_since` and\npage with `sort=updated_at\u0026order=asc`, bounded by `updated_until`: every page is then one index\nrange, and a record that changes while you page normally comes back later in the run. Start each\nrun with a `limit=1` request and read its `Date` header: that value is this run's `updated_until`\nand, minus a few minutes, the next run's `updated_since` — both bounds from the same value, or\nrecords between them are never read. Do not use the newest `updated_at` received instead: it\nskips a write that was still committing when you read past its timestamp.\nUpsert by `id` and let the most recent fetch win. Deleted records leave nothing for\n`updated_since` to match, so reconcile deletions separately: periodically list every record id\nwith no `updated_since`, and remove the local records that were not returned and were created\nbefore that listing's start (its first response's `Date` header) minus the overlap. Run one\nsync at a time.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/feedbackRecords","href":"/api-v3-reference/v3-feedback-records/list-feedback-records"},{"title":"Create a feedback record","description":"Stores one feedback record in the dataset named by `tenant_id` in the body. The gateway reads\n`tenant_id` from the JSON body to authorize the call — a body that is not JSON, or has no\n`tenant_id`, answers **400** before anything is stored.\n\nRequires an API key with **write** permission (or higher) on a workspace the dataset is\nassigned to. Creating is allowed on shared datasets (it is ordinary workspace work, like a CSV\nimport); only changing and deleting existing records is restricted to unshared ones.\n\nIngestion is idempotent per (`tenant_id`, `submission_id`, `field_id`): a second record with the\nsame triple answers **409** rather than creating a duplicate. Send exactly one `value_*` member,\nmatching `field_type`. A `text` record is enriched asynchronously — `sentiment`, `emotions` and\nthe translation members appear on the record once enrichment completes, and it becomes\nsearchable once embedded.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/feedbackRecords","href":"/api-v3-reference/v3-feedback-records/create-a-feedback-record"},{"title":"Delete a user's feedback records","description":"Permanently deletes every record in the dataset whose `user_id` matches — the erasure operation\nfor GDPR Article 17 requests. Derived embeddings are removed with the records. Idempotent:\nrepeating the call answers `deleted_count: 0`.\n\n`tenant_id` is **required**: the gateway scopes erasure to one dataset. (The underlying store\ncan erase a user across every dataset when `tenant_id` is omitted; that form is not reachable\nthrough this API.) Records written without a `user_id` cannot be reached this way — delete them\nindividually.\n\nDeletion is unrecoverable, so it requires an API key with **manage** permission on a workspace\nthe dataset is assigned to, and the dataset must be assigned to **exactly one** workspace: on a\nshared dataset no workspace permission can say whose records these are, so API-key mutations\nare refused with **403**.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml delete /api/v3/feedbackRecords","href":"/api-v3-reference/v3-feedback-records/delete-a-users-feedback-records"},{"title":"Search feedback records semantically","description":"Embeds `query` and returns the ids of the records in the dataset whose text is closest to it,\nwith cosine similarity scores. Only records with a non-empty `value_text` are embedded, so only\nthose can match. The gateway reads `tenant_id` from the JSON body to authorize the call.\nRequires an API key with **read** permission (or higher) on a workspace the dataset is\nassigned to.\n\nResults carry ids and the embedded text only — fetch a match with\n`GET /api/v3/feedbackRecords/{id}` for the full record. Answers **503** on instances without\nan embedding model configured.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml post /api/v3/feedbackRecords/search/semantic","href":"/api-v3-reference/v3-feedback-records/search-feedback-records-semantically"},{"title":"Get a feedback record","description":"Returns one feedback record by id, with its read-only assignment in the active directory\ntaxonomy. The assignment reflects the current visible path in the active run; editing a record\ndoes not reclassify it until another run. `taxonomy` is null if its lookup is unavailable.\nThe gateway looks the record up to learn its dataset and\nauthorizes against that, so no `tenant_id` is sent. Requires an API key with **read**\npermission (or higher) on a workspace the record's dataset is assigned to.\n\nAn unknown id, or one in a dataset you cannot read, answers **403** rather than 404, so ids\ncannot be probed. The exception is the minute after a delete: the gateway still has the\nrecord's dataset cached, authorizes the call, and the store answers **404**.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/feedbackRecords/{id}","href":"/api-v3-reference/v3-feedback-records/get-a-feedback-record"},{"title":"Delete a feedback record","description":"Permanently deletes one record and its derived embedding. Unrecoverable, so it requires an API\nkey with **manage** permission on a workspace the record's dataset is assigned to, and the\ndataset must be assigned to **exactly one** workspace: on a shared dataset no workspace\npermission can say whose record this is, so API-key mutations are refused with **403**.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml delete /api/v3/feedbackRecords/{id}","href":"/api-v3-reference/v3-feedback-records/delete-a-feedback-record"},{"title":"Update a feedback record","description":"Changes the answer, `language`, `user_id` or `metadata` of one record. Only the members sent\nare changed; provenance (`tenant_id`, `source_*`, `field_*`, `submission_id`, `collected_at`)\nis immutable. Requires an API key with **write** permission (or higher) on a workspace the\nrecord's dataset is assigned to, and the dataset must be assigned to **exactly one** workspace\n— see the delete operation for why.\n\nTwo behaviours are silent and worth knowing: `metadata` is **replaced**, not merged; and\nchanging `value_text` clears the enrichment members (`sentiment`, `sentiment_score`,\n`emotions`, `value_text_translated`, `translation_lang_key`) and queues re-enrichment and\nre-embedding — the response shows them absent until that completes. Changing `language` clears\nand re-queues the translation pair only.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml patch /api/v3/feedbackRecords/{id}","href":"/api-v3-reference/v3-feedback-records/update-a-feedback-record"},{"title":"Find similar feedback records","description":"Returns the records in the same dataset whose embedded text is closest to the given record's,\nwith cosine similarity scores. The anchor record itself is excluded. The gateway looks the\nrecord up to learn its dataset and authorizes against that. Requires an API key with **read**\npermission (or higher) on a workspace the record's dataset is assigned to.\n\nAnswers **403** for an unknown or inaccessible id. Answers **404** when the record exists but has\nno embedding — it has no text, or was created moments ago and is not embedded yet. Answers\n**503** on instances without an embedding model configured.\n","deprecated":null,"version":null,"openapi":"/api-v3-reference/openapi.yml get /api/v3/feedbackRecords/{id}/similar","href":"/api-v3-reference/v3-feedback-records/find-similar-feedback-records"}]}]}]},"title":"List workflow runs - Documentation - Formbricks","buildId":"dpl_GvhK4qVXq51DpfYJLCtPpYNN4YHN","deploymentId":"dpl_GvhK4qVXq51DpfYJLCtPpYNN4YHN","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-Bg4Z7D_G.js","utils-Biz734EK.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-C6F9YHs6.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-BoJjY_VP.js","snippetPresets-CnZ-mOFh.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","ApiExamples-DC_SB2pp.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-BYKtOiIP.js","shallow-COAac_UD.js","getApiPlaygroundDisplay-BV4Viqi2.js","CodeSnippet-DDgW-JXl.js","CodeSnippets-CP1LpNhG.js","Page-BeiUfucV.js","getPastedJson-Cvgvbfmv.js","icon-D-H368xH.js","MethodPill-CXSxH1VW.js","DuplicateIcon-JcbBzF1x.js","createIcon-BDt_aHZM.js","DynamicMarkdown-DO1Fz7ar.js","SectionHeading-mwKBArs3.js","axios-vUo_bRtp.js","Markdown-C3KUTGJN.js","clsx-C6CAjViH.js","lib--scc4DXi.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-C3vb5JQZ.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-C8Hisf3g.js"]}