DSAIL Quickstarts Guides Compare REST MCP tools Errors

"Quickstart: REST"

Three curl calls against the hosted service — a credential, a compile, a check — and the exact JSON that comes back.

For anything that speaks HTTPS. Check extracted values against a written policy from a service, a job, or a test, with no SDK.

1. A credential, no sign-up

export DSAIL_CRED=$(curl -s -X POST https://agents.jaxon.ai/v1/credentials/evaluation \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["credential"])')

The token is shown once; the service stores only its hash. Send it on every call as x-jaxon-credential. An evaluation credential is scoped to compile, check and the prompt pack, and capped; a full credential is issued by Jaxon.

2. Compile

cat > expenses.dsail <<'EOF'
version 1.3;
// @ask amount What is the total amount of this expense claim, in USD?
// @unit amount USD
declare amount as numeric;
// @ask has_receipt Is an itemised receipt attached?
declare has_receipt as boolean;
assert receipt_over_75 { Implies(amount > 75 "USD", has_receipt) };
assert within_cap { amount <= 5000 "USD" };
EOF

curl -s -X POST https://agents.jaxon.ai/v1/compile \
  -H "x-jaxon-credential: $DSAIL_CRED" -H "content-type: application/json" \
  -d "$(python3 -c 'import json; print(json.dumps({"source": open("expenses.dsail").read()}))')"

The response carries ruleset_hash (the content hash addressing exactly these bytes), manifest (every claim with its question, type and unit), claim_schema (JSON Schema for the claim dictionary), the validation contract a check will enforce, and review, a plain-text rendering for a person to sign.

3. Check

curl -s -X POST https://agents.jaxon.ai/v1/check \
  -H "x-jaxon-credential: $DSAIL_CRED" -H "content-type: application/json" \
  -d '{"ruleset_hash": "<ruleset_hash from step 2>",
       "claims": {"amount": "120 USD", "has_receipt": false}}'
{"ok": true,
 "ruleset_hash": "<ruleset_hash>", "unit_library_hash": null,
 "rules": [
   {"rule": "receipt_over_75", "assertions": [
     {"name": "receipt_over_75", "check": "FALSE", "unknown_policy": "neutral",
      "counterexample": "[amount = 120, has_receipt = False]"}]},
   {"rule": "within_cap", "assertions": [
     {"name": "within_cap", "check": "TRUE", "unknown_policy": "neutral"}]}],
 "claims": {"bound": ["amount", "has_receipt"], "unbound": [], "quantities": ["..."]},
 "versions": {"wire_version": "2.4.0", "...": "..."}}

Every assertion answers TRUE, FALSE, UNKNOWN or AMBIGUOUS; a FALSE carries the rule that decided, with a counterexample. There is no combined verdict — fold the results yourself, because what a FALSE costs is your decision. The payload is pure over its inputs (no timestamps, no request id), so the same ruleset and claims return the same bytes every time.

Where the claim values come from

GET /v1/prompt-pack/{ruleset_hash} returns one extraction prompt per claim, the claim schema and the validation rules. Run those prompts on your own model, assemble the claim dictionary, submit it. A claim your extraction could not determine is submitted as the string "unknown" — never a guess, never omitted.

Errors

One envelope for every failure, through every door:

{"ok": false,
 "error": {"code": "VALIDATION_REJECTED", "message": "1 field failed validation",
           "docs": "https://docs.agents.jaxon.ai/errors/validation-rejected.md",
           "failures": [{"field": "amount", "expected": "...", "received": "..."}]},
 "versions": {"...": "..."}}

failures names every failing field at once, so one corrected resubmission converges. Error codes lists them all; the full route list is the REST API reference, and the specification is GET https://agents.jaxon.ai/openapi.json.