Skip to main content

SystemOne API Reference (TypeSafe Jev)

RouteLLM exposes TypeSafe Jev, a dedicated classification model, at /v1/systemone. It accepts requests in the TypeSafe SystemOne format.

Overview​

Jev is not a chat model. A single request scores a state (the text or structured data you want judged) against a set of named, typed questions, and returns a calibrated probability for each one. The model does not generate any text:

  • noul: a yes/no question. The answer is the probability of yes, between 0 and 1.
  • choice: picks one of up to 255 named options, with a probability for every option.
  • score: rates the state on 2 to 10 ordered levels and returns a probability-weighted position.

Typical latency is 0.2 to 0.5 seconds, and only input tokens are billed. That makes Jev well suited to high-volume classification, routing, triage and guardrail checks, where a chat model would be slower and more expensive and would leave you parsing its reply.

Key Features​

  • Calibrated probabilities: Every answer comes with a probability or a full distribution that you can set thresholds on.
  • Structured state: state can be a JSON object or array as well as a string, so you can pass records as they are.
  • Several questions per request: Ask up to 10 questions about the same state in one call.
  • Low latency: Typical responses arrive in 0.2 to 0.5 seconds.
  • Input-only billing: Output tokens are free.
note

Jev is text only. To evaluate images, use the Decisions API. For open-ended generation, use /v1/chat/completions.

SystemOne or Decisions?​

Both endpoints return typed answers without generating text. Choose according to your input and how much you are willing to pay:

SystemOne (Jev)Decisions
Modeljev-latestgpt-6-luna
InputText, or JSON objects and arraysText and inline images
Question typesnoul, choice, scorepredicate, choice, score
Price per 1M input tokens$0.042$0.10

Base URLs​

The SystemOne endpoint lives at /v1/systemone under your RouteLLM base URL. The base URL depends on your organization type:

  • Self-Serve Organizations: https://routellm.abacus.ai/v1
  • Enterprise Platform: https://<workspace>.abacus.ai/v1

Replace <workspace> with your specific workspace identifier for enterprise deployments. To find your correct base URL, refer to the RouteLLM API page.

Authentication​

All requests require a RouteLLM API key in the Authorization header:

Authorization: Bearer <your_api_key>

You can obtain your API key from the Abacus.AI platform.

Request Parameters​

state (string, object or array, required)​

The context to evaluate. Pass a plain string, or a JSON object or array to send structured data such as a ticket, a transaction or a conversation as it is. state must not be empty, and it is limited to about 32,000 tokens (128,000 characters after serialization).

questions (object, required)​

A map from question name to question definition, with between 1 and 10 questions. The answer to each question is returned under the same name. Every question takes:

  • type (string, required): noul, choice or score.
  • instructions (string, required): what to evaluate. Jev reads instructions literally, so a question without instructions is rejected.
  • criteria: the options or levels to choose from. Its form depends on type, as described below.

The whole questions object is limited to 128,000 characters after serialization.

model (string, optional)​

Defaults to jev-latest, TypeSafe's flagship model. jev-preview serves the next release early. The exact version that answered, for example jev-1.13.0, is returned in the response.

Question Types​

Noul (yes/no)​

The answer is the probability of yes. criteria is optional. If you include it, give true and false strings that describe what counts as yes and what counts as no.

"is_urgent": {
"type": "noul",
"instructions": "Does this message convey urgency?",
"criteria": {
"true": "The sender reports an outage, lost money or a hard deadline",
"false": "General questions and feature requests, even when the sender is impatient"
}
}

Choice​

Picks one named option. criteria is an object of up to 255 options, each mapping the option name to a description, or to null if the name explains itself. When options are easy to confuse, the description can be a structured object such as {"what": ..., "not_for": ..., "examples": [...]}.

"department": {
"type": "choice",
"instructions": "Which team should handle this ticket?",
"criteria": {
"billing": "Charges, refunds, invoices and plan changes",
"technical": "Bugs, errors, outages and integrations",
"account": {
"what": "Login, password, profile and permissions",
"not_for": "SSO or SCIM configuration, which goes to technical"
}
}
}

Score​

Rates the state on ordered levels. criteria is an array of 2 to 10 level names, lowest first. The score is a probability-weighted level index, starting at 0, so it can fall between two levels.

