AI Development Guide

TypeSafe AI Quick Start for 2026: Your First Jev Call in cURL, Python and JavaScript

One endpoint, three fields, and an answer in about a tenth of a second. This tutorial takes you from the playground to a production-shaped integration, with the real code from TypeSafe's documentation and the errors you will meet on the way.

Distk Editorial Sep 2026 12 min read

A TypeSafe request is a POST to https://api.typesafe.ai/v1/systemone carrying three fields: the state to evaluate, the model (use jev-latest), and a map of questions whose keys you invent. Answers come back under the same keys, with choice, score or noul plus probabilities and confidence, alongside the versioned model ID and token usage. Start in the playground with your own text, then move to cURL, then to the Python SDK (pip install typesafe-sdk) or the JavaScript SDK (npm install @typesafe-ai/sdk, Node.js 20 or newer). Configure through TYPESAFE_API_KEY. Four errors cover the early days: 401 for a bad key, 422 for a malformed question, 429 for rate limits and 529 for overload, with the SDKs retrying the last two automatically. Install TypeSafe's official agent skill before asking a coding agent to build the integration for you in 2026.

What Do You Need Before Your First TypeSafe Call in 2026?

Three things: an account on the TypeSafe console, which requires signing in, an API key from the dashboard, and some real text to evaluate. There is no local model to download and no infrastructure to provision. Everything runs through one HTTP endpoint, POST https://api.typesafe.ai/v1/systemone, and the SDKs for Python and JavaScript are thin wrappers over it.

Use your own content rather than a sample. The whole point of the first hour is finding out whether the model's judgments match yours on the material your business actually handles, and a curated example will not tell you that.

Explain It Like I Am Five: What Are You Actually Sending?

Remember school worksheets? At the top of the page there is a little story. Underneath there are questions about the story, with boxes to fill in.

That is exactly what you send. The story at the top is called the state. It is whatever you want looked at: an email, a review, a form someone filled in.

The questions underneath are your questions. You get to write them. You also get to say what the allowed answers are, like on a multiple choice test where you write the options yourself.

You send the whole worksheet in one go. The model fills in every box and hands the page straight back, usually in about a tenth of a second.

Two nice things. First, it fills in every box at the same time, so ten questions come back nearly as fast as one. Second, each box is marked on its own, so a tricky question at the bottom cannot mess up the easy one at the top.

Your program then reads the boxes and decides what to do. The model never decides anything. It just fills in boxes.

How Do You Try TypeSafe in the Playground First?

TypeSafe's documented starting path is the playground, not the API, and it is the right order. You want to see the shape of an answer before you write code that depends on it. The steps in the official quick start are short.

  1. Open the playground and log in. The console requires signing in before you can use the playground or create a key.
  2. Paste any text as the state. TypeSafe's own sample is a support message: "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales. Please help ASAP."
  3. Add one question. The documented first question is a Noul: "Does this message express urgency?"
  4. Add more questions. Mix Noul, Choice and Score in one call and watch all results come back together.

That fourth step is the one to linger on. Add a fifth, sixth and seventh question and watch the response time barely move. Understanding that in the playground is what stops you from writing a loop of single-question calls later.

How Do You Make Your First TypeSafe API Call With cURL?

Get your API key from the dashboard, export it, and post a JSON body with three fields: state, model and questions. The example below is TypeSafe's own, with a single Noul question. It is the smallest useful request you can make in 2026.

curl -X POST https://api.typesafe.ai/v1/systemone \
  -H "Authorization: Bearer $TYPESAFE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "state": "Hi, I have been trying to connect my Stripe account for 3 days and the integration keeps failing. I am losing sales. Please help ASAP.",
    "model": "jev-latest",
    "questions": {
      "urgency": {
        "type": "noul",
        "instructions": "Does this message express urgency?"
      }
    }
  }'

The model field selects which model answers. Use jev-latest, which is the alias for the most recent stable release and the default in the SDKs. In 2026 it resolves to jev-1.13.0.

