# SpiceBook > Notebook interface for SPICE circuit simulation. Create, edit, and run SPICE netlists in a cell-based notebook UI with waveform visualization and schematic generation. Powered by ngspice. Base URL: `https://spicebook.warehack.ing` ## API Reference All endpoints accept and return JSON unless noted otherwise. Prefix all paths with the base URL. --- ### Notebooks #### List notebooks ``` GET /api/notebooks ``` **Response** `200` ```json [ { "id": "rc-low-pass-a1b2c3d4", "title": "RC Low-Pass Filter", "engine": "ngspice", "tags": ["filter", "rc"], "cell_count": 3, "modified": "2026-02-13T18:30:00+00:00" } ] ``` #### Create notebook ``` POST /api/notebooks ``` **Request body** ```json { "title": "My Circuit", "engine": "ngspice" } ``` Both fields are optional. Defaults: title = `"Untitled Notebook"`, engine = `"ngspice"`. **Response** `201` ```json { "id": "my-circuit-f8e2a91b", "spicebook_version": "2026-02-13", "metadata": { "title": "My Circuit", "engine": "ngspice", "tags": [], "created": "2026-02-13T18:30:00+00:00", "modified": "2026-02-13T18:30:00+00:00" }, "cells": [ { "id": "cell-a1b2c3d4e5f6", "type": "markdown", "source": "# My Circuit\n\nAdd SPICE cells below to begin simulating.", "outputs": [] } ] } ``` #### Get notebook ``` GET /api/notebooks/{notebook_id} ``` **Response** `200` — Full `Notebook` object (same shape as create response, without `id` wrapper). #### Update notebook ``` PUT /api/notebooks/{notebook_id} ``` **Request body** — Full `Notebook` object (replaces entire notebook). **Response** `200` — The saved `Notebook`. #### Delete notebook ``` DELETE /api/notebooks/{notebook_id} ``` **Response** `204` — No content. Only user-created notebooks can be deleted. --- ### Cells Cells are ordered elements within a notebook. Each cell has a `type` (`markdown`, `spice`, `python`, `schematic`) and `source` (text content). #### Add cell ``` POST /api/notebooks/{notebook_id}/cells ``` **Request body** ```json { "type": "spice", "source": "V1 1 0 DC 5\nR1 1 0 1k\n.op\n.end", "after_cell_id": "cell-a1b2c3d4e5f6" } ``` `after_cell_id` is optional — omit to append at end. **Response** `201` ```json { "id": "cell-b2c3d4e5f6a7", "type": "spice", "source": "V1 1 0 DC 5\nR1 1 0 1k\n.op\n.end", "outputs": [] } ``` #### Update cell ``` PUT /api/notebooks/{notebook_id}/cells/{cell_id} ``` **Request body** ```json { "source": "V1 1 0 DC 10\nR1 1 0 2k\n.op\n.end", "type": "spice" } ``` Both fields optional — only provided fields are updated. **Response** `200` — Updated `Cell`. #### Delete cell ``` DELETE /api/notebooks/{notebook_id}/cells/{cell_id} ``` **Response** `204` #### Reorder cells ``` PUT /api/notebooks/{notebook_id}/cells/reorder ``` **Request body** ```json { "cell_ids": ["cell-b2c3d4e5f6a7", "cell-a1b2c3d4e5f6"] } ``` Must include every cell ID exactly once. **Response** `200` — Array of `Cell` objects in new order. --- ### Simulation #### Run standalone simulation ``` POST /api/simulate ``` **Request body** ```json { "netlist": "V1 1 0 DC 5\nR1 1 2 1k\nR2 2 0 2k\n.op\n.end", "engine": "ngspice" } ``` **Response** `200` ```json { "success": true, "waveform": { "variables": [ {"name": "v(1)", "type": "voltage"}, {"name": "v(2)", "type": "voltage"} ], "points": 1, "x_data": [0.0], "y_data": {"v(1)": [5.0], "v(2)": [3.333]}, "x_type": "time", "is_complex": false, "y_magnitude_db": null, "y_phase_deg": null }, "log": "ngspice output...", "error": null, "elapsed_seconds": 0.42 } ``` #### Run cell in notebook ``` POST /api/notebooks/{notebook_id}/cells/{cell_id}/run ``` No request body — uses the cell's `source` as the netlist and the notebook's `engine`. **Response** `200` — Same `SimulationResponse` shape. The cell's outputs are updated in the saved notebook. --- ### Schematics #### Generate schematic from cell ``` POST /api/notebooks/{notebook_id}/cells/{cell_id}/schematic ``` No request body. Cell must be type `spice`. **Response** `200` ```json { "svg": "...", "success": true, "error": null, "component_map": {"R1": "resistor", "V1": "voltage_source"} } ``` **Color-coded resistors**: Resistors with parseable values between 0.01 and 1e9 ohms render as IEEE zigzag symbols with segments colored according to the standard 4-band resistor color code. A 10k resistor shows Brown-Black-Orange-Gold bands directly on the zigzag. The entry/exit half-segments and the gap before the tolerance band use the default wire color, mimicking the physical spacing that indicates reading direction. Parametric values (e.g. `{R_val}`) and out-of-range resistances fall back to a standard monochrome zigzag. Band-to-segment mapping (7 zigzag sub-segments): - Seg 0 (entry): wire color - Seg 1: 1st significant digit - Seg 2: 2nd significant digit - Seg 3: multiplier - Seg 4: gap (wire color, mimics physical spacing) - Seg 5: tolerance - Seg 6 (exit): wire color --- ### Waveforms #### Generate SVG plot (JSON-wrapped) ``` POST /api/waveforms/svg ``` **Request body** ```json { "waveform": { "...WaveformData from simulation response..." }, "title": "Output Voltage", "width": 800, "height": 500, "signals": ["v(2)"] } ``` `signals` is optional — omit to plot all signals. `width`, `height`, `title` have defaults. **Response** `200` ```json { "svg": "..." } ``` #### Generate SVG plot (raw) ``` POST /api/waveforms/svg/raw ``` Same request body as above. **Response** `200` with `Content-Type: image/svg+xml` — raw SVG string. --- ### Compose (convenience) Create a fully-populated notebook with multiple cells in a single call. #### Compose notebook ``` POST /api/notebooks/compose ``` **Request body** ```json { "title": "RC Low-Pass Filter", "engine": "ngspice", "tags": ["filter", "rc", "analog"], "cells": [ { "type": "markdown", "source": "# RC Low-Pass Filter\n\nA simple first-order low-pass filter." }, { "type": "spice", "source": "V1 in 0 AC 1\nR1 in out 1k\nC1 out 0 1u\n.ac dec 100 1 1meg\n.end" }, { "type": "markdown", "source": "## Analysis\n\nThe -3dB cutoff is at f = 1/(2*pi*R*C) = 159 Hz." } ], "run": false } ``` | Field | Type | Default | Description | |----------|-----------------|----------------------|------------------------------------------------------| | title | string | "Untitled Notebook" | Notebook title | | engine | string | "ngspice" | Simulation engine | | tags | list of strings | [] | Searchable tags | | cells | list of objects | (required) | Cells to create, each with `type` and `source` | | run | bool | false | If true, execute each SPICE cell after creation | **Response** `201` — Same shape as `POST /api/notebooks` (notebook with `id` at top level). When `run` is `true`, each `spice` cell is executed sequentially using the notebook's engine. Simulation results are stored in each cell's `outputs` array. Non-SPICE cells are unaffected. --- ## Data Models ### CellType (enum) `"markdown"` | `"spice"` | `"python"` | `"schematic"` ### Cell ```json { "id": "cell-a1b2c3d4e5f6", "type": "spice", "source": "V1 1 0 DC 5\n.op\n.end", "outputs": [ { "output_type": "simulation_result", "data": { "success": true, "waveform": {...}, "log": "...", "error": null, "elapsed_seconds": 0.3 }, "timestamp": "2026-02-13T18:35:00+00:00" } ] } ``` ### Notebook ```json { "spicebook_version": "2026-02-13", "metadata": { "title": "string", "engine": "ngspice", "tags": ["string"], "created": "ISO-8601 datetime", "modified": "ISO-8601 datetime" }, "cells": [Cell, ...] } ``` ### SimulationResponse ```json { "success": true, "waveform": WaveformData | null, "log": "string", "error": "string | null", "elapsed_seconds": 0.0 } ``` ### WaveformData ```json { "variables": [{"name": "v(out)", "type": "voltage"}], "points": 100, "x_data": [0.0, 0.001, ...], "y_data": {"v(out)": [0.0, 0.5, ...]}, "x_type": "time", "is_complex": false, "y_magnitude_db": null, "y_phase_deg": null } ``` For AC analysis (`is_complex: true`), `y_magnitude_db` and `y_phase_deg` contain per-signal arrays. `x_type` will be `"frequency"` and `x_data` holds frequency values in Hz. --- ## SPICE Netlist Primer SpiceBook uses **ngspice** as its simulation engine. Netlists are plain text describing a circuit and the analysis to perform. ### Basic structure ```spice * Title line (optional comment) V1 node_pos node_neg DC 5 * DC voltage source R1 node_a node_b 1k * Resistor: 1 kilo-ohm C1 node_a node_b 100n * Capacitor: 100 nanofarads L1 node_a node_b 10m * Inductor: 10 millihenrys .analysis_type parameters .end ``` Node `0` is always ground. ### Supported analysis types | Command | Description | Example | |---------|-------------|---------| | `.op` | DC operating point | `.op` | | `.dc` | DC sweep | `.dc V1 0 5 0.1` | | `.tran` | Transient (time-domain) | `.tran 1u 10m` | | `.ac` | AC frequency sweep | `.ac dec 100 1 1meg` | ### Engineering suffixes | Suffix | Multiplier | Example | |--------|-----------|---------| | T | 10^12 | `1T` = 1 tera | | G | 10^9 | `2.2G` = 2.2 giga | | meg | 10^6 | `1meg` = 1 mega (note: not `M` — that's milli in SPICE) | | k | 10^3 | `4.7k` = 4700 | | m | 10^-3 | `10m` = 0.01 | | u | 10^-6 | `100u` = 100 micro | | n | 10^-9 | `47n` = 47 nano | | p | 10^-12 | `10p` = 10 pico | | f | 10^-15 | `1f` = 1 femto | ### Common sources ```spice V1 node+ node- DC 5 * DC voltage V2 node+ node- AC 1 * AC source (for .ac analysis) V3 node+ node- PULSE(0 5 0 1n 1n 5u 10u) * Pulse source I1 node+ node- DC 1m * DC current source ``` --- ## Example Workflow ### 1. Create a notebook with the compose endpoint ```bash curl -X POST https://spicebook.warehack.ing/api/notebooks/compose \ -H "Content-Type: application/json" \ -d '{ "title": "Voltage Divider", "engine": "ngspice", "tags": ["resistive", "dc", "beginner"], "cells": [ { "type": "markdown", "source": "# Voltage Divider\n\nTwo resistors divide a 5V supply." }, { "type": "spice", "source": "V1 1 0 DC 5\nR1 1 2 1k\nR2 2 0 2k\n.op\n.end" }, { "type": "markdown", "source": "## Expected Result\n\nV(2) = 5 * 2k / (1k + 2k) = 3.333V" } ], "run": true }' ``` Response includes the notebook `id` and all cells. Because `run: true`, the SPICE cell's `outputs` array will contain the simulation result with `v(2) = 3.333`. ### 2. View the notebook in the browser Open `https://spicebook.warehack.ing/notebook/{id}` — the notebook renders with the markdown cells formatted and the SPICE cell showing its simulation output. ### 3. Add another cell ```bash curl -X POST https://spicebook.warehack.ing/api/notebooks/{id}/cells \ -H "Content-Type: application/json" \ -d '{ "type": "spice", "source": "V1 1 0 DC 5\nR1 1 2 1k\nR2 2 0 2k\n.dc V1 0 10 0.5\n.end" }' ``` ### 4. Run the new cell ```bash curl -X POST https://spicebook.warehack.ing/api/notebooks/{id}/cells/{cell_id}/run ``` ### 5. Generate a schematic ```bash curl -X POST https://spicebook.warehack.ing/api/notebooks/{id}/cells/{cell_id}/schematic ``` ### 6. Visualize waveform data Take the `waveform` from the simulation response and POST it to the waveform endpoint: ```bash curl -X POST https://spicebook.warehack.ing/api/waveforms/svg/raw \ -H "Content-Type: application/json" \ -d '{ "waveform": { ...waveform object from simulation response... }, "title": "DC Sweep", "signals": ["v(2)"] }' \ -o plot.svg ``` --- ## Health Check ``` GET /health ``` **Response** `200` ```json {"status": "ok", "version": "2026.02.13"} ```