visual-notebook / docs /api-reference.md
Sid-WC121
bug fix1
018ab56
|
Raw History Blame Contribute Delete
15.4 kB

API Reference

This document provides a complete reference for all Visual Notebook API endpoints, including request schemas, response schemas, status codes, and usage examples.

Base URL

  • Development: http://localhost:8000
  • Production: Same origin (backend serves the frontend)
  • All API endpoints are prefixed with /api
  • The health endpoint is at /health (no prefix)

Authentication

The API uses cookie-based session management. The session_id cookie is set automatically after the first CSV upload and sent with all subsequent requests. No explicit authentication is required.

Common Response Patterns

Error Responses

All error responses follow the RFC 7807 pattern with a detail field:

{
    "detail": "Error description"
}

Session Cookie

The first endpoint that creates a session (POST /api/upload/csv) sets an httponly cookie:

Set-Cookie: session_id=abc123def456; HttpOnly; Max-Age=604800; Path=/; SameSite=lax

Endpoints

POST /api/upload/csv

Upload a CSV file, register it in DuckDB, and create a new session.

Request: multipart/form-data

Field Type Required Description
file File Yes CSV file to upload (must have .csv extension)

Response: 200 OK

{
    "dataset_id": "a3b2c1d4",
    "table_name": "ds_a3b2c1d4",
    "row_count": 15000,
    "columns": [
        {
            "name": "order_id",
            "dtype": "INTEGER",
            "column_type": "numeric",
            "null_count": 0,
            "unique_count": 15000,
            "min": 1,
            "max": 15000,
            "mean": 7500.5,
            "std": 4330.1,
            "q25": 3750.75,
            "q50": 7500.5,
            "q75": 11250.25,
            "count": 15000
        },
        {
            "name": "status",
            "dtype": "VARCHAR",
            "column_type": "categorical",
            "null_count": 5,
            "unique_count": 3,
            "min": null,
            "max": null,
            "mean": null,
            "std": null,
            "q25": null,
            "q50": null,
            "q75": null,
            "count": 14995
        }
    ],
    "session_id": "a1b2c3d4e5f6"
}

Error Responses:

Status Condition
400 File does not have .csv extension
413 File exceeds MAX_UPLOAD_SIZE

GET /api/schema

Retrieve the schema and statistics for the currently loaded dataset.

Request: No parameters.

Response: 200 OK

{
    "table_name": "ds_a3b2c1d4",
    "row_count": 15000,
    "columns": [
        {
            "name": "order_id",
            "dtype": "INTEGER",
            "column_type": "numeric",
            "null_count": 0,
            "unique_count": 15000,
            "min": 1,
            "max": 15000,
            "mean": 7500.5,
            "std": 4330.1,
            "q25": 3750.75,
            "q50": 7500.5,
            "q75": 11250.25,
            "count": 15000
        }
    ]
}

Error Responses:

Status Condition
400 No dataset loaded in the current session

GET /api/rows

Retrieve paginated rows from the current dataset.

Query Parameters:

Parameter Type Default Description
offset integer 0 Row offset (0-based)
limit integer 50 Maximum number of rows to return

Response: 200 OK

{
    "rows": [
        {"order_id": 1, "status": "shipped", "amount": 99.99},
        {"order_id": 2, "status": "pending", "amount": 45.50}
    ],
    "columns": ["order_id", "status", "amount"],
    "offset": 0,
    "limit": 50,
    "total": 15000
}

Error Responses:

Status Condition
400 No dataset loaded

GET /api/ops

List all available data operations.

Request: No parameters.

Response: 200 OK