How Do You Ask Three Different Question Types at Once?

Put them all in the same questions map. Each key is an ID you invent, and the matching answer comes back under that same key. The ID is never sent to the model, so name it for your codebase. Below is the request from TypeSafe's quick start, mixing Choice, Score and Noul against one state.

{
  "state": "Hi, I've been trying to connect my Stripe account for 3 days
            and the integration keeps failing. I'm losing sales.",
  "model": "jev-latest",
  "questions": {
    "department": {
      "type": "choice",
      "instructions": "Which team should handle this",
      "criteria": {
        "billing": "Payment or subscription issues",
        "technical": "Bugs or integration problems",
        "sales": "Pricing or account questions"
      }
    },
    "frustration": {
      "type": "score",
      "instructions": "How frustrated the customer appears",
      "criteria": [
        "Calm, just stating facts",
        "Frustrated but civil",
        "Very angry, strong language"
      ]
    },
    "is_urgent": {
      "type": "noul",
      "instructions": "The message conveys urgency or time-sensitivity"
    }
  }
}

How Do You Read a TypeSafe Response in 2026?

The response has three top-level fields: model, which reports the versioned model ID that actually answered, answers, keyed by your question IDs, and usage with input and output token counts. Each answer carries a type matching its question. This is TypeSafe's documented response to the request above.

{
  "model": "jev-1.13.0",
  "answers": {
    "department": {
      "type": "choice",
      "choice": "technical",
      "confidence": 0.78,
      "probabilities": {
        "technical": 0.85,
        "sales": 0.0,
        "billing": 0.15
      }
    },
    "frustration": {
      "type": "score",
      "score": 1.0,
      "confidence": 1.0,
      "legend": {
        "0": "Calm, just stating facts",
        "1": "Frustrated but civil",
        "2": "Very angry, strong language"
      },
      "probabilities": { "0": 0.0, "1": 1.0, "2": 0.0 }
    },
    "is_urgent": {
      "type": "noul",
      "noul": 1.0
    }
  },
  "usage": { "input_tokens": 392, "output_tokens": 65 }
}
FieldAppears onHow to read it
choiceChoiceThe option with the highest probability.
scoreScoreA position along your levels, starting at 0. It can land between two levels.
noulNoulThe probability the answer is yes. Near 1 is a strong yes, near 0 a strong no, near 0.5 uncertain.
probabilitiesChoice, ScoreThe full distribution across your options or levels. Values sum to 1.
legendScoreEach level number mapped back to the description you wrote.
confidenceChoice, Score0 to 1, derived from how peaked the distribution is. Noul has none, because two outcomes are fully described by one number.
modelResponse rootThe versioned ID that answered. Log it, so you know which version produced each result.
usageResponse rootInput and output token counts. Only input tokens are billed.

How Do You Call TypeSafe From Python in 2026?

Install the SDK, set TYPESAFE_API_KEY in your environment, and pass typed question objects to client.system_one(). The SDK provides Choice, Score and Noul classes so your editor can check the shapes, and answers come back as typed objects rather than raw dictionaries.

pip install typesafe-sdk
# or, with uv
uv add typesafe-sdk
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient

client = TypeSafeClient()

ticket = "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales."

response = client.system_one(
    state=ticket,
    questions={
        "department": Choice(
            instructions="Which team should handle this",
            criteria={
                "billing": "Payment or subscription issues",
                "technical": "Bugs or integration problems",
                "sales": "Pricing or account questions",
            },
        ),
        "frustration": Score(
            instructions="How frustrated the customer appears",
            criteria=[
                "Calm, just stating facts",
                "Frustrated but civil",
                "Very angry, strong language",
            ],
        ),
        "is_urgent": Noul(
            instructions="The message conveys urgency or time-sensitivity",
        ),
    },
)

print(response.answers["department"].choice)   # "technical"
print(response.answers["frustration"].score)   # 1.0
print(response.answers["is_urgent"].noul)      # 1.0

