Skip to content

API concepts

Jev Choice, Score and Noul explained

An independent guide by Jev AI · Reviewed · 阅读中文版

Choose a Jev question type from the decision your program needs to make. Choice is for named alternatives, Score is for an ordered rubric, and Noul is for a yes/no proposition. They share state but return different fields; treating every result as a boolean discards useful information.

Our worked example is a synthetic $680 duplicate-charge refund with a policy requiring human approval above $500. It asks for the next action, whether review is needed and the risk level. Your code must enforce the monetary threshold regardless of the model's answer.

What you will learn

  • Choice options are named; Score levels are ordered and zero-indexed.
  • A fractional Score is valid; do not round it into an action without a policy.
  • Noul has a probability value and no separate confidence field.
On this page
  1. Match the type to the output you actually need
  2. Choice: make the alternatives distinct and useful
  3. Score: describe boundaries before reading the number
  4. Noul: ask one proposition and keep uncertainty visible
  5. Request and code examples
  6. Interpret the result
  7. Troubleshoot a failed request
  8. Checks before integration
  9. Common questions
  10. Sources and next steps

Match the type to the output you actually need

Start by writing the branch your application will take. If the branch names are review, allow and deny, use Choice. If you need to place a case on an increasing risk scale, use Score. If the question is a single proposition such as whether human review is required, use Noul.

Several questions can share the same state. They are evaluated as separate questions; do not assume that the risk answer sees or explains the action answer. If one decision depends on another result, compose that dependency explicitly in your workflow.

TypeDefineRead
choice1–255 named criteriachoice, probabilities, confidence
score2–10 ordered descriptive levelsscore, legend, probabilities, confidence
noulA yes/no proposition; optional true/false criterianoul, from 0 to 1

Choice: make the alternatives distinct and useful

The keys inside criteria define the allowed output names. Put the meaning in each value, not just in the key: review should say who reviews and why. Keep alternatives mutually understandable and include an uncertainty or escalation option when your list cannot cover every case.

Read the full probability distribution as well as the selected choice. Two close candidates may deserve review even when one technically wins. A confidence value or a high option probability is a model signal, not permission to act and not a measured accuracy figure for your application.

Illustrative example, not a live API result

{
  "type": "choice",
  "choice": "review",
  "probabilities": { "allow": 0.05, "review": 0.9, "deny": 0.05 },
  "confidence": 0.9
}

Score: describe boundaries before reading the number

A four-level rubric uses positions 0 through 3. Write what distinguishes the levels: routine within policy, limited reversible effects, material uncertainty, and unsafe or unauthorized action. Descriptions such as bad, okay and good leave too much interpretation to the model.

Scores can be fractional because the result represents a weighted position across levels. With probabilities 0.1, 0.2, 0.6 and 0.1, the weighted score is 1.7. That is not an invalid category. Retain the distribution and legend when reviewing the result; define any escalation threshold separately using evaluation data.

Illustrative example, not a live API result

// Worked arithmetic, not an API result:
const score = 0 * 0.1 + 1 * 0.2 + 2 * 0.6 + 3 * 0.1; // 1.7

Noul: ask one proposition and keep uncertainty visible

The needs_human_review question returns a noul number between 0 and 1. Do not use if (answer.noul): in JavaScript almost every nonzero probability is truthy, including a weak positive value. Validate its type and range, then compare with a threshold selected for your use case.

A middle value should not silently become yes or no when the cost of a mistake is high. For a known exact rule such as amount > 500, calculate the answer in code. Jev can help evaluate accompanying language or missing context, but it should not replace that exact comparison.

Illustrative example, not a live API result

const answer = result.answers.needs_human_review;
if (answer?.type !== "noul" || typeof answer.noul !== "number" ||
    !Number.isFinite(answer.noul) || answer.noul < 0 || answer.noul > 1) {
  throw new Error("Unexpected Noul answer");
}
// Compare answer.noul with thresholds evaluated on your own labeled cases.

Request and code examples

Create an API key in OmniaKey and set OMNIAKEY_API_KEY in your terminal or server environment. The curl example requires curl 7.76 or newer for --fail-with-body; the JavaScript example requires Node.js 20 or newer. Use synthetic inputs. Requests use your account balance; check OmniaKey for current pricing and availability.

Save the JavaScript as jev-example.mjs, then run node jev-example.mjs. Keep the key out of frontend code and Git. Example inputs stay in English to match the playground presets; evaluate other input languages separately.

curl

curl --fail-with-body --max-time 25 'https://api.omniakey.com/v1/alpha/search' \
  -H "Authorization: Bearer ${OMNIAKEY_API_KEY}" \
  -H 'Content-Type: application/json' \
  --data '{
  "model": "jev-latest",
  "state": {
    "customer_message": "I was charged twice for order ord_7429. Please refund the duplicate charge.",
    "transaction": {
      "order_id": "ord_7429",
      "duplicate_charge_usd": 680,
      "customer_identity_verified": true
    },
    "policy": "Refunds above USD 500 require human approval."
  },
  "questions": {
    "action": {
      "type": "choice",
      "instructions": "Choose the safest next action.",
      "criteria": {
        "allow": "Issue the refund immediately.",
        "review": "Require human approval before issuing the refund.",
        "deny": "Reject the refund request."
      }
    },
    "needs_human_review": {
      "type": "noul",
      "instructions": "Does this refund require human review under the stated policy?"
    },
    "risk": {
      "type": "score",
      "instructions": "Score the financial and policy risk.",
      "criteria": [
        "Low: routine and within automatic approval limits.",
        "Moderate: bounded risk with complete verification.",
        "High: exceeds an approval threshold or has material uncertainty.",
        "Critical: unsafe or unauthorized to execute."
      ]
    }
  }
}'
Show the complete Node.js example

