---
title: Simulation
description: Run SPICE netlists standalone or within notebook cells via the SpiceBook REST API.
---

import { Aside } from '@astrojs/starlight/components';

## Run Standalone Simulation

```
POST /api/simulate
```

Run a SPICE netlist without creating or modifying a notebook. Useful for one-off simulations or integration testing.

**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` setting.

**Response** `200` — same `SimulationResponse` shape as standalone. The cell's `outputs` array is updated in the saved notebook.

## SimulationResponse

| Field | Type | Description |
|-------|------|-------------|
| `success` | boolean | Whether the simulation completed without errors |
| `waveform` | WaveformData \| null | Simulation results (null if simulation failed) |
| `log` | string | Raw simulator output (stdout/stderr) |
| `error` | string \| null | Error message if simulation failed |
| `elapsed_seconds` | number | Wall-clock simulation time |

## 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
}
```

| Field | Type | Description |
|-------|------|-------------|
| `variables` | array | Signal names and types (voltage, current) |
| `points` | integer | Number of data points |
| `x_data` | number[] | Horizontal axis values (time or frequency) |
| `y_data` | object | Signal name → value array mapping |
| `x_type` | string | `"time"` or `"frequency"` |
| `is_complex` | boolean | `true` for AC analysis |
| `y_magnitude_db` | object \| null | Per-signal magnitude in dB (AC only) |
| `y_phase_deg` | object \| null | Per-signal phase in degrees (AC only) |

<Aside type="note">
For AC analysis (`is_complex: true`), use `y_magnitude_db` and `y_phase_deg` for Bode plots rather than `y_data`. The `x_type` will be `"frequency"` and `x_data` contains frequency values in Hz.
</Aside>

## Error Handling

When a simulation fails (syntax error, convergence failure, missing model), the response still returns `200` but with `success: false`:

```json
{
  "success": false,
  "waveform": null,
  "log": "Error: unknown subcircuit...",
  "error": "Simulation failed: unknown subcircuit 'LM741'",
  "elapsed_seconds": 0.1
}
```

Check the `log` field for the full simulator output — it often contains line numbers and detailed diagnostics that aren't in the `error` summary.
