jevbooks

Your first Jev decision

Finish with a result you can inspect: a saved response that identifies the model, answers your question and reports usage. Then decide what your application should do when the answer is uncertain or the request fails.

jevbooks is independent of TypeSafe. Model aliases and error guidance were checked in official docs on 2 November 2026. The response below is saved from 25 September with Jev 1.13; the revised scripts were checked offline, without a new API inference.

New to Jev? Read What is Jev? →

Prepare an account and a terminal

  1. Sign in to the official console at console.typesafe.ai and create a key at console.typesafe.ai/keys. No third-party registration tool is needed.
  2. Use Bash and curl on macOS/Linux, or a Bash environment such as WSL on Windows. The offline checker also needs Node.js 22 or later. No npm packages are required.
  3. The script prompts for your key without echoing it. Keep the key out of source files and saved request bodies. The request creates files in jev-first-decision/; another run replaces them, so copy any run you want to keep.

1. Send and save one request

Save the following as quickstart-request.sh in an empty working folder, then run bash quickstart-request.sh. It prompts for your key unless TYPESAFE_API_KEY is already set. This makes one billable API request.

Download quickstart-request.sh

#!/usr/bin/env bash
# Save as quickstart-request.sh; run: bash quickstart-request.sh
set -euo pipefail
mkdir -p jev-first-decision
cd jev-first-decision
if [[ -z "${TYPESAFE_API_KEY:-}" ]]; then
  read -r -s -p "TypeSafe API key: " TYPESAFE_API_KEY
  printf '\n'
  export TYPESAFE_API_KEY
fi
: "${TYPESAFE_API_KEY:?API key is required}"
cat > request.json <<'JSON'
{
  "model": "jev-latest",
  "state": "I was charged twice. Please fix this today.",
  "questions": {
    "urgency": {
      "type": "noul",
      "instructions": "Does this message express urgency?"
    }
  }
}
JSON
rm -f response.json response.status
if ! status=$(curl --silent --show-error --max-time 30 \
  https://api.typesafe.ai/v1/systemone \
  -H "Authorization: Bearer $TYPESAFE_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @request.json --output response.json --write-out '%{http_code}'); then
  printf 'Unfinished: network error or timeout. Do not use a partial response.\n' >&2
  exit 1
fi
printf '%s\n' "$status" > response.status
case "$status" in
  2??) printf 'HTTP %s. Now check jev-first-decision/response.json.\n' "$status" ;;
  *) printf 'Unfinished: HTTP %s. Inspect response.json before retrying.\n' "$status" >&2; exit 1 ;;
esac

The question asks whether the message expresses urgency. It does not judge the actual severity or authorize a refund. As checked on 2 November, jev-latest and jev-preview both resolve to jev-1.14.0. Use a fixed version when comparing runs and record the response’s actual model.

Official models and aliases

Saved response from 25 September 2026, when the alias resolved to Jev 1.13:

{
  "model": "jev-1.13.0",
  "answers": { "urgency": { "type": "noul", "noul": 0.95 } },
  "usage": { "input_tokens": 282, "output_tokens": 21 }
}

This JSON preserves the response stored in our tutorial source. A separate original HTTP transcript is not provided. A fresh request can return a different value or version; 0.95 is a historical observation, not an assertion your code should expect.

Download the saved 2026-09-25 response

2. Check the contract, then choose a queue

Download the checker into the same working folder. After the request succeeds, run the command below. It reads local files and makes no API call.

Download quickstart-check.mjs

node quickstart-check.mjs jev-first-decision/response.json "$(cat jev-first-decision/response.status)"
  • HTTP status must be 2xx. A timeout, error status or incomplete response leaves the task unfinished.
  • answers.urgency.type must be noul; noul must be a finite number from 0 to 1. Reject missing answers and wrong types.
  • Require a nonempty model and nonnegative integer usage.input_tokens / usage.output_tokens. Keep these with the input so runs remain comparable.

The checker prints the model, urgency, usage and a teaching-only queue: ≥0.8 goes to priority human review; ≤0.2 goes to the normal queue; the middle stays undecided for human review. These thresholds are illustrative, not calibrated. Passing the contract check says nothing about whether the judgment is correct.

Without a key, put the saved response beside the checker and run node quickstart-check.mjs quickstart-response-2026-09-25.json. It should print model jev-1.13.0, urgency 0.95 and priority-human-review. This checks a historical file, not current HTTP delivery.

3. Try three inputs

