Jev API Tutorial: Make Your First Call in 10 Minutes
You have an API key and ten minutes — that is genuinely all a first Jev call takes. Because the model’s main demo channel is OpenRouter’s OpenAI-compatible endpoint, the request is the same shape you already send to chat models; what changes is what comes back. This tutorial walks through a complete, copy-pasteable call in curl and Python, explains every field, and lists the three errors that catch almost everyone on their first run.
TL;DR: POST to
https://openrouter.ai/api/v1/chat/completionswithAuthorization: Bearer <key>, the Jev model id, and your question phrased as a judgment, choice or scoring question. The answer comes back inside the standard OpenAI-compatible envelope as structured JSON — an answer, a confidence score and a rationale. Parse the message content as JSON and read the fields.
The request, field by field
A first call is a judgment question — the simplest of the three primitives:
# Confirm the exact model slug on the OpenRouter model page
curl https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "typesafe/jev-1.13",
"messages": [
{
"role": "user",
"content": "Judgment question: does this comment contain spam? Comment: \"Great post, check my site for cheap meds\""
}
]
}'
What each part does:
| Part | Value | Purpose |
|---|---|---|
| URL | https://openrouter.ai/api/v1/chat/completions | OpenRouter’s OpenAI-compatible endpoint |
Authorization header | Bearer $OPENROUTER_API_KEY | Authenticates your key from the env variable |
Content-Type | application/json | Standard JSON request body |
model | typesafe/jev-1.13 | The Jev model id — confirm the exact slug on the OpenRouter model page |
messages[0].role | user | A single-turn question; Jev is not a chat partner |
messages[0].content | Your question | Phrase it as judgment / choice / scoring, with the input embedded |
Note what is not required: no special “judgment mode” parameter, no bespoke endpoint. The question type is carried by how you phrase the content. For the official TypeSafe AI channel, confirm the actual endpoint and fields in the official documentation at typesafe.ai.
The response, decoded
The HTTP response is the standard OpenAI-compatible envelope. Inside, the message content holds the structured answer — example fixture, confirm exact field names in the official documentation:
{
"answer": "yes",
"confidence": 0.97,
"rationale": "The comment promotes an unrelated pharmaceutical site, a classic spam pattern."
}
Reading the fields:
answer— for judgment questions, one ofyes,noorunclear. For choice questions it is one of your listed options; for scoring, a number plus thescaleit came from.confidence— a 0–1 score you can branch on. Anything below your threshold routes to review.rationale— a short explanation. Log it; it makes debugging question wording vastly easier.
The same call in Python
import json, os, requests
resp = requests.post(
"https://openrouter.ai/api/v1/chat/completions",
headers={
"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
"Content-Type": "application/json",
},
json={
# Confirm the exact model slug on the OpenRouter model page
"model": "typesafe/jev-1.13",
"messages": [{
"role": "user",
"content": "Judgment question: does this comment contain spam? Comment: \"Great post, check my site for cheap meds\"",
}],
},
timeout=30,
)
resp.raise_for_status()
result = json.loads(resp.json()["choices"][0]["message"]["content"])
print(result["answer"], result["confidence"])
The outer resp.json() is the standard envelope; the parsed result is an example fixture — the response shape shown is illustrative and official field names should be confirmed in the official documentation. The one line people forget is json.loads(...) on the message content: it is a JSON string, not a dict.
The three errors everyone hits first
401 Unauthorized. The key is missing from the environment or misread. Printos.environ.get("OPENROUTER_API_KEY")in the same shell you run from; if it isNone, the export did not load.404/ unknown model. The slug is wrong or outdated. Re-check the OpenRouter model page for the current id — this is the single most common first-day failure.TypeError: the JSON object must be str...You skippedjson.loadson the message content, or the content was not valid JSON for that call. Parse defensively and, if the payload is malformed, retry the call once before alerting.
Anything beyond these three is covered in the troubleshooting guide, and the choice/scoring request patterns are in the three-primitives guide. To see this exact call wired into a moderation pipeline, read the spam comment detection case.
This guide applies to Jev 1.13.