Tutorial

Getting started with Jev API: your first structured decision in 5 minutes

Create an account, add prepaid credit, mint a jev_live_ key and make your first POST /v1/systemone call with curl. Learn to read choice, score and noul answers.

Jev API answers bounded questions about a piece of text or data. You send a state (the facts) and a set of typed questions. You get back structured answers with probabilities, plus the token usage for the call. There is no chat endpoint and no free-form text generation: the API is built for classification, routing, scoring and yes/no judgments that your code can act on directly.

This tutorial goes from a new account to your first decision. You will create an account, add credit, mint an API key, check that the key works, send a request with curl, and learn how to read each part of the response. Allow about five minutes, plus however long the card payment takes.

What you need

  • A terminal with curl. jq is optional but makes JSON output easier to read.
  • A payment card for Stripe Checkout. The minimum top-up is $5.
  • A short piece of text you want to classify. The examples below use a customer support message.

Step 1: Create an account

Open the registration page and sign up with an email address and a password of at least 8 characters. No verification email or OAuth flow is involved. You are signed in straight away and taken to the dashboard, where you manage your balance, API keys, usage history and ledger.

Step 2: Add prepaid credit

Jev API is prepaid. Every successful call deducts its cost from your balance, so calls only work once the balance is above zero. On the dashboard, find the Add credit card, enter a whole-dollar amount (minimum $5) and click Pay with Stripe. You complete the payment on Stripe Checkout and come back to the dashboard.

Credit is applied when Stripe's signed webhook confirms the payment, so the balance may take a moment to update. Reload the dashboard if it still shows the old amount. Two terms are worth knowing before you pay. Purchased credits are non-refundable, and they cannot be withdrawn or cashed out (see the Terms of Service). Start with a small top-up until you have measured your real usage. The cost guide shows how to estimate it.

You can create keys before adding credit. Until the balance covers a call, POST /v1/systemone returns HTTP 402 with the error code insufficient_balance.

Step 3: Create an API key

In the New API key card, give the key a name that says where it will be used, such as support-triage-prod, and pick an environment:

  • live keys start with jev_live_
  • test keys start with jev_test_

Both kinds authenticate against the same endpoints and are billed from the same prepaid balance. Treat the environment as a label for organising keys, not as a free sandbox. The full key is shown once, right after you create it. Jev API keeps only a SHA-256 hash and a short prefix, which is what the keys table shows afterwards. Copy the key into a secret store or an environment variable straight away:

export JEV_API_KEY="jev_live_xxx"   # paste your real key here; never commit it

If a key leaks, click Revoke next to it on the dashboard. Requests with that key then fail with 401 Invalid or revoked API key.

Step 4: Check the key with GET /v1/models

GET /v1/models uses the same Bearer authentication as the decision endpoint. It does not run a model and does not deduct credit, so it is a safe way to confirm that your key and network path work:

curl -s https://jev-api.com/v1/models \
  -H "Authorization: Bearer $JEV_API_KEY"

A valid key returns a models array with the aliases jev-latest and jev-preview, each with a name, description and release_date:

{
  "models": [
    { "name": "jev-latest", "description": "…", "release_date": "2026-09-10T18:38:01.391457+00:00" },
    { "name": "jev-preview", "description": "…", "release_date": "2026-09-10T18:39:06.057655+00:00" }
  ]
}

The pinned version jev-1.13.0 is not in this list, but the decision endpoint accepts it.

Step 5: Send your first decision

Now call POST /v1/systemone. The request body has three fields:

  • model: which model to use. jev-latest is a sensible default.
  • state: the facts the decision is about. It can be a string, an object or an array.
  • questions: an object whose keys are your own identifiers and whose values are typed questions.

This request asks three things about a single support message: which team should handle it (choice), how urgent it is (score), and whether the customer wants money back (noul).

curl -s https://jev-api.com/v1/systemone \
  -H "Authorization: Bearer $JEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "jev-latest",
    "state": "Hi, I was charged twice for my March invoice and need one of the charges reversed before my card statement closes on Friday.",
    "questions": {
      "department": {
        "type": "choice",
        "instructions": "Which team should handle this message?",
        "criteria": {
          "billing": "Charges, invoices, refunds or subscription changes",
          "technical": "Bugs, outages, errors or integration problems",
          "sales": "Pricing questions or new purchases"
        }
      },
      "urgency": {
        "type": "score",
        "instructions": "How urgent is this message?",
        "criteria": ["Routine", "Needs attention this week", "Needs attention today"]
      },
      "wants_refund": {
        "type": "noul",
        "instructions": "Is the customer asking for money back?"
      }
    }
  }'

