- Technical Deep Dive
- Backend API Reference
Technical Deep Dive
Backend API Reference
Comprehensive documentation for all FastAPI routes exposed by Mako Code.
Backend API Reference
All endpoints are prefixed with /api and served by the FastAPI application defined in backend/main.py. The API is stateless—no session cookies or JWTs are required by default (suitable for local development). Every request/response body is JSON.
The FastAPI interactive docs are available live at
http://localhost:8001/api/docs.
Authentication
There is currently no authentication layer. If you deploy Mako Code to a public subnet, protect it via reverse-proxy (basic auth) or add an AuthRouter using FastAPI dependencies.
Table of Contents
POST /api/execute– Execute arbitrary Python or SQL.POST /api/lint– Lint Python source via Ruff.POST /api/dataset– Upload dataset (called by DataImportModal).GET /api/dataset/{path}– Fetch dataset schema & preview.DELETE /api/dataset– Delete dataset.GET /api/dataset/context/{name}– Retrieve dataset context JSON.POST /api/dataset/context– Update context file.GET /api/version/{tab}/{filename}– Load historical code snapshot.POST /api/rename-version-folder– Rename a tab’s version folder.POST /api/functions– Save user function.DELETE /api/functions/{name}– Delete saved function.
1 – POST /api/execute
Execute arbitrary Python (default) or SQL. The request model is defined in backend/main.py:
class CodeRequest(BaseModel):
code: str
language: Literal["python", "sql"] = "python"
Request
{
"code": "print(2 + 2)",
"language": "python"
}
Response
{
"stdout": "4\n",
"stderr": "",
"figures": [],
"success": true
}
If language = sql, the backend routes the snippet through functions.utils.execute_sql. Only basic SELECT … FROM queries are supported. The target table must match a dataset name in DATASETS_DIR.
2 – POST /api/lint
Lint Python source code using Ruff. Implementation excerpt:
@app.post("/api/lint")
async def lint_code(request: LintRequest):
try:
result = subprocess.run([
"ruff", "--stdin-filename", request.filename, "-"],
input=request.code.encode(),
capture_output=True,
)
return {"output": result.stdout.decode()}
except FileNotFoundError as se:
return {"error": str(se)}
Expect standard Ruff output. Integrations inside +page.svelte parse this into inline annotations.
3 – Dataset Endpoints
3.1 POST /api/dataset
Multipart upload expecting form-data field file.
POST /api/dataset
Content-Type: multipart/form-data; boundary=---123
---123
Content-Disposition: form-data; name="file"; filename="sales.parquet"
Content-Type: application/octet-stream
<binary>
---123--
The backend:
@app.post("/api/dataset")
async def upload_dataset(file: UploadFile):
target = ensure_dataset_dir() / file.filename
target.write_bytes(await file.read())
df = pl.read_parquet(target, n_rows=5)
return {"path": str(target), "preview": df.to_dict(as_series=False)}
3.2 GET /api/dataset/{path}
Responds with schema, row count, and sample preview. Consumed by DataframeView.svelte.
{
"schema": [
["customer_id", "Int64"],
["total_price", "Float64"]
],
"num_rows": 25786,
"preview": [...]
}
3.3 DELETE /api/dataset
Body:
{"path": "data/datasets/old.parquet"}
Returns { "deleted": true } on success.
4 – Versioning Endpoints
GET /api/version/{tab}/{filename} streams the raw Python file for historical view. VersionHistory.svelte parses timestamps from filenames and displays them in an accordion list.
@app.get("/api/version/{tab}/{version_filename}")
async def get_version(tab_name: str, version_filename: str):
version_path = Path("data/versions") / tab_name / version_filename
return Response(version_path.read_text(), media_type="text/x-python")
5 – Function Management
User helper functions are stored one-per-file under data/functions/. Each file has YAML front-matter describing the function (docstring, author, created_at). The user can enable/disable them via FunctionsModal.svelte.
5.1 POST /api/functions
{
"name": "my_udf",
"code": "def my_udf(df): return df.filter(pl.col('a') > 0)",
"description": "Filter out negative a's"
}
If the name already exists the backend overwrites the file.
5.2 DELETE /api/functions/{name}
Removes the file and returns { "deleted": true }.
Status Codes & Error Model
| Code | Meaning | Notes |
|---|---|---|
| 200 | OK | Successful operation |
| 400 | Bad Request | Code safety validation failed, or payload invalid |
| 404 | Not Found | Dataset or function missing |
| 500 | Internal Server Error | Uncaught exception inside execution sandbox |
Error responses are always JSON with at least an error field.
Pagination & Limits
Dataset preview endpoints accept query parameters offset and limit (default 0 and 100). This is enforced in backend/main.py#get_dataset_data:
rows = df.slice(request.offset, request.limit).to_dict(as_series=False)
Clients must request subsequent pages explicitly.
WebSocket Roadmap
Future versions may expose a /ws/execute channel for streaming stdout in real time. Contributions welcome; see Contributing Guide.