API server¶
kikolens api serves the analysis over HTTP and JSON, so other programs (a web app, a spreadsheet macro, a scheduler, another language) can use it. It runs on your machine, keeps everything in memory and sends nothing anywhere. It needs nothing beyond KikoLens.
kikolens api # http://127.0.0.1:8000
kikolens api --token s3cret --host 0.0.0.0 # reachable from the network: a token is mandatory
kikolens api --data-dir ./data --model my-model --cors http://localhost:3000
Open /openapi.json for the machine-readable description and /functions for the analyses and their parameters. The older kikolens serve MODEL is still there for serving one model only.
Security¶
- It listens only on this computer unless you pass another
--host, and then--tokenis required (Authorization: Bearer TOKEN;/healthis open). - Clients can only run a fixed list of analyses. They cannot run code, read arbitrary paths or run arbitrary SQL (queries are read-only and cannot open files).
- Files can be loaded only by name from the folder given with
--data-dir; without it, clients send rows or csv text. Names that escape the folder are refused. - At most 20 datasets of a million rows are held at once, request bodies are limited to 25 MB, and unexpected errors are reported by type only, never with paths or stack traces.
--modelopens a saved model file, which is code: serve only models you trust. Only the models you name are served.
Endpoints¶
| Call | What it does |
|---|---|
GET /health |
{"status": "ok"}. |
GET /functions |
The analyses: name, description, parameters. |
POST /datasets |
Create a dataset from {"rows": [{...}]}, {"csv": "a,b\n1,2"} or {"file": "sales.csv"}; optional "name". Returns its id. |
GET /datasets, GET /datasets/{id} |
List them, or see columns, types, missing values and the first rows. |
DELETE /datasets/{id} |
Forget a dataset. |
POST /run/{function} |
{"dataset": id, "args": {...}}. Runs the analysis and returns {"result": {"summary": ..., "table": {"columns", "rows", "total_rows"}, ...}, "omitted": [...]}. Add ?figures=1 for charts as Plotly JSON. Tables are cut to 200 rows. |
POST /jobs, GET /jobs/{id} |
The same in the background for slow work (lab, autopilot): {"function", "dataset", "args"} returns an id; poll until status is done or failed. |
GET /models, POST /models/{name}/predict |
The models named at startup; send {"rows": [...]} and get predictions with ranges and input warnings. |
Example¶
import requests
base = "http://127.0.0.1:8000"
rows = [{"price": 10, "units": 100}, {"price": 12, "units": 90}] # ...more rows
dataset = requests.post(f"{base}/datasets", json={"rows": rows}).json()["id"]
out = requests.post(f"{base}/run/regress", json={"dataset": dataset, "args": {"target": "units"}}).json()
print(out["result"]["summary"])
Status codes: 400 for an invalid request or arguments (the message says why), 401 for a missing or wrong token, 404 for an unknown dataset, function, job or model, 409 when too many datasets are held, 413 for a body that is too large.