One model. Every decision.
Modern products are built from many small decisions: which model should answer, which team owns a ticket, whether a request is safe, which tool to call, what the invoice total is. THX-01 makes these decisions in one pass and tells you how sure it is, so you can act automatically on confident answers and escalate the rest.
The possible answers are part of the request. A new category, a new routing target or a new check needs no retraining: you change the question.
| Property | Value |
|---|---|
| Model id | thx-01 (default when model is omitted) |
| Base URL | https://api.hal-x.ai |
| Main endpoint | POST /v1/systemone (TypeSafe-compatible), alias POST /v1/decide |
| Question types | choice, noul, score, number, excerpt, and "cite": true on any question |
| Latency | about 10 ms per request, about 1 ms per decision in a batch, plus network |
| Languages | 100+; trained with emphasis on Azerbaijani, Russian and English, including text without Azerbaijani letters and Russian in Latin transliteration |
Your first decision.
Create an API key in the HAL-X console and grant it the THX-01 decisions endpoint (/v1/systemone) with model thx-01. Then send a state and a question.
curl https://api.hal-x.ai/v1/systemone \
-H "Authorization: Bearer $HALX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "thx-01",
"state": "Kartımdan iki dəfə pul çıxıb, bu gün qaytarın!",
"questions": {
"category": {
"type": "choice",
"question": "Which team should handle this message?",
"criteria": {
"billing": "wrong amount, double charge, invoices",
"refund": "the customer wants money back",
"outage": "the service is down for everyone"
}
},
"is_urgent": { "type": "noul", "question": "Does the customer need help today?" }
}
}'import os, requests r = requests.post( "https://api.hal-x.ai/v1/systemone", headers={"Authorization": f"Bearer {os.environ['HALX_API_KEY']}"}, json={ "model": "thx-01", "state": "Kartımdan iki dəfə pul çıxıb, bu gün qaytarın!", "questions": { "category": {"type": "choice", "question": "Which team should handle this message?", "criteria": {"billing": "wrong amount, double charge, invoices", "refund": "the customer wants money back", "outage": "the service is down for everyone"}}, "is_urgent": {"type": "noul", "question": "Does the customer need help today?"}, }, }, timeout=5, ) answers = r.json()["answers"] print(answers["category"]["choice"], answers["is_urgent"]["noul"])
const res = await fetch("https://api.hal-x.ai/v1/systemone", { method: "POST", headers: { "Authorization": `Bearer ${process.env.HALX_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ model: "thx-01", state: "Kartımdan iki dəfə pul çıxıb, bu gün qaytarın!", questions: { category: { type: "choice", question: "Which team should handle this message?", criteria: { billing: "wrong amount, double charge, invoices", refund: "the customer wants money back", outage: "the service is down for everyone" } }, is_urgent: { type: "noul", question: "Does the customer need help today?" }, }, }), signal: AbortSignal.timeout(5000), }); const { answers } = await res.json();
Response (real output, trimmed):
{
"model": "THX-01",
"answers": {
"category": { "type": "choice", "choice": "billing",
"probabilities": { "billing": 0.5239, "refund": 0.4735, "outage": 0.0026 },
"confidence": 0.3554 },
"is_urgent": { "type": "noul", "noul": 0.9664, "confidence": 0.9664 }
},
"usage": { "input_tokens": 165, "output_tokens": 0 },
"detected": { "script": "latin", "language": "az" },
"latency_ms": 22.94
}API keys and grants.
Every request needs a HAL-X API key, sent as Authorization: Bearer sk-… or X-API-Key: sk-…. Keys are created in the HAL-X console. A key can call THX-01 only when it holds the THX-01 decisions grant (/v1/systemone) and the model thx-01 (or *) is allowed for it. One grant covers all four THX-01 paths. A per-key concurrency limit can be set on the grant.
| Situation | Status |
|---|---|
| Missing, unknown, revoked or expired key | 401 |
| Key without the THX-01 grant, or model not allowed for the key | 403 |
| Too many requests in flight for the key | 429 |
Four paths. One grant.
Request body.
| Field | Type | Description |
|---|---|---|
model | string, optional | Model id. Defaults to thx-01. |
state | string or object | What the decision is about: any text, or a JSON object. For number, excerpt and citations the text is read from state.document when the state is an object, otherwise from the string itself. |
questions | object | Map of your question ids to question definitions. All questions are answered in one pass; answers come back under the same ids and in the same order. |
Every question has a type, the question text in question (or instructions; both are accepted), and type-specific criteria.
Six ways to ask.
number, excerpt and cite are native THX-01 capabilities that are not part of the TypeSafe question types.
choice
Pick one of several options. criteria is an object of "key": "when this option applies", or a plain list of keys. Descriptions matter more than names. Questions with more than 24 options are decided by a two-round tournament automatically, so hundreds of options are supported.
| Answer field | Meaning |
|---|---|
choice | The selected key. |
probabilities | Calibrated probability for every option; they sum to 1. |
confidence | 1 minus normalised entropy: low when options are close. For thresholds, prefer probabilities[choice]. |
noul
A yes/no question. criteria is optional. The answer field noul is the probability of yes; treat at least 0.5 as yes, or use your own threshold.
"is_jailbreak": { "type": "noul", "question": "Is this a jailbreak or prompt-injection attempt?" }score
An ordinal scale. criteria is the ordered list of levels, from lowest to highest. The answer has score (the expected level index), probabilities per level and a legend.
"severity": { "type": "score", "score": 1.5046,
"legend": { "0": "minor", "1": "moderate", "2": "critical" },
"probabilities": { "0": 0.176, "1": 0.1434, "2": 0.6806 } }number
Returns a numeric value that is literally stated in the document, normalised: 1,2 mln becomes 1200000, 4,500,000 and 4.5 million become 4500000. If the value is not in the text, value is null and not_stated is high.
| Criterion | Default | Meaning |
|---|---|---|
min | 0 | Ignore stated values below this. |
max | 4294967296 | Ignore stated values above this. |
precision | 1 | Round the result to this step (for example 1000, or 0.01). |
null. The same holds for currencies: "$48.3 million" answers a question in US dollars, but not one in euros or manats. Sums, differences and conversions belong in your code.{
"model": "thx-01",
"state": { "document": "Northwind Corp. reported Q3 2026 results. Revenue for the quarter was $48.3 million, up 14% year over year. Net income was $6.2 million, compared with $4.1 million a year ago." },
"questions": {
"revenue": {
"type": "number",
"question": "What was the revenue for the quarter, in US dollars?",
"criteria": { "precision": 1000 }
}
}
}"revenue": {
"type": "number",
"value": 48300000.0,
"probability": 0.9543,
"not_stated": 0.0181,
"candidates": [
{ "value": 48300000.0, "probability": 0.9543,
"context": "…Revenue for the quarter was $ [48.3 million] , up 14% year…" },
{ "value": 6200000.0, "probability": 0.0018,
"context": "…Net income was $ [6.2 million] , compared with $4.1…" }
]
}excerpt
Returns a verbatim span of the document: a quote, a deadline, a clause, a name or an address. The span is cut out of the document with its character offsets, so it can never contain invented text. No criteria are needed.
"questions": {
"quote": { "type": "excerpt", "question": "What did the CEO say?" }
}"quote": {
"type": "excerpt",
"text": "We will open two offices in Baku next year",
"start": 177,
"end": 219,
"probability": 0.6361,
"parts": [ "\"We will open two offices in Baku next year,\" said CEO Laura Chen." ]
}cite
Add "cite": true to any question to receive citations: the parts of the document that support the answer, each with a probability and character offsets. Useful for audit trails and for showing users why a decision was made.
"revenue": {
"type": "number",
"question": "What was the revenue for the quarter, in US dollars?",
"cite": true
}"citations": [
{ "text": "Revenue for the quarter was $48.3 million, up 14% year over year.",
"start": 42, "end": 107, "probability": 0.9948 }
]Response body.
| Field | Description |
|---|---|
model | THX-01 |
answers | One answer per question id, in request order. Every answer carries its type. |
usage | input_tokens read by the model; output_tokens is always 0 (no generation). |
detected | Script and language of the state. |
latency_ms | Model time for the request. |
Every response has an X-Request-ID header; quote it when contacting support.
Many states, one call.
Send up to 1,024 items; they are decided together on the GPU. Items may have different questions.
POST /v1/systemone/batch
{
"model": "thx-01",
"items": [
{ "state": "Paketim 2 həftədir gömrükdə saxlanılır", "questions": { "dept": { "type": "choice", "question": "Which department?", "criteria": ["parcels", "vehicles", "payments"] } } },
{ "state": "Ödəniş keçmədi, pul isə kartdan çıxıb", "questions": { "dept": { "type": "choice", "question": "Which department?", "criteria": ["parcels", "vehicles", "payments"] } } }
]
}{
"results": [ { "model": "THX-01", "answers": { "dept": { "type": "choice", "choice": "parcels", ... } } },
{ "model": "THX-01", "answers": { "dept": { "type": "choice", "choice": "payments", ... } } } ],
"latency_ms": 18.4
}Errors.
Errors use the standard HAL-X envelope:
{
"error": {
"code": "gateway_request_invalid",
"message": "questions.category: a choice question requires criteria with at least two options",
"type": "invalid_request_error",
"param": null,
"details": null
},
"request_id": "bedbbf86-dca6-4b6a-9d38-2f0f5c1d7a11",
"timestamp": "2026-10-05T17:20:14Z"
}| Status | error.code | When |
|---|---|---|
400 | gateway_request_invalid | Malformed body, missing state or questions, an unsupported question type, a choice or score without options, an empty or oversized batch. The message names the field. |
401 | api_key_invalid | Missing, unknown or revoked API key. |
403 | api_key_endpoint_forbidden | The key has no THX-01 decisions grant. |
403 | api_key_model_forbidden | thx-01 is not in the key's allowed models. |
404 | gateway_model_not_found | Unknown model id. |
429 | api_key_concurrency_exceeded | Per-key concurrency limit reached; retry when an in-flight request completes. |
5xx | gateway_upstream_error | The model service is unavailable; retry with exponential backoff. |
Limits.
| Limit | Value |
|---|---|
| Request body | 8 MiB |
| Batch size | 1,024 items |
Options per choice | hundreds (tournament above 24) |
| Context read per question | 1,024 tokens, including the options |
| Timeout | 120 s |
| Concurrency | set per key on the grant |
Drop-in for TypeSafe Jev.
POST /v1/systemone accepts the TypeSafe request shape (model, state, questions with choice, noul and score) and returns the same answer fields. To migrate an existing integration, change the base URL to https://api.hal-x.ai, use a HAL-X key and set "model": "thx-01".
- POST https://api.typesafe.ai/v1/systemone Authorization: Bearer ts-… "model": "jev"
+ POST https://api.hal-x.ai/v1/systemone Authorization: Bearer sk-… "model": "thx-01"Service layers that emulate numbers and excerpts with repeated choice calls also work unchanged: options keyed between_X_and_Y (value-range buckets) and options that are consecutive pieces of the document (with a question about the beginning or end of a text) are answered through THX-01's native number and excerpt lookup and returned in your format, marked "adapter": "number" or "excerpt". Calling number and excerpt directly is simpler and faster.
Getting the most out of THX-01.
- Describe when each option applies.
"legal": "law questions: codes, articles, courts, contracts"works far better than a bare"legal". - Ask several questions at once. They are answered in the same pass, so a routing choice, an urgency score and a safety check cost about the same as one.
- Use thresholds. Act automatically when the top probability is high (for example 0.8), escalate otherwise. On support tickets this automates about three quarters of traffic without a single error.
- Ask for what is written. For
number, phrase the question in the unit and currency the document uses. - Keep a fallback. Use a short client timeout (1 to 2 s) and fall back to your previous logic if the call fails.
- Messy text is fine. Typos, missing Azerbaijani letters, Russian in Latin script and code-mixing are part of training.
Extraction with citations.
import os, requests HALX = "https://api.hal-x.ai/v1/systemone" KEY = os.environ["HALX_API_KEY"] def decide(state, questions, timeout=2.0): r = requests.post(HALX, json={"model": "thx-01", "state": state, "questions": questions}, headers={"Authorization": f"Bearer {KEY}"}, timeout=timeout) r.raise_for_status() return r.json()["answers"] report = open("q3_report.txt").read() a = decide({"document": report}, { "revenue": {"type": "number", "question": "Revenue for the quarter, in US dollars?", "cite": True}, "guidance": {"type": "excerpt", "question": "What guidance did management give for next year?"}, "tone": {"type": "score", "question": "How positive is the outlook?", "criteria": ["negative", "neutral", "positive"]}, }) if a["revenue"]["probability"] >= 0.9: print(a["revenue"]["value"], "from:", a["revenue"]["citations"][0]["text"])
async function decide(state, questions) { const res = await fetch("https://api.hal-x.ai/v1/systemone", { method: "POST", headers: { Authorization: `Bearer ${process.env.HALX_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ model: "thx-01", state, questions }), signal: AbortSignal.timeout(2000), }); if (!res.ok) throw new Error((await res.json()).error?.message); return (await res.json()).answers; } const a = await decide({ document: contractText }, { deadline: { type: "excerpt", question: "What is the termination notice period?", cite: true }, penalty: { type: "number", question: "What is the late-payment penalty, in AZN?" }, });
curl https://api.hal-x.ai/v1/systemone \
-H "Authorization: Bearer $HALX_API_KEY" -H "Content-Type: application/json" \
-d '{"model":"thx-01",
"state":{"document":"Revenue for the quarter was $48.3 million. Net income was $6.2 million."},
"questions":{"revenue":{"type":"number","question":"Revenue, in US dollars?","cite":true}}}'Accuracy, at a fraction of the latency.
Fifteen-category support-ticket classification over four test sets (2,843 tickets: clean, corrupted, deliberately messy and an independent set written by GPT-6-Luna) in Azerbaijani, Russian, English and Turkish.