The Authorization header must be exactly Bearer, one space, then the key. Pipe the output through jq if you want it pretty-printed.

Step 6: Read the response

A successful call returns HTTP 200 with model, answers and usage. The numbers below are illustrative. Yours will differ.

{
  "model": "jev-1.13.0",
  "answers": {
    "department": {
      "type": "choice",
      "choice": "billing",
      "confidence": 0.9,
      "probabilities": { "billing": 0.94, "technical": 0.04, "sales": 0.02 }
    },
    "urgency": {
      "type": "score",
      "score": 2.0,
      "confidence": 0.8,
      "legend": { "0": "Routine", "1": "Needs attention this week", "2": "Needs attention today" },
      "probabilities": { "0": 0.02, "1": 0.13, "2": 0.85 }
    },
    "wants_refund": { "type": "noul", "noul": 0.97 }
  },
  "usage": { "input_tokens": 310, "output_tokens": 58 }
}

Choice answers

choice is one of the keys you defined in criteria. probabilities gives a value for every option, and confidence summarises how decisive the answer is. In code, branch on choice. Use confidence or the probability gap between the top two options if you want to send uncertain cases to a person.

Score answers

Score questions take an ordered list of criteria, lowest level first. The response repeats the levels in legend, keyed "0", "1", "2" and so on, with a probability for each level and a numeric score on that scale. Keep the number for sorting and thresholds, and use legend to show a human-readable label.

Noul answers

A noul answer is a single value between 0 and 1: how strongly the state supports a “yes”. The API does not turn it into true or false for you. You choose the threshold that fits your workflow. The question design guide shows one way to pick it.

Model and usage

The response model is a versioned ID such as jev-1.13.0, even when you requested an alias like jev-latest. Log it next to each decision so you can tell later which version produced which result. usage.input_tokens is what you are billed for. Output tokens are free. At $0.084 per million input tokens, the 310-token call above costs 310 × 0.084 = 26.04 micro-dollars, rounded up to $0.000027.

When something goes wrong

Errors use one JSON envelope on every endpoint:

{ "error": { "code": "unauthorized", "message": "Invalid or revoked API key.", "request_id": "req_…" } }

Every response, successful or not, also carries an x-request-id header with the same ID. Note it when you report a problem. These are the errors you are most likely to see on a first call:

Statuserror.codeExample error.messageWhat it means
400invalid_requestJSON body is required.The body is missing or is not valid JSON.
400invalid_requestField `model` is required.No model string was sent.
400invalid_requestField `state` is required (string, object, or array).The state key is absent.
400invalid_requestField `questions` must be an object of typed questions.questions is missing, is an array, or is not an object.
400invalid_requestAt least one question is required.questions is an empty object.
400invalid_requestUnknown model. Use one of: jev-latest, jev-preview, jev-1.13.0.The model ID is not one the API accepts.
400invalid_requestThe model request failed validation.The request passed the basic checks, but the questions were rejected, for example because a question is malformed.
401unauthorizedProvide a Bearer API key (jev_live_… or jev_test_…).No Authorization: Bearer … header was sent.
401unauthorizedInvalid or revoked API key.The key is mistyped, does not exist, or was revoked on the dashboard.
402insufficient_balanceBalance 0.000000 USD is below the estimated 0.000057 USD charge.Your prepaid balance does not cover the estimated cost of this call.
429service_errorThe model service could not complete the request.The model service is rate limiting requests. Back off and retry.
502service_errorThe model service could not be reached.A temporary failure behind the API. Also used for “could not complete the request” and “returned an unexpected response”.
503service_errorThe model service is temporarily unavailable.Model requests are not available right now.
500internal_errorAn unexpected error occurred.An unhandled server error.

Authentication is checked before the body. A request with a bad key and a bad body therefore returns 401, not 400. Requests that end in an error are not charged, because credit is deducted only after a call succeeds.

Choosing a model

Three model IDs are available, all at the same price:

  • jev-latest follows the current stable Jev release.
  • jev-preview follows the newest release, including previews.
  • jev-1.13.0 pins a version. Use it when thresholds you tuned must stay stable from one request to the next.

Start on jev-latest while you experiment. Switch to the pinned version once you have tuned thresholds against real data.

Next steps

You now have a working key and know how to read each answer type. From here, move the call into your application code and harden it:

  • Docs: account, key and credit setup from start to finish.
  • API reference: the full request and response contract for POST /v1/systemone and GET /v1/models.
  • Pricing: current per-token price and how prepaid credit works.

More tutorials on this blog:

← All posts