Jev API Tutorial: Make Your First Call in 10 Minutes

Updated Applies to Jev 1.13

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/completions with Authorization: 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:

PartValuePurpose
URLhttps://openrouter.ai/api/v1/chat/completionsOpenRouter’s OpenAI-compatible endpoint
Authorization headerBearer $OPENROUTER_API_KEYAuthenticates your key from the env variable
Content-Typeapplication/jsonStandard JSON request body
modeltypesafe/jev-1.13The Jev model id — confirm the exact slug on the OpenRouter model page
messages[0].roleuserA single-turn question; Jev is not a chat partner
messages[0].contentYour questionPhrase 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:

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

  1. 401 Unauthorized. The key is missing from the environment or misread. Print os.environ.get("OPENROUTER_API_KEY") in the same shell you run from; if it is None, the export did not load.
  2. 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.
  3. TypeError: the JSON object must be str... You skipped json.loads on 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.

Frequently asked questions

What endpoint do I use for my first Jev call?

The main demo channel is OpenRouter's OpenAI-compatible chat completions endpoint. Official TypeSafe AI endpoints are documented on typesafe.ai — confirm them there rather than guessing.

What model id do I pass?

This guide uses typesafe/jev-1.13, but slugs change with versions — always confirm the exact model slug on the OpenRouter model page.

Why does my first call fail with a JSON error?

Usually because the answer text was not parsed as JSON before use, or the model id is wrong. Parse message content with a JSON loader and check the slug first.

Keep reading