Skip to documentation
DOCUMENTATION / PUBLIC BETA / HTTP API
BUILD WITH JUDGMENT

Evidence in.
Decisions out.

Turn your question and context into a typed judgment.
One request. A signed record your application can verify.

BASE URLhttps://jevlink.xyzHTTPS · JSON
01 / JEVLINK API

What is JevLink?#

JevLink turns unstructured evidence into typed machine judgments and wraps the result in a verifiable service receipt. Jev evaluates the text. You define the question. JevLink adds an evidence check, applies request limits, signs the output and stores the record.

01
Your evidence
02
Jev evaluation
03
Signed receipt
04
Your application
What ships today

Real inference, saved receipts and browser-side signature verification. Receipts are offchain and signed by JevLink. Decentralized consensus, autonomous contract execution, continuous feeds and token governance are not part of this API release.

02 / JEVLINK API

Your first request#

Run this from your terminal. Public Beta requests do not require an Authorization header. Send public text only: the input is stored in the receipt.

cURL · ask your own question
curl --fail-with-body https://jevlink.xyz/api/judgments \
  -H 'Content-Type: application/json' \
  --data '{
    "mode": "freeform",
    "prompt": "Does this order qualify for a refund? Policy: unused items within 30 days. Order: unopened, delivered 12 days ago."
  }'

A successful request returns 201 Created and a signed envelope. Decode its payload to inspect the fields; verify its signature before treating it as an authentic JevLink record.

JavaScript / Node.js

Download the verification helper into your project, save the example as judgment.mjs, then run node judgment.mjs. Node.js 20 or newer; no packages required.

Download verify-receipt.mjs ↓
JavaScript · request and verify
// Node.js 20+. Save as judgment.mjs.
// Download verify-receipt.mjs below into the same directory.
import { verifyReceipt } from './verify-receipt.mjs';

const response = await fetch('https://jevlink.xyz/api/judgments', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    mode: 'freeform',
    prompt: 'Does this order qualify for a refund? Policy: unused items within 30 days. Order: unopened, delivered 12 days ago.'
  }),
  signal: AbortSignal.timeout(35000)
});
const body = await response.json();
if (!response.ok) {
  throw new Error(
    response.status + ': ' + body.error +
    ' (Retry-After: ' + (response.headers.get('retry-after') ?? 'none') + ')'
  );
}
const receipt = await verifyReceipt(body.receipt);
console.log(receipt.id, receipt.model, receipt.durationMs);
console.log(receipt.answers, receipt.labels);
// Consume a concrete answer only when the evidence is sufficient.
const ready = receipt.answers.readiness.choice === 'answerable';
const choice = receipt.answers.judgment.choice;
console.log(ready && choice !== 'unclear' ? receipt.labels[choice] : 'Review context');
console.log('https://jevlink.xyz/explorer?id=' + receipt.id);
Python · standard-library example

This example decodes the result for inspection. It does not verify the signature; use Explorer or port the verification procedure below before acting on a record.

Python · request and inspect
# Python 3.10+. Standard library only.
import base64, json, urllib.request, urllib.error

data = {
    "mode": "freeform",
    "prompt": "Does this order qualify for a refund? Policy: unused items within 30 days. Order: unopened, delivered 12 days ago."
}
request = urllib.request.Request(
    "https://jevlink.xyz/api/judgments",
    data=json.dumps(data).encode("utf-8"),
    headers={"Content-Type": "application/json"},
    method="POST",
)
try:
    with urllib.request.urlopen(request, timeout=35) as response:
        envelope = json.load(response)["receipt"]
except urllib.error.HTTPError as error:
    raise RuntimeError(f"HTTP {error.code}: {error.read().decode()}") from None

# Inspection only: decoding is NOT signature verification.
payload = envelope["payload"]
receipt = json.loads(base64.urlsafe_b64decode(payload + "=" * (-len(payload) % 4)))
print(receipt["answers"], receipt["labels"])
print("Verify in Explorer: https://jevlink.xyz/explorer?id=" + receipt["id"])
03 / JEVLINK API

Create a judgment#

POST/api/judgments201 Created

Content-Type must be application/json. Unknown fields are rejected. The total request body must not exceed 20,000 bytes.

FieldTypeContract
modestring · required for freeformSend "freeform" for your own question and receipt v3.
promptstring · requiredYour question, claim or decision plus relevant context. 1–4,000 characters after trimming (JavaScript string length). Any topic or language; text only.
optionsstring[] · optional2–6 different answers, up to 80 characters each after trimming. Returned as option_1, option_2, etc. If omitted: yes / no. The unclear option is always added.