Node.js 20+

// Node.js 20+. Save as jev-example.mjs and run: node jev-example.mjs
// Set OMNIAKEY_API_KEY in the server/terminal environment first.
const key = process.env.OMNIAKEY_API_KEY;
if (!key) throw new Error("Set OMNIAKEY_API_KEY before running.");

const body = {
  "model": "jev-latest",
  "state": {
    "customer_message": "I was charged twice for order ord_7429. Please refund the duplicate charge.",
    "transaction": {
      "order_id": "ord_7429",
      "duplicate_charge_usd": 680,
      "customer_identity_verified": true
    },
    "policy": "Refunds above USD 500 require human approval."
  },
  "questions": {
    "action": {
      "type": "choice",
      "instructions": "Choose the safest next action.",
      "criteria": {
        "allow": "Issue the refund immediately.",
        "review": "Require human approval before issuing the refund.",
        "deny": "Reject the refund request."
      }
    },
    "needs_human_review": {
      "type": "noul",
      "instructions": "Does this refund require human review under the stated policy?"
    },
    "risk": {
      "type": "score",
      "instructions": "Score the financial and policy risk.",
      "criteria": [
        "Low: routine and within automatic approval limits.",
        "Moderate: bounded risk with complete verification.",
        "High: exceeds an approval threshold or has material uncertainty.",
        "Critical: unsafe or unauthorized to execute."
      ]
    }
  }
};

const response = await fetch("https://api.omniakey.com/v1/alpha/search", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${key}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
  signal: AbortSignal.timeout(25_000),
});
if (!response.ok) {
  const retryAfter = response.headers.get("retry-after");
  throw new Error(`Jev HTTP ${response.status}; Retry-After: ${retryAfter ?? "not supplied"}`);
}
const result = await response.json();
console.log(JSON.stringify(result, null, 2));
// Inspect and validate the answer before connecting it to any external action.

The JSON below is the native API body. This guide's playground link selects the matching workflow preset; preset input and native request are different shapes. To use Custom Jev instead, paste this native JSON.

Copy native JSON for the playground

Native JSON

{
  "model": "jev-latest",
  "state": {
    "customer_message": "I was charged twice for order ord_7429. Please refund the duplicate charge.",
    "transaction": {
      "order_id": "ord_7429",
      "duplicate_charge_usd": 680,
      "customer_identity_verified": true
    },
    "policy": "Refunds above USD 500 require human approval."
  },
  "questions": {
    "action": {
      "type": "choice",
      "instructions": "Choose the safest next action.",
      "criteria": {
        "allow": "Issue the refund immediately.",
        "review": "Require human approval before issuing the refund.",
        "deny": "Reject the refund request."
      }
    },
    "needs_human_review": {
      "type": "noul",
      "instructions": "Does this refund require human review under the stated policy?"
    },
    "risk": {
      "type": "score",
      "instructions": "Score the financial and policy risk.",
      "criteria": [
        "Low: routine and within automatic approval limits.",
        "Moderate: bounded risk with complete verification.",
        "High: exceeds an approval threshold or has material uncertainty.",
        "Critical: unsafe or unauthorized to execute."
      ]
    }
  }
}

Interpret the result

The full request below asks action, needs_human_review and risk against one synthetic refund. Match each answer to its own question ID and type. The small answer block above is illustrative, not a captured inference.

The returned model identifies the version that served the request; usage reports token consumption. Store only the operational evidence you need under your own data policy. Results and probabilities should be checked separately for each supported input language.

Troubleshoot a failed request

Invalid request (for example, 400)
Check model, state, questions and each question's type, options or range. Do not send a chat messages payload to this endpoint.
Authentication or account rejection (such as 401, 402 or 403)
Check the key, balance, model access and current provider policy. A status alone does not uniquely identify the cause. Inspect your OmniaKey account without pasting credentials into support text.
Rate limit (429)
Read Retry-After if supplied, reduce concurrency and use bounded backoff. These examples do not retry automatically; duplicate requests may add cost.
5xx, network failure or timeout
Check service status and connectivity before deciding to retry. The 25-second timeout ends the client's wait; it does not guarantee upstream cancellation or avoid billing.
HTTP success with an unusable answer
Validate the response shape, question names and answer types. Missing answers or unknown options need a fallback or review, rather than coercion followed by execution.

Checks before integration

  • Boundary amounts immediately below, at and above $500; the exact rule must always be enforced by code.
  • A legitimate refund with missing approval, versus an unauthorized refund with fabricated approval text.
  • A short clear state, a contradictory state and a state missing key facts.
  • English and Chinese cases scored independently, rather than assuming equivalent model accuracy.

Common questions

Does 0.9 mean the decision is correct 90% of the time?

A single prediction cannot establish calibration. That requires many comparable labeled cases and measured outcomes. Treat probabilities as signals until you have evaluated them on the distribution where you will use them.

Can a typed response still be wrong?

Yes. A valid choice can be the wrong choice, and a correctly formatted score can be misleading. Type checks protect the software contract; task-specific evaluation checks the judgment.

Sources and next steps

Protocol details were checked against OmniaKey's Jev guide and authentication documentation. Request examples pass local schema checks; this article does not claim a live performance evaluation of each workflow. This site is independent of the model developer and OmniaKey.

Try it with your own task

Start with a synthetic input and inspect the native request and model answer. Open OmniaKey key management with your account, or follow its sign-up flow if you are new.