Send the labels your process already uses
A classification request carries text (3–6,000 characters), instructions (3–1,500 characters), 2–12 unique labels of up to 60 characters each on one line, and a threshold between 0.5 and 1 that defaults to 0.85. The labels are the answer domain: an answer that names anything else is refused as a provider error instead of reaching your pipeline.
Two labels that always lead to the same action are one label. Add an other or an unclear outcome when a message can fall outside your categories, so text that fits nothing still has an honest destination rather than being pushed into the nearest queue.
curl https://jevapi.pro/api/v1/decisions \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: doc-8841-v1' \
-d '{
"text": "Invoice INV-2291 is still unpaid. Please send a copy with the tax breakdown.",
"instructions": "Choose the document this message asks for.",
"labels": ["invoice", "contract", "receipt", "other"],
"threshold": 0.85
}'One request can ask up to four typed questions
The same endpoint accepts typed questions instead of one label list: one to four questions, each with an id, a type and its criteria. A choice question takes 2–12 criteria labels, a noul question takes true and false criteria, and a score question takes 2–7 ordered levels. A body that carries both questions and instructions or labels is refused with 400 ambiguous_input, because one request cannot be two.
Every answer returns under the id you sent: a choice with its label and probabilities, a noul with a probability between 0 and 1, a score with its position on your rubric. The top-level choice, confidence and probabilities mirror the first question, and needsReview is true when any answer needs review, so one field can hold the whole response. One request costs one credit whether it asks a single label or four typed questions; a failed account request is refunded, and a replay of the same idempotency key is not charged again.
{
"text": "My checkout page shows a blank screen after I click Pay. I tried two browsers.",
"questions": [
{"id": "team", "type": "choice", "instructions": "Which team should own this ticket?", "criteria": {"billing": "Charges or refunds.", "technical": "Errors or broken behaviour.", "account": "Sign-in, permissions or profile."}},
{"id": "is_bug", "type": "noul", "instructions": "Is the writer reporting a defect?", "criteria": {"true": "They describe broken behaviour.", "false": "They ask a question or request a feature."}},
{"id": "urgency", "type": "score", "instructions": "How urgently does this need an answer?", "criteria": ["Can wait", "This week", "Blocking work"]}
],
"threshold": 0.85
}LLM as a judge: typed rules you can audit · Batch classification and exports
Read the answer as evidence, not as certainty
Probabilities are checked for domain and bounds only. The API promises neither a sum of one nor an answer that agrees with the largest probability, and a missing map is returned as an empty object rather than filled in. confidence is null when the model omits it, and needsReview is true in that case.
A model failure is an error response, never a default label: a 502 or 503 returns the credit and leaves no decision behind. Test negation, quoted text, several requests in one message, and instructions written inside the text you classify — the message is evidence, not a task. Then count errors on a held-out set you labeled yourself, because a provider’s published benchmark says nothing about your data.
Evaluate classification before automating work · Error codes and bounded retries