Decisions
The full request and response contract for POST /api/v1/decisions.
Endpoint
POST https://jevmodel.io/api/v1/decisions
Content-Type: application/json
Authorization: Bearer sk-your-key-hereThe endpoint accepts one task at a time and returns one decision.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
input | string | yes | The text the decision is about. state is accepted as an alias for the same field. |
questions | array or object | yes | At least one question. See question types. |
task | string | no | A label for this call, used in your request history and in the credit ledger. Defaults to support_triage. |
schema | any | no | Accepted for forward compatibility. It is not applied to the decision today. |
{
"task": "lead_scoring",
"input": "We run a 40-person agency looking for a CRM with a REST API.",
"questions": [
{
"key": "fit",
"type": "score",
"prompt": "How strong is the account fit?",
"criteria": ["1", "2", "3", "4", "5"]
},
{
"key": "route",
"type": "choice",
"prompt": "Should this lead go to sales or nurture?",
"criteria": {
"sales": "Ready to talk to a salesperson",
"nurture": "Interested, but not ready yet"
}
}
]
}questions accepts two shapes, and both produce the same result:
{ "questions": [ { "key": "fit", "type": "score", "prompt": "..." } ] }{ "questions": { "fit": { "type": "score", "prompt": "..." } } }In the object form the property name is used as the question key.
Question types
Every question has a key (yours, echoed back in the response), a prompt that describes the judgement to make, and a type.
choice
The model picks exactly one of your labels. criteria is required and must be an object that maps each label to a short description of what it means.
{
"key": "route",
"type": "choice",
"prompt": "Should this lead go to sales or nurture?",
"criteria": {
"sales": "Ready to talk to a salesperson",
"nurture": "Interested, but not ready yet"
}
}The answer carries the chosen label in choice, the per-label probabilities, and a confidence.
score
The model returns a value from the range you define. criteria is required and must be an array — the values it may answer with.
{
"key": "fit",
"type": "score",
"prompt": "How strong is the account fit?",
"criteria": ["1", "2", "3", "4", "5"]
}The answer carries the numeric score, the legend that maps the numbers back to your values, the probabilities, and a confidence.
noul
The model estimates the probability that the input cannot be answered at all. noul questions take no criteria — any that you send are ignored.
{
"key": "answerable",
"type": "noul",
"prompt": "Can this be answered from the text alone?"
}The answer is a single number: the no-answer probability. It is also surfaced at the top level of the result as no_answer_probability.
A noul question never becomes the headline decision
decision prefers a labelled answer. If your request contains only a noul question, decision is the literal string noul and no confidence is returned, because the model produced none.Response
{
"code": 0,
"message": "ok",
"data": {
"id": "jev_1761234567890",
"object": "jev.decision",
"created": 1761234567,
"model": "jev-1.14",
"provider": "TypeSafe",
"upstream_id": "gen-1761234567-abc",
"upstream_model": "typesafe/jev-1.14-20261014",
"result": {
"decision": "sales",
"confidence": 0.88,
"reason": "Probabilities: {\"sales\":0.88,\"nurture\":0.12}",
"latency_ms": 1740,
"no_answer_probability": 0.04,
"answers": {
"fit": {
"type": "score",
"score": 4,
"legend": { "1": "1", "2": "2", "3": "3", "4": "4", "5": "5" },
"probabilities": { "1": 0.01, "2": 0.03, "3": 0.08, "4": 0.88, "5": 0 },
"confidence": 0.88
},
"route": {
"type": "choice",
"choice": "sales",
"probabilities": { "sales": 0.88, "nurture": 0.12 },
"confidence": 0.88
}
},
"source": "live",
"upstream_usage": {
"cost": 0.0004,
"input_tokens": 812,
"output_tokens": 96
}
},
"usage": {
"credits": 1,
"remaining_credits": 999,
"daily_remaining": 99,
"cost": 0.0004,
"input_tokens": 812,
"output_tokens": 96
}
}
}Top level
| Field | Description |
|---|---|
id | Identifier for this decision, in the form jev_<timestamp>. |
object | Always jev.decision. |
created | Unix timestamp in seconds. |
model | The Jev model that produced the decision, e.g. jev-1.14. |
provider | The upstream provider, e.g. TypeSafe. |
upstream_id | The upstream request id, for support and traceability. |
upstream_model | The exact upstream model build. |
result
| Field | Description |
|---|---|
decision | The primary decision: the chosen label, the score, or noul. |
confidence | Confidence reported by the model. Omitted when the model reports none. |
reason | A short human-readable explanation of the decision. |
latency_ms | How long the decision took, in milliseconds. |
no_answer_probability | The no-answer probability, when the request contained a noul question. |
answers | The full answer set, keyed by your question keys. |
source | Always live for calls served by the API. |
upstream_usage | Cost and token accounting reported by the upstream. |
usage
| Field | Description |
|---|---|
credits | Credits this call consumed. Always 1. |
remaining_credits | Credits left on the account after the call. |
daily_remaining | Decisions left in today's allowance. Only present while you are on the gifted credits. |
cost | Upstream cost in USD, when the provider reports it. |
input_tokens / output_tokens | Upstream token accounting. |
Validation rules
The API validates the request before it spends anything, and the messages are meant to be read literally:
questionsmust contain at least one question.- Every question needs a
prompt(orinstructions). - A
choicequestion needs a non-emptycriteriaobject. - A
scorequestion needs a non-emptycriteriaarray. - A
noulquestion ignorescriteria— anything you send there is dropped before the call is made. typemust be one ofchoice,score,noul.
A request that breaks one of these rules returns 400 and is not billed.