curl --request GET \
--url https://api.closedloop.sh/v1/insights \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.closedloop.sh/v1/insights"
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://api.closedloop.sh/v1/insights', 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://api.closedloop.sh/v1/insights",
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://api.closedloop.sh/v1/insights"
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://api.closedloop.sh/v1/insights")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.closedloop.sh/v1/insights")
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": [
{
"id": "123e4567-e89b-42d3-a456-426614174000",
"title": "Scheduled exports are needed for reporting",
"category": "feature request",
"severity": "medium",
"customer_id": "c0ffee00-0000-4000-8000-000000000001",
"customer_name": "Acme Co",
"source": "gong_call_abc123",
"source_date": "2026-05-14T10:30:00Z",
"created_at": "2026-05-14T10:30:00Z",
"updated_at": "2026-05-15T08:12:00Z",
"feature_area_id": "523e4567-e89b-42d3-a456-426614174004",
"feature_area_name": "Exports",
"product_area_id": "423e4567-e89b-42d3-a456-426614174003",
"product_area_name": "Operations",
"products": [
{
"id": "223e4567-e89b-42d3-a456-426614174001",
"name": "Core Platform",
"status": "active"
}
],
"product_features": [
{
"id": "323e4567-e89b-42d3-a456-426614174002",
"title": "Scheduled exports",
"product_id": "223e4567-e89b-42d3-a456-426614174001"
}
]
}
],
"pagination": {
"total": 1,
"limit": 50,
"offset": 0
}
}List / search insights
Search your product insights by customer, severity, product, area, date, or text, page through the results, or export them incrementally.
curl --request GET \
--url https://api.closedloop.sh/v1/insights \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.closedloop.sh/v1/insights"
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://api.closedloop.sh/v1/insights', 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://api.closedloop.sh/v1/insights",
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://api.closedloop.sh/v1/insights"
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://api.closedloop.sh/v1/insights")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.closedloop.sh/v1/insights")
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": [
{
"id": "123e4567-e89b-42d3-a456-426614174000",
"title": "Scheduled exports are needed for reporting",
"category": "feature request",
"severity": "medium",
"customer_id": "c0ffee00-0000-4000-8000-000000000001",
"customer_name": "Acme Co",
"source": "gong_call_abc123",
"source_date": "2026-05-14T10:30:00Z",
"created_at": "2026-05-14T10:30:00Z",
"updated_at": "2026-05-15T08:12:00Z",
"feature_area_id": "523e4567-e89b-42d3-a456-426614174004",
"feature_area_name": "Exports",
"product_area_id": "423e4567-e89b-42d3-a456-426614174003",
"product_area_name": "Operations",
"products": [
{
"id": "223e4567-e89b-42d3-a456-426614174001",
"name": "Core Platform",
"status": "active"
}
],
"product_features": [
{
"id": "323e4567-e89b-42d3-a456-426614174002",
"title": "Scheduled exports",
"product_id": "223e4567-e89b-42d3-a456-426614174001"
}
]
}
],
"pagination": {
"total": 1,
"limit": 50,
"offset": 0
}
}Authorizations
Team-scoped API key created in the app (Settings → API Keys).
Sent as X-API-Key: <key> on every request. The header name apikey
is also accepted as an alias.
Query Parameters
Free-text search over titles and content.
Feedback category (e.g. bug, feature request, usability).
"bug"
critical, high, medium, low Filter to insights from one customer (same key as on context).
Filter by one product ID from /products: the insights filed under it.
Filter by one buildable product feature ID from /features.
Filter by one parent product-area ID from /areas: the insights filed on it or on one of its feature areas.
Filter by one feature area from /areas (an area, not a feature ID): the insights filed on it.
Start date (inclusive), YYYY-MM-DD. Other formats return 400.
^\d{4}-\d{2}-\d{2}$End date (inclusive), YYYY-MM-DD. Other formats return 400.
^\d{4}-\d{2}-\d{2}$Start an incremental export from this time: an ISO 8601 date-time with a
timezone, such as 2026-05-01T00:00:00Z. Cannot be combined with offset
or cursor.
The next_cursor from the previous export page. Send it with only limit,
using the same API key.
8192Page size (max 200).
1 <= x <= 200Number of records to skip.
x >= 0