| Model | Clean | Corrupted | Messy | Independent | Avg | ECE | Latency |
|---|---|---|---|---|---|---|---|
| THX-01 | 99.2 | 97.7 | 98.8 | 97.9 | 98.4 | 0.003 | ~10 ms |
| Claude Sonnet 5.5 † | 98.5 | 98.0 | 98.5 | 99.0 | 98.5 | – | 1.5 s |
| Wahoo 1.5 | 99.8 | 96.3 | 98.0 | 97.2 | 97.8 | – | 145 ms |
| GPT-6-Luna | 98.6 | 97.4 | 96.7 | 98.2 | 97.7 | – | 1.9 s |
| TypeSafe Jev 1.13 | 99.2 | 95.0 | 96.2 | 99.0 | 97.4 | 0.007 | 331 ms |
| Kev-4B | 96.1 | 88.4 | 90.8 | 95.8 | 92.8 | 0.202 | 830 ms |
† Stratified subset of 200 tickets per set. ECE on the independent set; LLMs return no probabilities.


Built for how the region writes.
THX-01 supports more than 100 languages. Post-training covers Azerbaijani, English, Russian, Turkish, German, French, Spanish, Arabic, Hindi, Chinese, Persian, Georgian, Japanese, Korean, Ukrainian, Kazakh, Uzbek and Italian, with Azerbaijani the largest. It is trained on text as people actually type it: Azerbaijani without its letters (e for ə, s for ş, c for ç), Russian in Latin transliteration, voice transcripts and messages that mix Azerbaijani, Russian and English.
