Analytics V2 Judge (source-grounding)
curl --request POST \
--url https://api.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"prompt": "For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.",
"response_schema": {
"type": "object",
"properties": {
"section_scores": {
"type": "object",
"additionalProperties": {
"type": "number"
}
},
"section_content_summaries": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"report": {
"type": "string"
}
},
"required": [
"section_scores",
"section_content_summaries",
"report"
]
}
}
'import requests
url = "https://api.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge"
payload = {
"prompt": "For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.",
"response_schema": {
"type": "object",
"properties": {
"section_scores": {
"type": "object",
"additionalProperties": { "type": "number" }
},
"section_content_summaries": {
"type": "object",
"additionalProperties": { "type": "string" }
},
"report": { "type": "string" }
},
"required": ["section_scores", "section_content_summaries", "report"]
}
}
headers = {
"X-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
prompt: 'For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.',
response_schema: {
type: 'object',
properties: {
section_scores: {type: 'object', additionalProperties: {type: 'number'}},
section_content_summaries: {type: 'object', additionalProperties: {type: 'string'}},
report: {type: 'string'}
},
required: ['section_scores', 'section_content_summaries', 'report']
}
})
};
fetch('https://api.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge', 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.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'prompt' => 'For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.',
'response_schema' => [
'type' => 'object',
'properties' => [
'section_scores' => [
'type' => 'object',
'additionalProperties' => [
'type' => 'number'
]
],
'section_content_summaries' => [
'type' => 'object',
'additionalProperties' => [
'type' => 'string'
]
],
'report' => [
'type' => 'string'
]
],
'required' => [
'section_scores',
'section_content_summaries',
'report'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge"
payload := strings.NewReader("{\n \"prompt\": \"For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.\",\n \"response_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"section_scores\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"number\"\n }\n },\n \"section_content_summaries\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"report\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"section_scores\",\n \"section_content_summaries\",\n \"report\"\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-KEY", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"prompt\": \"For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.\",\n \"response_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"section_scores\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"number\"\n }\n },\n \"section_content_summaries\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"report\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"section_scores\",\n \"section_content_summaries\",\n \"report\"\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"prompt\": \"For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.\",\n \"response_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"section_scores\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"number\"\n }\n },\n \"section_content_summaries\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"report\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"section_scores\",\n \"section_content_summaries\",\n \"report\"\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"error": null,
"payload": {
"chat_message_id": "5b37f46c-f5de-4b8a-af09-5058dd4779b3",
"verdict": {
"section_scores": {
"Market Snapshot": 9.5,
"What CLSA Says": 8
},
"section_content_summaries": {
"Market Snapshot": "Index levels and deltas match the cited FactSet/market-data sources.",
"What CLSA Says": "Ratings and targets trace to the cited CLSA notes; one target could not be verified against any cited source."
},
"report": "## Market Snapshot\n- Strengths: index levels match the cited sources.\n- Contradicted or unverifiable: none.\n\n## What CLSA Says\n- Weaknesses: one price target is absent from the cited notes (flagged)."
},
"judge_model": "gpt-4.1",
"references_evaluated": 24
}
}{
"error": {
"code": "INVALID_REQUEST_BODY",
"msg": "prompt is required",
"message": "prompt is required"
},
"payload": null
}{
"error": {
"code": "INVALID_REQUEST_BODY",
"msg": "query is required and must be a string",
"message": "query is required and must be a string"
},
"payload": "<unknown>"
}{
"error": {
"code": "INVALID_REQUEST_BODY",
"msg": "query is required and must be a string",
"message": "query is required and must be a string"
},
"payload": "<unknown>"
}{
"error": {
"code": "INVALID_REQUEST_BODY",
"msg": "query is required and must be a string",
"message": "query is required and must be a string"
},
"payload": "<unknown>"
}{
"error": {
"code": "INVALID_REQUEST_BODY",
"msg": "query is required and must be a string",
"message": "query is required and must be a string"
},
"payload": "<unknown>"
}{
"error": {
"code": "INVALID_REQUEST_BODY",
"msg": "query is required and must be a string",
"message": "query is required and must be a string"
},
"payload": "<unknown>"
}Analytics V2
Analytics V2 Judge
Runs a source-grounding judge over one Analytics answer. You supply the answer’s chat_message_id plus your own judging prompt (and an optional response_schema); we resolve the original prompt, the generated answer, and every reference the answer cited, run a tool-less GPT-4.1 over them, and return a verdict shaped by your schema.
Usage flow:
- Call
POST /v2/analytics/sse; while consuming the stream, capture thechat_message_idevent. - POST that id here with your
prompt— your prompt is the entire judging instruction; we add no criteria of our own — and an optionalresponse_schema. - The verdict scores how well each claim is grounded in the sources the answer actually cited (a number that contradicts its source, or is absent from all sources, is flagged as not grounded).
Tenant-scoped: you can only judge answers generated by your own organization; others return 404.
POST
/
v2
/
analytics
/
messages
/
{chat_message_id}
/
judge
Analytics V2 Judge (source-grounding)
curl --request POST \
--url https://api.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"prompt": "For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.",
"response_schema": {
"type": "object",
"properties": {
"section_scores": {
"type": "object",
"additionalProperties": {
"type": "number"
}
},
"section_content_summaries": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"report": {
"type": "string"
}
},
"required": [
"section_scores",
"section_content_summaries",
"report"
]
}
}
'import requests
url = "https://api.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge"
payload = {
"prompt": "For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.",
"response_schema": {
"type": "object",
"properties": {
"section_scores": {
"type": "object",
"additionalProperties": { "type": "number" }
},
"section_content_summaries": {
"type": "object",
"additionalProperties": { "type": "string" }
},
"report": { "type": "string" }
},
"required": ["section_scores", "section_content_summaries", "report"]
}
}
headers = {
"X-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
prompt: 'For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.',
response_schema: {
type: 'object',
properties: {
section_scores: {type: 'object', additionalProperties: {type: 'number'}},
section_content_summaries: {type: 'object', additionalProperties: {type: 'string'}},
report: {type: 'string'}
},
required: ['section_scores', 'section_content_summaries', 'report']
}
})
};
fetch('https://api.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge', 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.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'prompt' => 'For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.',
'response_schema' => [
'type' => 'object',
'properties' => [
'section_scores' => [
'type' => 'object',
'additionalProperties' => [
'type' => 'number'
]
],
'section_content_summaries' => [
'type' => 'object',
'additionalProperties' => [
'type' => 'string'
]
],
'report' => [
'type' => 'string'
]
],
'required' => [
'section_scores',
'section_content_summaries',
'report'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge"
payload := strings.NewReader("{\n \"prompt\": \"For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.\",\n \"response_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"section_scores\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"number\"\n }\n },\n \"section_content_summaries\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"report\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"section_scores\",\n \"section_content_summaries\",\n \"report\"\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-KEY", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"prompt\": \"For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.\",\n \"response_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"section_scores\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"number\"\n }\n },\n \"section_content_summaries\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"report\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"section_scores\",\n \"section_content_summaries\",\n \"report\"\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.linqalpha.com/v2/analytics/messages/{chat_message_id}/judge")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"prompt\": \"For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or rating absent from the cited sources must appear under Contradicted or unverifiable.\",\n \"response_schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"section_scores\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"number\"\n }\n },\n \"section_content_summaries\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"string\"\n }\n },\n \"report\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"section_scores\",\n \"section_content_summaries\",\n \"report\"\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"error": null,
"payload": {
"chat_message_id": "5b37f46c-f5de-4b8a-af09-5058dd4779b3",
"verdict": {
"section_scores": {
"Market Snapshot": 9.5,
"What CLSA Says": 8
},
"section_content_summaries": {
"Market Snapshot": "Index levels and deltas match the cited FactSet/market-data sources.",
"What CLSA Says": "Ratings and targets trace to the cited CLSA notes; one target could not be verified against any cited source."
},
"report": "## Market Snapshot\n- Strengths: index levels match the cited sources.\n- Contradicted or unverifiable: none.\n\n## What CLSA Says\n- Weaknesses: one price target is absent from the cited notes (flagged)."
},
"judge_model": "gpt-4.1",
"references_evaluated": 24
}
}{
"error": {
"code": "INVALID_REQUEST_BODY",
"msg": "prompt is required",
"message": "prompt is required"
},
"payload": null
}{
"error": {
"code": "INVALID_REQUEST_BODY",
"msg": "query is required and must be a string",
"message": "query is required and must be a string"
},
"payload": "<unknown>"
}{
"error": {
"code": "INVALID_REQUEST_BODY",
"msg": "query is required and must be a string",
"message": "query is required and must be a string"
},
"payload": "<unknown>"
}{
"error": {
"code": "INVALID_REQUEST_BODY",
"msg": "query is required and must be a string",
"message": "query is required and must be a string"
},
"payload": "<unknown>"
}{
"error": {
"code": "INVALID_REQUEST_BODY",
"msg": "query is required and must be a string",
"message": "query is required and must be a string"
},
"payload": "<unknown>"
}{
"error": {
"code": "INVALID_REQUEST_BODY",
"msg": "query is required and must be a string",
"message": "query is required and must be a string"
},
"payload": "<unknown>"
}What it does
The judge takes an answer you already generated and returns a structured verdict on how well each claim is backed by the sources that answer cited. For every cited source it reads the verbatim quoted text plus its metadata (document, type, tickers, dates, publisher, and FactSet fields), then checks each claim against that source. A figure that contradicts its source, or that appears in no cited source, is flagged. The check is deterministic (temperature 0); your prompt is the entire judging instruction and your response_schema defines the verdict shape, so we add no criteria of our own.
Getting the chat_message_id
As you consume the Analytics V2 SSE stream (POST /v2/analytics/sse), the id arrives as its own event:
data: {"event_name": "chat_message_id", "data": {"chat_message_id": "5b37f46c-f5de-4b8a-af09-5058dd4779b3"}}
event_name == "chat_message_id" and keep data.chat_message_id.
Example
import requests
resp = requests.post(
"https://api.linqalpha.com/v2/analytics/messages/5b37f46c-f5de-4b8a-af09-5058dd4779b3/judge",
headers={"X-API-KEY": "<your-api-key>", "Content-Type": "application/json"},
json={
# Your judge prompt, used verbatim as the judge's instruction.
"prompt": (
"For each section of the answer, return: (1) a score from 0 to 10 reflecting how well its "
"claims are grounded in the cited sources [N], (2) a concise summary, and (3) a short report "
"covering Strengths, Weaknesses, and any Contradicted or unverifiable facts. Any figure or "
"rating absent from the cited sources must appear under Contradicted or unverifiable."
),
# Optional. Any valid JSON Schema (dynamic-key maps supported); omit for the default verdict shape.
"response_schema": {
"type": "object",
"properties": {
"section_scores": {"type": "object", "additionalProperties": {"type": "number"}},
"section_content_summaries": {"type": "object", "additionalProperties": {"type": "string"}},
"report": {"type": "string"},
},
"required": ["section_scores", "section_content_summaries", "report"],
},
},
timeout=160,
)
resp.raise_for_status()
payload = resp.json()["payload"]
print(payload["verdict"], payload["judge_model"], payload["references_evaluated"])
You can only judge answers generated by your own organization; judging another org’s answer returns
404. The call is a single long-running LLM request, so allow a generous client timeout (~160s).Authorizations
Path Parameters
The assistant answer's ChatMessage UUID. Emitted as the chat_message_id event on the Analytics SSE V2 stream.
Body
application/json
Was this page helpful?
⌘I