curl --request GET \
--url https://app.formbricks.com/api/v3/responses/{responseId} \
--cookie next-auth.session-token=import requests
url = "https://app.formbricks.com/api/v3/responses/{responseId}"
headers = {"cookie": "next-auth.session-token="}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {cookie: 'next-auth.session-token='}};
fetch('https://app.formbricks.com/api/v3/responses/{responseId}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.formbricks.com/api/v3/responses/{responseId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_COOKIE => "next-auth.session-token=",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.formbricks.com/api/v3/responses/{responseId}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("cookie", "next-auth.session-token=")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.formbricks.com/api/v3/responses/{responseId}")
.header("cookie", "next-auth.session-token=")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.formbricks.com/api/v3/responses/{responseId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["cookie"] = 'next-auth.session-token='
response = http.request(request)
puts response.read_body{
"data": {
"id": "clrs1234567890123456789012",
"surveyId": "clsv1234567890123456789012",
"surveyName": "Q3 Product Feedback",
"workspaceId": "clws1234567890123456789012",
"createdAt": "2026-08-27T09:14:03.417Z",
"updatedAt": "2026-08-27T09:17:41.902Z",
"finished": true,
"endingId": "cmpthankyou00000000000000",
"language": "de",
"durationSeconds": 8.2,
"resolution": {
"labelPolicy": "currentSurveyDefinition",
"labelsLanguage": "de",
"surveyUpdatedAt": "2026-08-20T11:02:55.000Z"
},
"answers": [
{
"position": 1,
"elementId": "satisfaction",
"elementType": "rating",
"elementLabel": "Wie zufrieden sind Sie?",
"valueNumber": 4,
"range": {
"min": 1,
"max": 5
},
"scale": "star",
"durationSeconds": 8.2
},
{
"position": 2,
"elementId": "signup_date",
"elementType": "date",
"elementLabel": "Wann haben Sie sich registriert?",
"valueDate": "2026-05-14"
},
{
"position": 3,
"elementId": "your_address",
"elementType": "address",
"elementLabel": "Ihre Adresse",
"fields": [
{
"slot": 0,
"fieldId": "addressLine1",
"fieldLabel": "Adresszeile 1",
"valueText": "Hauptstrasse 1"
},
{
"slot": 1,
"fieldId": "addressLine2",
"fieldLabel": "Adresszeile 2",
"valueText": ""
},
{
"slot": 2,
"fieldId": "city",
"fieldLabel": "Stadt",
"valueText": "Berlin"
},
{
"slot": 3,
"fieldId": "state",
"fieldLabel": "Bundesland",
"valueText": ""
},
{
"slot": 4,
"fieldId": "zip",
"fieldLabel": "PLZ",
"valueText": "10115"
},
{
"slot": 5,
"fieldId": "country",
"fieldLabel": "Land",
"valueText": "Deutschland"
}
]
},
{
"position": 4,
"elementId": "screenshots",
"elementType": "fileUpload",
"elementLabel": "Screenshots",
"fileUrls": [
"/storage/clws1234567890123456789012/private/surveys/clsv1234567890123456789012/elements/screenshots/shot.png"
],
"fileCount": 1
},
{
"position": 5,
"elementId": "priorities",
"elementType": "ranking",
"elementLabel": "Bitte sortieren Sie nach Wichtigkeit",
"selections": [
{
"optionId": "opt_speed",
"optionLabel": "Geschwindigkeit",
"rawValue": "Geschwindigkeit",
"match": "label",
"rank": 1
},
{
"optionId": "opt_price",
"optionLabel": "Preis",
"rawValue": "Preis",
"match": "label",
"rank": 2
}
]
},
{
"position": 6,
"elementId": "nps_matrix",
"elementType": "matrix",
"elementLabel": "Bewerten Sie die Bereiche",
"rows": [
{
"rawKey": "Support",
"rowId": "row_support",
"rowLabel": "Support",
"columnId": "col_good",
"columnLabel": "Gut",
"rawValue": "Gut",
"match": "label"
}
]
}
],
"embeddedData": [
{
"key": "plan",
"kind": "ingested",
"type": "string",
"label": "Plan",
"value": "enterprise"
},
{
"key": "deviceType",
"kind": "reserved",
"type": "string",
"label": "Device Type",
"value": "desktop"
}
],
"unresolved": [],
"tags": [
{
"id": "cltg1234567890123456789012",
"name": "vip"
}
],
"contact": {
"id": "clct1234567890123456789012",
"userId": "u_123"
},
"displayId": "cldp1234567890123456789012",
"singleUseId": null,
"data": {
"satisfaction": 4,
"signup_date": "2026-05-14",
"your_address": [
"Hauptstrasse 1",
"",
"Berlin",
"",
"10115",
"Deutschland"
],
"screenshots": [
"/storage/clws1234567890123456789012/private/surveys/clsv1234567890123456789012/elements/screenshots/shot.png"
],
"priorities": [
"Geschwindigkeit",
"Preis"
],
"nps_matrix": {
"Support": "Gut"
}
}
}
}Get a response
Returns one response in the detailed view — everything the list view carries, plus contact, displayId, singleUseId, and the stored answer map data.
The 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.
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:
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.
curl --request GET \
--url https://app.formbricks.com/api/v3/responses/{responseId} \
--cookie next-auth.session-token=import requests
url = "https://app.formbricks.com/api/v3/responses/{responseId}"
headers = {"cookie": "next-auth.session-token="}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {cookie: 'next-auth.session-token='}};
fetch('https://app.formbricks.com/api/v3/responses/{responseId}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.formbricks.com/api/v3/responses/{responseId}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_COOKIE => "next-auth.session-token=",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://app.formbricks.com/api/v3/responses/{responseId}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("cookie", "next-auth.session-token=")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.formbricks.com/api/v3/responses/{responseId}")
.header("cookie", "next-auth.session-token=")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.formbricks.com/api/v3/responses/{responseId}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["cookie"] = 'next-auth.session-token='
response = http.request(request)
puts response.read_body{
"data": {
"id": "clrs1234567890123456789012",
"surveyId": "clsv1234567890123456789012",
"surveyName": "Q3 Product Feedback",
"workspaceId": "clws1234567890123456789012",
"createdAt": "2026-08-27T09:14:03.417Z",
"updatedAt": "2026-08-27T09:17:41.902Z",
"finished": true,
"endingId": "cmpthankyou00000000000000",
"language": "de",
"durationSeconds": 8.2,
"resolution": {
"labelPolicy": "currentSurveyDefinition",
"labelsLanguage": "de",
"surveyUpdatedAt": "2026-08-20T11:02:55.000Z"
},
"answers": [
{
"position": 1,
"elementId": "satisfaction",
"elementType": "rating",
"elementLabel": "Wie zufrieden sind Sie?",
"valueNumber": 4,
"range": {
"min": 1,
"max": 5
},
"scale": "star",
"durationSeconds": 8.2
},
{
"position": 2,
"elementId": "signup_date",
"elementType": "date",
"elementLabel": "Wann haben Sie sich registriert?",
"valueDate": "2026-05-14"
},
{
"position": 3,
"elementId": "your_address",
"elementType": "address",
"elementLabel": "Ihre Adresse",
"fields": [
{
"slot": 0,
"fieldId": "addressLine1",
"fieldLabel": "Adresszeile 1",
"valueText": "Hauptstrasse 1"
},
{
"slot": 1,
"fieldId": "addressLine2",
"fieldLabel": "Adresszeile 2",
"valueText": ""
},
{
"slot": 2,
"fieldId": "city",
"fieldLabel": "Stadt",
"valueText": "Berlin"
},
{
"slot": 3,
"fieldId": "state",
"fieldLabel": "Bundesland",
"valueText": ""
},
{
"slot": 4,
"fieldId": "zip",
"fieldLabel": "PLZ",
"valueText": "10115"
},
{
"slot": 5,
"fieldId": "country",
"fieldLabel": "Land",
"valueText": "Deutschland"
}
]
},
{
"position": 4,
"elementId": "screenshots",
"elementType": "fileUpload",
"elementLabel": "Screenshots",
"fileUrls": [
"/storage/clws1234567890123456789012/private/surveys/clsv1234567890123456789012/elements/screenshots/shot.png"
],
"fileCount": 1
},
{
"position": 5,
"elementId": "priorities",
"elementType": "ranking",
"elementLabel": "Bitte sortieren Sie nach Wichtigkeit",
"selections": [
{
"optionId": "opt_speed",
"optionLabel": "Geschwindigkeit",
"rawValue": "Geschwindigkeit",
"match": "label",
"rank": 1
},
{
"optionId": "opt_price",
"optionLabel": "Preis",
"rawValue": "Preis",
"match": "label",
"rank": 2
}
]
},
{
"position": 6,
"elementId": "nps_matrix",
"elementType": "matrix",
"elementLabel": "Bewerten Sie die Bereiche",
"rows": [
{
"rawKey": "Support",
"rowId": "row_support",
"rowLabel": "Support",
"columnId": "col_good",
"columnLabel": "Gut",
"rawValue": "Gut",
"match": "label"
}
]
}
],
"embeddedData": [
{
"key": "plan",
"kind": "ingested",
"type": "string",
"label": "Plan",
"value": "enterprise"
},
{
"key": "deviceType",
"kind": "reserved",
"type": "string",
"label": "Device Type",
"value": "desktop"
}
],
"unresolved": [],
"tags": [
{
"id": "cltg1234567890123456789012",
"name": "vip"
}
],
"contact": {
"id": "clct1234567890123456789012",
"userId": "u_123"
},
"displayId": "cldp1234567890123456789012",
"singleUseId": null,
"data": {
"satisfaction": 4,
"signup_date": "2026-05-14",
"your_address": [
"Hauptstrasse 1",
"",
"Berlin",
"",
"10115",
"Deutschland"
],
"screenshots": [
"/storage/clws1234567890123456789012/private/surveys/clsv1234567890123456789012/elements/screenshots/shot.png"
],
"priorities": [
"Geschwindigkeit",
"Preis"
],
"nps_matrix": {
"Support": "Gut"
}
}
}
}Authorizations
NextAuth session JWT cookie. Development: often next-auth.session-token.
Production (HTTPS): often __Secure-next-auth.session-token. Send the cookie your browser receives after sign-in.
Path Parameters
Response identifier.
Response
Response retrieved successfully
A survey response in the detailed view, as returned by GET /api/v3/responses/{responseId} and by the write endpoints. Everything in ResponseListItem, plus the identity and provenance fields the list view omits.
It also carries data — the answers as stored, returned unchanged, so a client can read a response, edit an answer and send it straight back. Embedded Data is not echoed in stored form: the read's embeddedData[] and a request's embeddedData map already address the same fields by the same names, so a second raw map would only republish the storage layout. That is the property v1/v2 had for free by being symmetric, and the one OpenAPI 3.1.1 argues for directly: its "Validating readOnly and writeOnly" section notes that making clients strip fields before a write is "burdensome for clients, particularly when the JSON data is complex or deeply nested".
They are not the same view, and the differences are deliberate. A write accepts ingested and computed fields only: a reserved entry describes the submission environment, and being able to read one back is not a licence to author it. An unset field is omitted from the read while null on a write clears one, because a merge-shaped map has no other way to spell deletion. And a name the read returns twice under different kinds cannot be written at all — see ResponseEmbeddedDataInput, which refuses an ambiguous name rather than guessing.
Values themselves round-trip: within those two kinds every value the read emits is accepted verbatim on a write, and a date reads and writes as the same ISO-8601 string. So a read-edit-write cycle loses nothing except in two cases, both confined to rows v1 or v2 wrote. The first is the finite set of legacy surveys carrying one name as both a variable and a hidden field, where the write refuses the name outright. The second is a data map holding more keys than ResponseDataMapInput accepts: the stored map is unbounded and the write bound is not, so such a response cannot be patched here — and trimming it to fit is not a workaround, since data is replaced wholesale and an omitted key is a deletion.
Note which fields carry readOnly here and which do not, because it is the opposite of what an "echo" framing would suggest. readOnly means a value is managed exclusively by the server, so it marks the derived views — answers[], embeddedData[], unresolved[], resolution, the denormalized surveyName and workspaceId, the timestamps, durationSeconds and id. data is not read-only: it is exactly what the write endpoints accept, and leaving it unmarked is what makes this representation round-trippable rather than merely informative.
To correct one answer, read this resource, take data, change the entry you want and PATCH { "data": … }. Send only the fields you are changing — PATCH rejects unknown and non-patchable keys, so passing the whole representation back verbatim is not the intended flow; passing data back is.
Never exposed on this resource, in either view: the respondent's IP address, and the contactAttributes snapshot that v1/v2 return. That snapshot is copied from the contact at submission time and never updated after, so it is stale PII by construction — contact covers the legitimate need to know who answered.
Show child attributes
Show child attributes
Was this page helpful?