Free input, structured output

Jev evaluates your question and an evidence-readiness check in one request. It selects from typed answer options rather than generating chat responses. Without custom options, ask a yes/no question or provide a claim to assess. For routing, add options such as Billing, Access and Performance.

There is no topic whitelist or minimum beyond one non-whitespace character. A live-price query is accepted in freeform mode and evaluated by Jev, but no price feed or web search is attached. Expect needs_live_data when current evidence is missing. Pasted URLs are text, not fetched pages.

Compatibility · announcement and directional methods

Existing requests still work: send mode: "announcement", asset and news for four venue signals (v2). Omit mode and send asset/news for bullish, bearish, neutral or insufficient (v1). Asset is 1–20 ASCII letters, digits, spaces, periods or hyphens and normalized to uppercase; news is 1–4,000 characters. These legacy modes reject standalone price lookups with 422. Do not mix their fields with freeform fields.

Response · signed envelope
// HTTP 201 — shape only; placeholders are not a valid receipt.
{
  "receipt": {
    "payload": "<base64url-encoded JSON>",
    "signature": "<base64url-encoded ECDSA signature>",
    "keyId": "jevlink-<key fingerprint>",
    "algorithm": "ECDSA-P256-SHA256"
  }
}
04 / JEVLINK API

Read the signals#

For v3, read answers.judgment and answers.readiness. Both contain the actual Jev choice, full probabilities and confidence. Resolve the answer label through labels[answers.judgment.choice].

Readiness choiceMeaning
answerableJev considers the supplied text and options sufficient.
needs_contextThe question, evidence or rule needs clarification.
needs_live_dataCurrent or external information is required but not present.
needs_optionsThe request needs possible answers or should be reformulated as a decision.

The website applies a simple presentation rule: only readiness = answerable with judgment ≠ unclear produces a signal. Otherwise it displays a context check. The unmodified Jev answers remain in the receipt. This is not a safety guarantee or an executed policy.

Decoded payload · illustrative excerpt, not an API envelope
// Selected fields after verification; illustrative values.
// The actual payload also includes inputHash, questions and usage.
{
  "schema": "jevlink.receipt.v3",
  "id": "<UUID>",
  "issuedAt": "<UTC timestamp>",
  "issuer": "JevLink",
  "model": "jev-1.13.0",
  "provider": "TypeSafe Direct",
  "method": "freeform-judgment-v1",
  "input": { "prompt": "<your question and context>" },
  "labels": { "yes": "Yes", "no": "No", "unclear": "Undetermined" },
  "answers": {
    "judgment": { "choice": "yes", "probabilities": { "yes": 0.98, "no": 0.01, "unclear": 0.01 }, "confidence": 0.98 },
    "readiness": { "choice": "answerable", "probabilities": { "answerable": 0.97, "needs_context": 0.01, "needs_live_data": 0.01, "needs_options": 0.01 }, "confidence": 0.97 }
  },
  "durationMs": 500
}

Announcement mode · v2 compatibility

These four fixed signals apply only to the legacy announcement method, not to freeform questions.

SignalAllowed choicesQuestion
withdrawalsyes · no · unclearAre withdrawals currently paused or suspended?
tradingyes · no · unclearIs trading currently paused or suspended?
securityyes · no · unclearDoes the announcement disclose an actual security anomaly?
lossesconfirmed · unconfirmed · explicitly_denied · unclearAre user fund losses confirmed, still unconfirmed, explicitly denied, or not clearly discussed?
“Not confirmed” is not “no loss.”

Missing or ambiguous evidence means unclear, not safe. Probabilities describe the model’s classification, not verified facts, measured accuracy or the chance of a future market move.

Each signal contains choice and probabilities. New direct responses contain the full choice distribution. Legacy receipts can contain null probabilities; handle them as unknown, not zero risk.

05 / JEVLINK API

Receipts & fields#

The outer envelope contains payload, signature, keyId and algorithm. Both the payload and signature are unpadded base64url. The payload decodes to UTF-8 JSON.

