The 67-signal schema manifest.
curl --request GET \
--url https://api.keplerinsights.us/v1/signals \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.keplerinsights.us/v1/signals"
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.keplerinsights.us/v1/signals', 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.keplerinsights.us/v1/signals",
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.keplerinsights.us/v1/signals"
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.keplerinsights.us/v1/signals")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.keplerinsights.us/v1/signals")
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{
"version": "<string>",
"signals": [
{
"key": "founder_years_experience",
"label": "<string>",
"bucket": "team_structure",
"category": "<string>",
"weight": 123,
"actionability": "actionable",
"description": "<string>"
}
]
}{
"error": "unauthorized",
"message": "<string>",
"reason": "<string>"
}Endpoints
GET /v1/signals
The 67-signal manifest. What every score is composed of.
GET
/
v1
/
signals
The 67-signal schema manifest.
curl --request GET \
--url https://api.keplerinsights.us/v1/signals \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.keplerinsights.us/v1/signals"
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.keplerinsights.us/v1/signals', 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.keplerinsights.us/v1/signals",
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.keplerinsights.us/v1/signals"
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.keplerinsights.us/v1/signals")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.keplerinsights.us/v1/signals")
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{
"version": "<string>",
"signals": [
{
"key": "founder_years_experience",
"label": "<string>",
"bucket": "team_structure",
"category": "<string>",
"weight": 123,
"actionability": "actionable",
"description": "<string>"
}
]
}{
"error": "unauthorized",
"message": "<string>",
"reason": "<string>"
}A read-only manifest of every signal the engine evaluates. Use it to render bucket / category breakdowns and to look up labels + descriptions for stored
signal_scores keys.
When to use it
- Building a UI that lists a company’s signal scores by category.
- Documenting your integration (“these 17 signals contributed most to this score”).
- Periodic snapshot — fetch once, cache locally, refresh weekly. The manifest changes only on engine releases.
Response shape
{
"version": "2026-05-12",
"signals": [
{
"key": "founder_years_experience",
"label": "Founder years of experience",
"bucket": "team_structure",
"category": "founding_team",
"weight": 12.5,
"actionability": "immutable",
"description": "Total professional years across the founding team. Sourced from professional employment data with AI enrichment fallback."
},
...
]
}
Fields
key— stable identifier. Matches the keys in storedsignal_scoresmaps. Don’t render this directly; uselabel.label— human-readable name.bucket— one ofteam_structure,market_position,momentum_tailwinds,financial_health.category— finer grouping inside the bucket.weight— relative weight in its category. Categories sum to 100 within their parent bucket; signals sum to 100 within their parent category.actionability—actionable(a founder can change this in months),slow_actionable(years), orimmutable(e.g. academic background, prior exits).description— one-sentence narrative of what the signal measures.
Identical in sandbox and live
The manifest is deterministic content —ki_test_ and ki_live_ keys both return the same JSON. The response does not carry a mode: "sandbox" field, by design (no canned-vs-real distinction to make).
When to refresh
The manifest changes when:- Kepler adds a new signal (rare; major engine version bump).
- Kepler retires a signal (e.g.
competitor_hq_distributionwas removed pre-launch). - Weights are tuned (frequent — but the schema stays the same).
version field is a date string and bumps on every change. Compare it to your cached value to decide whether to refresh.Authorizations
Live keys are prefixed ki_live_, test keys ki_test_. Issue + revoke
keys at https://console.keplerinsights.us. Never embed a key in client-side
code — every endpoint is backend-to-API only.