The SDK also supports a context manager form, with TypeSafeClient() as client:, which the documentation uses in most examples. For a Noul that needs its yes and no spelled out, there is a NoulCriteria type.

from typesafe_sdk import Noul, NoulCriteria, TypeSafeClient

with TypeSafeClient() as client:
    response = client.system_one(
        model="jev-latest",
        state="I have asked three times now. Can I please just talk to a real person?",
        questions={
            "is_repeat_contact": Noul(
                instructions="Has the customer contacted support about this before?",
                criteria=NoulCriteria(
                    true="Mentions a prior attempt, ticket, or that they have asked before",
                    false="No sign of any previous contact",
                ),
            ),
        },
    )
    print(response.answers["is_repeat_contact"].noul)

How Do You Call TypeSafe From JavaScript or TypeScript?

Install the package on Node.js 20 or newer, set the same environment variable, and call client.systemOne(). Answer types are inferred from your questions, and the package ships ESM, CommonJS and TypeScript declarations. Note the helper functions, choice, score and noul, which build the question objects for you.

npm install @typesafe-ai/sdk
import { choice, TypeSafeClient } from "@typesafe-ai/sdk";

const client = new TypeSafeClient();

const response = await client.systemOne({
  state: { document: "I was charged twice. Please fix this ASAP." },
  questions: {
    category: choice("What is this ticket about?", {
      billing: null,
      technical: null,
      other: null,
    }),
  },
});

console.log(response.answers.category.choice);

The null values in that criteria map are deliberate. TypeSafe allows null when an option name is clear enough on its own and needs no extra description. Start there and add descriptions only when the model confuses two options.

How Do You Configure the Client in 2026?

Configuration is by environment variable with per-client overrides, which keeps keys out of your code. The Python SDK reads four variables, and the defaults are sensible enough that most projects set only the key.

VariableConfiguresDefault
TYPESAFE_API_KEYAPI key, requiredNone
TYPESAFE_BASE_URLAPI root URLhttps://api.typesafe.ai
TYPESAFE_DEFAULT_MODELDefault modeljev-latest
TYPESAFE_LOG_LEVELLogger level, applied once at importUnset

Keys are cleaned before use: leading and trailing whitespace is stripped, including newlines from key files, and empty keys, internal whitespace, control characters and non-ASCII characters are rejected before a request is sent. An explicitly empty key does not fall back to the environment. If you have ever lost an afternoon to a trailing newline in a secret, that is a welcome detail.

The SDK can also talk to TypeSafe-compatible endpoints from other providers. TypeSafe documents using it with an OpenRouter key and base URL, and with Vercel's AI Gateway, which requires the alternative API to follow the TypeSafe OpenAPI specification.

What Errors Will You Hit First, and How Do You Handle Them?

Four status codes cover almost everything in a first integration. TypeSafe documents each with a JSON body describing what went wrong, and the SDKs raise typed exceptions rather than returning error objects.

StatusWhat it meansWhat to do in 2026
401 UnauthorizedMissing or invalid API keyCheck the Authorization header. In the SDK, an invalid key raises during client creation, before any request.
422 Unprocessable EntityThe body failed validation, such as a missing field or a malformed questionRead the body; it names the offending field. Usually a Score with fewer than two levels or a Choice missing criteria.
429 Too Many RequestsYou exceeded the tokens-per-second or requests-per-minute limitRetry with exponential backoff. The SDKs do this by default and honour retry-after.
529 OverloadedTypeSafe is temporarily overloadedSame treatment as a 429: back off and retry.
from typesafe_sdk import RetryPolicy, TypeSafeAPIError, TypeSafeClient

client = TypeSafeClient(retry=RetryPolicy(max_retries=3, backoff_max=0.2, timeout=1.0))

try:
    response = client.system_one(state, questions)
except TypeSafeAPIError as error:
    print(error.status, error.request_id)

