| Did you know ... | Search Documentation: |
| Pack le -- api.md |
The LE API is a JSON-over-HTTP REST endpoint served at `/leapi` (default port 3050).
Every request must include a "token" field in the JSON body. The expected
token is:
"myToken123" as the historical default fallback when LE_API_TOKEN is
unset.
This behaviour is backwards-compatible: callers using the historical default continue to work unchanged, while deployments needing a real shared secret can set the env var without code changes.
All requests are HTTP POST with Content-Type: application/json.
All responses are JSON objects. On failure the response contains an error key.
examples — Retrieve a built-in example documentReturns the source text of a named LE example file.
Request
{
"token": "myToken123",
"operation": "examples",
"file": "<example_name>"
}
| Field | Type | Description |
|---|---|---|
file | string | Name of the example (without extension), e.g. "1_net_asset_value_test_3" |
Response
{ "document": "<LE source text>" }
On error: { "answer": "...", "details": "...", "document": "" }
curl example
curl -s -X POST http://localhost:3050/leapi \
-H 'Content-Type: application/json' \
-d '{"token":"myToken123","operation":"examples","file":"1_net_asset_value_test_3"}'
answer — Parse a document and answer one query/scenario pairLoads the LE document, applies the named scenario, and returns an explanation for a single query.
Request
{
"token": "myToken123",
"operation": "answer",
"file": "<program_name>",
"document": "<LE source text>",
"theQuery": "<query sentence>",
"scenario": "<scenario name>"
}
| Field | Type | Description |
|---|---|---|
file | string | Logical name / identifier for the program |
document | string | Full LE source text |
theQuery | string | Name of the query to run, e.g. "one" |
scenario | string | Name of the scenario to use, e.g. "alice" |
Response
{ "answer": <explanation term> }
curl example
curl -s -X POST http://localhost:3050/leapi \
-H 'Content-Type: application/json' \
-d '{"token":"myToken123","operation":"answer","file":"testingle",
"document":"...","theQuery":"one","scenario":"alice"}'
explain — Parse a document and return all answers for a query/scenario
Like answer but collects every answer, not just the first.
Request
{
"token": "myToken123",
"operation": "explain",
"file": "<program_name>",
"document": "<LE source text>",
"theQuery": "<query sentence>",
"scenario": "<scenario name>"
}
Same fields as answer.
Response
{ "results": [ <explanation>, ... ] }
The `<explanation>` is rendered as an HTML string nested-list. For machine
consumption of the proof-tree shape (preserving per-node ref, source,
and origin annotations), use explain_json
instead.
explain_json — Like explain but with a structured JSON proof tree
Identical to explain in inputs and applicability. The difference is in the
response shape: each answer's explanation field is a list of structured node
dicts rather than a stringified HTML rendering. This preserves the per-node
ref (clause reference), source (originating program / module), and
origin (the actual Prolog clause that fired) annotations that the HTML
rendering strips out via the underscored variables in explanationLEHTML/2.
Designed for agentic / programmatic consumers (e.g. compliance certifiers, structured-output advisory systems) that need to attach proof trees to structured output without having to parse rendered HTML.
Request
{
"token": "myToken123",
"operation": "explain_json",
"file": "<program_name>",
"document": "<LE source text>",
"theQuery": "<query sentence>",
"scenario": "<scenario name>"
}
Same fields as explain / answer.
Response
{
"results": [
{
"answer": "Yes | No | Unknown | Failure",
"bindings": "<stringified ground goal>",
"explanation": [
{
"type": "proven | failed | unknown",
"literal": "<stringified goal>",
"ref": "<clause reference or null>",
"source": "<source program / module or null>",
"origin": "<the actual Prolog clause that fired or null>",
"children": [ <node>, ... ]
},
...
]
},
...
]
}
Node type values:
"proven" — the goal was successfully proved (SLD-resolution succeeded)."failed" — the goal could not be proved."unknown" — the goal is a hypothesis lacking sufficient facts.
For a leaf step that exercised a Prolog built-in (e.g. an arithmetic
comparison `160000 is greater or equal to 150000`), ref and origin are
null and source carries the LE program name. For a step that exercised
a user-defined rule, all four annotation fields are populated.
curl example
curl -s -X POST http://localhost:3050/leapi \
-H 'Content-Type: application/json' \
-d '{"token":"myToken123",
"operation":"explain_json",
"file":"gst",
"document":"<full LE source>",
"theQuery":"A",
"scenario":"A"}'
answer_via_llm — Translate free-form user input via an LLM, then answer
Sends userinput to a configured LLM (Gemini) to generate a new LE scenario/query pair, appends it to document, and then runs the combined program.
Environment variables required on the server:
| Variable | Description |
|---|---|
| LE_LLM_K | API key for the LLM service |
| USED_LLM | Model identifier, e.g. gemini-2.5-flash |
Request
{
"token": "myToken123",
"operation": "answer_via_llm",
"file": "<program_name>",
"document": "<LE source text>",
"userinput": "<free-form description / question>"
}
| Field | Type | Description |
|---|---|---|
file | string | Logical name for the program |
document | string | Existing LE source text used as context |
userinput | string | Natural-language description of the situation and question |
Response
{
"results": [ <explanation>, ... ],
"translation": "<LLM-generated LE text>"
}
On failure: "results" contains an error dict and "translation" is "I did not understand".
curl example
curl -s -X POST http://localhost:3050/leapi \
-H 'Content-Type: application/json' \
-d '{"token":"myToken123","operation":"answer_via_llm",
"file":"testllm","document":"...","userinput":"Is Alice eligible?"}'
load — Load a LE or Prolog program into a fresh session moduleParses and asserts a LE (or plain Prolog) program, returning its metadata.
Request — inline LE source
{
"token": "myToken123",
"operation": "load",
"le": "<LE source text>"
}
Request — load from file
{
"token": "myToken123",
"operation": "load",
"file": "<path under /moreExamples/>"
}
The file path must reside under `/moreExamples/`. Files ending in `.le` are parsed as Logical English; all others are loaded as plain Prolog.
Response
{
"sessionModule": "<generated module name>",
"kb": "<kb name or null>",
"predicates": [ "<predicate/arity>", ... ],
"examples": [ { "name": "...", "scenarios": [ { "assertion": "...", "clauses": "..." } ] } ],
"queries": [ "<query term>", ... ],
"language": "le | prolog",
"target": "taxlog | prolog"
}
The sessionModule value must be passed to subsequent answeringQuery and loadFactsAndQuery calls.
le2prolog — Translate a LE program to Prolog sourceReturns the Prolog text equivalent of a LE program without asserting anything.
Request
{
"token": "myToken123",
"operation": "le2prolog",
"le": "<LE source text>"
}
Response
{
"prolog": "<Prolog source text>",
"kb": "<kb name>",
"predicates": [ "<predicate string>", ... ],
"examples": [ ... ],
"queries": "<Prolog query clauses>",
"target": "taxlog | prolog"
}
answeringQuery — Run an English query against a loaded session module
Requires a prior load call to obtain sessionModule.
Request
{
"token": "myToken123",
"operation": "answeringQuery",
"query": "<English query string>",
"scenario": "<Prolog scenario term>",
"sessionModule": "<module name from load>"
}
Response
{ "answer": "<answer term as string>", "result": "ok" }
loadFactsAndQuery — Assert facts into a session module and run a goalAsserts a list of ground facts into an existing session module, then optionally evaluates a goal against them.
Request
{
"token": "myToken123",
"operation": "loadFactsAndQuery",
"sessionModule": "<module name>",
"facts": [ "<fact term string>", ... ],
"goal": "<Prolog goal string>",
"vars": [ "<var name>", ... ]
}
goal and vars are optional. Only ground facts (no :- heads) are accepted.
Response
{
"facts": [ ... ],
"goal": "<goal>-(vars)",
"answers": [ { "bindings": { "<var>": <value> }, "explanation": <tree> } ],
"result": "true | false | unknown"
}
query — Low-level Prolog/taxlog query (legacy taxkbapi)Evaluates a Prolog term against a named module's knowledge base, optionally with hypothetical facts.
Request
{
"token": "myToken123",
"operation": "query",
"theQuery": "<Prolog term string>",
"module": "<module URL or name>",
"facts": [ "<fact term string>", ... ]
}
facts is optional.
Response
{
"results": [
{
"result": "true | false | unknown",
"bindings": { "<VarName>": <value>, ... },
"unknowns": [ { "goal": <term>, "module": "<module>" }, ... ],
"why": <explanation tree>
}
]
}
curl examples
# Simple query
curl -X POST http://localhost:3050/leapi \
-H 'Content-Type: application/json' \
-d '{"token":"myToken123","operation":"query","theQuery":"a(1,Y)","module":"http://tests.com"}'
# With hypothetical facts
curl -X POST http://localhost:3050/leapi \
-H 'Content-Type: application/json' \
-d '{"token":"myToken123","operation":"query","theQuery":"a(13,Y)","facts":["d(13)"],"module":"http://tests.com"}'
draft — Draft a Prolog file from web-page content (legacy)Accepts structured page content and returns a drafted Prolog text.
Request
{
"token": "myToken123",
"operation": "draft",
"pageURL": "http://mysite/page1#section2",
"content": [
{ "url": "http://mysite/page1#section2!chunk1", "text": "john flies by instruments" }
]
}
Response
{ "pageURL": "http://mysite/page1#section2", "draft": "<Prolog text>" }
The why / explanation fields returned by query and loadFactsAndQuery are arrays of node objects:
{
"type": "<node type>",
"literal": "<goal as string>",
"module": "<module>",
"source": "<source reference>",
"textOrigin": "<origin>",
"children": [ <node>, ... ]
}
?- use_module(api), start_api_server. % listens on port 3050 ?- use_module(api), start_api_server(8080). % custom port
When loaded inside SWISH the server start is a no-op (SWISH already handles HTTP).