Payload fieldMeaning
schemajevlink.receipt.v3 for freeform; v2 for announcement signals; v1 for direction.
id / issuedAtUUID v4 record identifier and UTC ISO timestamp. The timestamp is issuance time, not the event time.
issuer / provider / modelJevLink / TypeSafe Direct / the model ID returned by TypeSafe. Historical records may say Vercel AI Gateway.
methodfreeform-judgment-v1, announcement-signals-v1 or crypto-news-direction-v1.
input / inputHashv3: trimmed prompt and optional trimmed options; v1/v2: asset and news. inputHash is lowercase hex SHA-256 of JSON.stringify(input).
questions / answers / labelsv3 only: exact evaluation questions, raw Jev answers, and option ID-to-label mapping. All are covered by the signature.
questions / signalsv2 only: the exact questions and choice criteria used, plus their outputs.
policyv2 only: vault-hold-v1, threshold 0.9, simulation true. A description of the demo policy, not an executed action.
question / direction / probabilitiesv1 only: directional question, chosen classification and distribution.
durationMsServer evaluation interval in milliseconds, including provider communication and receipt preparation up to measurement. Excludes quota checks, signing, saving and browser network transit.
usageinputTokens and outputTokens returned by the provider; historical values may be null. Usage is not a JevLink invoice.

The browser separately measures the full request round trip. Neither timing is blockchain settlement time or a latency guarantee. Consumers should validate the schema and fields they use, and reject unsupported versions.

06 / JEVLINK API

Verify a receipt#

GET/api/receipt-key?keyId=…200 OK

The response contains keyId, publicKey (a P-256 JSON Web Key) and algorithm. Without a keyId, it returns the current signing key. Pass the envelope’s keyId so older records use the correct key. An unknown key returns 404.

  1. Obtain the public key from the trusted JevLink origin, or use a previously trusted copy. Never trust a key embedded in a receipt or a URL supplied by the receipt.
  2. Check that the keyId and algorithm match. The algorithm is ECDSA P-256 with SHA-256.
  3. Verify the decoded signature against the UTF-8 bytes of the original base64url payload string. Do not verify against decoded JSON or reserialized JSON. The signature uses the 64-byte IEEE P1363 r‖s format, not DER.
  4. Decode the payload. Compute SHA-256 over UTF-8 JSON.stringify(receipt.input) and compare its lowercase hex digest to inputHash. Preserve key order and JavaScript JSON serialization semantics.
  5. Validate the supported schema, method, expected input and options, field types and your own freshness policy before consuming the signal.

The downloadable Node.js helper implements signature and input-hash verification and basic schema checks. Your application must still validate the fields it consumes and decide how old a receipt may be. For offline verification, retain a trusted public key and the original envelope.

A signature proves origin and integrity.

It proves JevLink signed this payload and it has not changed. It does not prove the source announcement is true, the model is correct, that a specific model execution is cryptographically attested, or that a transaction settled onchain.

To verify without writing code, open Explorer, enter the receipt ID or import its JSON, then select Verify receipt.

07 / JEVLINK API

Retrieve a record#

GET/api/receipts/{id}200 OK

Use the UUID inside the decoded payload. This returns the original { "receipt": envelope }, not a new model evaluation. Invalid UUIDs return 400; records not found return 404. Receipt retrieval does not consume the inference quota.

JavaScript · retrieve and verify
// Node.js 20+. Use an ID returned by your first request.
import { verifyReceipt } from './verify-receipt.mjs';
const id = process.argv[2];
if (!id) throw new Error('Usage: node inspect.mjs <receipt-id>');
const response = await fetch(
  'https://jevlink.xyz/api/receipts/' + encodeURIComponent(id)
);
if (!response.ok) throw new Error('Receipt lookup failed: ' + response.status);
const body = await response.json();
const receipt = await verifyReceipt(body.receipt);
console.log(receipt);

Share a record with https://jevlink.xyz/explorer?id={id}. Anyone with that link or ID can read the input and output. There is no public receipt-list endpoint. All API responses specify Cache-Control: no-store; save envelopes in your own application when you need a durable independent copy. No retention-duration guarantee or deletion API is published in this Beta.

08 / JEVLINK API

Connect your application#

Call JevLink from your backend, scheduled job or terminal. The public API does not enable cross-origin browser access; a third-party browser should call your server, which then calls JevLink. Never embed TypeSafe’s provider key in your frontend or send it to this public endpoint.

Any decision, your policy

Ask whether an order satisfies a refund policy, whether a message exhibits phishing indicators, or which team should handle an incident. Supply the evidence and options, then verify the record. Your application defines any action and should route undetermined or low-confidence results for review.

A venue-risk control · announcement mode

Ingest a public venue announcement, request the four signals, verify the record, and route the result to an operator alert or an application-controlled hold. Preserve the receipt ID beside the resulting decision for review.