A retry policy can also be passed per call rather than on the client, which is useful when one code path is latency-sensitive and another can afford to wait. For debugging, set the logger to debug and note the caveat TypeSafe publishes: secret headers are redacted from logs, but request and response bodies are not, so debug logging on production traffic will write your customer data to your log sink.

How Do You Get a Coding Agent to Write the Integration?

TypeSafe publishes an official agent skill that gives a coding agent full context on the API shapes, the three question types, the patterns and the best practices. Installing it before you ask an agent to build anything prevents the most common failure, which is an agent inventing request or response fields that do not exist.

# Claude Code
claude plugin marketplace add typesafe-ai/skills
claude plugin install typesafe@typesafe-ai

# Other agents
npx skills add typesafe-ai/skills --skill typesafe-ai

TypeSafe's own guidance on working this way is worth following. Talk the problem through with the agent first; review the plan before implementation; put the questions and thresholds in a single file so a human can review them, because agents are not great at writing questions; and do not take the agent's assertions at face value. If the agent starts inventing fields, the usual cause is a stale skill, so update it and retry.

What Should Your First Real Integration Look Like in 2026?

Pick one decision your code currently makes badly with string matching, and replace just that. A first integration that tries to restructure a whole pipeline will not tell you whether the model's judgment is good enough for your material.

  1. Find the decision. Somewhere your code guesses intent, category, urgency or relevance from text.
  2. Write the question in one file. Instructions, criteria and the threshold, all as constants a colleague can read without hunting.
  3. Run it over 50 real examples you have already labelled. Compare the model's answer to yours, and plot confidence against whether it was right.
  4. Set the threshold from that plot, not from instinct. TypeSafe's documented advice is to test thresholds by plotting confidence against accuracy on your own data.
  5. Add the speculative questions. Anything else your code might want to know about the same text, since extra questions barely change response time.
  6. Route the uncertain middle to a person. Not to a default branch.
  7. Log the model ID and the probabilities. When an alias moves to a new version, you will want the history.

Our primitives deep dive covers writing good questions, and the confidence guide covers choosing that threshold properly.

What Are the Common First-Integration Mistakes in 2026?

Key Takeaways for 2026

Distk builds these integrations for growth and operations teams, including the part most projects skip: labelling a real sample, plotting confidence against accuracy, and setting thresholds from evidence rather than instinct.

Sources

TypeSafe AI Quick Start in 2026: FAQs

How do I make my first TypeSafe API call?

POST to https://api.typesafe.ai/v1/systemone with a Bearer token and a JSON body containing state, model and questions. The smallest useful request is one Noul question against a string of text. The response returns your answer under the question ID you chose.

What Python package do I install?

pip install typesafe-sdk, or uv add typesafe-sdk. Set TYPESAFE_API_KEY in your environment, create a TypeSafeClient, and pass Choice, Score and Noul objects to client.system_one().

What JavaScript package do I install?

npm install @typesafe-ai/sdk on Node.js 20 or newer. Create a TypeSafeClient and call client.systemOne() with state and questions. The package includes ESM, CommonJS and TypeScript declarations, and answer types are inferred from your questions.

Which model name should I use?

jev-latest, which is the alias for the most recent stable release and the default in the SDKs. In 2026 it resolves to jev-1.13.0. The response reports the versioned ID that actually answered, so log it.

What errors should I expect?

401 for a missing or invalid API key, 422 when the request body fails validation, 429 when you exceed the rate limit, and 529 when TypeSafe is temporarily overloaded. The SDKs retry 429 and 529 with exponential backoff by default.

Can a coding agent write the integration for me?

Yes, and TypeSafe publishes an official agent skill for exactly that. Install it before you start, because the usual cause of an agent inventing request or response fields is a missing or stale skill.

Get the first integration right, not just running

Distk builds TypeSafe integrations end to end, including the part most first projects skip: labelling a real sample, plotting confidence against accuracy, and setting thresholds from evidence.

Start the conversation →