Change only state in your chosen script and save each run separately. Record the actual answer and queue; the reading goals below are human checks, not invented model outputs.

InputWhat to inspect
I was charged twice. Please fix this today.There is an explicit timing request. Does your question detect the urgency expressed in the words?
Where can I download last month’s invoice?A routine billing inquiry. Does mentioning money alone push it into priority review?
Send it.Context is missing. What is being sent, and by when? A confident number cannot supply those missing facts.

The third case is a test of your application too: require the missing context or keep it for human review. A model can be confidently wrong; a numeric middle band alone is not a complete unknown policy.

If the request does not finish

The examples stop and save any completed HTTP error body. They do not retry automatically.

ConditionNext action
401Check that the key is present and the Authorization header is correct. Do not paste the key into bug reports.
400 / 422Read the saved error body; fix invalid JSON, context size or the field identified by the server before retrying.
429 / 529Use bounded exponential backoff; follow Retry-After when present. Avoid an immediate retry loop.
Timeout, other non-2xx, invalid JSON or missing answerLeave the decision unfinished. Inspect the saved result and the relevant service status before retrying; never substitute zero for a missing probability.

Official error handling guide

A local test on 22 October received HTTP 451 and produced no new inference. That historical environment result does not establish what other accounts or locations will receive.

4. Map it to your own task

Fill in four boxes before adding another question. Here is the support-queue example:

Material
The customer message, plus only the context needed to interpret it.
Decision
Does the message express urgency? Keep severity and refund eligibility as separate questions.
Allowed outcomes
Priority human review, normal queue, or undecided human review.
Unknown behavior
Ask for missing context; if the API fails or the answer is invalid, leave the task unfinished.

Bring these four boxes to Ask →

Prefer JavaScript or Python?

These alternatives send the same request and check the response. Set TYPESAFE_API_KEY in your terminal before running either file; the command below reads it without putting the value in shell history. Each run replaces files under jev-first-decision/.

# Bash
read -r -s -p "TypeSafe API key: " TYPESAFE_API_KEY
printf '\n'
export TYPESAFE_API_KEY

Python 3.10+ with its standard library; no pip install. Save as quickstart-request.py, then run python3 quickstart-request.py.

Download the complete file · Python

View the complete Python file
# Python 3.10+; standard library only, no pip install.
# Save as quickstart-request.py; run: python3 quickstart-request.py
import json
import math
import os
import sys
from pathlib import Path
from urllib.error import HTTPError
from urllib.request import Request, urlopen


def inspect_response(data):
    answer = data.get("answers", {}).get("urgency", {})
    value = answer.get("noul")
    if (answer.get("type") != "noul" or type(value) not in (int, float)
            or not math.isfinite(value) or not 0 <= value <= 1):
        raise ValueError("urgency must be a noul number in [0, 1]")
    if not isinstance(data.get("model"), str) or not data["model"].strip():
        raise ValueError("missing model version")
    usage = data.get("usage", {})
    if any(type(usage.get(k)) is not int or usage[k] < 0
           for k in ("input_tokens", "output_tokens")):
        raise ValueError("invalid token usage")
    # Teaching thresholds only; validate on labelled examples before use.
    queue = ("priority-human-review" if value >= 0.8 else "normal-queue"
             if value <= 0.2 else "undecided-human-review")
    return dict(model=data["model"], urgency=value, usage=usage, queue=queue)


def main():
    key = os.environ.get("TYPESAFE_API_KEY")
    if not key:
        raise ValueError("Set TYPESAFE_API_KEY first")
    folder = Path("jev-first-decision")
    folder.mkdir(exist_ok=True)
    request = {
        "model": "jev-latest",
        "state": "I was charged twice. Please fix this today.",
        "questions": {"urgency": {
            "type": "noul", "instructions": "Does this message express urgency?"
        }},
    }
    payload = json.dumps(request)
    (folder / "request.json").write_text(payload, encoding="utf-8")
    for name in ("response.json", "response.status"):
        (folder / name).unlink(missing_ok=True)
    req = Request("https://api.typesafe.ai/v1/systemone", payload.encode(), {
        "Authorization": f"Bearer {key}", "Content-Type": "application/json"
    })
    try:
        with urlopen(req, timeout=30) as response:
            status, body = response.status, response.read()
    except HTTPError as error:
        status, body = error.code, error.read()
    (folder / "response.json").write_bytes(body)
    (folder / "response.status").write_text(str(status), encoding="utf-8")
    if not 200 <= status < 300:
        raise ValueError(f"HTTP {status}; inspect response.json before retrying")
    print(json.dumps(inspect_response(json.loads(body)), indent=2))


