API reference
Routes
Section titled “Routes”| method and path | auth in OpenJevX | returns |
|---|---|---|
POST /v1/systemone |
API key (Authorization: Bearer <key>), on when the server listens beyond loopback |
decisions as JSON 1 2 3 |
GET /health |
none | model and load status as JSON 4 5 |
GET / |
dashboard password | the dashboard page 6 |
GET /recipes |
dashboard password | the recipe pages 7 |
GET /stats |
dashboard password | a JSON snapshot 8 9 |
GET /metrics |
dashboard password | Prometheus format 10 9 |
The default listen address is 127.0.0.1:21118. 11
POST /v1/systemone
Section titled “POST /v1/systemone”Request
Section titled “Request”The request body has a state and a map of named questions. 12
state is the text or JSON the question is about. 13
If state is a JSON string, the server uses the string’s text. 14
Otherwise it uses the raw JSON as text. 15
The server reads three fields from each question: type, instructions and criteria. 16
There are three question types: noul, choice and score. 17
The criteria for each type are on the question types page.
One request can ask three questions of the three types. 18
The recipe calls send OPENJEVX_API_KEY; on 127.0.0.1 with no key set the server ignores the header. 19 20
curl -s -H "Authorization: Bearer $OPENJEVX_API_KEY" localhost:21118/v1/systemone -d '{"state": "Checkout is down, customers are being charged twice", "questions": {"urgent": {"type": "noul", "instructions": "Is this urgent?"}, "team": {"type": "choice", "instructions": "Which team?", "criteria": {"web": "frontend", "api": "backend", "billing": "payments"}}, "sev": {"type": "score", "instructions": "How severe?", "criteria": ["low", "medium", "high"]}}}' | jq -c .answersThrough the Marketplace gate, state can be a JSON object and the call carries the API key. 21
curl -s <Endpoint>/healthcurl -s <Endpoint>/v1/systemone -H "Authorization: Bearer <ApiKey>" \ -d '{"state": {"order_total_rs": 501}, "questions": {"discount": {"type": "noul", "instructions": "Does the order get the discount? Orders over Rs 500 get 10% off."}}}'Response
Section titled “Response”The response JSON has the keys model, answers and usage. 3
model is always the string "openjevx", whatever model folder is loaded. 22
GET /health reports the loaded model’s version and sha256. 23
usage holds input_tokens, output_tokens (always 0) and server_ms. 24
input_tokens is the token count of the request’s encoded items. 25
answers maps each question id to its answer. 26 27 28
Each answer carries type, probabilities, confidence and answer_confidence. 29
A choice answer also has choice. 30
A score answer also has score. 31
A noul answer also has noul. 32
When the model returns finite action outputs, the answer also has action.act_probability. 33
The fields are explained on the question types page.
The real answer to this three-question request, from model 0.5.2 on server 0.5.7, CPU, is below. 34
{"sev":{"action":{"act_probability":1},"answer_confidence":0.9339,"confidence":0.9339,"probabilities":{"0":0.0294,"1":0.0367,"2":0.9339},"score":1.9045,"type":"score"},"team":{"action":{"act_probability":1},"answer_confidence":0.5491,"choice":"billing","confidence":0.5491,"probabilities":{"api":0.3245,"billing":0.5491,"web":0.1264},"type":"choice"},"urgent":{"action":{"act_probability":1},"answer_confidence":0.9119,"confidence":0.9119,"noul":0.9119,"probabilities":{"false":0.0881,"true":0.9119},"type":"noul"}}The team is not settled on this model: billing at only 0.55 is below jevx’s 0.6 confidence line. 35
Server-Timing
Section titled “Server-Timing”Every decision response carries a Server-Timing header with encode, wait, run and total durations in ms. 36
wait is time queued for the model session. 37
total runs from reading the request to the decoded answer. 38
The same total is usage.server_ms in the JSON body. 39
Each request takes a lock (inferMu.Lock()) before it runs the model and releases it after. 40
GET /health
Section titled “GET /health”/health returns status, device, model, version, sha256, source, fallback, loaded_at and dir. 41
It adds remote_version and offline when they apply, and previous, the model it replaced. 42 43
/health needs no password. 5
Dashboard, /stats, /metrics, /recipes
Section titled “Dashboard, /stats, /metrics, /recipes”The routes /, /recipes, /stats and /metrics all go through guard. 44
The guard reads the password from HTTP Basic auth and ignores the user name. 45
Without Basic auth, it reads a password query parameter. 46
A wrong or missing password gets 401 with WWW-Authenticate: Basic realm="openjevx". 47
The password is password in openjevx.json or OPENJEVX_PASSWORD; the environment wins over openjevx.json. 48 49
The dashboard password is always on: unset, the server generates one into openjevx.password. 48
A start that creates it shows the value once, and only on a terminal. 50
When stderr is a log (Docker, systemd, ECS, CloudWatch), the server logs the file and a fingerprint (sha256 ...37dd), never the secret, so read it from the file. 51
The old published password adminadmin (in openjevx.json up to v0.5.6) is ignored and replaced by a generated one. 52
Warning:
allow_no_password(orOPENJEVX_ALLOW_NO_PASSWORD=1) turns the dashboard password off. 53 With no password, the guard runs the handler without checking. 54
The Docker image refuses to start without OPENJEVX_PASSWORD and OPENJEVX_API_KEY, or your own openjevx.json mounted at /data/openjevx.json. 55
The entrypoint stops with “OPENJEVX_PASSWORD must be at least 12 characters” when it is shorter. 56
/metrics exports request, error, question and input-token counters and latency gauges (avg, p50, p95, p99, max). 57
Errors
Section titled “Errors”Errors are written with http.Error. 58
| status | when |
|---|---|
| 405 | the method is not POST 59 |
| 400 | the body is not valid JSON 60 |
| 400 | questions missing 61 |
| 400 | unknown type 62 63 |
| 400 | need at least two options 64 63 |
| 400 | missing criteria 65 63 |
| 500 | the model run returns an error 66 |
| 401 | missing or wrong API key on POST /v1/systemone, body {"error":"missing or wrong API key"} and WWW-Authenticate: Bearer 67 68 |
| 401 | (jev-cloud gate, when an API key is set) missing or wrong API key on a /v1/ path, body {"error":"missing or wrong API key"} 69 |
The error text for a bad question starts with the question id. 70
OpenJevX checks an API key on POST /v1/systemone, sent as Authorization: Bearer <key>. 67
The key is api_key in openjevx.json or OPENJEVX_API_KEY; the environment wins over openjevx.json. 71 49
It is on whenever the server listens beyond loopback, and off on 127.0.0.1, ::1 and localhost unless one is set. 72
When the key is needed but unset, the server generates one into openjevx.api-key beside openjevx.json. 71
Generated files are created once with mode 0600 and reused. 49
They go beside openjevx.json, else in $OPENJEVX_DATA, else the working folder, whichever is writable, so a config mounted read-only still starts. 73
A start that creates one of these files shows the value once, and only on a terminal; a log gets the file and a fingerprint, never the secret. 51
A key shorter than 16 characters fails startup with api key from … is N characters; use at least 16. 74 75 76
allow_no_api_key (or OPENJEVX_ALLOW_NO_API_KEY=1) turns the key off even when public, e.g. behind a proxy that checks it. 77
At startup the server logs whether the key is required or off. 78
curl -H "Authorization: Bearer YOUR_API_KEY" http://<host>:21118/v1/systemone -d @body.jsonWarning: on the default listen address
127.0.0.1:21118the key is off unless you set one. 11 72 The Docker image listens on0.0.0.0:21118, so there the key is required. 79 72
The jev-cloud gate puts an API-key check in front of OpenJevX. 80
/health stays open, and every /v1/* call needs Authorization: Bearer <JEV_API_KEY>. 81
The gate checks the Bearer key with a constant-time compare. 82
curl -s <Endpoint>/v1/systemone -H "Authorization: Bearer YOUR_API_KEY" \ -d '{"state": {"order_total_rs": 501}, "questions": {"discount": {"type": "noul", "instructions": "Does the order get the discount? Orders over Rs 500 get 10% off."}}}'In the container product (EKS/ECS) the gate runs openjevx on 127.0.0.1:21119, where openjevx’s own key is off. 83
Sources
Section titled “Sources”Footnotes
Section titled “Footnotes”-
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/auth.goL22–23 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL206–208 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL96–100 ↩ ↩2 -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL190–205 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL165–172 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL192–194 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL206 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL207 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL447–448 ↩ ↩2 -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL28–31 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
recipes/README.mdL34–35 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL484–488 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL479–490 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/decide/decide.goL63–68 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
recipes/README.mdL35–41 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
recipes/17-several-judgements.mdL3 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
recipes/17-several-judgements.mdL7 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
recipes/README.mdL21–22 ↩ -
jev-cloud @ origin/main (10a744c) ·
marketplace/aws/listing/usage-instructions-openjevx-server.txtL20–21 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL96–97 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL82–83 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL99 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL92–99 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL93–98 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/decide/decide.goL196–198 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/decide/decide.goL254–256 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/decide/decide.goL229–234 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/decide/decide.goL235–237 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/decide/decide.goL238–243 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/decide/decide.goL244–246 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/decide/decide.goL248–253 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
recipes/17-several-judgements.mdL10–13 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
recipes/17-several-judgements.mdL39 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL19–20 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL59–61 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL60–61 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL61 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL72–83 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL190–194 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL195–204 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL115–116 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL165–188 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL514 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL514–516 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL515–525 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL38–39 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL42–43 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL34 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL510–512 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL169–170 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
deploy/docker-entrypoint.shL10 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/stats/stats.goL135–143 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL32–34 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL23–26 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL52–55 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL56–59 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/decide/decide.goL117–118 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL61–65 ↩ ↩2 ↩3 -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/decide/decide.goL120–121 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/decide/decide.goL270–273 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/decision.goL81–87 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/auth.goL182–186 ↩ -
jev-cloud @ origin/main (10a744c) ·
image/gate/main.goL132–136 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
internal/decide/decide.goL54–57 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/auth.goL23 ↩ ↩2 ↩3 -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL36–38 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/auth.goL33 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/auth.goL76–78 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL97–100 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
README.mdL33 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
cmd/openjevx/main.goL101–105 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
deploy/docker-entrypoint.shL16 ↩ -
jev-cloud @ origin/main (10a744c) ·
image/gate/main.goL1–6 ↩ -
jev-cloud @ origin/main (10a744c) ·
image/gate/main.goL5–6 ↩ -
jev-cloud @ origin/main (10a744c) ·
image/gate/main.goL5 ↩ -
openjevx @ v0.5.9 (ee2a1f4) ·
docs/DEPLOY.mdL85–87 ↩