curl --request GET \
--url https://api.closedloop.sh/v1/themes/{id} \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.closedloop.sh/v1/themes/{id}"
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/themes/{id}', 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/themes/{id}",
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/themes/{id}"
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/themes/{id}")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.closedloop.sh/v1/themes/{id}")
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{
"id": "a1b2c3d4-e5f6-4a7b-8c9d-000000000001",
"title": "Dark mode across the product",
"ric_score": 7.8,
"status": "active",
"replacement_theme_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"description": "Customers repeatedly ask for a dark theme for night-time and accessibility.",
"reach": 0.62,
"impact": 0.8,
"confidence": 0.9,
"insight_count": 34,
"unique_customer_count": 19,
"deal_blocker_count": 4,
"feature_count": 4,
"created_at": "2026-04-02T00:00:00Z",
"updated_at": "2026-06-01T00:00:00Z",
"severity_breakdown": {
"critical": 1,
"high": 8,
"medium": 20,
"low": 5
},
"features": [
{
"id": "b2c3d4e5-f6a7-4b8c-9d0e-000000000002",
"theme_id": "a1b2c3d4-e5f6-4a7b-8c9d-000000000001",
"title": "Dark mode toggle in settings",
"ric_score": 6.9,
"status": "active",
"description": "A user-controllable dark / light toggle in the settings panel.",
"insight_count": 12,
"unique_customer_count": 9,
"product_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"product_name": "Core Platform",
"created_at": "2026-04-05T00:00:00Z",
"updated_at": "2026-06-01T00:00:00Z"
}
],
"top_insights": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"severity": "critical",
"source": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"category": "<string>",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_name": "<string>",
"source_date": "2023-11-07T05:31:56Z"
}
],
"affected_customers": [
{
"id": "c0ffee00-0000-4000-8000-000000000001",
"name": "Acme UK",
"domain": "acme.example",
"family": {
"id": "fa111e00-0000-4000-8000-000000000001",
"name": "Acme",
"is_grouped": true,
"member_count": 3,
"members": [
{
"id": "c0ffee00-0000-4000-8000-000000000003",
"name": "Acme Germany",
"external_ids": [
{
"integration_id": "1e7e6600-0000-4000-8000-000000000001",
"source": "salesforce",
"external_id": "001A000001AbCdEAAZ"
}
],
"domain": "acme.com"
}
]
}
}
]
}Get a theme
Get one product theme with its severity breakdown, affected customers, top supporting insights, features, and the theme that replaced it if it was merged.
curl --request GET \
--url https://api.closedloop.sh/v1/themes/{id} \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.closedloop.sh/v1/themes/{id}"
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/themes/{id}', 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/themes/{id}",
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/themes/{id}"
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/themes/{id}")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.closedloop.sh/v1/themes/{id}")
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{
"id": "a1b2c3d4-e5f6-4a7b-8c9d-000000000001",
"title": "Dark mode across the product",
"ric_score": 7.8,
"status": "active",
"replacement_theme_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"description": "Customers repeatedly ask for a dark theme for night-time and accessibility.",
"reach": 0.62,
"impact": 0.8,
"confidence": 0.9,
"insight_count": 34,
"unique_customer_count": 19,
"deal_blocker_count": 4,
"feature_count": 4,
"created_at": "2026-04-02T00:00:00Z",
"updated_at": "2026-06-01T00:00:00Z",
"severity_breakdown": {
"critical": 1,
"high": 8,
"medium": 20,
"low": 5
},
"features": [
{
"id": "b2c3d4e5-f6a7-4b8c-9d0e-000000000002",
"theme_id": "a1b2c3d4-e5f6-4a7b-8c9d-000000000001",
"title": "Dark mode toggle in settings",
"ric_score": 6.9,
"status": "active",
"description": "A user-controllable dark / light toggle in the settings panel.",
"insight_count": 12,
"unique_customer_count": 9,
"product_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"product_name": "Core Platform",
"created_at": "2026-04-05T00:00:00Z",
"updated_at": "2026-06-01T00:00:00Z"
}
],
"top_insights": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"severity": "critical",
"source": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"category": "<string>",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_name": "<string>",
"source_date": "2023-11-07T05:31:56Z"
}
],
"affected_customers": [
{
"id": "c0ffee00-0000-4000-8000-000000000001",
"name": "Acme UK",
"domain": "acme.example",
"family": {
"id": "fa111e00-0000-4000-8000-000000000001",
"name": "Acme",
"is_grouped": true,
"member_count": 3,
"members": [
{
"id": "c0ffee00-0000-4000-8000-000000000003",
"name": "Acme Germany",
"external_ids": [
{
"integration_id": "1e7e6600-0000-4000-8000-000000000001",
"source": "salesforce",
"external_id": "001A000001AbCdEAAZ"
}
],
"domain": "acme.com"
}
]
}
}
]
}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.
Path Parameters
Resource UUID.
Response
Theme detail
Stable theme ID.
"a1b2c3d4-e5f6-4a7b-8c9d-000000000001"
"Dark mode across the product"
Reach × Impact × Confidence.
7.8
active, declined, shipped, parked "active"
Only on a merged theme returned by include_retired=true; the current theme that replaced it.
"Customers repeatedly ask for a dark theme for night-time and accessibility."
0.62
0.8
0.9
Supporting insights across the theme.
34
19
Customers with a deal blocker in this theme.
4
Features shown under this theme.
4
"2026-04-02T00:00:00Z"
"2026-06-01T00:00:00Z"
{
"critical": 1,
"high": 8,
"medium": 20,
"low": 5
}
The buildable features under this theme.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Up to 50 customer accounts behind these insights, ordered by name, each with its family. Customers not matched to a CRM account are counted but not listed.
Show child attributes
Show child attributes