if __name__ == "__main__":
    try:
        main()
    except Exception as error:
        print(f"Unfinished: {error}", file=sys.stderr)
        sys.exit(1)

Node.js 22+; no npm install. Save as quickstart-request.mjs and keep quickstart-check.mjs beside it, then run node quickstart-request.mjs.

Download the complete file · JavaScript

Download quickstart-check.mjs

View the complete JavaScript file
// Node.js 22+; no npm install. Keep quickstart-check.mjs beside this file.
// Run: node quickstart-request.mjs (TYPESAFE_API_KEY must be set).
import { mkdirSync, writeFileSync, rmSync } from "node:fs";
import { inspectResponse } from "./quickstart-check.mjs";

const request = {
  model: "jev-latest",
  state: "I was charged twice. Please fix this today.",
  questions: {
    urgency: { type: "noul", instructions: "Does this message express urgency?" },
  },
};
try {
  if (!process.env.TYPESAFE_API_KEY) throw new Error("Set TYPESAFE_API_KEY first.");
  mkdirSync("jev-first-decision", { recursive: true });
  writeFileSync("jev-first-decision/request.json", JSON.stringify(request, null, 2));
  for (const file of ["response.json", "response.status"]) {
    rmSync(`jev-first-decision/${file}`, { force: true });
  }
  const response = await fetch("https://api.typesafe.ai/v1/systemone", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.TYPESAFE_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(request),
    signal: AbortSignal.timeout(30_000),
  });
  const body = await response.text();
  writeFileSync("jev-first-decision/response.json", body);
  writeFileSync("jev-first-decision/response.status", String(response.status));
  if (!response.ok) throw new Error(`HTTP ${response.status}; inspect response.json.`);
  console.log(inspectResponse(JSON.parse(body), response.status));
} catch (error) {
  console.error(error.message.startsWith("Unfinished:") ? error.message : `Unfinished: ${error.message}`);
  process.exitCode = 1;
}

These are direct HTTP examples, not SDK examples. For the official Python and JavaScript SDK installation and retry defaults, follow TypeSafe’s SDK documentation.

Official SDK documentation

Price and model limits

Model table checked in official docs on 2 November 2026. Experimental image details were last checked on 22 October.

TypeSafe API
Input price$0.042 per 1M tokens; output tokens are free
Default contextstate plus all questions ≤64k tokens; state plus any one question ≤32k
Experimental long contextBoth limits become 262k with TypeSafe-Danger-Zone-Long-Context: true; slower and less accurate
Model namesjev-latest and jev-preview → jev-1.14.0 as of 2 November. Fixed IDs include jev-1.13.0 and jev-1.14.0. There is no separate preview build at that check date.
ImagesExperimental assets require TypeSafe-Danger-Zone-Images: true; box requires 1.14. This tutorial sends text only.
Rate limitsPer organization; see console.typesafe.ai/rate-limits

At the listed input price, 1,000 tokens cost $0.000042. The saved 282-input-token response cost about $0.000012. Check the console for current account offers.

Other routes

  • September 2026 OpenRouter measurements used typesafe/jev-1.13 at /api/alpha/decisions; they do not establish current support for 1.14 or experimental image features. Use the direct route above for this tutorial.

Choose the next task

Frequently asked questions

How do I register for Jev?

Sign in at console.typesafe.ai, then create an API key at console.typesafe.ai/keys. jevbooks is independent of TypeSafe and cannot create accounts for you.

Is Jev free?

The official model price checked on 2 November 2026 is $0.042 per 1M input tokens, with output free. Check the console for account-specific credits or offers.

Do I need an SDK?

No. These examples use curl, Node.js built-in fetch, or the Python standard library. TypeSafe also publishes official Python and JavaScript SDKs.

Which model name should I send?

On 2 November 2026 the official docs list both jev-latest and jev-preview as jev-1.14.0. You can pin jev-1.13.0 or jev-1.14.0 for version comparisons. Record the response’s model field; a fixed version does not guarantee identical repeated answers.

Does a valid response mean the decision is correct?

No. HTTP success and type checks confirm delivery and response shape. Use labelled examples to measure the decision quality and choose thresholds and a fallback.

Take the next step

Bring your task to AskBrowse the galleryOfficial docsGet an API key