Skip to content

DocsAPI reference

Jev: TypeSafe System One

Run TypeSafe's Jev through INFRO with POST /v1/systemone: TypeSafe's body and model names, your TypeSafe account, spend limits and a cost per decision.


INFRO is in private early access. Running these examples requires an early-access account, an active trial or subscription entitlement, and your own provider connection. Self-serve purchasing is not generally open. See Early access.

Jev, TypeSafe's System One model, answers typed questions about a state — yes or no (noul), one of several options (choice), a level on a scale (score) — with probabilities, and writes no text. INFRO serves TypeSafe's endpoint at the same path, with the same request body and model names, so code written for TypeSafe points at INFRO by changing its base URL and its key.

Every request runs on your own TypeSafe connection, under your TypeSafe key, and TypeSafe bills your account for it. INFRO estimates what TypeSafe will charge and takes 0% markup on model spend; what INFRO charges is your subscription. The same endpoint serves every other decision model you connect — OpenAI's GPT-6 Luna, Cloudflare's Clef and the rest — on your own account with its provider.

Jev through INFRO

  1. Connect your TypeSafe key under Providers (TypeSafe issues it at console.typesafe.ai/keys). It is tested before it is saved, stored encrypted, and sent only to TypeSafe.
  2. Create an INFRO gateway key under Keys. To keep it to Jev, limit it to TypeSafe in the key's providers.
  3. Send requests to https://api.infro.io/v1/systemone with the gateway key as the bearer token. With TypeSafe's SDK, point it at INFRO's API host in place of TypeSafe's (api.infro.io for api.typesafe.ai) and give it the gateway key where it takes the TypeSafe key.
  4. Name the model: a pinned version (jev-1.13.0, as TypeSafe advises), a moving name (jev-latest, jev-preview) or the catalog id typesafe/jev-1.13. Each response's model is the version that answered.
  5. Read usage.cost on each response: the estimated TypeSafe charge for that decision.
  6. Set a spend limit on the organization, a project, the key or a member under Budgets. It is checked before TypeSafe is called.
  7. Find each decision in the request log by the response's id. Send metadata (for example {"workflow": "support-triage"}) to group decisions by workflow in usage, beside the LLM calls the same workflow makes.
POST /v1/systemone
curl https://api.infro.io/v1/systemone \
  -H "Authorization: Bearer $INFRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "jev-1.13.0",
    "state": "My order arrived broken and I want my money back.",
    "questions": {
      "intent": {
        "type": "choice",
        "instructions": "The primary intent of this customer message",
        "criteria": { "order_status": null, "return_refund": null, "complaint": null }
      },
      "urgent": { "type": "noul", "instructions": "Does this need a reply today?" }
    },
    "metadata": { "workflow": "support-triage" }
  }'

Model names

You sendSent to TypeSafe asEstimated as
jev-1.13.0 or typesafe/jev-1.13jev-1.13.0Jev 1.13
jev-latest or jev-preview, with or without typesafe/As typedThe version TypeSafe reports having served
A route's slugThe route's targetThe target's model

A moving name follows TypeSafe's releases: jev-latest is TypeSafe's latest stable release and jev-preview its latest release, both jev-1.13.0 when TypeSafe's models page was read on 6 October 2026. The version that answers can therefore change without a deploy on your side. The response's model and the request log name it, and the estimate is priced as that version. A version INFRO's catalog does not carry yet is recorded as unpriced — cost: null, never $0 — until it is added.

Request body

modelstringrequired
A Jev version, a moving name, the catalog id or a route. See Model names.
statestring | object | arrayrequired
What the questions are about. TypeSafe reads it once for every question.
questionsobjectrequired
Your question ids mapped to questions; the answers come back under the same ids, which are not sent to the model. INFRO accepts 1 to 1,000 per request.
typeFieldsAnswer
noulinstructions; optional criteria.true and criteria.falsenoul: the probability of yes
choiceinstructions; criteria: up to 255 optionschoice, probabilities, confidence
scoreinstructions; criteria: 2 to 10 levelsscore, legend, probabilities, confidence

INFRO checks the envelope — a state, between 1 and 1,000 questions, each with a known type — and leaves the rest of each question to TypeSafe, which validates it. TypeSafe's own limits apply: 64k tokens per request, with the state and the longest question within 32k, and rate limits TypeSafe adjusts as demand changes (docs.typesafe.ai/models, read 6 October 2026).

INFRO extensions

