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-here

The endpoint accepts one task at a time and returns one decision.

Request body

FieldTypeRequiredDescription
inputstringyesThe text the decision is about. state is accepted as an alias for the same field.
questionsarray or objectyesAt least one question. See question types.
taskstringnoA label for this call, used in your request history and in the credit ledger. Defaults to support_triage.
schemaanynoAccepted 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

The top-level 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

FieldDescription
idIdentifier for this decision, in the form jev_<timestamp>.
objectAlways jev.decision.
createdUnix timestamp in seconds.
modelThe Jev model that produced the decision, e.g. jev-1.14.
providerThe upstream provider, e.g. TypeSafe.
upstream_idThe upstream request id, for support and traceability.
upstream_modelThe exact upstream model build.

result

FieldDescription
decisionThe primary decision: the chosen label, the score, or noul.
confidenceConfidence reported by the model. Omitted when the model reports none.
reasonA short human-readable explanation of the decision.
latency_msHow long the decision took, in milliseconds.
no_answer_probabilityThe no-answer probability, when the request contained a noul question.
answersThe full answer set, keyed by your question keys.
sourceAlways live for calls served by the API.
upstream_usageCost and token accounting reported by the upstream.

usage

FieldDescription
creditsCredits this call consumed. Always 1.
remaining_creditsCredits left on the account after the call.
daily_remainingDecisions left in today's allowance. Only present while you are on the gifted credits.
costUpstream cost in USD, when the provider reports it.
input_tokens / output_tokensUpstream token accounting.

Validation rules

The API validates the request before it spends anything, and the messages are meant to be read literally:

  • questions must contain at least one question.
  • Every question needs a prompt (or instructions).
  • A choice question needs a non-empty criteria object.
  • A score question needs a non-empty criteria array.
  • A noul question ignores criteria — anything you send there is dropped before the call is made.
  • type must be one of choice, score, noul.

A request that breaks one of these rules returns 400 and is not billed.