Superion S1 API

Documentation

Base URL https://api.punkytigerlabs.com · Authentication Authorization: Bearer s1k_… · JSON over HTTPS. The API follows the standard System One request and response format.

On this page: First decision · Models · Questions · Answers · Errors · Headers and limits · Billing · Keys

Your first decision

Send a state (the text, document or conversation to judge) and named questions. Every answer comes back under the name you gave it.

curl https://api.punkytigerlabs.com/v1/systemone \
  -H "Authorization: Bearer $S1_KEY" -H "Content-Type: application/json" \
  -d '{"model": "superion-s1-latest",
       "state": "Message: The laptop arrived broken. I want my money back now, this is unacceptable.",
       "questions": {
         "refund": {"type": "noul", "instructions": "Does the customer ask for a refund or a replacement?", "criteria": {"true": "yes", "false": "no"}},
         "sentiment": {"type": "choice", "instructions": "Overall sentiment of the message.", "criteria": {"pos": "positive", "neg": "negative", "neu": "neutral"}},
         "urgency": {"type": "score", "instructions": "How urgent is a reply?", "criteria": ["not urgent", "somewhat urgent", "very urgent"]}}}'
{"model": "superion-s1-v6-int4e-vllm-kv1@sha256:e6dc49dc",
 "answers": {
   "refund": {"type": "noul", "noul": 0.9998},
   "sentiment": {"type": "choice", "choice": "neg", "confidence": 0.9661, "probabilities": {"pos": 0.0003, "neg": 0.9941, "neu": 0.0056}},
   "urgency": {"type": "score", "score": 1.9393, "confidence": 0.7917, "probabilities": {"0": 0.0, "1": 0.0607, "2": 0.9393}, "legend": {"0": "not urgent", "1": "somewhat urgent", "2": "very urgent"}}},
 "usage": {"input_tokens": 135, "output_tokens": 0},
 "meta": {"request_id": "63a6718e-ab64-404b-92f3-fdba826d0dfe", "mode": "live", "latency_ms": 103}}

Real response to this exact request (12 Nov 2026, model superion-s1-v6-int4e-vllm-kv1@sha256:e6dc49dc), rounded to four decimals for display; the API returns full precision. latency_ms is server-side processing time.

Python

import os, requests
r = requests.post("https://api.punkytigerlabs.com/v1/systemone", timeout=120,
    headers={"Authorization": "Bearer " + os.environ["S1_KEY"]},
    json={"model": "superion-s1-latest",
          "state": "Message: I was charged twice this month. Can you refund the extra payment?",
          "questions": {"team": {"type": "choice", "instructions": "Which team should handle this?",
                                 "criteria": {"billing": "Payments, invoices and refunds",
                                              "support": "Technical problems and bugs"}}}})
r.raise_for_status()
print(r.json()["answers"]["team"]["choice"])   # "billing"

JavaScript

