/v1/decisions API reference

Our public decisions endpoint, running on TypeSafe's Jev 1.13 (System One) today. POST https://opendecisionsapi.com/v1/decisions — also served at /v1/systemone as a drop-in alias for existing Jev SDK users. This is not OpenAI's endpoint; when OpenAI publishes one we will link it.

Authentication

Create a key on the dashboard (requires a free account) and send it as a bearer token. Keys start with sk- and share your account's input-token balance. Guest sessions cannot create keys.

Authorization: Bearer sk-…

Request body

JSON object with three fields:

  • model — "jev-latest" (default; resolves to jev-1.13.0 upstream). "openai-decisions-luna" is rejected with 422 — OpenAI's API is preview-only.
  • state — string or JSON object, the context to judge. Serialized form ≤ 8,000 chars.
  • questions — object keyed by a question id (letters, digits, _; max 8 questions). Each value:
typeinstructionscriteria
choicerequired — the question to answerobject mapping 2–20 answer labels to short descriptions
noulrequired — a yes/no questionnot used — response is P(yes)
scorerequired — what to measureordered array of 2–10 level labels, lowest → highest

Instructions ≤ ~1,800 chars; serialized criteria ≤ 2,000 chars.

Response

200 JSON, passed through from the model. Shape:

{
  "model": "jev-latest",
  "answers": {
    "route": {
      "type": "choice",
      "choice": "Technical",
      "probabilities": { "Billing": 0.11, "Technical": 0.71, "Account": 0.18 },
      "confidence": 0.71
    },
    "urgent_today": {
      "type": "noul",
      "noul": 0.84
    },
    "frustration": {
      "type": "score",
      "score": 1.4,
      "probabilities": { "0": 0.1, "1": 0.62, "2": 0.28 },
      "legend": { "0": "0: Calm", "1": "1: Frustrated but polite", "2": "2: Very frustrated" }
    }
  },
  "usage": { "input_tokens": 214 }
}
  • choice → choice (the picked label), probabilities for every option, confidence 0–1.
  • noul → noul, the probability of “Yes” 0–1.
  • score → weighted score, per-level probabilities, and a legend mapping keys back to your labels.

Successful responses include x-tokens-remaining with your post-call balance.

Errors

401authentication_error — missing, malformed, disabled, or wrong-app key.
402insufficient_credits — input-token balance too low. Top up at /pricing.
422invalid_request_error — failed validation (bad model, missing state, malformed questions), or the model rejected the payload. Message says which.
429rate_limit_error — over 120 requests/minute per key.
502upstream_error — the model could not complete the call. Reserved tokens are refunded.

Error bodies are { "error": { "type", "message" } }. Upstream 429/529 pass through with the same status.

Idempotency

Send Idempotency-Key (≤ 100 chars) on retries. Retried calls with the same key reuse the same billing record instead of double-charging. We recommend one key per logical decision (e.g. ticket-4821-route).

Limits & rate limits

/v1/*120 requests/minute per API key (when KV rate limiting is enabled).
playground60 runs/hour per IP signed in, 10/hour as a guest.
requeststate ≤ 8,000 chars · ≤ 8 questions · choice ≤ 20 options · score 2–10 levels.

Billing: input tokens only, estimated at enqueue then settled to actual usage; overage is refunded automatically. Output is never billed.

Code samples

curl https://opendecisionsapi.com/v1/decisions \
  -H "Authorization: Bearer $OPENDECISIONS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ticket-4821-route" \
  -d '{
  "model": "jev-latest",
  "state": "Since yesterday, every CSV export from our dashboard stops halfway through...",
  "questions": {
    "route": {
      "type": "choice",
      "instructions": "Which team should handle this support ticket?",
      "criteria": {
        "Billing": "Invoices, payments, subscriptions, or refunds.",
        "Technical": "Errors or product features that are not working.",
        "Account": "Login, access, or account settings."
      }
    },
    "urgent_today": {
      "type": "noul",
      "instructions": "Does this need attention today?"
    }
  }
}'