metadataobject
Recorded on the request and not sent to TypeSafe. Group usage and the request log by it.
loggingboolean
false keeps this request's state and answers out of the request log, even when your organization turned prompt logging on.
fallbacksstring[]
Other Jev models or routes to try when every TypeSafe connection for model fails.

X-INFRO-User-Id names your end customer for end-customer caps, and the cost attribution headers work as on every endpoint.

Response

200 OK
{
  "id": "req_…",
  "model": "jev-1.13.0",
  "answers": {
    "intent": {
      "type": "choice",
      "choice": "return_refund",
      "probabilities": { "order_status": 0.03, "return_refund": 0.94, "complaint": 0.03 },
      "confidence": 0.91
    },
    "urgent": { "type": "noul", "noul": 0.72 }
  },
  "usage": { "input_tokens": 1000, "output_tokens": 0, "cost": 0.000042, "price_source": "list" },
  "route": "primary",
  "route_name": null,
  "provider": "typesafe",
  "connection": "conn_…"
}
idstring
The request id, also in X-INFRO-Request-Id. Look the decision up with GET /v1/requests/{id}.
modelstring
The versioned model TypeSafe reports having served.
answersobject
TypeSafe's answers, unchanged, under your question ids.
usage.input_tokensinteger
As TypeSafe reports them.
usage.output_tokensinteger
As TypeSafe reports them. Output is free on Jev.
usage.costnumber | null
The estimated TypeSafe charge in US dollars, at TypeSafe's list rate or the rate you entered for your organization. null when it cannot be priced: a version the catalog does not carry, or no token counts reported.
usage.price_sourcestring
list, custom or custom_provider. Absent when cost is null.
route, route_namestring | null
primary when the first connection tried served it, standby_a and on when a later one did; route_name is the route's slug when model named one.
provider, connectionstring
typesafe and the id of the TypeSafe connection that served it.

Before TypeSafe is called

  • The key: its project, environment, IP allowlist, model allowlist and providers. A key limited to other providers gets 503 connection_out_of_scope.
  • Spend limits: the request's size in bytes — never fewer than its tokens — is reserved at the Jev rate against every blocking limit that applies: organization, project, key, member and end customer. Over one, the request is refused with a 402, and TypeSafe is not called.
  • The key's rate limit, and your organization's guardrail setting for endpoints guardrails cannot read (below).

Several TypeSafe keys

With several TypeSafe keys connected, requests are spread across them. A key TypeSafe refuses (401, 403), a model the key cannot name (404) or a key over its rate limit (429) passes the request to the next key, then to fallbacks. A request TypeSafe rejects as invalid (400 or 422) is not retried: every TypeSafe key validates it the same way. Only connections whose provider answers decisions serve this endpoint: TypeSafe, and the providers of the other decision models — an OpenRouter connection on OpenRouter's own System One endpoint, never on its chat completions.

Errors

StatusCodeWhen
400invalid_requestThe envelope is wrong, or TypeSafe rejected the request: the message carries TypeSafe's words and the field it named (param: …).
402budget_exceededA blocking spend limit. TypeSafe was not called.
403model_not_allowed, guardrail_blockedThe key's allowlist excludes the model, or your guardrails refuse endpoints they cannot read.
404model_not_foundA vendor/model id no provider names.
429rate_limit_exceeded, provider_rate_limitedThe key's rate limit, or every TypeSafe key is over TypeSafe's (with TypeSafe's Retry-After).
502upstream_errorEvery TypeSafe connection failed.
503no_provider_connected, connection_out_of_scopeNo connection serves the model (for Jev, TypeSafe or OpenRouter), or the key may not use the provider that does.

The full list is on Errors.

Compatibility notes

  • The key changes: send an INFRO gateway key, not the TypeSafe key, which stays in your INFRO connection.
  • Responses add id, usage.cost, usage.price_source, route, route_name, provider and connection to TypeSafe's fields.
  • Errors use INFRO's error envelope (error.message, error.type, error.code) rather than TypeSafe's validation body; the field TypeSafe named is in the message.
  • Guardrails inspect chat completions only and do not read these requests. A guardrail policy set to block endpoints it cannot inspect refuses them with 403 guardrail_blocked.
  • The state and the answers are stored only when your organization turned on prompt logging and the request did not send logging: false.
  • The console Playground does not run System One requests yet; decision policies have their own Try it panel.

Use decisions when the question, its thresholds and its fallback should live in a policy rather than in your code.

↑ ↓ navigate↵ open/ anywhere in docs