The announcement receipt viewer’s Vault Guard applies this illustrative policy: a qualifying adverse signal at 90% or above yields PAUSED; otherwise, all four explicit clear signals at 90% or above yield NO HOLD TRIGGER; any remaining case yields REVIEW.

JavaScript · v2 announcement demo policy
// Apply only AFTER signature, schema and freshness checks.
const ids = ['withdrawals', 'trading', 'security', 'losses'];
const signals = receipt.signals;
const threshold = receipt.policy.threshold;
const adverse = ids.some(id => {
  const answer = signals[id];
  const trigger = id === 'losses' ? 'confirmed' : 'yes';
  return answer.choice === trigger &&
    (answer.probabilities?.[trigger] ?? 0) >= threshold;
});
const explicitClear = ids.every(id => {
  const answer = signals[id];
  const clear = id === 'losses' ? 'explicitly_denied' : 'no';
  return answer.choice === clear &&
    (answer.probabilities?.[clear] ?? 0) >= threshold;
});
const decision = adverse ? 'PAUSED' : explicitClear ? 'NO HOLD TRIGGER' : 'REVIEW';
console.log(decision); // Your application decides what to do; no transaction is sent.

No hold trigger is not a safety clearance. Never automatically clear an earlier hold just because a later announcement is silent or reassuring. The API does not execute the policy, call smart contracts or move funds.

Other practical integrations

  • Exchange monitoring: route withdrawal and trading disruptions to separate incident channels.
  • Portfolio operations: flag new exposure to an affected venue for human approval, with the original announcement attached.
  • Incident triage: distinguish confirmed fund losses from ongoing investigations, and queue unclear reports for follow-up.

These are consumer-side integration patterns, not additional live endpoints. Event ingestion, source authentication, stale-data checks, deduplication and any action execution belong to your application.

09 / JEVLINK API

Access, limits & privacy#

ControlCurrent Beta behavior
AuthenticationNo caller API key or wallet is required. Key issuance, per-account plans and token-gated access are not implemented.
Per-client quota5 POST requests per fixed minute window, grouped by the client IP reported by Vercel. Shared egress/NAT clients share a bucket.
Global quota200 POST requests per UTC day across the entire site, including the website console. This is not 200 per user.
Failed requestsRequests that reserve quota can consume it even if inference or saving subsequently fails. Invalid input is rejected before reservation.
Timeouts20-second provider request timeout; 30-second function limit. Use a client timeout around 35 seconds to receive the error when possible.
PriceNo JevLink per-call billing is implemented in the public Beta. TypeSafe provider usage is handled by JevLink; no paid plan or SLA is offered here.
PrivacyText is sent to TypeSafe and stored with the result in JevLink’s database. Anyone with the receipt ID can retrieve it. Submit public text only.
Token & network$JLINK governance and decentralized network concepts do not affect current API access or validation.

Do not submit secrets, private account data or personal information. Signature validity does not imply freshness: compare issuedAt with your own expiry window and verify that the original announcement is still relevant.

10 / JEVLINK API

Errors & recovery#

Errors return JSON with an error string. In legacy modes only, unsupported price-lookups also include code: "unsupported_input". Status codes are the reliable branch; do not parse English message text as a stable API contract.

HTTPMeaningWhat to do
400Invalid JSON, content type, fields, size, or receipt ID.Correct the request. Extra fields and unsupported modes are rejected.
403A supplied Origin does not match the API origin.Call through your own backend, not a third-party browser frontend.
404Receipt or verification key not found.Check the exact ID or keyId. Do not substitute an arbitrary key.
405HTTP method not supported.Use POST for judgments, GET for receipts and keys. Framework-generated errors may not be JSON.
422Legacy announcement/direction price query is unsupported.Use freeform to evaluate an arbitrary prompt, or provide evidence for the legacy mode. Freeform does not fetch live prices.
429Client/global quota reached, or the provider is busy.Respect Retry-After (currently 60 seconds). The global daily cap resets at 00:00 UTC, not after 60 seconds.
503Provider, configuration, signing or storage unavailable; provider budget may be exhausted.Keep the input, show an unavailable state and retry later with a bounded backoff. Never invent a successful result.
Error response · example
{
  "error": "Please wait a minute before running another judgment."
}

Retry deliberately

There is no idempotency-key support. Every repeated POST can create a new inference and receipt and consume quota. A timeout does not prove the first request failed. Use a bounded retry budget with backoff and jitter, and deduplicate evidence in your application. Do not retry invalid input or keep polling a depleted daily quota.

Store the receipt before triggering downstream work. If verification, freshness or schema checks fail, stop the action and surface the failure to an operator.