API Reference
POST /v1/systemone — one forward pass returns a structured decision. No generation, no hallucination.
Endpoint Overview
ENDPOINTOne endpoint, one forward pass: the request carries a task primitive and text, and the service returns the argmax decision, probability distribution, and calibrated confidence — with no free-form text generated.
| Item | Value |
|---|---|
| Method | POST |
| Path | /v1/systemone |
| Public endpoint | https://api.unfork.ai/v1/systemone |
| Content-Type | application/json |
| Auth | The public evaluation endpoint needs no auth; private deployments can add an intranet gateway or gateway key |
| Interface | Native systemone interface; an OpenAI-compatible wrapper is also provided for drop-in replacement |
| Determinism | Same input, same output; no sampling, no stochastic decoding, fully auditable |
Primitive Interfaces
PRIMITIVESSwitch primitives via the task field: use choice for multiple-choice, score for ordered scoring, and noul for open judgment without preset options. All three share one endpoint and the same response shape.
Multiple-choice over a candidate set: returns option probabilities and the argmax decision.
Ordered scoring: returns numerical scores and distribution over buckets.
Open judgment without preset choices: returns label confidence probabilities.
Request Parameters
REQUESTThe request body is a JSON object. Besides task and text, choice requires candidates; score / noul take candidates or labels as defined by the task.
| Field | Type | Required | Description |
|---|---|---|---|
| task | string | Yes | Task primitive: choice / score / noul |
| text | string | Yes | Raw text input to decide on, effective length ≤ 896 tokens |
| candidates | string[] | Conditional | Candidate array; required for choice, optional labels for score |
Response Fields
The response body is a JSON object; everything is a structured number or label with no free text, ready for persistence and audit.
| Field | Type | Description |
|---|---|---|
| decision | string | Returns: argmax decision (a candidate or label) |
| probabilities | number[] | Returns: normalized probability distribution over candidates / buckets (100% structured) |
| calibrated_confidence | number | Returns: temperature-calibrated confidence (0–1); 0.85 recommended as the human-routing threshold |
| latency_ms | number | Returns (optional): latency of this decision, for observability |
All fields are deterministic outputs; route low-confidence requests to human triage.
Call Examples
EXAMPLESThree common client patterns. Point ENDPOINT at the public endpoint or your private intranet address — the request and response shapes are identical.
bashcurl -X POST https://api.unfork.ai/v1/systemone \
-H "Content-Type: application/json" \
-d '{
"task": "choice",
"text": "Refund request is 3 days overdue, but credit history is excellent. Approve automatically?",
"candidates": ["approve", "reject", "escalate_to_human"]
}'
pythonimport requests
ENDPOINT = "https://api.unfork.ai/v1/systemone"
def decide(text, candidates, threshold=0.85):
res = requests.post(ENDPOINT, json={
"task": "choice",
"text": text,
"candidates": candidates,
}, timeout=12).json()
decision = res["decision"]
confidence = res["calibrated_confidence"]
probs = res.get("probabilities", [])
# Low confidence → escalate to human; high confidence → execute directly
if confidence < threshold:
return {"route": "human_review", "reason": "low_calibrated_conf",
"confidence": confidence, "probs": probs}
return {"route": "execute", "decision": decision, "confidence": confidence}
print(decide("Large withdrawal request from an unusual location",
["allow", "challenge_otp", "block_and_alert"]))
javascriptconst ENDPOINT =
"https://api.unfork.ai/v1/systemone";
async function decide(text, candidates) {
const res = await fetch(ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ task: "choice", text, candidates }),
});
if (!res.ok) throw new Error(`decide failed: ${res.status}`);
const data = await res.json();
return { decision: data.decision, confidence: data.calibrated_confidence };
}
// Batch concurrency: each text is decided independently; results can go straight into the audit table
const texts = ["Ticket A content", "Ticket B content", "Ticket C content"];
const results = await Promise.all(
texts.map((t) => decide(t, ["route_billing", "route_tech", "escalate"]))
);
console.log(results);
Set a 12-second timeout and a retry cap per request; if the endpoint is unavailable, degrade by business criticality (e.g. route to a human or use a cached decision).
Primitive Request / Response Examples
PAYLOADSjson{
"task": "choice",
"text": "Refund request is 3 days overdue, but credit history is excellent. Approve automatically?",
"candidates": ["approve", "reject", "escalate_to_human"]
}
json{
"decision": "approve",
"probabilities": [0.91, 0.04, 0.05],
"calibrated_confidence": 0.91,
"latency_ms": 31
}
json{
"task": "score",
"text": "The support agent was accurate, friendly, and resolved the issue on the first try.",
"candidates": ["1 star", "2 stars", "3 stars", "4 stars", "5 stars"]
}
json{
"decision": "5-star",
"probabilities": [0.01, 0.01, 0.04, 0.19, 0.75],
"calibrated_confidence": 0.93,
"latency_ms": 28
}
json{
"task": "noul",
"text": "This is an urgent!!! reminder to verify your account at http://x.co",
"candidates": ["spam", "legit", "unknown"]
}
json{
"decision": "spam",
"probabilities": [0.95, 0.03, 0.02],
"calibrated_confidence": 0.95,
"latency_ms": 26
}
score / noul share the same response shape as choice: decision returns the top bucket or label, probabilities holds the bucket probabilities, and calibrated_confidence is the calibrated score.
Status Codes & Errors
ERRORSStandard HTTP status codes are used; on failure a JSON error object is returned with an error field describing the cause, making unified client handling straightforward.
| Status | Meaning | Description |
|---|---|---|
| 200 | Success | Returns decision / probabilities / calibrated_confidence |
| 400 | Invalid request | Illegal task value, or choice without candidates |
| 413 | Text too long | Exceeds the 896-token effective context; split first |
| 429 | Rate limited | Too many requests; retry with exponential backoff |
| 500 | Server error | Internal inference error; safe to retry (idempotent) |
| 503 | Unavailable | Endpoint under maintenance or overloaded; consider degrading to human or a cached decision |
json{
"error": "invalid_candidates",
"message": "choice primitive requires at least 2 candidates",
"status": 400
}
Confidence Routing Guidance
Use calibrated_confidence for single- or dual-threshold routing: execute at high confidence, escalate at low confidence to System 2 or a human, and sample-review the middle band.
| Confidence range | Recommended action |
|---|---|
| ≥ 0.85 | Execute the decision directly; enter routine audit sampling |
| 0.60 – 0.85 | Execute but flag; sample a proportion for human review |
| < 0.60 | Escalate to a System 2 reasoning model or a human; do not auto-execute |
Calibrate thresholds against business risk and human cost; public benchmarks show good calibration, so 0.85 is a sensible general starting point.