Get Verdict
curl --request GET \
--url https://api.zerodrift.ai/api/v3/jobs/{job_id} \
--header 'x-api-key: <api-key>'import requests
url = "https://api.zerodrift.ai/api/v3/jobs/{job_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.zerodrift.ai/api/v3/jobs/{job_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.zerodrift.ai/api/v3/jobs/{job_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.zerodrift.ai/api/v3/jobs/{job_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.zerodrift.ai/api/v3/jobs/{job_id}")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zerodrift.ai/api/v3/jobs/{job_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{
"api_version": "v3",
"job_id": "a1b2c3",
"status": "processing",
"mode": "async",
"submitted_at": "2026-09-23T04:44:13.879781+00:00",
"model_engine": "anchor_3_0",
"progress": { "step": "score" }
}
{
"api_version": "v3",
"job_id": "a1b2c3",
"status": "completed",
"mode": "async",
"submitted_at": "2026-09-23T04:44:13.879781+00:00",
"model_engine": "anchor_3_0",
"applied_validation_scope": {
"source": "request",
"rules_count": 235
},
"result": {
"overall_status": "needs_changes",
"summary": {
"do_not_send": 0,
"send_with_caution": 1,
"document_pages": 1
},
"revalidation_recommended": false,
"relevant_rule_ids": ["guarantee_of_returns"],
"units": 1,
"cost": {
"currency": "USD",
"amount": "0.01"
},
"violations": [
{
"rule_id": "guarantee_of_returns",
"signal_name": "Guarantees of returns",
"rule_type": "SLM_SIGNAL",
"severity": "send_with_caution",
"confidence": "high",
"quote": "Our fund guarantees 18% returns with no downside risk.",
"fix": {
"action": "replace",
"suggested_text": "Returns are not guaranteed and involve risk."
}
}
]
},
"extracted_text": null
}
{
"api_version": "v3",
"job_id": "mini123",
"status": "completed",
"mode": "async",
"submitted_at": "2026-09-23T04:44:13.879781+00:00",
"model_engine": "anchor_3_0_mini",
"result": {
"overall_status": "needs_changes",
"summary": {
"do_not_send": 0,
"send_with_caution": 1,
"document_pages": 1
},
"revalidation_recommended": false,
"flagged_rules": [
{
"rule_id": "guarantee_of_returns",
"signal_name": "Guarantees of returns",
"rule_type": "SLM_SIGNAL",
"rule_pack_id": "zd-us-securities",
"rule_pack_name": "US Securities",
"severity": "send_with_caution",
"confidence": "high",
"p": 0.94
}
],
"any_violation_detected": true,
"any_violation_p": 0.97,
"units": 1,
"cost": {
"currency": "USD",
"amount": "0.002"
}
},
"extracted_text": null
}
{
"api_version": "v3",
"job_id": "a1b2c3",
"status": "failed",
"mode": "async",
"submitted_at": "2026-09-23T04:44:13.879781+00:00",
"model_engine": "anchor_3_0",
"error": "Validation engine unavailable"
}
Enforce
Get Verdict
Retrieve the verdict for an enforcement job.
GET
/
api
/
v3
/
jobs
/
{job_id}
Get Verdict
curl --request GET \
--url https://api.zerodrift.ai/api/v3/jobs/{job_id} \
--header 'x-api-key: <api-key>'import requests
url = "https://api.zerodrift.ai/api/v3/jobs/{job_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.zerodrift.ai/api/v3/jobs/{job_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.zerodrift.ai/api/v3/jobs/{job_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.zerodrift.ai/api/v3/jobs/{job_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.zerodrift.ai/api/v3/jobs/{job_id}")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zerodrift.ai/api/v3/jobs/{job_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{
"api_version": "v3",
"job_id": "a1b2c3",
"status": "processing",
"mode": "async",
"submitted_at": "2026-09-23T04:44:13.879781+00:00",
"model_engine": "anchor_3_0",
"progress": { "step": "score" }
}
{
"api_version": "v3",
"job_id": "a1b2c3",
"status": "completed",
"mode": "async",
"submitted_at": "2026-09-23T04:44:13.879781+00:00",
"model_engine": "anchor_3_0",
"applied_validation_scope": {
"source": "request",
"rules_count": 235
},
"result": {
"overall_status": "needs_changes",
"summary": {
"do_not_send": 0,
"send_with_caution": 1,
"document_pages": 1
},
"revalidation_recommended": false,
"relevant_rule_ids": ["guarantee_of_returns"],
"units": 1,
"cost": {
"currency": "USD",
"amount": "0.01"
},
"violations": [
{
"rule_id": "guarantee_of_returns",
"signal_name": "Guarantees of returns",
"rule_type": "SLM_SIGNAL",
"severity": "send_with_caution",
"confidence": "high",
"quote": "Our fund guarantees 18% returns with no downside risk.",
"fix": {
"action": "replace",
"suggested_text": "Returns are not guaranteed and involve risk."
}
}
]
},
"extracted_text": null
}
{
"api_version": "v3",
"job_id": "mini123",
"status": "completed",
"mode": "async",
"submitted_at": "2026-09-23T04:44:13.879781+00:00",
"model_engine": "anchor_3_0_mini",
"result": {
"overall_status": "needs_changes",
"summary": {
"do_not_send": 0,
"send_with_caution": 1,
"document_pages": 1
},
"revalidation_recommended": false,
"flagged_rules": [
{
"rule_id": "guarantee_of_returns",
"signal_name": "Guarantees of returns",
"rule_type": "SLM_SIGNAL",
"rule_pack_id": "zd-us-securities",
"rule_pack_name": "US Securities",
"severity": "send_with_caution",
"confidence": "high",
"p": 0.94
}
],
"any_violation_detected": true,
"any_violation_p": 0.97,
"units": 1,
"cost": {
"currency": "USD",
"amount": "0.002"
}
},
"extracted_text": null
}
{
"api_version": "v3",
"job_id": "a1b2c3",
"status": "failed",
"mode": "async",
"submitted_at": "2026-09-23T04:44:13.879781+00:00",
"model_engine": "anchor_3_0",
"error": "Validation engine unavailable"
}
Retrieve the verdict for an enforcement job started via
Enforce Content. Poll this
endpoint until
status is completed or failed.
Sync responses and polled async responses use the same envelope. Completed
jobs nest the verdict under result; the async envelope reports
mode: "async". Public responses report billed result.units and
result.cost, not raw input/output token counts.
Path Parameters
string
required
The
job_id returned by
Enforce Content.Response
string
Always
v3.string
Unique identifier for the enforcement job.
string
Job status:
queued, processing, completed, or failed.string
async for a polled job.string
Time when the job was submitted.
string
Requested engine after explicit custom-rule routing:
anchor_3_0_mini (Mini), anchor_3_0 (Flagship), or
anchor_3_0_max (Max). A scope-less Flagship request stays on Flagship.
See Choose a model.string
Present when a Flagship request explicitly named custom rule text or a
cust_* rule and was upgraded to Max.string
Engine the job fell back to when Max could not complete the request.
string
Why fallback ran (for example
client_error). Present with fallback_engine.object
The enforced scope as
source plus rule, rulepack, or import counts. Full
rule ID lists are not echoed in HTTP responses.string
Error details (present only when
status is failed).object
Verdict payload on completed jobs. Fields below are nested inside this
object.
string
Overall compliance assessment:
approved, needs_changes, or
do not send; trained adapters can also return send with caution.
do not send contains spaces. This is the verdict: approved = Pass,
needs_changes = Fix, and do not send = Block.object
integer
Number of lines with at least one compliance violation. Absent for older
jobs or when only grouped fixes exist (per-line positions unavailable).
integer
Number of lines with no violations. Absent for older jobs or when only
grouped fixes exist.
integer
Total number of lines in the document. Absent for older jobs or when only
grouped fixes exist.
boolean
True when more than one fix is found, suggesting a re-scan after applying
fixes.
array
Rule IDs the Anchor 3.0 SLM identified as relevant to the content (the
per-request evaluated rule set).
integer
Billed validation units: zero when no input tokens were consumed, otherwise
the ceiling of input tokens divided by 2,000.
object
Billed list price with
currency: "USD" and decimal-string amount.array
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 line violation properties
Show line violation properties
integer
1-indexed line number in the document
string
The text content of the violating line (trimmed)
integer
Character offset of the best fix’s original text start
integer
Character offset of the best fix’s original text end
integer
Page number where the violation appears
integer
Number of distinct rules violated on this line
array
All rules violated on this line, sorted by severity then confidence.
Each entry carries
rule_id (canonical rule identifier — rule-pack id,
or cust_{customer_id}_{id} for activated custom rules), rule_name,
rule_ref (regulatory citation, e.g. FINRA 2210(d)(1)(B)), severity
(do_not_send or send_with_caution), confidence (0–1), and action
(replace, insert_after, remove, or warning).object
The recommended fix for this line (from the highest-severity,
highest-confidence rule):
severity, rule_id, rule_name, rule_ref,
action, suggested_text (null when action is remove/warning),
human_action, and confidence. Max does not rewrite: on a Max job
suggested_text carries the rule’s own fix note when it has one and is
otherwise null or empty. See Choose a model.array
Individual fix entries (rule-centric, one per violation per quote). Each
entry carries
rule_id — the canonical rule identifier (rule-pack id, or
cust_{customer_id}_{id} for activated custom rules).object
Grouped fixes for rules that aggregate across pages. Each value additionally
carries
rule_id (the canonical rule identifier — also the key under which
the group is stored in this object).array
Mini’s whole-message per-rule verdicts. Each entry includes
rule_id,
signal_name, severity, confidence, and probability p. Mini returns
this instead of per-line violations.boolean
Mini’s independent whole-message violation head. It can be true even when
flagged_rules is empty.number
Probability behind
any_violation_detected (Mini only).object
Document metadata submitted with the request.
Status Values
| Status | Description |
|---|---|
queued | Async job accepted |
processing | Enforcement in progress |
completed | Success; verdict is under result |
failed | Enforcement failed with error |
Error Responses
| Status | Description |
|---|---|
| 403 | Forbidden — missing, invalid, inactive, or unresolved API key |
| 404 | Job Not Found |
{
"api_version": "v3",
"job_id": "a1b2c3",
"status": "processing",
"mode": "async",
"submitted_at": "2026-09-23T04:44:13.879781+00:00",
"model_engine": "anchor_3_0",
"progress": { "step": "score" }
}
{
"api_version": "v3",
"job_id": "a1b2c3",
"status": "completed",
"mode": "async",
"submitted_at": "2026-09-23T04:44:13.879781+00:00",
"model_engine": "anchor_3_0",
"applied_validation_scope": {
"source": "request",
"rules_count": 235
},
"result": {
"overall_status": "needs_changes",
"summary": {
"do_not_send": 0,
"send_with_caution": 1,
"document_pages": 1
},
"revalidation_recommended": false,
"relevant_rule_ids": ["guarantee_of_returns"],
"units": 1,
"cost": {
"currency": "USD",
"amount": "0.01"
},
"violations": [
{
"rule_id": "guarantee_of_returns",
"signal_name": "Guarantees of returns",
"rule_type": "SLM_SIGNAL",
"severity": "send_with_caution",
"confidence": "high",
"quote": "Our fund guarantees 18% returns with no downside risk.",
"fix": {
"action": "replace",
"suggested_text": "Returns are not guaranteed and involve risk."
}
}
]
},
"extracted_text": null
}
{
"api_version": "v3",
"job_id": "mini123",
"status": "completed",
"mode": "async",
"submitted_at": "2026-09-23T04:44:13.879781+00:00",
"model_engine": "anchor_3_0_mini",
"result": {
"overall_status": "needs_changes",
"summary": {
"do_not_send": 0,
"send_with_caution": 1,
"document_pages": 1
},
"revalidation_recommended": false,
"flagged_rules": [
{
"rule_id": "guarantee_of_returns",
"signal_name": "Guarantees of returns",
"rule_type": "SLM_SIGNAL",
"rule_pack_id": "zd-us-securities",
"rule_pack_name": "US Securities",
"severity": "send_with_caution",
"confidence": "high",
"p": 0.94
}
],
"any_violation_detected": true,
"any_violation_p": 0.97,
"units": 1,
"cost": {
"currency": "USD",
"amount": "0.002"
}
},
"extracted_text": null
}
{
"api_version": "v3",
"job_id": "a1b2c3",
"status": "failed",
"mode": "async",
"submitted_at": "2026-09-23T04:44:13.879781+00:00",
"model_engine": "anchor_3_0",
"error": "Validation engine unavailable"
}
Example
Poll until the job iscompleted or failed. The Python and JavaScript samples wait
2 seconds between requests; the cURL sample is a single GET you repeat yourself.
curl "https://api.zerodrift.ai/api/v3/jobs/a1b2c3" \
-H "x-api-key: $ZERODRIFT_API_KEY"
import os
import requests
import time
API_BASE = "https://api.zerodrift.ai"
def get_results(job_id):
while True:
response = requests.get(
f"{API_BASE}/api/v3/jobs/{job_id}",
headers={"x-api-key": os.environ["ZERODRIFT_API_KEY"]}
)
result = response.json()
if result["status"] in ("completed", "failed"):
return result
time.sleep(2)
results = get_results("a1b2c3")
print(results)
const axios = require('axios');
const API_BASE = 'https://api.zerodrift.ai';
async function getResults(jobId) {
while (true) {
const response = await axios.get(
`${API_BASE}/api/v3/jobs/${jobId}`,
{ headers: { 'x-api-key': process.env.ZERODRIFT_API_KEY } }
);
if (['completed', 'failed'].includes(response.data.status)) {
return response.data;
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
const results = await getResults('a1b2c3');
console.log(results);