{
    "operations": [
        {
            "key": "filter",
            "label": "Filter",
            "description": "Filter rows by condition",
            "param_schema": {
                "type": "object",
                "required": ["column", "operator"],
                "properties": {
                    "column": {"type": "string"},
                    "operator": {"type": "string", "enum": ["eq", "neq", "gt", "lt", "gte", "lte", "contains", "is_null", "is_not_null"]},
                    "value": {"type": ["string", "number"]}
                }
            }
        },
        {
            "key": "sort",
            "label": "Sort",
            "description": "Sort by column",
            "param_schema": {
                "type": "object",
                "required": ["column"],
                "properties": {
                    "column": {"type": "string"},
                    "descending": {"type": "boolean", "default": false}
                }
            }
        },
        {
            "key": "select",
            "label": "Select Columns",
            "description": "Keep only selected columns",
            "param_schema": {
                "type": "object",
                "required": ["columns"],
                "properties": {
                    "columns": {"type": "array", "items": {"type": "string"}}
                }
            }
        },
        {
            "key": "rename",
            "label": "Rename Columns",
            "description": "Rename columns using a mapping",
            "param_schema": {
                "type": "object",
                "required": ["mapping"],
                "properties": {
                    "mapping": {"type": "object", "additionalProperties": {"type": "string"}}
                }
            }
        },
        {
            "key": "groupby",
            "label": "Group By",
            "description": "Aggregate data by groups",
            "param_schema": {
                "type": "object",
                "required": ["group_by", "aggregations"],
                "properties": {
                    "group_by": {"type": "array", "items": {"type": "string"}},
                    "aggregations": {"type": "object", "additionalProperties": {"type": "array", "items": {"type": "string"}}}
                }
            }
        },
        {
            "key": "fill_nulls",
            "label": "Fill Nulls",
            "description": "Fill null values using a strategy",
            "param_schema": {
                "type": "object",
                "properties": {
                    "strategy": {"type": "string", "enum": ["forward", "backward", "mean", "zero", "constant"], "default": "forward"},
                    "columns": {"type": "array", "items": {"type": "string"}},
                    "value": {"type": ["string", "number"]}
                }
            }
        },
        {
            "key": "clip",
            "label": "Clip Values",
            "description": "Clip values to a range",
            "param_schema": {
                "type": "object",
                "required": ["column"],
                "properties": {
                    "column": {"type": "string"},
                    "lower": {"type": "number"},
                    "upper": {"type": "number"}
                }
            }
        }
    ]
}

POST /api/ops/{op_key}

Apply a data operation to the current dataset.

Path Parameters:

Parameter Type Description
op_key string Operation key (filter, sort, select, rename, groupby, fill_nulls, clip)

Request Body:

{
    "op_key": "filter",
    "params": {
        "column": "amount",
        "operator": "gt",
        "value": 100
    }
}

Response: 200 OK

{
    "state_id": "e5f6a7b8",
    "columns_schema": [
        {
            "name": "order_id",
            "dtype": "INTEGER",
            "column_type": "numeric",
            "null_count": 0,
            "unique_count": 5200,
            "min": 1,
            "max": 15000,
            "mean": 7800.3,
            "std": 4200.5,
            "q25": 3900.0,
            "q50": 7800.0,
            "q75": 11700.0,
            "count": 5200
        }
    ],
    "row_count": 5200,
    "sample_rows": [
        {"order_id": 5, "status": "shipped", "amount": 150.00},
        {"order_id": 12, "status": "pending", "amount": 220.50}
    ]
}

Error Responses:

Status Condition
400 No dataset loaded
404 Operation key not found
422 Parameter validation failed
500 Operation execution failed

Operation Parameter Examples:

Filter:

{"column": "status", "operator": "eq", "value": "shipped"}
{"column": "amount", "operator": "gte", "value": 50}
{"column": "notes", "operator": "contains", "value": "urgent"}
{"column": "email", "operator": "is_null"}

Sort:

{"column": "amount", "descending": true}

Select:

{"columns": ["order_id", "amount", "status"]}

Rename:

{"mapping": {"order_id": "id", "amount": "total"}}

GroupBy:

{"group_by": ["status"], "aggregations": {"amount": ["mean", "sum", "count"]}}

Fill Nulls:

{"strategy": "forward"}
{"strategy": "zero"}
{"strategy": "constant", "value": "N/A", "columns": ["status"]}

Clip:

{"column": "amount", "lower": 0, "upper": 1000}

POST /api/history/undo

Undo the last operation, reverting to the previous state.

Request: No body.

Response: 200 OK

{
    "state_id": "a3b2c1d4",
    "operation": "upload",
    "columns_schema": [
        {
            "name": "order_id",
            "dtype": "INTEGER",
            "column_type": "numeric",
            "null_count": 0,
            "unique_count": 15000,
            "min": 1,
            "max": 15000,
            "mean": 7500.5,
            "std": 4330.1,
            "q25": 3750.75,
            "q50": 7500.5,
            "q75": 11250.25,
            "count": 15000
        }
    ],
    "row_count": 15000
}

Error Responses:

Status Condition
400 Cannot undo (at the beginning of history)

POST /api/history/redo

Redo the next operation, advancing to the subsequent state.

Request: No body.

Response: 200 OK

Same schema as undo response.

Error Responses:

Status Condition
400 Cannot redo (at the end of history)