const r = await fetch("https://api.punkytigerlabs.com/v1/systemone", {
  method: "POST",
  headers: { "Authorization": `Bearer ${process.env.S1_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ model: "superion-s1-latest", state: "…", questions: { /* … */ } })
});
if (!r.ok) throw new Error(await r.text());
const { answers } = await r.json();

Use a client timeout of at least 120 s. Most requests finish well under a second; under heavy load a request waits in the fair queue instead of failing.

Models

modelWhat it is
superion-s1-latestAlways the current recommended release (today v6). Also used when model is omitted. The response names the exact release that answered.
superion-s1-v6-int4e-vllm-kv1@sha256:e6dc49dcSuperion S1 v6, pinned. Recommended.
superion-s1-v5-int4e-vllm-kv1@sha256:47f7571cSuperion S1 v5, pinned. Available.

Pinned IDs are immutable: the hash identifies the exact package served, and results are deterministic within a pinned release: the same request returns the same probabilities. New releases get new IDs; retirement comes with at least 90 days notice. GET /v1/models lists what is served. Superion S1 is built on Gemma 4 26B-A4B, served with mixture-of-experts weights in INT4.

Questions

typecriteriaanswer fields
noulobject with true and false descriptionsnoul: probability that the answer is yes
choiceobject: option id → description (2–255 options)choice, confidence, probabilities
scorearray of 2–16 ordered levels, lowest firstscore, confidence, probabilities, legend

Every question needs type, instructions and criteria. Describe each option or level the way you would for a careful human reviewer; clear descriptions give better answers. You can ask any number of questions about the same state in one request, within the token limits below. Before automating on a threshold, check the probabilities on a sample of your own data.

Answers

fieldmeaning
modelThe pinned release that answered.
answers.<name>.noulProbability of yes, 0–1.
answers.<name>.choiceThe most likely option id.
answers.<name>.scoreExpected level on the scale, from 0 to N−1 (probability-weighted).
answers.<name>.probabilitiesCalibrated probability per option id (choice) or per level index (score). They sum to 1.
answers.<name>.confidenceHow concentrated the probabilities are: 1 − H(p) / ln(n) for n options. 1 when one option holds all the probability, 0 when all are equally likely. It is not the probability of the chosen option.
answers.<name>.legendScore only: level index → your level description.
usage.input_tokensBilled input tokens (what counts). output_tokens is always 0.
meta.request_idUnique id of the request; same as the X-Request-ID header. Quote it to support.
meta.latency_msServer-side time: admission, queue and inference. It excludes your network round trip.
meta.cost_usdPrepaid keys: the exact charge for this request, in USD.

Errors

Errors return JSON with an error message and, where useful, a machine-readable code. Check the HTTP status before reading answers. Requests that fail are never charged and do not count toward quotas.

{"error": "insufficient balance: add credits at https://punkytigerlabs.com/s1/ (prepaid, 0.042 USD per million input tokens)",
 "code": "insufficient_credits", "contact_url": "https://punkytigerlabs.com/s1/account", "balance_usd": 0.0}
StatusMeaningWhat to do
400Invalid JSON, unknown model or malformed questionFix the request; the message says what
401Missing, wrong, rotated or revoked keyCheck the key
402Prepaid balance is used up (code: "insufficient_credits", with contact_url)Add credits
413Body over 4 MBSplit the request
422A question exceeds 32,768 tokens, the request exceeds 65,536 billable tokens, more than 255 options or more than 16 levelsShorten the state or split the questions
429Daily quota used up, prepaid per-minute limit, or queue full (code: "rate_limited")Wait for Retry-After
503Service temporarily unavailableRetry with backoff, respecting Retry-After; quote the request id if it persists

Headers and limits

HeaderWhen
X-Request-IDEvery response, including errors.
Retry-After429 and 503, in seconds.
X-RateLimit-Limit-Tokens-Day, -Remaining-Tokens-Day, -Reset-DayFree keys (daily quota; reset at 00:00 UTC).
X-RateLimit-Limit, -Remaining, -Reset and the same with -Tokens; X-S1-Balance-USDPrepaid keys (per-minute limits and balance).
PlanPer minutePer day (UTC)In flight
Freeno limit (fair queue)20 M input tokens8
Prepaid240 requests · 80,000 input tokensno cap (balance)32

Size limits: each question (state + that question) up to 32,768 tokens; each request up to 65,536 billable input tokens; body up to 4 MB. Longer inputs are refused with 422, never truncated. When the service is busy, requests wait in a fair queue (up to 60 s; paid keys first) instead of failing.

Billing: what counts as input tokens

usage.input_tokens is what we bill: your state once per request, plus each question's instructions, criteria and option labels, in the Gemma 4 tokenizer. Asking more questions about the same state only adds the questions' own tokens. Output is always free. Prepaid: 0.042 USD per million input tokens, deducted per successful request with exact integer accounting; meta.cost_usd shows the charge. The request that crosses zero is completed; the next one returns 402.

Your key and usage

GET /v1/usagePlan, today's counters, limits, balance, daily history (90 days), purchases
POST /v1/keys/rotateReturns a new key; the old one stops working at once
POST /v1/keys/revokeDisables the key
GET /v1/models · GET /healthNo key needed

Keep keys on your server: /v1/systemone, /v1/usage and /v1/keys/* send no CORS headers, so browsers cannot call them. We store only a hash of each key.

Data

We do not store your requests or answers. See privacy and the API terms. For custom and industry models or dedicated capacity, contact us.