"sentiment": {
"type": "score",
"instructions": "How satisfied is the customer?",
"criteria": ["very unhappy", "unhappy", "neutral", "happy", "very happy"]
}

Response Format​

{
"id": "systemone-3f2b9c0e8d4a4b1f9e6c7a5d2b1e0f9a",
"object": "systemone.classification",
"created": 1791360000,
"model": "jev-1.13.0",
"answers": {
"is_urgent": {
"type": "noul",
"noul": 0.95
},
"department": {
"type": "choice",
"choice": "technical",
"probabilities": { "billing": 0.03, "technical": 0.94, "account": 0.03 },
"confidence": 0.91
},
"sentiment": {
"type": "score",
"score": 0.62,
"legend": { "0": "very unhappy", "1": "unhappy", "2": "neutral", "3": "happy", "4": "very happy" },
"probabilities": { "0": 0.45, "1": 0.48, "2": 0.07, "3": 0.0, "4": 0.0 },
"confidence": 0.71
}
},
"usage": {
"input_tokens": 296,
"output_tokens": 20
}
}
Answer typeFields
noulnoul: probability of yes, 0 to 1
choicechoice: the most likely option. probabilities: option name to probability. confidence: how concentrated the distribution is, 0 to 1
scorescore: probability-weighted level index, starting at 0. legend: level index to level name. probabilities: level index to probability. confidence: 0 to 1

Pricing​

SystemOne is billed on input tokens only, at the provider's price of $0.042 per 1M input tokens. Output tokens are reported in usage but not charged.

Rate Limits​

SystemOne has its own rate limits, separate from the other RouteLLM endpoints:

LimitValue
Requests per minute, per organization60 (20 for self-serve organizations)
Questions per request10

A request over a limit returns 429 with a Retry-After header that gives the number of seconds to wait. A 429 can also mean the service as a whole is at capacity. In both cases, retry with exponential backoff.

Errors​

Errors use the OpenAI error envelope:

{
"error": {
"message": "Question \"department\" needs a non-empty \"instructions\" string: Jev reads instructions literally and cannot answer an uninstructed question.",
"type": "invalid_request_error",
"param": null,
"code": null
}
}
StatustypeCause
400invalid_request_errorMissing, empty or oversized state; empty, oversized or more than 10 questions; a question without instructions; criteria that does not match the question's type or exceeds its limits; or an unknown model
429rate_limit_exceededOver the per-organization rate limit, or the service is at capacity. Wait for the time given in Retry-After
429insufficient_quotaYour organization is out of credits
503server_errorThe classification service is temporarily unavailable

Code Examples​

SystemOne is not part of the OpenAI API, so send it as a plain HTTP request.

import requests

response = requests.post(
"<your base url>/systemone",
headers={"Authorization": "Bearer <your_api_key>"},
json={
"state": "Help! My payouts have been failing for 3 days.",
"questions": {
"is_urgent": {
"type": "noul",
"instructions": "Does this message convey urgency?",
},
"department": {
"type": "choice",
"instructions": "Which team should handle this ticket?",
"criteria": {"billing": None, "technical": None, "account": None},
},
},
},
timeout=10,
)
response.raise_for_status()
answers = response.json()["answers"]

print(answers["is_urgent"]["noul"])
print(answers["department"]["choice"], answers["department"]["probabilities"])

Structured State​

Pass records as JSON instead of turning them into prose first. Instructions can refer to a field by putting its name in backticks:

{
"state": {
"plan": "enterprise",
"days_since_last_login": 41,
"open_tickets": 3,
"last_message": "We're evaluating other vendors this quarter."
},
"questions": {
"churn_risk": {
"type": "score",
"instructions": "How likely is this customer to cancel, judging mainly from `last_message`?",
"criteria": ["low", "medium", "high"]
}
}
}

Best Practices​

  1. Write instructions literally. Jev does exactly what the instructions say. Put boundary cases in criteria, for example what does not count as yes, instead of relying on the model to infer them.
  2. Precompute numbers and dates. Jev is weak at arithmetic, counting and comparing dates. Do those calculations in your code and put the result in state, for example "days_overdue": 12 or "over_limit": true.
  3. Batch questions. Ask up to 10 questions about the same state in one request instead of making one call per question.
  4. Use the probabilities. Set your own thresholds on noul and confidence, and send low-confidence cases to a person or to a larger model.
  5. Handle 429 with backoff. Respect the Retry-After header rather than retrying straight away.