Get Validation Results
curl --request POST \
--url https://api.example.com/api/validate_stream_result/ \
--header 'Content-Type: application/json' \
--data '
{
"job_id": "<string>"
}
'import requests
url = "https://api.example.com/api/validate_stream_result/"
payload = { "job_id": "<string>" }
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({job_id: '<string>'})
};
fetch('https://api.example.com/api/validate_stream_result/', 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.example.com/api/validate_stream_result/",
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([
'job_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$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.example.com/api/validate_stream_result/"
payload := strings.NewReader("{\n \"job_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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.example.com/api/validate_stream_result/")
.header("Content-Type", "application/json")
.body("{\n \"job_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/validate_stream_result/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"job_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"job_id": "abc123def456",
"status": "in_progress",
"started": "2026-01-08T10:30:00Z",
"timestamp": "2026-01-08T10:30:15Z"
}
{
"job_id": "abc123def456",
"status": "done",
"started": "2026-01-08T10:30:00Z",
"timestamp": "2026-01-08T10:30:45Z",
"overall_status": "needs_changes",
"summary": {
"critical": 0,
"major": 2,
"medium": 0,
"minor": 1,
"document_pages": 1
},
"violating_line_count": 2,
"compliant_line_count": 3,
"total_line_count": 5,
"revalidation_recommended": true,
"violations_by_line": [
{
"line_number": 2,
"line_text": "Our fund guarantees 18% returns with no downside risk.",
"char_from": 45,
"char_to": 98,
"page": 1,
"rule_count": 1,
"rules_violated": [
{
"rule_name": "Prohibited Promissory Language (Keywords)",
"rule_ref": "FINRA 2210(d)(1)(B)",
"severity": "Critical",
"confidence": 0.92,
"action": "replace"
}
],
"best_fix": {
"severity": "Critical",
"rule_name": "Prohibited Promissory Language (Keywords)",
"rule_ref": "FINRA 2210(d)(1)(B)",
"action": "replace",
"suggested_text": "Our fund has historically delivered returns, though past performance does not guarantee future results.",
"human_action": "Replace promissory language with compliant disclosure",
"confidence": 0.92
}
}
],
"fixes": [],
"fixes_group": {},
"metadata": {
"document_category": "retail_investor_letter"
}
}
{
"job_id": "abc123def456",
"status": "failed",
"started": "2026-01-08T10:30:00Z",
"timestamp": "2026-01-08T10:30:05Z",
"error": "Failed to parse document: Invalid PDF format"
}
Validation
Get Validation Results
Retrieve results of an async validation job
POST
/
api
/
validate_stream_result
/
Get Validation Results
curl --request POST \
--url https://api.example.com/api/validate_stream_result/ \
--header 'Content-Type: application/json' \
--data '
{
"job_id": "<string>"
}
'import requests
url = "https://api.example.com/api/validate_stream_result/"
payload = { "job_id": "<string>" }
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({job_id: '<string>'})
};
fetch('https://api.example.com/api/validate_stream_result/', 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.example.com/api/validate_stream_result/",
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([
'job_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$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.example.com/api/validate_stream_result/"
payload := strings.NewReader("{\n \"job_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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.example.com/api/validate_stream_result/")
.header("Content-Type", "application/json")
.body("{\n \"job_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/validate_stream_result/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"job_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"job_id": "abc123def456",
"status": "in_progress",
"started": "2026-01-08T10:30:00Z",
"timestamp": "2026-01-08T10:30:15Z"
}
{
"job_id": "abc123def456",
"status": "done",
"started": "2026-01-08T10:30:00Z",
"timestamp": "2026-01-08T10:30:45Z",
"overall_status": "needs_changes",
"summary": {
"critical": 0,
"major": 2,
"medium": 0,
"minor": 1,
"document_pages": 1
},
"violating_line_count": 2,
"compliant_line_count": 3,
"total_line_count": 5,
"revalidation_recommended": true,
"violations_by_line": [
{
"line_number": 2,
"line_text": "Our fund guarantees 18% returns with no downside risk.",
"char_from": 45,
"char_to": 98,
"page": 1,
"rule_count": 1,
"rules_violated": [
{
"rule_name": "Prohibited Promissory Language (Keywords)",
"rule_ref": "FINRA 2210(d)(1)(B)",
"severity": "Critical",
"confidence": 0.92,
"action": "replace"
}
],
"best_fix": {
"severity": "Critical",
"rule_name": "Prohibited Promissory Language (Keywords)",
"rule_ref": "FINRA 2210(d)(1)(B)",
"action": "replace",
"suggested_text": "Our fund has historically delivered returns, though past performance does not guarantee future results.",
"human_action": "Replace promissory language with compliant disclosure",
"confidence": 0.92
}
}
],
"fixes": [],
"fixes_group": {},
"metadata": {
"document_category": "retail_investor_letter"
}
}
{
"job_id": "abc123def456",
"status": "failed",
"started": "2026-01-08T10:30:00Z",
"timestamp": "2026-01-08T10:30:05Z",
"error": "Failed to parse document: Invalid PDF format"
}
Retrieve results of an asynchronous validation job. Poll this endpoint until status is
done or failed.
Request Body
Job ID to retrieve results for
Response
Unique identifier for the validation job
Job status:
started, in_progress, done, or failedISO 8601 UTC timestamp when the job was created. Present from the initial
started status onward.ISO 8601 UTC timestamp of the current status snapshot.
Overall compliance assessment (when done):
approved, needs_changes, or do not send. Note: the do not send value contains spaces — this matches the API response exactly.Summary of violations by severity
Number of lines with at least one compliance violation. Absent for older jobs or when only grouped fixes exist.
Number of lines with no violations. Absent for older jobs or when only grouped fixes exist.
Total number of lines in the document. Absent for older jobs or when only grouped fixes exist.
True when more than one fix is found, suggesting a re-scan after applying all fixes.
One entry per violating line, with all rules violated and the best fix. Absent for older jobs or when only grouped fixes exist. Present but empty for fully compliant documents.
Show LineViolation properties
Show LineViolation properties
1-indexed line number in the document
The text content of the violating line (trimmed)
Character offset of the best fix’s original text start
Character offset of the best fix’s original text end
Page number where the violation appears
Number of distinct rules violated on this line
All rules violated on this line, sorted by severity then confidence
The recommended fix for this line (from the highest-severity, highest-confidence rule)
Show best_fix properties
Show best_fix properties
Severity level of the violation
Name of the compliance rule
Regulatory citation
Fix action:
replace, insert_after, remove, or warningThe replacement text (null when action is
remove or warning)Human-readable description of the fix action
Confidence score (0-1)
Individual fix entries (rule-centric, one per violation per quote)
Grouped fixes for rules that aggregate across pages
Document metadata used for scenario matching
Error message (when status is
failed)Job Status Values
| Status | Description |
|---|---|
started | Job created and queued for processing |
in_progress | Validation in progress |
done | Validation completed successfully |
failed | Validation failed with error |
Overall Status Values
| Status | Description |
|---|---|
approved | Document passes compliance checks |
needs_changes | Document has violations that should be addressed |
do not send | Document has critical violations and should not be distributed |
{
"job_id": "abc123def456",
"status": "in_progress",
"started": "2026-01-08T10:30:00Z",
"timestamp": "2026-01-08T10:30:15Z"
}
{
"job_id": "abc123def456",
"status": "done",
"started": "2026-01-08T10:30:00Z",
"timestamp": "2026-01-08T10:30:45Z",
"overall_status": "needs_changes",
"summary": {
"critical": 0,
"major": 2,
"medium": 0,
"minor": 1,
"document_pages": 1
},
"violating_line_count": 2,
"compliant_line_count": 3,
"total_line_count": 5,
"revalidation_recommended": true,
"violations_by_line": [
{
"line_number": 2,
"line_text": "Our fund guarantees 18% returns with no downside risk.",
"char_from": 45,
"char_to": 98,
"page": 1,
"rule_count": 1,
"rules_violated": [
{
"rule_name": "Prohibited Promissory Language (Keywords)",
"rule_ref": "FINRA 2210(d)(1)(B)",
"severity": "Critical",
"confidence": 0.92,
"action": "replace"
}
],
"best_fix": {
"severity": "Critical",
"rule_name": "Prohibited Promissory Language (Keywords)",
"rule_ref": "FINRA 2210(d)(1)(B)",
"action": "replace",
"suggested_text": "Our fund has historically delivered returns, though past performance does not guarantee future results.",
"human_action": "Replace promissory language with compliant disclosure",
"confidence": 0.92
}
}
],
"fixes": [],
"fixes_group": {},
"metadata": {
"document_category": "retail_investor_letter"
}
}
{
"job_id": "abc123def456",
"status": "failed",
"started": "2026-01-08T10:30:00Z",
"timestamp": "2026-01-08T10:30:05Z",
"error": "Failed to parse document: Invalid PDF format"
}
Example
curl -X POST "https://{api-url}/api/validate_stream_result/" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"job_id": "abc123def456"}'
import requests
import time
API_KEY = "YOUR_API_KEY"
API_BASE = "https://{api-url}"
def get_results(job_id):
while True:
response = requests.post(
f"{API_BASE}/api/validate_stream_result/",
headers={
"x-api-key": API_KEY,
"Content-Type": "application/json"
},
json={"job_id": job_id}
)
result = response.json()
if result["status"] in ["done", "failed"]:
return result
time.sleep(2)
results = get_results("abc123def456")
print(results)
const axios = require('axios');
const API_KEY = 'YOUR_API_KEY';
const API_BASE = 'https://{api-url}';
async function getResults(jobId) {
while (true) {
const response = await axios.post(
`${API_BASE}/api/validate_stream_result/`,
{ job_id: jobId },
{
headers: {
'x-api-key': API_KEY,
'Content-Type': 'application/json'
}
}
);
if (['done', 'failed'].includes(response.data.status)) {
return response.data;
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
const results = await getResults('abc123def456');
console.log(results);
⌘I

