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
- Sign in to the official console at
console.typesafe.aiand create a key atconsole.typesafe.ai/keys. No third-party registration tool is needed. - 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.
- 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 ;;
esacThe 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.
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.
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.
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.typemust benoul;noulmust be a finite number from 0 to 1. Reject missing answers and wrong types.- Require a nonempty
modeland nonnegative integerusage.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.
| Input | What 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.
| Condition | Next action |
|---|---|
| 401 | Check that the key is present and the Authorization header is correct. Do not paste the key into bug reports. |
| 400 / 422 | Read the saved error body; fix invalid JSON, context size or the field identified by the server before retrying. |
| 429 / 529 | Use bounded exponential backoff; follow Retry-After when present. Avoid an immediate retry loop. |
| Timeout, other non-2xx, invalid JSON or missing answer | Leave the decision unfinished. Inspect the saved result and the relevant service status before retrying; never substitute zero for a missing probability. |
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.
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
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.
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 context | state plus all questions ≤64k tokens; state plus any one question ≤32k |
| Experimental long context | Both limits become 262k with TypeSafe-Danger-Zone-Long-Context: true; slower and less accurate |
| Model names | jev-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. |
| Images | Experimental assets require TypeSafe-Danger-Zone-Images: true; box requires 1.14. This tutorial sends text only. |
| Rate limits | Per 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.13at/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