curl --request GET \
--url https://app.formbricks.com/api/v3/feedbackRecords/{id}/similar \
--header 'x-api-key: <api-key>'import requests
url = "https://app.formbricks.com/api/v3/feedbackRecords/{id}/similar"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://app.formbricks.com/api/v3/feedbackRecords/{id}/similar', 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/feedbackRecords/{id}/similar",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$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/feedbackRecords/{id}/similar"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
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/feedbackRecords/{id}/similar")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.formbricks.com/api/v3/feedbackRecords/{id}/similar")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"data": [
{
"feedback_record_id": "018e1234-5678-7abc-8ef0-1234567890aa",
"score": 0.83,
"field_label": "Anything else?",
"value_text": "Took 40 minutes to get in. Please open more turnstiles."
}
],
"limit": 10
}Find similar feedback records
Returns the records in the same dataset whose embedded text is closest to the given record’s, with cosine similarity scores. The anchor record itself is excluded. The gateway looks the record up to learn its dataset and authorizes against that. Requires an API key with read permission (or higher) on a workspace the record’s dataset is assigned to.
Answers 403 for an unknown or inaccessible id. Answers 404 when the record exists but has no embedding — it has no text, or was created moments ago and is not embedded yet. Answers 503 on instances without an embedding model configured.
curl --request GET \
--url https://app.formbricks.com/api/v3/feedbackRecords/{id}/similar \
--header 'x-api-key: <api-key>'import requests
url = "https://app.formbricks.com/api/v3/feedbackRecords/{id}/similar"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://app.formbricks.com/api/v3/feedbackRecords/{id}/similar', 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/feedbackRecords/{id}/similar",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$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/feedbackRecords/{id}/similar"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
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/feedbackRecords/{id}/similar")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.formbricks.com/api/v3/feedbackRecords/{id}/similar")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"data": [
{
"feedback_record_id": "018e1234-5678-7abc-8ef0-1234567890aa",
"score": 0.83,
"field_label": "Anything else?",
"value_text": "Took 40 minutes to get in. Please open more turnstiles."
}
],
"limit": 10
}Authorizations
Management API key; must include workspaceId as an allowed workspace with read, write, or manage permission.
Path Parameters
Feedback record id (UUID). The dataset is resolved from the record itself, so the caller cannot choose which dataset it is authorized against. An id that is not a UUID answers 400, and an id whose dataset the API key cannot reach answers 403 rather than 404, so ids cannot be probed. The gateway caches the record→dataset lookup for 60 seconds, so for up to a minute after a delete the id is still authorized and the store answers 404; after that the same id answers 403.
Query Parameters
Page size, at most 100. Unlike the limit on GET /api/v3/feedbackRecords, this one is never rejected: the search endpoints clamp instead of answering 400. A value above 100 is reduced to 100, and 0, a negative number or a non-numeric value falls back to the default of 10. Read the limit in the response to see what was actually applied.
Opaque keyset cursor returned as next_cursor by the previous page. Omit on the first request. A malformed cursor answers 400.
Only matches with score >= min_score are returned. Like limit, this value is clamped rather than rejected: above 1 it becomes 1, below 0 it becomes 0, and a non-numeric value falls back to the default of 0.7. That default is conservative — on the embedding model we measured, query→record similarities for genuinely relevant text often landed around 0.55–0.7 — so if a good query returns nothing, lower it (e.g. 0.5) and filter on the returned value_text. Score distributions differ per model, so treat those numbers as an observation rather than a guarantee.
Response
Similar records retrieved
Matches ordered by descending score.
100Show child attributes
Show child attributes
The page size that was applied.
Opaque keyset cursor for the next page. Present only when a full page was returned and there may be more results. Pass it back unchanged as cursor.
Was this page helpful?