POST /api/history/branch

Branch from a specific historical state, resetting the current pointer to that state.

Request Body:

{
    "state_id": "a3b2c1d4"
}

Note: The state_id is passed as a query parameter in the current implementation.

Response: 200 OK

{
    "state_id": "a3b2c1d4",
    "operation": "upload"
}

Error Responses:

Status Condition
404 State ID not found in history

GET /api/history

Retrieve the full history tree for the current session.

Request: No parameters.

Response: 200 OK

{
    "nodes": [
        {
            "id": "a3b2c1d4",
            "operation": "upload",
            "params": {"filename": "orders.csv"},
            "parent_id": null,
            "children": ["e5f6a7b8"],
            "is_current": false
        },
        {
            "id": "e5f6a7b8",
            "operation": "filter",
            "params": {"column": "amount", "operator": "gt", "value": 100},
            "parent_id": "a3b2c1d4",
            "children": [],
            "is_current": true
        }
    ],
    "current_id": "e5f6a7b8",
    "order": ["a3b2c1d4", "e5f6a7b8"]
}

POST /api/viz/chart

Compute a chart specification for the current dataset.

Request Body:

{
    "chart_type": "histogram",
    "params": {
        "column": "amount",
        "bins": 20
    }
}

Chart Type Parameters:

Chart Type Required Params Optional Params
histogram column bins (default: 20)
scatter x_col, y_col color_col
bar_topn category_col value_col, n (default: 15), sort_desc (default: true)
timeline date_col, value_col agg (default: "sum")
heatmap x_col, y_col, value_col agg (default: "mean")
map lat_col, lon_col label_col

Response: 200 OK

For ECharts-based charts (histogram, scatter, bar_topn, timeline, heatmap):

{
    "chart_type": "histogram",
    "spec": {
        "animation": true,
        "animationDuration": 600,
        "grid": {"left": 60, "right": 30, "top": 60, "bottom": 50, "containLabel": true},
        "title": {"text": "Distribution of amount", "left": "center"},
        "tooltip": {"trigger": "item", "backgroundColor": "rgba(255,255,255,0.95)"},
        "xAxis": {"type": "category", "data": ["0-50", "50-100", "100-150"]},
        "yAxis": {"type": "value", "name": "Count"},
        "series": [{"type": "bar", "data": [3200, 5100, 4500]}]
    }
}

For map charts:

{
    "chart_type": "map",
    "spec": {
        "type": "map",
        "points": [{"lat": 40.7, "lon": -74.0, "label": "NYC"}],
        "bounds": {"minLat": 25.0, "maxLat": 48.0, "minLon": -125.0, "maxLon": -67.0},
        "center": {"lat": 36.5, "lon": -96.0},
        "pointCount": 1500
    }
}

Error Responses:

Status Condition
400 No dataset loaded, or chart requires DuckDB backend
422 Missing required parameter
500 Chart computation failed

GET /api/export/csv

Export the current dataset as a CSV file download.

Request: No parameters.

Response: 200 OK with Content-Type: text/csv

The response is a file download with the table name as the filename.

Error Responses:

Status Condition
400 No dataset loaded

POST /api/checkpoint

Save a checkpoint of the current session state, including the history tree and data.

Request: No body.

Response: 200 OK

{
    "path": "checkpoints/a1b2c3d4e5f6/checkpoint_20240101_120000.json",
    "timestamp": "20240101_120000",
    "state_id": "e5f6a7b8"
}

GET /api/checkpoints

List all saved checkpoints for the current session.

Request: No parameters.

Response: 200 OK

[
    {
        "path": "checkpoints/a1b2c3d4e5f6/checkpoint_20240101_120000.json",
        "timestamp": "20240101_120000",
        "session_id": "a1b2c3d4e5f6"
    },
    {
        "path": "checkpoints/a1b2c3d4e5f6/checkpoint_20240101_090000.json",
        "timestamp": "20240101_090000",
        "session_id": "a1b2c3d4e5f6"
    }
]

GET /health

Health check endpoint for infrastructure monitoring.

Request: No parameters.

Response: 200 OK

{
    "status": "ok",
    "version": "0.1.0"
}

Status Code Summary

Code Meaning When Used
200 Success All successful responses
400 Bad Request No dataset loaded, invalid state transition
404 Not Found Unknown operation key or history state
413 Payload Too Large File exceeds MAX_UPLOAD_SIZE
422 Unprocessable Entity Parameter validation failure
500 Internal Server Error Operation or chart computation failure