Overview
Jev evaluates one state — a support ticket, a chat log, a tool call, any text or JSON you pass — against a set of typed questions, and returns structured answers your code can branch on. It does not generate text.
One request can ask up to 8 questions; they are evaluated together and share the state input cost. The request body is the same shape TypeSafe’s SystemOne API accepts — to move a working integration, swap the base URL and the Bearer key.
- POST
https://jevmodel.org/v1/systemone— the single decision endpoint. - CORS is open (
access-control-allow-origin: *), so the endpoint answers from any origin. Keep your key on a server anyway. - The playground sends the identical request shape through your browser session — what you preview there is what you send.
Authentication
Every API call needs a jevmodel.org API key. Create one in Dashboard → API keys; keys start with sk- and are shown once at creation. Store it as an environment variable, for example JEVMODEL_API_KEY.
Authorization: Bearer $JEVMODEL_API_KEY Keys belong to your account’s token balance and can be revoked from the dashboard. Never ship a key in client-side code or commit it to a repository — if a key leaks, revoke it and mint a new one. The playground authenticates with your signed-in browser session instead and does not need a key.
HTTP endpoint
Send a JSON body to the evaluation endpoint with Bearer authentication:
POST /v1/systemone HTTP/1.1
Host: jevmodel.org
Authorization: Bearer $JEVMODEL_API_KEY
Content-Type: application/json
Idempotency-Key: ticket-4821-run-1 # optional Idempotency-Key is optional (up to 100 characters). Retries sent with the same key reuse the original billing record, so a retried request cannot be charged twice for the same input.
curl -X POST https://jevmodel.org/v1/systemone \
-H "Authorization: Bearer $JEVMODEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "jev-latest",
"state": "The customer has been billed twice and wants a refund today.",
"questions": {
"route": {
"type": "choice",
"instructions": "Which queue should own this ticket?",
"criteria": {
"billing": "Payments, refunds, invoices",
"technical": "Product errors and usage problems",
"sales": "Pricing, upgrades, new business"
}
},
"escalate": {
"type": "noul",
"instructions": "Does this need a human right now?"
},
"urgency": {
"type": "score",
"instructions": "How urgent is this for the customer?",
"criteria": ["routine", "soon", "urgent", "critical"]
}
}
}' Request body
One JSON object with a state and a map of questions:
{
"model": "jev-latest",
"state": "The customer has been billed twice and wants a refund today.",
"questions": {
"route": {
"type": "choice",
"instructions": "Which queue should own this ticket?",
"criteria": {
"billing": "Payments, refunds, invoices",
"technical": "Product errors and usage problems",
"sales": "Pricing, upgrades, new business"
}
},
"escalate": {
"type": "noul",
"instructions": "Does this need a human right now?"
},
"urgency": {
"type": "score",
"instructions": "How urgent is this for the customer?",
"criteria": ["routine", "soon", "urgent", "critical"]
}
}
} | Field | Type | Notes |
|---|---|---|
model | string | Optional; defaults to jev-latest. |
state | string, object, or array | Required. Serialized form is limited to 1,000,000 characters. |
questions | object | Required map of 1–8 question names to typed definitions. Names are identifiers: letters, digits, and _, at most 64 characters. |
assets | object | Optional (experimental). Up to 4 PNG/JPEG images, each keyed by a reference you write inside state, instructions, or criteria. See Images & Box. |
Each question needs a type and instructions (up to 1,800 characters) telling the model what to decide. criteria supplies the answer space — required for choice and score, optional for noul.
Question types
Choose the answer shape your application can act on.
| Type | Criteria | Answer |
|---|---|---|
noul | Optional true / false label descriptions. | noul — the probability of yes, from 0 to 1. |
choice | Object of 2–20 option keys mapped to descriptions. | Selected choice, a probabilities map, and confidence. |
score | Ordered array of 2–10 levels. | Numeric score (may be fractional) and confidence. |
box | Not used — instructions only. | box with normalized edges (top/bottom/left/right, 0–1) and confidence. Experimental; needs jev-preview. |
Serialized criteria are limited to 2,000 characters per question. Validation failures return 422 before any tokens are reserved — bad requests are never billed.
Images and Box (experimental)
Jev 1.14 accepts PNG and JPEG images as decision input — image understanding, not generation. Attach each image in assets under a reference name, then write that reference inside state, a question’s instructions, or criteria; the reference resolves to the image at that position. Image and Box requests need the preview model — set model to jev-preview.
{
"model": "jev-preview",
"state": "Shipment photo attached as img-1.",
"assets": {
"img-1": { "type": "image", "format": "jpg", "data_base64": "/9j/4AAQSkZJRg…" }
},
"questions": {
"damage_visible": {
"type": "noul",
"instructions": "Is there visible damage to the package in img-1?"
},
"damage_region": {
"type": "box",
"instructions": "Locate the damaged area in img-1"
}
}
} assetsmaps a reference to{ "type": "image", "format": "png|jpg", "data_base64": "…" }— at most 4 images, ~4 MB each after encoding.- Every asset must be referenced, and every use is billed — images count toward
usage.input_tokensexactly like text. boxtakes onlyinstructionsand always returns a box — pair it with a noul like “is X visible” when the target might be absent.- This is an opt-in experimental surface: the proxy applies the upstream opt-in header automatically when a request carries assets or a box question. Multipart uploads are not supported — send base64.
Audio and video are still unsupported — convert them to text or structured data first.
Response JSON
A 200 response is the model output itself: the resolved model, one answer per question name, and usage. The values below are illustrative — run the request for real output.
{
"model": "jev-latest",
"answers": {
"route": {
"type": "choice",
"choice": "billing",
"probabilities": { "billing": 0.93, "technical": 0.05, "sales": 0.02 },
"confidence": 0.93
},
"escalate": {
"type": "noul",
"noul": 0.12
},
"urgency": {
"type": "score",
"score": 1.4,
"confidence": 0.88
}
},
"usage": { "input_tokens": 136, "output_tokens": 18 }
} answersis keyed by your question names — you read the fields you asked for.- For
choice, branch on the selected label and inspectprobabilitieswhen you need the full distribution. noulis P(yes) — your code picks the action threshold.usage.input_tokensis what this call actually billed; output tokens are free.
Billing
The API bills input tokens only — output is free. Each call is charged the actual usage.input_tokens the model reports. On free tokens an estimate is reserved up front and then settled to that figure. If Jev fails upstream, nothing is charged.
- Sign in once and get 100,000 input tokens free; paid packs start at $9.90 and never expire.
- Insufficient balance returns
402before Jev is called. X-Tokens-Remainingon every 200 response is your balance after settlement.- Estimate it yourself:
Σ ceil((state + question).length / 4)— the state counts once per question, so trim it before adding questions.
Models and limits
jev-latest is the default and the model currently served — the model field is optional. Laya variants shown in the playground are upcoming and not yet exposed through this endpoint.
| Limit | Value |
|---|---|
| Questions per request | 8 |
| Question name | Identifier ≤ 64 characters |
Serialized state | 1,000,000 characters |
instructions per question | 1,800 characters |
| Choice options / score levels | 2–20 options, 2–10 levels |
Serialized criteria | 2,000 characters per question |
| Rate limit | 120 requests / minute per key |
Images per request (assets) | 4 |
| Image format / size | PNG or JPEG base64, ≤ ~4 MB each |
| Image dimensions | 256–1,568 px per side |
These figures describe the API validator; the upstream model may have its own context limits.
Errors and retries
Errors return a JSON envelope with a machine-readable type and a human message:
{
"error": {
"type": "invalid_request_error",
"message": "At most 8 questions per request."
}
} | Status | Type | Cause | Charged? |
|---|---|---|---|
401 | authentication_error | Missing, invalid, or revoked key. | No |
402 | insufficient_credits | Estimated input tokens exceed your balance. | No |
422 | invalid_request_error | Body failed validation — see message. | No |
429 | rate_limit_error | More than 120 requests this minute. | No |
502 | upstream_error | Jev could not complete the call. | No — refunded |
Retry 429 and 502 with exponential backoff — the rate window is per minute, so short pauses are usually enough. Send an Idempotency-Key when retrying so a repeated request settles against the same billing record instead of charging twice.
MCP server for agents
jevmodel.org also runs a remote MCP server over Streamable HTTP at https://jevmodel.org/mcp. It exposes four tools — jev_decide (the full state-plus-questions contract), jev_noul, jev_choice, and jev_score — so coding agents like Claude Code, Cursor, or Cline can call Jev without writing HTTP.
claude mcp add --transport http jev https://jevmodel.org/mcp \
--header "Authorization: Bearer $JEVMODEL_API_KEY" - Same
Authorization: Bearer sk-…key and the same token balance as this API —tools/callbills input tokens only. initialize,ping, andtools/listare unauthenticated; onlytools/calluses your key.GET /mcpreturns a JSON discovery card for agents and humans.
Setup commands for Claude Code, Cursor, and the matching agent skill (judgment playbook) are on the agent tools page.
Playground to API
Build the scenario in the playground first — the request preview shows the exact JSON body your application should send, and Copy API example gives you the matching cURL. When the answers look right, create a key in the dashboard and swap the browser session for Bearer authentication.
More reading: How to use Jev walks through a first call end to end, and Jev API examples has production patterns for each question type.