Agentic API
File a question, poll for a verdict, answer clarifications, read the outcome — the full machine loop for autonomous agents and headless callers.
VectorCourt is a bounded adversarial council: independent models argue a decision under pressure and a compressor collapses the result into a single structured verdict. This page documents the HTTP API an agent calls directly. There is no SDK to install — it is plain HTTP with a JSON body and one header.
POST /v1/submit a question → poll GET /v1/submissions/{id} until status: completed → read decision.outcome.kind to decide what to do. If the council needs input first, it asks; you answer with POST /v1/cases/{id}/clarify and keep polling.
Authentication
Send your key in the X-VC-Key header. Keys are issued per account (Pro and above). Submitting and answering clarifications require a key; polling a submission does not — the submission UUID is itself an unguessable capability, so an agent can hand the poll URL to another worker without sharing the key.
X-VC-Key: vc_your_key_here
If you exceed your plan's daily budget you get 429 with {"error":"daily_spend_limit","resets_at":"..."} — back off until resets_at or upgrade. See pricing.
1 — File a question
POST /v1/submit
Request body
| Field | Type | Notes | |
|---|---|---|---|
question | string | required | The decision to adjudicate. State the options and constraints; vague questions get vague verdicts. |
extended_deliberation | bool | optional | Opt into a larger reasoning budget (Pro/Enterprise). Slower, deeper. |
callback_url | string | optional | HTTPS URL notified on clarification_pending and finalized (see Webhooks). Requires a key. |
initial_leaning | string | optional | Your expected answer; the verdict reports how it diverged. |
include_patent_search | bool | optional | Search the patent / prior-art corpus for evidence. Runs automatically when the question is about patents, IP, prior art, freedom-to-operate, novelty, or infringement; set this to force it on for other questions. Premium — may add cost and latency. |
Optionally send an Idempotency-Key header (≤200 bytes) so a retried submit returns the same submission instead of filing twice.
Response — 202 Accepted
{
"submission_id": "3fc1c266-…",
"case_id": "9545b6b9-…",
"status": "queued",
"poll_url": "/v1/submissions/3fc1c266-…",
"verdict_url": "/v/9545b6b9-…",
"created_at": "2026-06-16T12:34:56Z"
}
curl
curl -sS -X POST https://vectorcourt.com/v1/submit \
-H "Content-Type: application/json" \
-H "X-VC-Key: $VC_KEY" \
-d '{"question":"Should a 15-person startup build its own auth or use Auth0/Clerk? Argue both sides.","extended_deliberation":true}'
2 — Poll for the verdict
GET /v1/submissions/{id}
Poll every few seconds. A verdict takes minutes — the council is really deliberating, not template-filling. Status moves through:
| status | meaning |
|---|---|
queued | accepted, waiting for a worker |
processing | the council is deliberating |
completed | verdict is ready in result.body |
failed | terminal error; error explains |
When completed, the verdict lives at result.body. The two fields an agent acts on:
{
"status": "completed",
"result": {
"body": {
"verdict_status": "full",
"one_liner": "Use Auth0 now; revisit only if SSO/compliance forces a build.",
"decision": {
"outcome": {
"kind": "answer",
"conditions": [],
"escalation": null,
"source": "proposed"
}
},
"cost": 0.79,
"duration_seconds": 327.9
}
}
}
3 — The outcome contract (read this)
Every finalized verdict carries a sealed tri-state outcome at decision.outcome.kind. This is the single field an agent branches on — it tells you whether you may act, act with caveats, or must wake a human.
outcome.conditions[] (each an assumption plus optional metric/threshold/window). Re-escalate if a condition breaks.outcome.escalation.trigger is one of authority_boundary, irreversibility, insufficient_evidence, scope_violation; detail explains why.The contract is guaranteed consistent: answer never carries conditions, answer_with_conditions always carries at least one, and escalate_to_human always carries an escalation reason. Branch on kind and you never have to parse prose.
3a — The North Star: are you asking the right question?
The outcome above answers what you asked. But a verdict can also tell you the question itself was the wrong one — and correctly answering the wrong question is the catastrophe. A single-model assistant answers inside the frame you hand it. The council, when the deliberation produces a strong counter-signal, answers and names the direction worth choosing next, with proof. In the verdict markdown this appears as a prominent ## North Star — block right after the decision; it fires on a wrong-target disambiguation, an inverted minority (a dissenter who outscored the winner), a surviving challenge to the question's premise, or a high-severity risk in a domain you never asked about. Most clean verdicts show none — its presence is the signal.
The machine-readable form is next_action in the agent view (GET /v1/submissions/{id}?view=agent), the server's conclusion folding quorum, quality, and run-time system pressure into one recommendation:
| next_action | What it means | What to do |
|---|---|---|
proceed | Quality gate passed; verdict binding. | Use it. |
proceed_with_conditions | Holds under stated conditions. | Use it, honor the conditions. |
escalate_to_human | The court escalated. | Surface to a person. |
rerun_degraded | Low quality because a seat dropped — an infrastructure failure, not the question's fault. | Re-file the same question. |
resend | Low quality under full quorum but high system pressure — plausibly transient. | Wait, then re-file the same question. |
reframe_question | Low quality under a full, unstressed court — an epistemic failure. The question is mis-posed; resending reproduces it. | Do not resend as-is. Reframe, or step back and ask what decision this actually serves. |
The load-bearing distinction is epistemic vs infrastructure failure: same symptom (low quality), opposite cause, opposite fix. The worst case is reframe_question with no directional counter-signal — a healthy, unstressed court (full quorum, low pressure) that produced low quality and could not even point at a better target. The verdict body still carries a North Star block here, but instead of naming a better direction it says step back before you re-ask: you are in the wrong place — reframe, do not retry. (So the North Star section is present, not absent; what is missing is a better target, not the block itself.)
4 — Answer a clarification
The council often needs a missing constraint before it can rule. When it does, the verdict's escalation.questions[] are populated (and a callback_url, if set, fires a clarification_pending event). The agent — not a human — is usually the right one to answer: it can ground the answer in the system the question is about.
POST /v1/cases/{case_id}/clarify (requires X-VC-Key; only the filing key or an admin may answer)
{
"answers": [
{ "question_id": "esc-q-1a2b…", "answer": "~50K QPS, multi-region, p99 budget 40ms", "confidence": "firm" }
]
}
Answer all pending questions in one call. confidence is firm, preferred, or uncertain. The case returns to deliberating and re-runs; keep polling the submission (or the case wait_url) until it finalizes. Answers are PII-scrubbed before they reach the council.
5 — Webhooks (optional)
Pass callback_url on submit to be pushed to instead of polling. VectorCourt POSTs a JSON body on clarification_pending and finalized:
{
"event": "finalized",
"case_id": "9545b6b9-…",
"status": "finalized",
"verdict_url": "/v/9545b6b9-…",
"verdict_status": "full",
"outcome": { "kind": "answer", "conditions": [], "source": "proposed" },
"sent_at": "2026-06-16T12:45:30Z"
}
Each callback is signed. Verify it before trusting it:
| header | value |
|---|---|
X-VectorCourt-Callback-Signature | v1=<hex> — HMAC-SHA256 over timestamp + "." + body, keyed by your API key |
X-VectorCourt-Callback-Timestamp | RFC3339 send time |
X-VectorCourt-Callback-Event | clarification_pending | finalized |
Callback URLs must be HTTPS and public (private/loopback IPs are rejected at dial time to prevent SSRF). Delivery retries on transient failure; respond 2xx to acknowledge.
A minimal agent loop
sid=$(curl -sS -X POST https://vectorcourt.com/v1/submit \
-H "X-VC-Key: $VC_KEY" -H "Content-Type: application/json" \
-d '{"question":"...","extended_deliberation":true}' | jq -r .submission_id)
while :; do
body=$(curl -sS https://vectorcourt.com/v1/submissions/$sid)
case "$(echo "$body" | jq -r .status)" in
completed) echo "$body" | jq '.result.body.decision.outcome'; break ;;
failed) echo "$body" | jq -r .error; break ;;
*) sleep 5 ;;
esac
done
Once you have outcome.kind: answer → proceed; answer_with_conditions → proceed and watch the conditions; escalate_to_human → hand off. That is the whole contract.