API models¶
The request and response bodies of the API routes, one section per model. A field marked yes under Required must be sent (or is always present in a response); an optional field that is left out takes the default named in its description.
AbortResponse¶
Response body for POST /sessions/{id}/abort.
The endpoint is fire-and-forget at the wire level - it sets the session's
abort event and returns immediately. The actual TDS exit happens
cooperatively at the next callpert tick on the worker (typically
within a few milliseconds for IEEE 14, longer for larger cases). The
streaming WebSocket emits the terminal done message with
final_t < tf once the integration loop exits.
There is no aborted flag on the WS done payload - the UI infers
user-initiated abort from local state (it set the abort itself) vs.
numerical instability (a done with final_t < tf arrived without
a local abort).
| Field | Type | Required | Description |
|---|---|---|---|
aborted |
True |
no | Always true on a successful response. The signal has been delivered to the worker; the actual TDS exit is cooperative and lands on the next per-step callpert tick. No-op when no TDS is currently running on the session (the abort event is set but never consumed). Default true. |
AddDisturbancesRequest¶
Request body for POST /sessions/{id}/disturbances.
Accepts a list so a caller can register multiple disturbances in one
request - useful for the v0.2 timeline editor that wants to commit a
full study scenario at once. ANDES rejects all post-setup add() calls,
so this endpoint is gated on pre-setup state (returns 409 otherwise with
a hint to call /reload).
| Field | Type | Required | Description |
|---|---|---|---|
disturbances |
array of FaultSpec or ToggleSpec or AlterSpec | yes | List of disturbance specifications. Discriminated by the kind field (fault, toggle, alter). Limits: min items 1. |
AddDisturbancesResponse¶
Response body for POST /sessions/{id}/disturbances.
| Field | Type | Required | Description |
|---|---|---|---|
accepted |
array of DisturbanceAck | yes | One ack entry per accepted disturbance, in input order. |
job_id |
string or null | no | Job-registry id mirroring the disturbance-commit routine (kind disturbance-commit). One job covers the whole batch; null on legacy responses. |
AddElementRequest¶
Request body for POST /sessions/{id}/elements.
Adds a single topology element (Bus, Line, generator, load, shunt) to a
pre-setup System. The wrapper validates the model name + param keys
against an internal whitelist BEFORE invoking ANDES; unknown keys
surface as 422 ProblemDetails listing both the rejected and the
allowed sets.
| Field | Type | Required | Description |
|---|---|---|---|
model |
string | yes | ANDES model class name. It must be one of the buildable models listed by GET /api/topology/schema (buses, lines, generators, loads, shunts, exciters, governors, the ESD1 battery, and other controllers). Unknown models are rejected with 422. Limits: min length 1. |
params |
object (names to number or integer or string or boolean) | yes | Flat dict of model parameters. Keys are validated against the per-model whitelist; values pass through to ss.add(). A reference to another device (bus, gen, syn) may be sent as text or as a number: it is matched to the idx the case holds. A request that leaves out a parameter ANDES has no default for is rejected with 422 and adds nothing. Required keys vary per model - query GET /api/topology/schema for the live form metadata. |
AddPmuRequest¶
Request body for POST /sessions/{id}/pmu.
bus_idx accepts a string (which the substrate forwards as-is to
ANDES - ss.add('PMU', dict(bus=...))). Bus idx values can be
integers (PSS/E .raw cases) or strings (.xlsx cases); the substrate
coerces both via string-equality so the API surface stays uniform.
Ta / Tv (optional) are the angle / voltage low-pass filter
time constants in seconds. The defaults are an empirical sweet spot
(0.05 s): small enough to track a 60 Hz swing, large enough to
suppress integration noise on stiff cases. ANDES's own defaults are
0.1 s.
| Field | Type | Required | Description |
|---|---|---|---|
bus_idx |
string | yes | Bus idx the PMU attaches to. Must reference a Bus that exists on the loaded System. Integer-typed bus idxes (from PSS/E .raw cases) are accepted as their string representation. Limits: min length 1. |
Ta |
number or null | no | Angle filter time constant in seconds. Defaults to 0.05 s when omitted (the substrate's recommended sweet spot). Limits: above 0. |
Tv |
number or null | no | Voltage filter time constant in seconds. Defaults to 0.05 s when omitted. Limits: above 0. |
AddProfileRequest¶
Request body for POST /sessions/{id}/profiles.
Mirrors the ss.add('TimeSeries', ...) parameter surface from
andes/models/timeseries.py:38-72. profile_path is the
absolute path returned by the prior POST /profiles/upload.
| Field | Type | Required | Description |
|---|---|---|---|
profile_path |
string | yes | Absolute path of the on-disk profile xlsx - the value returned by POST /profiles/upload. The file must exist before this call (ANDES reads it during setup). Limits: min length 1. |
sheet |
string | yes | XLSX sheet name to read. CSV uploads are transcoded to a single sheet named profile; XLSX uploads keep their original sheet names. Limits: min length 1. |
fields |
string | yes | Comma-separated column names from the source sheet providing the time series of values (e.g., p0, p0,q0). Each entry must match an existing column in the sheet. Limits: min length 1. |
model |
string | yes | ANDES model class name of the target device (e.g., PQ, PV, Slack). Must reference a model present on the loaded System. Limits: min length 1. |
dev |
string | yes | Idx of the target device within model (e.g., PQ_5). The substrate validates existence before the underlying ss.add so the user gets a clean 422 instead of an ANDES-internal error. Limits: min length 1. |
dests |
string | yes | Comma-separated parameter names on the target device that receive the profile values (e.g., p0, p0,q0). Must align with fields (one destination per source column). Limits: min length 1. |
tkey |
string | no | Source column carrying the timestamp (in seconds). Defaults to t - the convention shipped by ANDES's bundled examples. Limits: min length 1. Default "t". |
mode |
integer | no | Application mode. 1 (exact) applies values at exact step times. 2 (interpolated) raises NotImplementedError in ANDES, so the substrate rejects mode=2 with 422; default to mode=1. Limits: min 1, max 2. Default 1. |
AlterSpec¶
Parameter alteration at a scheduled time - used for load steps, parameter ramps, set-point changes, etc.
Maps to ss.add('Alter', model=..., dev=..., src=..., t=..., method=...,
amount=...). ANDES's Alter model has NO value parameter - the new
value is v_new = v_current <method> amount where method is one of
+ - * / = and amount is the operand (verified against ANDES 2.0.0;
method is MANDATORY - omitting it raises "Mandatory parameter method
missing"). Examples:
- set absolute:
method='=', amount=1.2 - step up by 0.2 pu:
method='+', amount=0.2 - scale (e.g. +20% load):
method='*', amount=1.2
NOTE for load increases: ANDES applies time-domain alterations to Ppf /
Qpf on PQ loads, not p0 / q0 (the latter only feed power flow and
are no-ops in TDS) - pick Ppf/Qpf as src for a load change that
actually moves the simulation.
| Field | Type | Required | Description |
|---|---|---|---|
kind |
"alter" |
no | Discriminator: this spec creates an ANDES Alter device. Default "alter". |
model |
string | yes | ANDES model class name containing the parameter. |
dev_idx |
integer or string | yes | ANDES idx of the device within model. |
src |
string | yes | Source parameter name on the model (e.g., 'Ppf' for a PQ load's time-domain active power, or a generator set-point). |
t |
number | yes | Time the parameter change applies, in seconds. |
method |
string | no | How amount is combined with the parameter's current value: '=' set, '+' add, '-' subtract, '*' multiply, '/' divide. Mandatory in ANDES; defaults to '=' (absolute set). One of +, -, *, /, =. Default "=". |
amount |
number | yes | Operand applied via method (the absolute value when method='=', the delta/factor otherwise). |
AlterableParamsResponse¶
Response body for GET /sessions/{id}/topology/models/{model}/alterable_params.
Returns the ordered list of parameter names that ANDES will accept as
src for the Alter disturbance on the given model. The UI uses
this to populate the AlterSpec form's parameter dropdown.
The introspection rule (mirrors ANDES's own alter() contract):
a parameter is alterable iff it is a NumParam and not an
ExtParam (which is a derived/external param read off another
model). This excludes topology refs (IdxParam: bus, bus1,
bus2, area, zone, owner, coi, etc.) and string
identifiers (DataParam: idx, name).
| Field | Type | Required | Description |
|---|---|---|---|
model |
string | yes | ANDES model class name the params belong to (echoed back from the path). Example: Bus, PQ, GENROU. |
params |
array of string | yes | Ordered list of parameter names that ss.<model>.alter(src=...) will accept. Order matches ANDES's internal declaration order on the model class. Empty when the model has no alterable params. |
BlankSystemResponse¶
Response body for POST /sessions/{id}/blank (201).
Returns the empty topology so the client immediately switches to the
blank-system rendering path (centered Add your first bus prompt).
| Field | Type | Required | Description |
|---|---|---|---|
topology |
TopologySummary | yes | Empty topology snapshot for the freshly-created blank System. All buckets are empty; state is pre-setup. |
Body_importBundle¶
| Field | Type | Required | Description |
|---|---|---|---|
file |
string | yes | Reproducibility bundle .zip (the same format produced by POST /api/sessions/{id}/bundle/export). |
force_resolve |
boolean | no | When False (default), the substrate validates the bundle and returns status=plan if any conflict is detected (sha mismatch, version mismatch, missing addfile). When True, the substrate proceeds with the extraction + replay honouring use_bundle_case / accept_version_mismatch. Default false. |
use_bundle_case |
boolean | no | Sha-mismatch resolution. True (default) overwrites the workspace's copy of the case file with the bundle's; False preserves the workspace file and writes the bundle's to a sibling <filename>.from-bundle for offline diff. Default true. |
accept_version_mismatch |
boolean | no | When True (default), the substrate proceeds even when the bundle's ANDES major.minor differs from the installed version (the warning surfaces in the response's plan). Default true. |
Body_uploadProfile¶
| Field | Type | Required | Description |
|---|---|---|---|
file |
string | yes | CSV or XLSX file. CSV inputs are transcoded to xlsx (single sheet named profile) for uniformity with ANDES's preferred input format. |
BundleConflictModel¶
One conflict surfaced by validate_bundle.
| Field | Type | Required | Description |
|---|---|---|---|
kind |
string | yes | Conflict category detected while validating the bundle. One of andes-version, addfile-missing, sha-mismatch. |
severity |
string | yes | warning conflicts can be overridden with force_resolve; blocker conflicts prevent the import entirely. One of warning, blocker. |
message |
string | yes | Human-readable explanation of the conflict. |
filename |
string or null | no | Workspace-relative case filename the conflict refers to, when applicable. |
bundle_meta |
object or null | no | Side-by-side metadata for the bundle's copy of the case file. Populated for sha-mismatch. |
workspace_meta |
object or null | no | Side-by-side metadata for the workspace's copy of the case file. Populated for sha-mismatch. |
bundle_andes_version |
string or null | no | ANDES version recorded in the bundle manifest. Populated for andes-version. |
current_andes_version |
string or null | no | ANDES version installed on this server. Populated for andes-version. |
BundleExportRequest¶
Request body for POST /sessions/{id}/bundle/export.
All fields are optional - the substrate happily exports a minimal
bundle (case + manifest only) when none are present. The substrate
contributes the case file, the ANDES + tensa versions, and
the manifest; this body carries the substrate-external state that
lives in the frontend's runs / disturbance / ui slices today.
| Field | Type | Required | Description |
|---|---|---|---|
disturbances |
array of FaultSpec or ToggleSpec or AlterSpec | no | Disturbance specs (the discriminated union) the user composed in the timeline editor. Empty list when no disturbances were registered; disturbances.json is omitted from the bundle in that case. |
sim_params |
BundleSimParams or null | no | Last TDS run's sim params. null when no run has fired yet; sim_params.json is omitted from the bundle in that case. |
results_csv |
string or null | no | Last TDS run's results as a long-form CSV body. null when no run has fired yet OR the caller chose not to ship the body. When omitted, results.csv is absent from the bundle but the run is still reproducible from case + disturbances + sim_params. |
run_id |
string or null | no | Run id of the most recent TDS run. Surfaced in the manifest for cross-referencing with run-history exports. |
layout |
SidecarLayout or null | no | The diagram's layout as the client shows it, written to the bundle as layout.json so an import opens with the same picture. null uses the layout saved beside the case file; with neither, the bundle holds no layout.json. One over the cap PUT /workspace/layout holds a layout to is refused (413). |
BundleImportPlanModel¶
BundleImportPlan shape echoed in both plan and committed responses.
| Field | Type | Required | Description |
|---|---|---|---|
manifest |
object | yes | Parsed manifest.json from the bundle, echoed verbatim. |
case_files |
array of string | yes | Case filenames contained in the bundle (workspace-relative). |
conflicts |
array of BundleConflictModel | no | Conflicts detected between the bundle and this server/workspace. |
blocked |
boolean | yes | true if any conflict has blocker severity - the import cannot proceed. |
has_conflicts |
boolean | yes | true if conflicts is non-empty. |
BundleImportResponse¶
Response body for POST /sessions/{id}/bundle/import.
| Field | Type | Required | Description |
|---|---|---|---|
status |
string | yes | plan = conflicts present, nothing committed; the user resolves them and re-issues with force_resolve=true. committed = case loaded and disturbances replayed. One of plan, committed. |
plan |
BundleImportPlanModel | yes | The validation plan (conflicts, case files, manifest). |
warnings |
array of string | no | Non-blocking warnings emitted during commit (e.g. overridden conflicts). |
case_filename |
string or null | no | Basename of the case file the substrate loaded. Populated on status=committed; null on status=plan. |
addfile_filenames |
array of string | no | Basenames of any addfiles the substrate extracted alongside the primary case (e.g., ieee14.dyr for a PSS/E .raw + .dyr bundle). Empty on status=plan. |
disturbances_replayed |
integer | no | Count of disturbance specs successfully re-applied to the newly-loaded System. Zero on status=plan. Default 0. |
layout_restored |
boolean | no | true when the bundle held the diagram's layout (layout.json) and it is now saved beside the imported case, replacing any layout that was there. false on status=plan, for a bundle with no layout, and when the workspace's own case file was kept. Default false. |
job_id |
string or null | no | Job-registry id mirroring the bundle-import routine (kind bundle-import). Recorded in the manager-wide global registry so it survives the session being replaced on a committed import. Present on both the committed (200) body and the plan (409) body. null on legacy responses. |
BundleSimParams¶
Sim-params subset embedded in sim_params.json of the bundle.
Mirrors the fields the RunStream start-tds message ships. All
fields are optional so a partially-populated client (e.g., a
pre-Unit-7 session) can still produce a bundle.
| Field | Type | Required | Description |
|---|---|---|---|
tf |
number or null | no | Final sim time of the last TDS run, in seconds. |
h |
number or null | no | Fixed integration step of the last TDS run, in seconds. null when the substrate's adaptive integrator was used. |
vars |
array of string or null | no | Variable groups streamed during the last run (e.g., ["bus_v", "gen_state"]). |
decimation |
string or null | no | Decimation mode used during streaming (none or mean). |
max_rate_hz |
number or null | no | Output-rate clamp (Hz) the UI applied to the stream. |
BusCoord¶
One position on the diagram.
Coordinates are in arbitrary canvas units; the UI rescales them at render time. Infinity / NaN are rejected at validation time.
| Field | Type | Required | Description |
|---|---|---|---|
x |
number | yes | X coordinate, finite (no NaN/Inf). |
y |
number | yes | Y coordinate, finite (no NaN/Inf). |
CaseEvent¶
A timed event the next time-domain run applies that the client did not schedule: one the case's files define, or one a bundle import or a snapshot restore replayed.
| Field | Type | Required | Description |
|---|---|---|---|
source |
string | yes | case: a Fault, Toggle or Alter device the case file or one of its add-on files defines. restored: a disturbance a bundle import or a snapshot restore replayed onto the system. One of case, restored. |
kind |
string | yes | Which ANDES event model it is. One of fault, toggle, alter. |
t |
number | yes | Time the event starts, in seconds: a fault's tf, otherwise the time the toggle or alteration fires. |
name |
string or null | no | The device's name in the case file. null for a restored disturbance, which has none. |
tc |
number or null | no | Fault only: time the fault is cleared, in seconds. null when the case gives none, which leaves the fault on. |
model |
string or null | no | ANDES model of the device the event acts on: Bus for a fault, the toggled or altered model otherwise (a group name is possible in a case file). |
dev_idx |
integer or string or null | no | ANDES idx of the device within model (the bus, for a fault). |
src |
string or null | no | Alter only: the parameter the event changes. |
method |
string or null | no | Alter only: how amount is combined with the parameter's current value (=, +, -, * or /). |
amount |
number or null | no | Alter only: the operand applied via method. |
CloneDiffPair¶
One changed param's original-vs-current file values.
| Field | Type | Required | Description |
|---|---|---|---|
original |
number or integer or string or boolean or null | no | The param value in the ORIGINAL case file (pre-setup read). null when the param is absent on the original device. |
current |
number or integer or string or boolean or null | no | The param value in the CLONE case file (pre-setup read). null when the param is absent on the clone device. |
CloneDiffResponse¶
Response body for GET /sessions/{id}/case/clone/diff/{model}/{idx}.
Maps each whitelisted controller param whose clone-file value differs from
the original-file value to its {original, current} pair. An empty
params means no edits relative to the original (or no clone yet).
| Field | Type | Required | Description |
|---|---|---|---|
params |
object (names to CloneDiffPair) | no | Changed params keyed by name; unchanged / unedited params are absent. Empty when no clone is initialised. |
CloneEditRequest¶
Request body for PUT /sessions/{id}/case/clone/params/{model}/{idx}/{param}.
Carries only the new value - model / idx / param are path
parameters, whitelist-validated by the route BEFORE any clone work. The
edit modifies the cloned case file (never the original), then re-loads +
re-setups the System so runs reflect the new value.
| Field | Type | Required | Description |
|---|---|---|---|
value |
number or integer or string or boolean | yes | New value for the parameter. Written to the clone case file; ANDES re-reads it on the subsequent load(setup=False) → setup() cycle. Some params are per-unit-normalised at setup, so the read-back live value may differ from the file value. |
CloneEditResponse¶
Response body for the clone edit / undo / redo routes.
Returns the post-setup live value plus the current undo / redo stack depths so the inspector can enable / disable its undo / redo affordances.
| Field | Type | Required | Description |
|---|---|---|---|
model |
string | yes | ANDES model class of the edited device (echoed from the path). Empty string on undo / redo responses (the stack entry, not a single field, is the unit of work). |
idx |
string | yes | Device idx of the edited element (empty on undo / redo). |
param |
string | yes | Edited parameter name (empty on undo / redo). |
new_value |
number or integer or string or boolean or null | no | The parameter value read back from the re-setup System (ss.<model>.<param>.v[i]). null on undo / redo. |
undo_depth |
integer | yes | Number of edits currently recoverable via undo (0-50). |
redo_depth |
integer | yes | Number of undone edits currently re-appliable via redo. |
job_id |
string or null | no | Job-registry id mirroring the clone routine (kinds clone-edit / clone-undo / clone-redo). null on legacy responses. |
CloneInitResponse¶
Response body for POST /sessions/{id}/case/clone (clone init).
| Field | Type | Required | Description |
|---|---|---|---|
clone_dir |
string | yes | Absolute path of the per-session clone scratch directory. |
clone_files |
array of string | no | Absolute paths of the cloned case files (case + addfiles). |
already_initialized |
boolean | yes | true when the clone already existed (idempotent re-init - no re-copy, so pending edits are preserved). |
job_id |
string or null | no | Job-registry id for the clone-init routine. |
CloneResetResponse¶
Response body for POST /sessions/{id}/case/clone/reset.
| Field | Type | Required | Description |
|---|---|---|---|
reset |
boolean | yes | Always true - the clone dir was discarded and the session reverted to the original case files. |
job_id |
string or null | no | Job-registry id for the clone-reset routine. |
CloneSaveAsRequest¶
Request body for POST /sessions/{id}/case/clone/save-as.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Workspace-relative case name (stem only - no extension, no path separators or traversal). The clone's files are written as <name>.<ext> for each cloned format. |
overwrite |
boolean | no | When false (the default), save-as REFUSES to overwrite an existing workspace file (a 422) - this protects the loaded original case, which lives in the same workspace, from being silently clobbered. Pass true to intentionally overwrite an existing case. Default false. |
CloneSaveAsResponse¶
Response body for POST /sessions/{id}/case/clone/save-as (201).
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | The saved case name (stem). |
files |
array of string | no | Absolute paths of the written workspace files. |
job_id |
string or null | no | Job-registry id for the clone-save-as routine. |
ComplexNumberModel¶
JSON-friendly complex number {real, imag}.
| Field | Type | Required | Description |
|---|---|---|---|
real |
number | yes | Real part of the eigenvalue. |
imag |
number | yes | Imaginary part of the eigenvalue. |
ComtradeChannelSeries¶
One signal of a COMTRADE export. A batch run's traces.variables entries
have this shape.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | What the signal is called; it becomes the channel's identifier, reduced to ASCII without commas and cut to 64 characters. Limits: min length 1, max length 200. |
unit |
string or null | no | The unit the values are in (pu, MW, rad), reduced to ASCII and cut to 32 characters. A channel given none is written with the unit NONE, since the field cannot be empty. Limits: max length 200. |
values |
array of number or null | yes | The signal's value at each time in t. null marks a missing value (a diverged step), which the data file holds as 99999. |
ComtradeExportRequest¶
Request body for POST /comtrade.
| Field | Type | Required | Description |
|---|---|---|---|
t |
array of number | yes | Sample times in seconds, not decreasing, at least one. Times need not be evenly spaced: the record carries a time stamp per sample. |
channels |
array of ComtradeChannelSeries | yes | The signals, each with one value per time in t. At most 5000000 values in all (channels times samples). Limits: min items 1. |
name |
string | no | File name the record's two files share: the archive holds <name>.cfg and <name>.dat. 1-64 chars of [A-Za-z0-9._-] starting with an alphanumeric, not ending in a dot, and not a Windows device name (CON, NUL, COM1, ...). Default "tensa". |
station |
string | no | The record's station name, for instance the case the run was made on. Reduced to ASCII without commas and cut to 64 characters. Limits: max length 200. Default "". |
device |
string or null | no | The record's recording device, for instance a name for the run. Reduced as station is. Defaults to TENSA and its version. Limits: max length 200. |
frequency_hz |
number | no | The system's nominal frequency in Hz, the record's line frequency. Limits: above 0. Default 60.0. |
start_time |
string (date-time) or null | no | The date and time simulated time zero stands for (ISO 8601). The record's first date line is this plus the first time in t. The format carries no time zone, so the clock reading is written as given. Defaults to the server's local time when the request arrives. |
trigger_t |
number or null | no | Simulated time of the trigger point in seconds, for instance when a fault is applied; it must lie inside the record. Defaults to the first time in t. |
ConnectivityResponse¶
Wire shape of GET /sessions/{id}/connectivity.
Mirrors tensa.core.connectivity_result.ConnectivityResult
1:1. Bus idxes are stringified for stable JSON keying - case-file
formats may carry int or str idx values, but the SLD always stringifies
when keying nodes, so the wire payload normalises here.
| Field | Type | Required | Description |
|---|---|---|---|
island_count |
integer | yes | Total number of islands, including singleton 'islands' of one degree-zero bus. Equals len(Bus.islands). A fully-interconnected case yields 1; tripping a critical line yields >= 2. |
islands |
array of array of string | yes | List of lists of bus idx values. Each inner list is one island's bus membership. Index-aligned with Bus.islands so the first entries are singleton islands for any degree-zero buses; the larger connected components follow. |
islanded_bus_idxes |
array of string | yes | Convenience: just the degree-zero (lone) bus idxes. Each appears as its own singleton in islands too. The SLD uses this for the primary 'grey out' trigger. |
CpfGeneratorIncrease¶
What one PV generator gains for each unit of lambda in a custom direction.
| Field | Type | Required | Description |
|---|---|---|---|
idx |
integer or string | yes | The generator's PV idx. The slack generator cannot be named: it supplies whatever the rest of the direction leaves. |
p |
number | yes | Active power added per unit of lambda, in MW. |
CpfGeneratorTraceSchema¶
One PV or slack generator along the path. Mirrors
tensa.core.cpf_result.CpfGeneratorTrace.
| Field | Type | Required | Description |
|---|---|---|---|
idx |
string | yes | The generator's idx. |
model |
string | yes | Its ANDES model. One of PV, Slack. |
bus |
string | yes | The idx of the bus it sits on. |
q |
array of number | yes | Reactive output in MVAr at every step, index-aligned with lambdas. |
q_min |
number or null | no | Lower reactive limit in MVAr; null when not finite. |
q_max |
number or null | no | Upper reactive limit in MVAr; null when not finite. |
CpfLimitEventSchema¶
The first step at which a generator is held at a reactive limit. Mirrors
tensa.core.cpf_result.CpfLimitEvent.
| Field | Type | Required | Description |
|---|---|---|---|
step |
integer | yes | Index into lambdas. 0 means the power flow the continuation started from already held the generator there. |
lam |
number | yes | The value of lambdas at that step. |
idx |
string | yes | The generator's idx. |
model |
string | yes | Its ANDES model. One of PV, Slack. |
bus |
string | yes | The idx of the bus it sits on. |
limit |
string | yes | The limit it is held at. One of qmax, qmin. |
at_nose |
boolean | no | true when the nose is where this generator switched: lambda turned at the switch or in the step after it, or the path could not get past the switch at all. The loadability then ends because the generator ran out of reactive power (a limit-induced collapse), not at a smooth fold. Default false. |
would_release_step |
integer or null | no | The first step, from step on, at which the generator's terminal voltage is back across its set-point (above it for qmax, below for qmin), where a real exciter would take the voltage up again and leave the limit. ANDES keeps a generator at a limit once it is there, so from that step the curve is the one for a generator pinned at its limit. null when it does not happen. |
CpfLoadIncrease¶
What one PQ load gains for each unit of lambda in a custom direction.
| Field | Type | Required | Description |
|---|---|---|---|
idx |
integer or string | yes | The load's PQ idx. |
p |
number | no | Active power added per unit of lambda, in MW. Negative takes load off. Default 0.0. |
q |
number | no | Reactive power added per unit of lambda, in MVAr. Default 0.0. |
CpfQvRunRequest¶
Request body for POST /sessions/{id}/cpf/qv.
| Field | Type | Required | Description |
|---|---|---|---|
bus_idx |
string | yes | Bus idx to draw the QV-curve at. Must match an entry in the loaded case's Bus.idx; ANDES requires at least one PQ device at this bus (raises ValueError otherwise, surfaced as 422 here). Limits: min length 1. |
q_range |
number or null | no | Reactive-power range for the QV continuation. Default matches ANDES's own q_range=5.0. Limits: above 0. |
enforce_q_limits |
boolean or null | no | Hold generators to their reactive limits along the curve, as enforce_q_limits of POST /sessions/{id}/cpf does. |
CpfResultResponse¶
Wire shape of POST /sessions/{id}/cpf and
POST /sessions/{id}/cpf/qv.
Field semantics mirror tensa.core.cpf_result.CpfResult
1:1; see that class for prose.
| Field | Type | Required | Description |
|---|---|---|---|
lambdas |
array of number | yes | Per-step continuation parameter values. For PV-curve runs this is CPF.lam (lambda); for QV-curve runs it is CPF.qv_q (reactive injection). The mode field tells the UI which axis label to use. |
voltages_per_bus |
object (names to array of number) | yes | Per-bus voltage trace, index-aligned with lambdas. PV runs include every bus in the loaded case; QV runs include only the requested bus_idx. |
bus_idxes |
array of string | yes | Ordered list of bus idxes (stringified) matching the row order of CPF.V. Surfaced separately so the UI can render in canonical order without dict-key iteration ambiguity. |
nose_idx |
integer | yes | Index into lambdas of the nose point (the voltage-collapse margin): the point after which lambda first goes down. -1 when the run was truncated before reaching the nose. On a full curve the steps after it are the lower branch. |
max_lam |
number | yes | Lambda at the nose, which is the largest value reached on the way up. Without a nose, the largest value reached. For a QV curve, the largest reactive power at the bus (the axis lambdas is on). Always populated, even on truncation. |
truncated |
boolean | yes | True when the run terminated without finding a nose point (e.g. hit max_steps or did not branch-switch to a NOSE event). When True, nose_idx == -1 and the UI shows the truncation note from done_msg. |
done_msg |
string | yes | ANDES's terminal status string (e.g., "Nose point at lambda=3.258046", "Reached max steps (5)"). Used by the UI to label the truncation banner. |
mode |
string | yes | Discriminator: "pv" for the full PV-curve sweep (CPF.run) or "qv" for a single-bus QV-curve (CPF.run_qv). The wire shape is the same; the UI uses mode to label the X-axis (lambda vs Q). Pattern ^(pv\\|qv)$. |
generators |
array of CpfGeneratorTraceSchema | no | Every in-service PV and slack generator's reactive output along the path, with its limits. Empty only when the readings could not be matched to the steps. |
limit_events |
array of CpfLimitEventSchema | no | The generators held at a reactive limit, each with the first step at which it is, in step order. Those at step 0 are held by the power flow the run started from. A generator has at most one entry: one that is held stays held for the rest of the path. |
q_limits_enforced |
boolean | no | Whether generators were switched to PQ at their reactive limits along the path. When false only the generators the base power flow held are held. Default false. |
stop_at |
string | no | What the run was asked to trace: up to the nose, or the full curve. One of nose, full. Default "nose". |
complete |
boolean | no | Whether the run ended the way stop_at asked. false with truncated: false is a full curve whose lower branch broke off; done_msg says where. Default true. |
direction |
string or null | no | The direction of the increase a PV run was asked for; null for a QV curve. One of load, load-only, gen, custom. |
job_id |
string or null | no | Job-registry id mirroring this CPF routine (kind cpf for the PV sweep, cpf-qv for the QV curve). GET /sessions/{id}/jobs/{job_id} returns the matching record; null on legacy responses. |
CpfRunRequest¶
Request body for POST /sessions/{id}/cpf.
All fields are optional, and each applies to this run only.
direction says what lambda increases, enforce_q_limits holds
generators to their reactive limits along the path, stop_at asks
for the lower branch as well, and step and max_iter set the
corresponding ss.CPF.config values for the run.
| Field | Type | Required | Description |
|---|---|---|---|
direction |
string | no | What lambda increases. 'load' (default) scales every load and every PV generator's output in proportion to its base value (CPF.run(load_scale=2.0)). 'load-only' scales the loads and leaves the PV generators where they are, so the slack generator supplies the increase. 'gen' scales the PV generators and leaves the loads. With these three, lambda = 1 is twice the base value. 'custom' moves the devices named in load_increase and generator_increase by the amounts given there, and lambda counts multiples of them. The slack generator is never part of a direction, and only PQ loads and PV generators move: ANDES's routine leaves every other load model as it is. One of load, load-only, gen, custom. Default "load". |
load_increase |
array of CpfLoadIncrease or null | no | For direction: 'custom': the MW and MVAr each named PQ load gains per unit of lambda. A load left out does not move. Limits: max items 100000. |
generator_increase |
array of CpfGeneratorIncrease or null | no | For direction: 'custom': the MW each named PV generator gains per unit of lambda. A generator left out does not move, and what the loads gain beyond the generators is supplied by the slack. Limits: max items 100000. |
enforce_q_limits |
boolean or null | no | Switch a PV or slack generator to a PQ bus held at qmin or qmax when its reactive output reaches one along the path. Left out, the case's own setting stands (off unless the case file turns pv2pq on). The continuation starts from the power flow as solved, so run that with enforce_q_limits as well: the request is refused with 409 when the solved power flow leaves a generator past a limit. Without it, the generators the power flow holds at a limit stay held and no other switches. A generator held at a limit stays held for the rest of the path (ANDES's limiter does not let go); would_release_step of its entry in limit_events says from where a real exciter would have. |
stop_at |
string | no | 'nose' (default) stops at the nose. 'full' turns there and follows the lower-voltage solutions back to lambda = 0 (CPF.config.stop_at = 'FULL'); the steps after nose_idx are that lower branch. One of nose, full. Default "nose". |
step |
number or null | no | Optional initial continuation step size for lambda (ss.CPF.config.step for this run). Default uses ANDES's own default (0.1). Limits: above 0. |
max_iter |
integer or null | no | Optional cap on the number of continuation steps (ss.CPF.config.max_steps for this run). This maps the user-facing parameter name onto ANDES's max_steps field, which actually controls truncation; ANDES's own max_iter config is the Newton corrector iterations per step. Default uses ANDES's own default (500). Limits: min 1. |
DaeVariableInfo¶
One ANDES variable of one device of the loaded case.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | <variable> <Model> <idx> as ANDES spells it in dae.x_name / dae.y_name (omega GENROU 1): what dae_vars asks for it by, and the name of its column in a stream. |
kind |
string | yes | x for a state variable, y for an algebraic one. One of x, y. |
model |
string | yes | ANDES model the device belongs to. |
var |
string | yes | The variable's name within the model. |
idx |
integer or string | yes | The device's idx. |
unit |
string or null | no | ANDES's unit for the variable; null where it gives none. |
info |
string or null | no | ANDES's description of the variable; null where it gives none. |
DaeVariableList¶
A page of the ANDES variables of the loaded case.
| Field | Type | Required | Description |
|---|---|---|---|
total |
integer | yes | How many variables match the filters, across all pages. Limits: min 0. |
items |
array of DaeVariableInfo | yes | The requested page, in the models' own order. |
DampingEstimate¶
The oscillation of a signal, from the log decrement of its swings.
| Field | Type | Required | Description |
|---|---|---|---|
ratio |
number | yes | Damping ratio, d / sqrt(pi**2 + d**2) for the half-cycle log decrement d. Negative for a swing that grows. |
frequency_hz |
number | yes | Frequency of the oscillation, in hertz. |
extrema |
integer | yes | How many extremes of the signal the estimate rests on. |
DeleteBlockedResponse¶
Response body for DELETE /sessions/{id}/elements/{model}/{idx}
when the element cannot be deleted alone (HTTP 422): other elements
depend on it, or disturbances act on it or on one of those.
Sending the delete again with cascade=true deletes them all with it.
Each list is capped at 25 entries; total and disturbances_total
report the full counts so the UI can render a "Showing 25 of N" footer
when truncated.
| Field | Type | Required | Description |
|---|---|---|---|
dependents |
array of TopologyEntry | yes | Up to 25 of the elements that cannot stay without the target: the ones that name it (the lines and generators on a bus, the machine on a static generator), the ones that name those, and so on. The nearest come first. Empty when only disturbances stand in the way. Limits: max items 25. |
total |
integer | yes | Full count of dependent elements. Equals len(dependents) when total <= 25; greater when the list was truncated. Limits: min 0. |
disturbances |
array of DeletedDisturbance | no | Up to 25 of the disturbances that act on the target or on one of its dependents, and would be removed with them. Limits: max items 25. |
disturbances_total |
integer | no | Full count of those disturbances. Limits: min 0. Default 0. |
detail |
string or null | no | The refusal in one sentence, with the way out. |
DeleteElementResponse¶
Response body for DELETE /sessions/{id}/elements/{model}/{idx}: the
topology after the delete, with what the delete removed.
| Field | Type | Required | Description |
|---|---|---|---|
state |
string | yes | pre-setup if disturbances can still be added; committed after PF or TDS has triggered ss.setup(). Once committed, callers must POST /sessions/{id}/reload to add more disturbances. One of pre-setup, committed. |
buses |
array of TopologyEntry | yes | Bus elements. |
lines |
array of TopologyEntry | yes | Line elements. |
transformers |
array of TopologyEntry | yes | Transformer elements split out from the ANDES Line bucket via the tap != 1.0 OR phi != 0.0 heuristic. Pure transmission lines remain in lines; off-nominal-tap and phase-shifting branches move here. |
generators |
array of TopologyEntry | yes | Generator elements (PV, Slack, GENROU, GENCLS, etc.). |
loads |
array of TopologyEntry | yes | Load elements - both static (PQ) and dynamic (ZIP). |
shunts |
array of TopologyEntry | no | Shunt elements (capacitors and reactors). Modeled as ANDES Shunt devices; rendered with the IEC 60617 shunt-cap or shunt-reactor icon depending on the sign of b. |
controllers |
array of TopologyEntry | no | Dynamic controller devices: exciters (IEEEX1, ESDC2A, SEXS), governors (IEEEG1, TGOV1), the IEEEST PSS, and the REGCA1 renewable-converter model. Surfaces the seven Unit-8 whitelist additions so the disturbance editor can populate device pickers when the case includes them. An ESD1 battery is listed here as well: like REGCA1 it takes over a static generator (its gen) in a time-domain run. Empty for cases that carry no dynamics addfile (stock IEEE 14 .raw alone). |
freq_hz |
number or null | no | System nominal frequency in Hz, as the case sets it: the header of a PSS/E RAW file, or the _config section of an xlsx or json file. A MATPOWER file, and any other case that sets none, keeps ANDES's default of 60. A per-unit rotor speed omega times this is the speed in Hz. null when the configuration has no usable value. |
base_mva |
number or null | no | System MVA base, as the case sets it: the header of a PSS/E RAW file, baseMVA of a MATPOWER file, or the _config section of an xlsx or json file. Any other case, and a blank system, keeps ANDES's default of 100. A power in per unit on the system base times this is the power in MW or MVAr. A device with its own rating Sn gives some values per unit of that instead; an ESD1 battery reads alike on both only when its Sn equals this. null when the configuration has no usable value. |
buses_without_vn |
array of integer or string | no | Idx of the buses whose rated voltage (Vn in the bus's params) the case file does not give: it is absent, blank or zero there, and ANDES fills in 110 kV. That 110 is not the bus's voltage base, so a client must not use it to turn a per-unit voltage into kV. Empty when every bus has a rated voltage. A bus whose Vn has been edited since the case was loaded is no longer listed. |
events |
array of CaseEvent | no | Timed events the next time-domain run applies besides the disturbances a client commits through POST /sessions/{id}/disturbances: the Fault, Toggle and Alter devices the case's files define (the bundled kundur_full.xlsx trips Line_8 at 2 s), and the disturbances a bundle import or snapshot restore replayed. A client that says what a run will do must count these. A device that cannot act (switched off with u = 0, or a time below zero) is not listed. Empty when there are none. |
undo |
EditStep or null | no | The edit POST /sessions/{id}/undo-last-edit would take back: the last element added, changed or deleted since the case was loaded. null when there is none. Edits are taken back while state is pre-setup. |
redo |
EditStep or null | no | The edit POST /sessions/{id}/redo-edit would put back: the one taken back last. null when there is none, which is the case after any new edit. |
job_id |
string or null | no | Job-registry id mirroring the routine that produced this topology snapshot: case load / reload, element delete / undo / redo, or blank-system create. null when the summary is a plain read (GET /topology). |
deleted |
array of TopologyEntry | no | Every element the delete removed, as it was: the dependents a cascade took, then the element asked for, last. |
disturbances |
array of DeletedDisturbance | no | Every disturbance the delete removed because it acted on one of deleted. A client that keeps its own list of disturbances to commit should drop the matching ones too. |
DeletedDisturbance¶
A disturbance that acts on an element a delete removes, or would remove.
| Field | Type | Required | Description |
|---|---|---|---|
source |
string | yes | case: a Fault, Toggle or Alter device the case's files define. restored: one a bundle import or a snapshot restore replayed. committed: one a client committed through POST /sessions/{id}/disturbances. One of case, restored, committed. |
kind |
string | yes | Which ANDES event model it is. One of fault, toggle, alter. |
model |
string or null | no | ANDES model of the device it acts on: Bus for a fault. |
dev_idx |
integer or string or null | no | Idx of the device it acts on. |
t |
number or null | no | Time it starts, in seconds: a fault's tf. null for a device of the case that never fires (switched off, or a time below zero); it names the element all the same, so it goes too. |
name |
string or null | no | The device's name in the case file, for a case one. |
DisturbanceAck¶
One entry in the response to POST /sessions/{id}/disturbances.
| Field | Type | Required | Description |
|---|---|---|---|
kind |
string | yes | Discriminator from the original spec. One of fault, toggle, alter. |
idx |
integer or string | yes | ANDES idx assigned to the created disturbance device. Use this to reference the disturbance in subsequent operations. |
DroopController¶
Frequency droop: power in proportion to the frequency deviation beyond a dead band, positive (discharging) when the frequency is below nominal.
| Field | Type | Required | Description |
|---|---|---|---|
model |
string | yes | ANDES model of the device the controller commands: one of the distributed generation models (ESD1, PVD1, EV1, EV2). GET /sessions/{id}/tds/controllers lists the devices of the loaded case that can be named. Limits: min length 1, max length 64. |
idx |
integer or string | yes | The device's idx. 5 and "5" name the same device. |
frequency |
string | no | The frequency the controller reads. coi: the centre-of-inertia frequency, the inertia-weighted mean speed of the synchronous machines in service times the system's nominal frequency. bus: the frequency the device measures at its own bus (its fHz), which jumps during a fault. One of coi, bus. Default "coi". |
period |
number | no | Seconds between two samples. The controller reads the frequency and sets its command once a period and holds it in between. A period shorter than the integration step samples at every step. Limits: min 0.001, max 60. Default 0.1. |
t_start |
number | no | Simulation time, in seconds, before which the controller commands nothing. Limits: min 0. Default 0.0. |
ramp |
number or null | no | The most the command may change, in MW per second. null lets it jump from one sample to the next. Limits: above 0. |
type |
"droop" |
yes | Discriminator: a frequency droop. |
gain |
number | yes | MW commanded per Hz of deviation beyond the dead band. Limits: above 0. |
deadband |
number | no | Deviation from nominal, in Hz either way, the controller ignores. Limits: min 0. Default 0.0. |
p_max |
number or null | no | The largest command, in MW, discharging or charging. null uses the device's own limit: the smaller of its power limit pmx and its current limit ialim. Limits: above 0. |
EditElementRequest¶
Request body for PUT /sessions/{id}/elements/{model}/{idx}.
Updates one or more parameters on an existing element. The same
pre-setup gate + whitelist as AddElementRequest apply. idx and
name cannot be edited (they would desync ANDES's internal indexes);
create a new element if you need to reassign topology references.
| Field | Type | Required | Description |
|---|---|---|---|
params |
object (names to number or integer or string or boolean) | yes | Subset of model parameters to overwrite. Each key must be in the per-model whitelist; idx / name are explicitly rejected (create a new element instead). |
EditStep¶
One edit to the system made before a run: an element added, changed or
deleted. What undo and redo of a topology summary name.
| Field | Type | Required | Description |
|---|---|---|---|
op |
string | yes | What the edit did to the element. One of add, edit, delete. |
model |
string | yes | ANDES model of the element. |
idx |
integer or string or null | no | The element's idx. |
params |
array of string | no | edit only: the params whose values it changed. |
also |
integer | no | delete only: how many more devices went with the element because they depended on it. Limits: min 0. Default 0. |
EigParticipationResponse¶
Wire shape of GET /sessions/{id}/eig/modes/{mode_idx}/participation.
| Field | Type | Required | Description |
|---|---|---|---|
mode_idx |
integer | yes | Echo of the requested mode index. Limits: min 0. |
participation |
array of ParticipationFactorModel | yes | Per-state participation factor row for the requested mode. Length equals the EIG result's state_count. |
EigResultResponse¶
Wire shape of POST /sessions/{id}/eig.
The state matrix itself (As) is intentionally omitted from this
response - for NPCC 140-bus it would be ~110k entries. The UI
fetches the matrix on demand via GET /eig/state-matrix.mat.
| Field | Type | Required | Description |
|---|---|---|---|
eigenvalues |
array of ComplexNumberModel | yes | Eigenvalues of EIG.As (the system's reduced state matrix). Length equals mode_count. Each entry is {real, imag} so the JSON payload doesn't carry an out-of-band complex encoding. An eigenvalue ANDES counts as zero (magnitude within EIG.config.tol, 1e-6 by default) is exactly {0, 0}: what the solver returns for it is rounding noise whose sign differs between machines. |
damping_ratios |
array of number | yes | Per-mode damping ratio -Re(z) / \|z\|. Index-aligned with eigenvalues. A zero eigenvalue, which neither oscillates nor grows, has 1.0. NaN-collapsed to 0.0 so the wire payload never carries non-finite floats. |
frequencies_hz |
array of number | yes | Per-mode oscillation frequency \|Im(z)\| / (2*pi) in Hz. 0 for purely-real eigenvalues. |
mode_count |
integer | yes | Number of eigenvalues == len(EIG.mu) (the reduced state count post fold/elimination). Stock IEEE 14 (no dyn models) → 0; full IEEE 14 + dyr → 62; kundur_full → 52. |
state_count |
integer | yes | Same value as mode_count - surfaced as a separate field for clarity in the UI (the state matrix shape is [state_count, state_count]). |
state_names |
array of string | yes | Reduced-state names indexed identically to participation factor rows. Falls back to state_<i> labels when the reduced count differs from ss.dae.x_name. |
tds_initialized |
boolean | yes | Always true after a successful EIG.run. ANDES's EIG._pre_check calls TDS.init() + TDS.itm_step() if not already initialised - the substrate surfaces this so the UI can warn that subsequent TDS / re-run PF will start from this initialised dae. |
job_id |
string or null | no | Job-registry id mirroring this EIG routine (kind eig). GET /sessions/{id}/jobs/{job_id} returns the matching record; null on legacy responses. |
EigRunRequest¶
Request body for POST /sessions/{id}/eig.
Empty body - ANDES's EIG.run() takes no public arguments. Kept
as a model (rather than None) so the route can declare a
model_config extra="forbid" and reject typos in the
forward-compatible way.
Type: object.
ElementCreated¶
Response body for POST /sessions/{id}/elements (201).
Carries the newly-built TopologyEntry so the client can update its
cache without re-fetching the full topology. Web-side mutation hooks
use this to optimistically update bus dropdowns before the topology
re-fetch resolves.
| Field | Type | Required | Description |
|---|---|---|---|
element |
TopologyEntry | yes | The element that was just added, with its assigned idx + the parameters as ANDES read them back. |
job_id |
string or null | no | Job-registry id mirroring the element-add routine (kind element-add). null on legacy responses. |
FaultSpec¶
3-phase-to-ground fault on a bus.
Maps to ss.add('Fault', bus=..., tf=..., tc=..., xf=..., rf=...).
Single-phase faults are not natively supported by ANDES and are not
supported here either.
| Field | Type | Required | Description |
|---|---|---|---|
kind |
"fault" |
no | Discriminator: this spec creates an ANDES Fault device. Default "fault". |
bus_idx |
integer or string | yes | ANDES idx of the bus where the fault is applied. |
tf |
number | yes | Time the fault is applied, in seconds. |
tc |
number | yes | Time the fault is cleared, in seconds. Must be > tf. |
xf |
number | no | Fault reactance in pu. Default 0.0001. |
rf |
number | no | Fault resistance in pu. Default 0.0. |
FfrController¶
Fast frequency response: a fixed power, delivered once for a set time when the frequency leaves a threshold or moves too fast.
| Field | Type | Required | Description |
|---|---|---|---|
model |
string | yes | ANDES model of the device the controller commands: one of the distributed generation models (ESD1, PVD1, EV1, EV2). GET /sessions/{id}/tds/controllers lists the devices of the loaded case that can be named. Limits: min length 1, max length 64. |
idx |
integer or string | yes | The device's idx. 5 and "5" name the same device. |
frequency |
string | no | The frequency the controller reads. coi: the centre-of-inertia frequency, the inertia-weighted mean speed of the synchronous machines in service times the system's nominal frequency. bus: the frequency the device measures at its own bus (its fHz), which jumps during a fault. One of coi, bus. Default "coi". |
period |
number | no | Seconds between two samples. The controller reads the frequency and sets its command once a period and holds it in between. A period shorter than the integration step samples at every step. Limits: min 0.001, max 60. Default 0.1. |
t_start |
number | no | Simulation time, in seconds, before which the controller commands nothing. Limits: min 0. Default 0.0. |
ramp |
number or null | no | The most the command may change, in MW per second. null lets it jump from one sample to the next. Limits: above 0. |
type |
"ffr" |
yes | Discriminator: a fast frequency response. |
power |
number | yes | MW commanded once triggered. Positive discharges and answers a low frequency; negative absorbs and answers a high one. Not zero. |
trigger_deviation |
number or null | no | Triggers when the frequency is this many Hz below nominal (above, for a negative power). null leaves the deviation out. Limits: above 0. |
trigger_rocof |
number or null | no | Triggers when the frequency falls this many Hz per second or faster (rises, for a negative power), measured between two samples. null leaves the rate out. At least one of the two triggers must be given. Limits: above 0. |
hold |
number | no | Seconds the power is held before the controller lets go. Limits: above 0. Default 10.0. |
GeneratorOutput¶
Per-generator PF output. Active + reactive injection at the
generator's terminal bus, plus the terminal voltage (pu). A generator that
is switched off injects nothing: p and q are 0.
| Field | Type | Required | Description |
|---|---|---|---|
p |
number | yes | Active power generated at the terminal bus, in MW. |
q |
number | yes | Reactive power generated at the terminal bus, in MVAr. |
v |
number | yes | Terminal bus voltage magnitude (pu). |
bus |
integer or string | yes | Terminal bus idx. |
q_min |
number or null | no | Lower reactive power limit the case sets (qmin), in MVAr. Power flow does not enforce it unless the run asked for enforce_q_limits, so q can lie below it. null for a generator that is switched off. |
q_max |
number or null | no | Upper reactive power limit the case sets (qmax), in MVAr. Power flow does not enforce it unless the run asked for enforce_q_limits, so q can lie above it. null for a generator that is switched off. |
HTTPValidationError¶
| Field | Type | Required | Description |
|---|---|---|---|
detail |
array of ValidationError | no |
HealthCache¶
State of ANDES's generated code (~/.andes/pycode), which a case load needs.
| Field | Type | Required | Description |
|---|---|---|---|
state |
string | yes | ready: generated and checked against the installed ANDES. unchecked: there is code, but nothing has checked it against this ANDES (it was upgraded, or another ANDES regenerated the code). missing: ANDES has generated nothing yet. One of ready, unchecked, missing. |
warm |
boolean | yes | True when state is ready: the next case load does not generate code. |
generating |
boolean | yes | True while the server's background process is generating the code. A case loaded meanwhile waits for it. |
HealthResponse¶
Response shape for GET /health.
| Field | Type | Required | Description |
|---|---|---|---|
status |
"ok" |
yes | Always ok: a server that cannot answer sends no response. |
version |
string | yes | Installed tensa version. |
andes_version |
string | yes | Installed ANDES version, or unknown when its package metadata is missing. |
sessions |
HealthSessions | yes | How many sessions are open, against the cap on them. |
cache |
HealthCache | yes | Whether ANDES's generated code is ready, so that a case load does not wait for it. |
HealthSessions¶
How full the server is.
| Field | Type | Required | Description |
|---|---|---|---|
active |
integer | yes | Sessions open now, each with its own worker process. |
max |
integer | yes | Cap on open sessions (--max-sessions). Creating one past it answers 429. |
JobRecordSchema¶
HTTP-visible shape of a _JobRegistry record.
Returned by GET /sessions/{id}/jobs and GET /sessions/{id}/jobs/{job_id}.
Every routine response also embeds a job_id that resolves to one of
these records.
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | yes | Server-generated UUID identifier for the job. |
kind |
string | yes | Discriminator for the routine kind (pflow, tds-stream, eig, cpf, cpf-qv, se, sweep, snapshot-*, bundle-*, element-*, clone-*, etc.). The full enum lives in tensa.core.jobs.JobKind. One of pflow, tds-batch, tds-stream, eig, cpf, cpf-qv, se, se-measurements, sweep, snapshot-save, snapshot-restore, snapshot-delete, bundle-export, bundle-import, case-load, case-reload, case-save, element-add, element-edit, element-delete, element-undo, element-redo, disturbance-commit, pmu-add, pmu-delete, profile-upload, profile-add, profile-delete, clone-init, clone-edit, clone-undo, clone-redo, clone-save-as, clone-reset. |
status |
string | yes | Lifecycle state: pending (registered), running (worker actively executing), done (completed successfully), failed (worker raised; problem populated), or cancelled (cooperative-abort succeeded). One of pending, running, done, failed, cancelled. |
started_at |
number | yes | Monotonic clock seconds when the job was registered. Use differences between started_at / updated_at / ended_at for elapsed-time display. |
updated_at |
number | yes | Monotonic clock seconds at the most recent state mutation. |
ended_at |
number or null | no | Monotonic clock seconds at terminal transition (done/failed/cancelled). None while in-flight. |
can_cancel |
boolean | yes | True if the job exposes a cooperative-abort path (TDS streaming, sweep, clone reload-replay). Synchronous routines like PF/EIG/CPF/SE are not cancellable; the UI must NOT render a cancel button for can_cancel: false records. |
progress |
number or null | no | Fractional progress in [0.0, 1.0] when the job emits per-step progress (sweep iterations, clone reload-replay phases). None means indeterminate. |
request_summary |
object | no | Serializable subset of the original request body. Used by the Activity panel's Retry affordance to re-fire the same mutation variables. Must NOT carry credentials or large blobs (R16: this field is in-memory only and excluded from any Zustand persist whitelist on the web side). |
result_ref |
string or null | no | Opaque reference to the job's result, populated on done. For TDS this is the run_id; for sweep, the sweep_id; for clone edits, the new param value reference. |
problem |
ProblemDetails or null | no | Populated on failed with the full ProblemDetails envelope (includes the typed recovery axes). Drives the Activity panel's per-job <ProblemDetailsErrorSurface>. |
repeated_count |
integer | no | Number of identical-signature failures that coalesced into this record, which keeps the first of them. For done and in-flight jobs this is always 0. Default 0. |
LayoutBranchRoute¶
How one line or transformer is drawn between its two buses.
| Field | Type | Required | Description |
|---|---|---|---|
routing |
string | no | auto: the branch is drawn from where its two buses are now, and bend_points is not used. polyline: it is drawn through bend_points as they are stored, a route the diagram made. manual: it is drawn through bend_points too, and the route was drawn by hand: tidying the diagram leaves it as it is, and it is brought along when one of its buses is moved. One of auto, polyline, manual. Default "auto". |
bend_points |
array of BusCoord | no | The points of a polyline or manual route in order: where it leaves the first bus, each bend, and where it reaches the second bus. A polyline route is only drawn while both ends still sit on their buses, so moving a bus sends its branches back to auto; a manual one follows its buses. Limits: max items 256. |
bus1 |
string or null | no | idx of the bus the route starts at, with bus2 what the route is anchored to: a reader draws it only for a branch between those two buses. null: not recorded. |
bus2 |
string or null | no | idx of the bus the route ends at. null: not recorded. |
source_face |
string or null | no | Face of the first bus (bus1) the branch leaves from, when it was chosen. null lets the renderer pick the face that points at the other bus. One of north, east, south, west. |
target_face |
string or null | no | Face of the second bus (bus2) the branch arrives on, when it was chosen. null lets the renderer pick. One of north, east, south, west. |
LayoutBusbar¶
The bar a bus is drawn as.
| Field | Type | Required | Description |
|---|---|---|---|
length |
number or null | no | Length of the bar in canvas units. null leaves it to the renderer, which sizes the bar to what connects to it. A bar with a length set is still drawn longer when its connections need more room than that. Limits: above 0. |
orientation |
string | no | Whether the bar lies across the diagram or stands upright. One of horizontal, vertical. Default "horizontal". |
LayoutConnection¶
Where the connector between a device and its bus attaches.
| Field | Type | Required | Description |
|---|---|---|---|
device_face |
string or null | no | Face of the device symbol the connector leaves from, when it was chosen. null lets the renderer use the face that points at the bus. One of north, east, south, west. |
bus_face |
string or null | no | Face of the bus the connector lands on, when it was chosen. null lets the renderer pick. One of north, east, south, west. |
bend_points |
array of BusCoord | no | The points of a connector that was drawn by hand, in order: where it leaves the device, each bend, and where it lands on the bar of the bus. They are for the device and the bus where this layout has them, and the connector is brought along when either is moved. Empty: the connector is worked out from where the two stand. Limits: max items 256. |
bus |
string or null | no | idx of the bus the connector ran to when it was drawn. A reader uses bend_points only for a device on that bus, as it uses the position of a device. null: not recorded. |
LayoutDeviceCoord¶
Where a generator, load or shunt is drawn, and the bus it hangs off.
| Field | Type | Required | Description |
|---|---|---|---|
x |
number | yes | X coordinate, finite (no NaN/Inf). |
y |
number | yes | Y coordinate, finite (no NaN/Inf). |
bus |
string or null | no | idx of the bus the device was connected to when it was placed. A reader uses the position only for a device on that bus, so an idx that has come to name another element (a .raw file numbers its devices afresh) does not put it somewhere it never was. null: not recorded (a version 1 document); the idx alone is trusted. |
LayoutLabelOffset¶
How far a label sits from where the renderer would put it.
| Field | Type | Required | Description |
|---|---|---|---|
dx |
number | yes | Shift to the right, in canvas units. |
dy |
number | yes | Shift downwards, in canvas units. |
LayoutUnit¶
How one generating unit is drawn.
| Field | Type | Required | Description |
|---|---|---|---|
expanded |
boolean | no | true when the unit's control chain (exciter, governor, stabiliser) is drawn out; false when the unit is collapsed to its machine symbol. Default false. |
bus |
string or null | no | idx of the bus the unit was on when this was chosen. A reader uses the entry only for a unit on that bus, so an idx that has come to name another generator does not draw the chain of that one out. null: not recorded; the idx alone is trusted. |
LineFlow¶
Per-line active and reactive power flow at both terminals: p / q
at terminal 1 (bus1) and p_to / q_to at terminal 2 (bus2),
each flowing from the bus INTO the line, plus the line's loss and its
loading against its rating.
Sign convention: positive p means real power flowing FROM bus1
INTO the line; positive q means reactive power flowing FROM bus1
INTO the line, and the same at terminal 2 for p_to / q_to. On a
line that carries power from bus1 to bus2, p is positive and
p_to negative, and the two sum to the loss. The SLD overlay uses the
sign of p to render directional arrows along each branch.
| Field | Type | Required | Description |
|---|---|---|---|
p |
number | yes | Active power leaving bus1 into the line, in MW (i.e., computed in pu and multiplied by the system base MVA). |
q |
number | yes | Reactive power leaving bus1 into the line, in MVAr. |
from_idx |
integer or string | yes | ANDES idx of the bus1 terminal (the from-side bus). |
to_idx |
integer or string | yes | ANDES idx of the bus2 terminal (the to-side bus). |
p_to |
number | yes | Active power leaving bus2 into the line, in MW. Negative when the line delivers power to bus2. |
q_to |
number | yes | Reactive power leaving bus2 into the line, in MVAr. |
loss |
number | yes | Active power the line dissipates, in MW: p + p_to. |
rate_a |
number or null | no | The line's long-term rating (the case's rate_a), in MVA. null when the case gives none (a rate_a of zero), in which case the line has no loading either. |
loading_pct |
number or null | no | The larger of the apparent powers at the two terminals, sqrt(p^2 + q^2) and sqrt(p_to^2 + q_to^2), as a percentage of rate_a. Above 100 is an overload. null when the line has no rating. |
ListDisturbancesResponse¶
Wire shape of GET /sessions/{id}/disturbances.
Mirrors the substrate's Wrapper.list_disturbances() - the
discriminated union over Fault / Toggle / Alter, in the order the
specs were accepted. Empty list when no disturbances are pending.
| Field | Type | Required | Description |
|---|---|---|---|
disturbances |
array of FaultSpec or ToggleSpec or AlterSpec | yes | Currently-recorded disturbance specs. Same shape as the POST /sessions/{id}/disturbances request body's disturbances field. |
ListPmusResponse¶
Wire shape of GET /sessions/{id}/pmu.
Mirrors a slice of TopologySummary.controllers filtered to the
PMU model class - surfaced as a dedicated route so the placement
dialog doesn't have to load the full topology snapshot just to read
the PMU list.
| Field | Type | Required | Description |
|---|---|---|---|
pmus |
array of TopologyEntry | yes | Currently-placed PMU instances. Each entry's params carries bus / Ta / Tv. Empty list when no PMUs have been placed. |
ListProfilesResponse¶
Wire shape of GET /sessions/{id}/profiles.
| Field | Type | Required | Description |
|---|---|---|---|
profiles |
array of TopologyEntry | yes | Currently-staged TimeSeries devices. Each entry's params carries path, sheet, fields, model, dev, dests, tkey, mode. Empty list when none have been added. |
ListSnapshotsResponse¶
Response body for GET /sessions/{id}/snapshots.
| Field | Type | Required | Description |
|---|---|---|---|
snapshots |
array of SnapshotListEntry | no | Saved snapshots for this session's case, newest first. |
LoadCaseRequest¶
Request body for POST /sessions/{id}/case. All paths are
workspace-relative; the substrate canonicalizes them with O_NOFOLLOW
before passing to ANDES.
| Field | Type | Required | Description |
|---|---|---|---|
primary_path |
string | yes | Workspace-relative path to the primary case file. Supported formats: xlsx, raw, dyr, json, m. The substrate routes through ANDES's native readers; format is detected from the extension. Limits: min length 1. |
addfiles |
array of string or null | no | Optional list of workspace-relative addfile paths. PSS/E .raw (steady-state) and .dyr (dynamics) are paired via this mechanism; pass [.dyr path] when loading a .raw. |
LoadConsumption¶
Per-load PF consumption at the converged voltage. A load that is
switched off draws nothing: p and q are 0.
| Field | Type | Required | Description |
|---|---|---|---|
p |
number | yes | Active power drawn, in MW. |
q |
number | yes | Reactive power drawn, in MVAr. |
bus |
integer or string | yes | Terminal bus idx. |
MetricExtremum¶
A value of the signal and when it is reached.
| Field | Type | Required | Description |
|---|---|---|---|
value |
number | yes | The value, in the signal's unit. |
t |
number | yes | The time it is reached, in seconds. |
MetricsSeries¶
One signal to describe.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | What the signal is called; echoed back on its result. Limits: min length 1, max length 200. |
t |
array of number | yes | Sample times in seconds, not decreasing. Samples at one time count as one, the last of them. Limits: max items 200000. |
y |
array of number or null | yes | The signal's value at each time, in whatever unit the caller reads it in. null marks a missing value (a diverged step); that sample is left out. Limits: max items 200000. |
ParticipationFactorModel¶
One per-state participation factor row entry.
| Field | Type | Required | Description |
|---|---|---|---|
state_name |
string | yes | Reduced-state label. |
factor |
number | yes | Participation factor magnitude. By ANDES convention (calc_pfactor in routines/eig.py) these are real-valued. |
PflowResult¶
Power-flow run result. Bus voltages and angles are keyed by ANDES idx.
| Field | Type | Required | Description |
|---|---|---|---|
run_id |
string | yes | Server-generated identifier for this PF run. Results are not stored under it: read the solved state again with GET /sessions/{id}/operating-point. |
converged |
boolean | yes | true if PF converged within the iteration limit. Non-convergence is NOT a server error; it is a valid power-system outcome the caller must handle. |
iterations |
integer | yes | Number of Newton-Raphson iterations executed. |
mismatch |
number | yes | Final mismatch (max element of the residual vector) at the converged solution. For non-converged runs this is the last iteration's mismatch. |
bus_voltages |
object (names to number) | yes | Bus voltage magnitudes (pu) keyed by ANDES idx (stringified). JSON object keys must be strings; the ANDES idx is converted at the boundary. |
bus_angles |
object (names to number) | yes | Bus voltage angles (radians) keyed by ANDES idx (stringified). |
line_flows |
object (names to LineFlow) | no | Per-line P/Q flow at both terminals, with the line's loss and its loading against rate_a, keyed by line idx (stringified). Empty if the wrapper could not extract line flows from the post-PF System (e.g., on an unexpected ANDES API change). Populated by computing the standard pi-equivalent line injection at each end from the converged v1/a1/v2/a2 algebraic variables and the line's series + shunt admittances. |
generator_outputs |
object (names to GeneratorOutput) | no | Per-generator P / Q output, terminal voltage and reactive limits, keyed by generator idx (stringified). Covers the static generators (PV and Slack). A dynamic machine (GENROU, GENCLS) has no entry of its own: read the entry of the static generator named by its gen parameter. Empty when PF did not converge. |
load_consumption |
object (names to LoadConsumption) | no | Per-load P / Q consumption at the converged voltage, keyed by load idx (stringified). Covers PQ and ZIP. Empty when PF did not converge. |
settings |
PflowSettings or null | no | The settings this run used, whether or not it converged. null on GET /sessions/{id}/operating-point, which runs nothing. |
summary |
PflowSummary or null | no | System totals: generation, load, bus shunts, line losses and the slack output. null when the run did not converge, and on GET /sessions/{id}/operating-point. |
job_id |
string or null | no | Job-registry id mirroring this routine invocation. Additive: GET /sessions/{id}/jobs/{job_id} returns the matching JobRecord (kind pflow). null only on legacy responses synthesised outside the job lifecycle. |
PflowRunRequest¶
Request body for POST /sessions/{id}/pflow. Every field is optional:
one that is left out keeps the case's own setting (ANDES's default unless
the case file's _config section says otherwise). The settings apply to
this run only; the next request starts from the case's settings again.
| Field | Type | Required | Description |
|---|---|---|---|
tolerance |
number or null | no | Convergence tolerance: the solver stops once the largest residual (mismatch), in pu, is below it. From 1e-12 to 0.01. ANDES's default is 1e-6. Limits: min 1e-12, max 0.01. |
max_iterations |
integer or null | no | Iteration limit. ANDES gives up once the count passes it. From 1 to 1000. ANDES's default is 25. Limits: min 1, max 1000. |
flat_start |
boolean or null | no | Start from 1 pu at angle 0 on every bus instead of the voltages and angles in the case. A bus with a generator holding its voltage still starts at that setpoint. Helps when the case's own starting point is far from the solution. Left out, the case's own setting stands; false turns off a flat start the case file asks for. |
enforce_q_limits |
boolean or null | no | Hold a PV or slack generator at qmin or qmax when its reactive power goes past one (PV to PQ switching). Without it the limits are reported and not enforced. Left out, the case's own setting stands; false turns off enforcement the case file asks for. |
PflowSettings¶
The settings a power-flow run used: the request's where it gave one, the case's own (ANDES's default unless the case file sets one) where it did not.
| Field | Type | Required | Description |
|---|---|---|---|
tolerance |
number | yes | Mismatch (max residual, in pu) below which the solver stopped. |
max_iterations |
integer | yes | The iteration limit. ANDES stops once the count passes it, so a run that does not converge reports iterations one above this. |
flat_start |
boolean | yes | true if the solver started from 1 pu at angle 0 on every bus that has no generator holding its voltage, false if it started from the voltages and angles in the case. |
enforce_q_limits |
boolean | yes | true if a PV or slack generator whose reactive power went past qmin or qmax was held at that limit (PV to PQ switching). |
PflowSummary¶
System totals of a converged power flow, in MW and MVAr.
Generation, load, bus shunts and lines balance: generation = load +
shunt + loss, in P and in Q, to the solver's tolerance. Devices that are
switched off count for nothing.
| Field | Type | Required | Description |
|---|---|---|---|
generation_p |
number | yes | Active power the in-service generators produce, in MW. |
generation_q |
number | yes | Reactive power the in-service generators produce, in MVAr. |
load_p |
number | yes | Active power the loads draw, in MW. |
load_q |
number | yes | Reactive power the loads draw, in MVAr. |
shunt_p |
number | yes | Active power the bus shunts absorb, in MW (0 for a pure susceptance). |
shunt_q |
number | yes | Reactive power the bus shunts absorb, in MVAr: negative for a capacitor, which supplies it. |
loss_p |
number | yes | Active power the lines and transformers dissipate, in MW. |
loss_q |
number | yes | Reactive power the lines and transformers absorb, in MVAr: their series losses less their charging, so negative when charging dominates. |
slack_p |
number or null | no | Active power the in-service slack generators produce, in MW: what the case's schedules leave for the slack to make up. null when there is none. |
slack_q |
number or null | no | Reactive power the in-service slack generators produce, in MVAr. null when there is none. |
ProblemDetails¶
RFC 7807 problem-details object. Used for all 4xx and 5xx responses.
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | no | URI reference identifying the problem type. about:blank means the title is the canonical reason for the status code. Default "about:blank". |
title |
string | yes | Short, human-readable summary of the problem. |
status |
integer | yes | HTTP status code for this response. |
detail |
string or null | no | Human-readable explanation specific to this occurrence of the problem (e.g., 'session id is required to be server-generated; remove the session_id field from your request body'). |
instance |
string or null | no | URI reference that identifies the specific occurrence of the problem. |
recovery |
RecoveryDescriptor or null | no | Optional recovery call-to-action describing how the client can resolve the problem (e.g., load a case, run power flow, retry). None means no recovery action is offered. Populated by the shared error mapper from the error's recovery kind. |
RecoveryDescriptor¶
Recovery call-to-action attached to an error response.
The kind is the stable, machine-readable discriminator the UI keys
off to render the right action (e.g., a "Run power flow" button); the
label is the human-facing copy. kind == "none" means the error was
considered but has no canonical recovery action - the UI renders it
without a CTA, same as an absent recovery.
| Field | Type | Required | Description |
|---|---|---|---|
kind |
string | yes | Stable, machine-readable discriminator for the recovery action the client should offer (e.g., run-pflow, load-case, retry). none means no canonical recovery action applies. One of load-case, reload-case, run-pflow, retry, add-measurements, none, wait-for-job, wait-for-sweep. |
label |
string | yes | Human-readable copy describing the recovery action, suitable for rendering on a call-to-action button or hint. |
ReportResponse¶
Wire shape of GET /sessions/{id}/report.
| Field | Type | Required | Description |
|---|---|---|---|
routine |
ReportRoutineEnum | yes | Echo of the requested routine. |
plain_text |
string | yes | Report text - for pflow, the file ANDES would have written to <case>_out.txt; for tds, TDS.summary()'s log output augmented with run statistics. It is ANDES's own text, except that the server's paths are taken out of it: the case file in the header reads relative to the workspace. |
structured |
ReportStructured | yes | Structured tabular blocks parsed out of plain_text. |
ReportRoutineEnum¶
Routines that can be reported.
Type: string.
One of pflow, tds, eig.
ReportStructured¶
Structured-table envelope. Empty tables is valid - the frontend
falls back to the plain-text view.
| Field | Type | Required | Description |
|---|---|---|---|
tables |
array of ReportTableModel | no | Best-effort parse of the plain-text report into tabular blocks. Empty when the parser couldn't recognise any sections; the plain_text body remains the source of truth. |
ReportTableModel¶
One tabular block of a routine's report.
Matches tensa.core.report.ReportTable 1:1. Each row's
length always matches headers - the wrapper-side parser pads /
truncates so the frontend's renderer doesn't have to think about
ragged rows.
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | yes | Section title (e.g., BUS DATA). |
headers |
array of string | yes | Column names, in order. |
rows |
array of array of string | yes | Rows of stringified cell values. Numeric columns are pre-formatted by the wrapper so the frontend can render verbatim without locale issues. |
ResponseMetricsRequest¶
Request body for POST /response-metrics.
| Field | Type | Required | Description |
|---|---|---|---|
series |
array of MetricsSeries | yes | The signals to describe, each on its own timeline. Limits: min items 1, max items 64. |
t_start |
number or null | no | Start of the window the metrics are read over, in seconds. A bound that falls between two samples is interpolated. Defaults to the first sample. |
t_end |
number or null | no | End of the window, in seconds. Defaults to the last sample. |
settling_band |
number | no | The settling band as a fraction of the signal's largest distance from its final value: 0.02 is 2 %. Limits: above 0, below 1. Default 0.02. |
rocof_window |
number | no | Width in seconds the rate of change is measured over: the steepest slope of the line from y(s) to y(s + rocof_window). Cut to the window when the window is shorter. Limits: above 0. Default 0.5. |
ResponseMetricsResponse¶
Response body for POST /response-metrics.
| Field | Type | Required | Description |
|---|---|---|---|
results |
array of SeriesMetrics | yes | One entry per requested series, in the order sent. |
RestoreSnapshotRequest¶
Request body for POST /sessions/{id}/snapshot/restore.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Snapshot name to restore. |
use_dill_optimization |
boolean | no | Default False restores by reloading the case, re-adding the recorded disturbances, and re-running setup and the power flow, which works on any ANDES version. When True, try the dill blob first (andes.utils.snapshot.load_ss) and skip all of that. Falls back to the replay path on ANDES version mismatch, a missing dill blob (the snapshot was saved without include_dill), or a load failure; the response's fallback_reason carries the explanation. Default false. |
RestoreSnapshotResponse¶
Response body for POST /sessions/{id}/snapshot/restore.
| Field | Type | Required | Description |
|---|---|---|---|
used_dill |
boolean | yes | True when the dill optimisation succeeded. False means the replay+PF path was taken (the default, or a fallback when use_dill_optimization was requested). |
fallback_reason |
string or null | no | Human-readable explanation when used_dill=False despite use_dill_optimization=True. Surfaced inline in the load dialog so the user understands why a fallback fired. |
disturbances_replayed |
integer | yes | Count of disturbance specs from the snapshot metadata that the restored System carries (re-applied on the replay path, already inside the dill blob on the dill path). |
metadata |
SnapshotMetadataModel | yes | Sidecar metadata of the restored snapshot. |
layout |
SidecarLayout or null | no | The diagram's layout the snapshot held, in the current schema version, or null when it held none. For a case loaded from a file the server has already written it beside that file, replacing the layout that was there; a system built from scratch has no file, so the layout is only returned here. |
job_id |
string or null | no | Job-registry id mirroring the snapshot-restore routine (kind snapshot-restore). Recorded in the manager-wide global registry so it survives the session being replaced, yet still surfaces via GET /sessions/{id}/jobs/{job_id}. null on legacy responses. |
SaveCaseRequest¶
Request body for POST /sessions/{id}/save.
filename is workspace-relative; the substrate canonicalizes it
through the workspace path validator (rejects traversal). format
selects the writer: ANDES's own for xlsx and json, and the substrate's
PSS/E v33 writer for raw (ANDES 2.0 has none).
| Field | Type | Required | Description |
|---|---|---|---|
filename |
string | yes | Workspace-relative output filename. Extension must match format (.xlsx for xlsx, .json for json, .raw for raw). The file name must be portable to Windows: no :, trailing dot or space, or device names such as CON or nul.xlsx. Limits: min length 1. |
format |
string | yes | Output format. xlsx is the ANDES-native Excel layout. json is the ANDES JSON serialization. raw is PSS/E v33 emitted by the substrate's hand-rolled writer; it covers the power-flow data: Bus, PQ loads, Shunt, PV and Slack generators, Line, and 2W transformers. 3W transformers and other PSS/E sections are emitted as empty terminators. A .raw holds no dynamic data, so the dynamic models of the case (machines, exciters, a ZIP load) are left out: save as xlsx or json to keep them. One of xlsx, json, raw. |
overwrite |
boolean | no | When true, overwrites an existing file at the same path. Default false returns 409 if the file exists. Default false. |
SaveCaseResponse¶
Response body for POST /sessions/{id}/save (201).
| Field | Type | Required | Description |
|---|---|---|---|
filename |
string | yes | Workspace-relative path of the file just written. |
bytes_written |
integer | yes | Size in bytes of the file just written, as reported by os.stat. Limits: min 0. |
job_id |
string or null | no | Job-registry id mirroring the case-save routine (kind case-save). null on legacy responses. |
SaveSnapshotRequest¶
Request body for POST /sessions/{id}/snapshot.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Snapshot name. 1-64 chars of [A-Za-z0-9._-] starting with an alphanumeric, not ending in a dot, and not a Windows device name (CON, NUL, COM1, ...). Names are unique per case; collisions return 409 unless force=true. |
force |
boolean | no | When True, overwrite any existing snapshot under the same name. Default False rejects collisions with 409 so the UI can prompt the user. Default false. |
include_dill |
boolean | no | When True, also write the full System state as a dill blob (andes.utils.snapshot.save_ss) beside the metadata, so a later restore can opt in to use_dill_optimization. Costs a couple of seconds and 2-3 MB per save, and the blob only loads on the same ANDES major.minor. A snapshot saved after the power flow but before the TDS was initialised on a case with dynamic models cannot be loaded by ANDES 2.0; its restore falls back to replay. Default False writes the metadata only. Default false. |
layout |
SidecarLayout or null | no | The diagram's layout as the client shows it. It is kept in the snapshot and put back beside the case when the snapshot is restored. null keeps the layout saved beside the case file, if there is one. One over the cap PUT /workspace/layout holds a layout to is refused (413). |
SaveSnapshotResponse¶
Response body for POST /sessions/{id}/snapshot.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Snapshot name as saved (unique per session workspace). |
metadata |
SnapshotMetadataModel | yes | Sidecar metadata written alongside the snapshot. |
dill_bytes |
integer | yes | Size of the dill blob on disk, in bytes. 0 when the snapshot was saved without one (include_dill=false). |
metadata_bytes |
integer | yes | Size of the sidecar JSON on disk, in bytes. |
job_id |
string or null | no | Job-registry id mirroring the snapshot-save routine (kind snapshot-save). null on legacy responses. |
SeGenerateMeasurementsRequest¶
Request body for POST /sessions/{id}/se/measurements/generate.
Only optional knob is the noise seed - pinning the seed makes runs reproducible across browser refreshes (useful for the UI's "Generate measurements" button).
| Field | Type | Required | Description |
|---|---|---|---|
noise_seed |
integer or null | no | Optional non-negative integer seed for the Gaussian-noise draw inside Measurements.generate_from_pflow. None (default) uses an unseeded np.random.default_rng; pinning the seed lets the UI re-generate the same measurement set across page refreshes. ge=0 because numpy's default_rng rejects negative seeds - a clean 422 here beats a misleading non-convergent error downstream. Limits: min 0. |
SeMeasurementsGeneratedResponse¶
Wire shape of POST /sessions/{id}/se/measurements/generate.
| Field | Type | Required | Description |
|---|---|---|---|
count |
integer | yes | Number of scalar measurements in the substrate's Measurements object. For IEEE 14: 14 bus voltage measurements + 28 bus injection (P+Q for each bus) = 42. Note: SE.init adds an angle-reference pseudo-measurement at the slack bus on the first run_se call, so the eventual SeResult.residuals length will be one greater per island. Limits: min 0. |
job_id |
string or null | no | Job-registry id mirroring the SE measurement-generation routine (kind se-measurements). GET /sessions/{id}/jobs/{job_id} returns the matching record; null on legacy responses. |
SeResultResponse¶
Wire shape of POST /sessions/{id}/se.
Field semantics mirror tensa.core.se_result.SeResult
1:1; see that class for prose.
| Field | Type | Required | Description |
|---|---|---|---|
converged |
boolean | yes | True when ANDES's SE.run returned True (Gauss-Newton residual fell below config.tol within config.max_iter). False cases are surfaced as 422 errors rather than converged=false payloads - the UI always sees a converged result on a 200. |
iterations |
integer | yes | Number of WLS Gauss-Newton iterations to convergence. ANDES's result['n_iter'] is 1-indexed; echoed verbatim. Limits: min 0. |
mismatch |
number | yes | Final WLS objective J = sum(w * r^2). Smaller is better; the chi-squared test on J (not surfaced yet) flags whether the measurement set fits the model at a given confidence level. |
residuals |
array of number | yes | Per-measurement residuals z - h(x_est). Length equals measurement_count. The UI bins these into a histogram. |
measurement_count |
integer | yes | Total measurements (including the angle-reference pseudo-measurement that SE.init injects). Equal to len(residuals). Surfaced as a separate field so the UI's histogram doesn't have to derive it from the array length. Limits: min 0. |
flagged_indices |
array of integer | yes | Indices into residuals whose normalised residual \|r_i\| / sigma_i exceeds 3-sigma. These are candidate bad-data measurements; the UI highlights the corresponding histogram bars in red. |
job_id |
string or null | no | Job-registry id mirroring the SE run routine (kind se). GET /sessions/{id}/jobs/{job_id} returns the matching record; null on legacy responses. |
SeRunRequest¶
Request body for POST /sessions/{id}/se.
Empty body - the substrate's Wrapper.run_se reads the cached
measurement set from the prior generate call. Kept as a model so
the route can declare extra="forbid" and reject typos forward-
compatibly.
Type: object.
SeriesMetrics¶
What one signal's response metrics came to. Either error says why it
could not be described, or the rest is filled in.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | The series' name, as sent. |
error |
string or null | no | Why this signal has no metrics (too few samples, a window outside it, times that run backwards); null when it has them. |
samples |
integer or null | no | Samples in the window, its two bounds included. |
t_start |
number or null | no | Start of the window used, in seconds. |
t_end |
number or null | no | End of the window used, in seconds. |
initial |
number or null | no | Value at the start of the window. |
final |
number or null | no | Time-weighted mean over the last 10 % of the window: what it settled to. |
peak |
MetricExtremum or null | no | Largest value and when. |
nadir |
MetricExtremum or null | no | Smallest value and when. |
max_deviation |
MetricExtremum or null | no | Largest distance from initial: value is signed (y - initial). |
rocof |
MetricExtremum or null | no | Steepest rate of change over rocof_window, in the signal's unit per second, sign kept; t is the start of that window. |
settling_time |
number or null | no | Seconds from the start of the window after which the signal stays within the settling band; null when it had not settled by the end. |
overshoot_pct |
number or null | no | How far the signal went past its final value, in percent of the step from initial to final; null when final is within the settling band of initial. |
damping |
DampingEstimate or null | no | null for a signal that does not oscillate. |
SessionDescriptor¶
Response shape for session create / read.
| Field | Type | Required | Description |
|---|---|---|---|
session_id |
string | yes | Server-generated UUID-shaped opaque identifier for the session. Use it in subsequent URL paths (e.g., /sessions/{session_id}/case). |
state |
string | yes | live if the worker subprocess is alive and accepting commands; closed if the session has been reaped or explicitly closed. One of live, closed. |
workspace_id |
string | no | An opaque name for the workspace folder this server serves: the same for every session of one folder, and another for another folder. It is a digest and holds no path. A client that keeps something by case file name (the web UI keeps the drafts of a diagram in the browser) keys it by this as well, so that a file of the same name in another workspace is another case. Default "". |
SessionList¶
Response shape for GET /sessions.
| Field | Type | Required | Description |
|---|---|---|---|
sessions |
array of SessionDescriptor | yes | Snapshot of currently-active sessions for this token. |
SessionMessageSchema¶
One message in a session's log: something ANDES reported while the session's worker ran a command.
| Field | Type | Required | Description |
|---|---|---|---|
seq |
integer | yes | Number of the message in the session, from 1, in the order the server received them. Numbers are never reused, not even after the log is cleared, so after=<seq> always reads what came next. A message that repeats the newest one is not added: its repeat grows and it takes the next number, so a reader that follows the log replaces the message it holds that says the same. |
time |
number | yes | Unix time, in seconds, at which ANDES logged the message. |
level |
string | yes | info for what ANDES reports about a run's progress, warning for something that may make a result wrong (a device whose initialisation failed, a limit that was not adjusted), error for what stopped the command. One of info, warning, error. |
logger |
string | yes | Name of the logger that said it: an ANDES module (andes.routines.pflow), or tensa.notice for what the server worked out itself because ANDES does not log it (a generator switched from PV to PQ, a load turned into an impedance). |
source |
string | yes | The command the worker was running: load_case, run_pflow, run_tds, run_eig, ... Empty for a message logged between commands. |
text |
string | yes | The message. It can span several lines: ANDES logs tables. A message longer than 20000 characters is cut. Paths of the server are not in it: the workspace is written relative to itself, the home directory as ~ and any other absolute path as <path>. |
repeat |
integer | yes | How many times in a row ANDES logged this exact message, which is kept once (a solver that warns on every step). The count can grow after the message was read: it is then numbered again. Limits: min 1. |
SessionMessages¶
Response of GET /sessions/{id}/messages.
| Field | Type | Required | Description |
|---|---|---|---|
messages |
array of SessionMessageSchema | yes | The messages asked for, oldest first. |
first_seq |
integer | yes | The number of the oldest message the session still holds (of the next one to arrive, when it holds none). A reader that kept older messages should drop them: they were evicted or cleared. |
last_seq |
integer | yes | The number of the newest message the session has had; 0 before any. |
next_after |
integer | yes | What to pass as after to read on from here: the last message returned when the read stopped at limit, otherwise last_seq. |
dropped |
integer | yes | How many messages were lost to the caps (the worker keeps 1000 between two replies, the session keeps the latest 2000), over the session's life. Clearing the log does not count. |
SidecarLayout¶
The layout of one case's diagram (one file per case).
Stored on disk as <case_path>.layout.json adjacent to the case file.
Every section but coordinates is optional and reads as empty when
absent, which is how a version 1 document (bus and device positions only)
is still accepted; the server stores and answers with version 2.
| Field | Type | Required | Description |
|---|---|---|---|
schema_version |
string | yes | Schema version of the document. The server writes and answers with "2"; a version 1 document ("1", "1.0") is accepted and upgraded. Limits: min length 1. |
andes_version |
string | yes | ANDES version the layout was saved against (e.g., "2.0.0"). Recorded for diagnosis; not validated on read. Limits: min length 1. |
coordinates |
object (names to BusCoord) | yes | Per-bus coordinates, keyed by bus idx (stringified). Buses missing from this dict fall back to the renderer's auto-layout. |
non_bus_coordinates |
object (names to object (names to LayoutDeviceCoord)) | no | Per-non-bus-element coordinates, two-level dict keyed by ANDES model class (e.g., PV, GENROU, PQ, Shunt) OR by UI category (generator, load, shunt), then by element idx (stringified). The writer emits BOTH the model-class-keyed entry and the UI-category-keyed entry for every non-bus element so kind-edits (e.g., PV → GENROU) survive: the model-class entry becomes orphaned but the UI-category entry still resolves on read. Optional + additive - old sidecars without this field read as {} and the renderer falls back to kind-default offsets. |
controller_coordinates |
object (names to object (names to BusCoord)) | no | Positions of controllers that were placed on their own, keyed by ANDES model class (EXST1, TGOV1), then by idx. A controller with no entry is drawn docked beside the device it acts on and moves with it. |
units |
object (names to LayoutUnit) | no | Per generating unit (a generator with its machine and their controllers), keyed by the idx of the unit's generator symbol, the same idx its position has under generator in non_bus_coordinates. |
busbars |
object (names to LayoutBusbar) | no | The bar of a bus where it differs from the default, keyed by bus idx. |
branches |
object (names to object (names to LayoutBranchRoute)) | no | How branches are drawn, keyed by line or transformer, then by idx. A branch with no entry is routed automatically. |
label_offsets |
object (names to object (names to LayoutLabelOffset)) | no | Labels that were moved, keyed like non_bus_coordinates with bus, line and transformer as further outer keys, then by idx. |
connections |
object (names to object (names to LayoutConnection)) | no | Where the connector of a generator, load or shunt attaches and, where it was drawn by hand, the points it runs through, keyed like non_bus_coordinates. A device with no entry has its connector worked out from where it sits. |
figure |
object (names to boolean or integer or number or string) | no | Display settings of this diagram and of a figure made from it (for example a monochrome style, a line width, which labels are shown), by name. The diagram reads connector_style: straight (the default) draws the connector of a generator, load or shunt to its bus as one line, elbow with one right angle. Values are booleans, finite numbers or short text; at most 64 settings. |
last_modified |
string | yes | ISO 8601 timestamp recorded by the client at save time. The server does NOT regenerate this on write; it stores the value the client sent so collaborative-edit conflict detection (a future feature) has a single source of truth. Limits: min length 1. |
SnapshotListEntry¶
One entry in the GET /sessions/{id}/snapshots response.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Snapshot name. |
saved_at |
string | yes | ISO-8601 UTC timestamp of the save. |
has_pflow |
boolean | yes | Whether a converged power flow existed at save time. |
has_tds |
boolean | yes | Whether a TDS run had completed at save time. |
has_dill |
boolean | yes | Whether the optional dill blob is present on disk. False for a snapshot saved without include_dill or when only the sidecar JSON survives (e.g., manual half-delete); the snapshot is still restorable via the replay path. |
andes_version |
string | yes | ANDES version that produced the snapshot. |
disturbance_count |
integer | yes | Number of disturbance specs recorded in the snapshot metadata. |
SnapshotMetadataModel¶
Sidecar JSON metadata shape echoed in save/restore/list responses.
| Field | Type | Required | Description |
|---|---|---|---|
andes_version |
string | yes | ANDES version that produced the snapshot. |
tensa_version |
string | yes | tensa version that produced the snapshot. |
case_filename |
string or null | yes | Workspace-relative case filename loaded when the snapshot was saved. |
case_sha256 |
string or null | yes | SHA-256 of the case file at save time (drift detection on restore). |
disturbance_log |
array of object | no | Disturbance specs active at save time; replayed on the fallback restore path. |
saved_at |
string | yes | ISO-8601 UTC timestamp of the save. |
has_pflow |
boolean | yes | Whether a converged power flow existed at save time. |
has_tds |
boolean | yes | Whether a TDS run had completed at save time. |
has_layout |
boolean | no | Whether the snapshot holds the diagram's layout. The layout itself is left out of this echo; a restore returns it. Default false. |
StartSweepResponse¶
Response body for POST /sessions/{id}/sweep.
| Field | Type | Required | Description |
|---|---|---|---|
sweep_id |
string | yes | Identifier the WS progress channel keys on. The UI uses this to subscribe via /api/ws/{session_id}/sweep/{sweep_id}. |
total |
integer | yes | Number of iterations the sweep will run. |
job_id |
string or null | no | Job-registry id mirroring this sweep. Additive and IDENTICAL to sweep_id - the two fields alias the same value, with sweep_id preserved for backward compatibility. GET /sessions/{id}/jobs/{job_id} returns the matching JobRecord (kind sweep). |
SweepParameter¶
Discriminated sweep target.
target is the ANDES-side device identifier the parameter applies
to (e.g., the disturbance idx returned by add_disturbance). The
orchestrator looks up the matching spec in the snapshot's recorded
disturbance_log and overrides its field.
For v2.0 the target is the disturbance's index in the snapshot's log (zero-based). Future revisions may extend this to (model, idx, field) tuples for topology parameters.
| Field | Type | Required | Description |
|---|---|---|---|
kind |
string | yes | Discriminator: which spec field is being swept. Includes the disturbance kind so the spec lookup can validate the target type matches. One of disturbance.fault.tc, disturbance.fault.tf, disturbance.fault.xf, disturbance.fault.rf, disturbance.toggle.t, disturbance.alter.t, disturbance.alter.amount, disturbance.alter.value. |
target |
integer | yes | Index into the snapshot's disturbance_log identifying which spec to mutate. v2.0 only supports per-disturbance sweeps; topology sweeps are deferred. Limits: min 0. |
range |
SweepRange | yes | Inclusive linear sweep range over the parameter values. |
SweepRange¶
Inclusive-endpoint linear sweep range.
steps is the iteration count (>= 2). The endpoints start and
end always appear in the iteration set so the user gets exactly
the boundary they asked for.
| Field | Type | Required | Description |
|---|---|---|---|
start |
number | yes | First parameter value. |
end |
number | yes | Last parameter value. |
steps |
integer | yes | Iteration count (must be >= 2; capped at 200 to keep memory + runtime bounded for v2.0). Limits: min 2, max 200. |
SweepRequest¶
Request body for POST /sessions/{id}/sweep.
| Field | Type | Required | Description |
|---|---|---|---|
parameter |
SweepParameter | yes | Parameter target + range definition. Identifies the spec to mutate per iteration and the values to iterate over. |
sim |
SweepSimParams | yes | Per-iteration TDS simulation parameters (tf, optional h, optional vars). Applied identically to every iteration. |
snapshot_name |
string | yes | Name of a previously-saved snapshot. Each iteration restores this snapshot before applying the parameter override. |
SweepSimParams¶
Per-iteration TDS parameters. Mirrors the run_tds call shape.
| Field | Type | Required | Description |
|---|---|---|---|
tf |
number | yes | Final sim time per iteration. Limits: above 0. |
h |
number or null | no | Fixed integration step (seconds) for every iteration, as for POST /tds. None keeps the ANDES default (1/30 s). Limits: above 0. |
vars |
array of string or null | no | Variable groups to record per iteration (kept as metadata only - the sweep stores aggregate convergence + final_t, not the full per-step state, to keep memory bounded). |
TdsBatchResult¶
Result of a batch TDS run (post-completion delivery).
Streaming TDS uses a different code path (the WebSocket at
/ws/{session_id}) that emits Arrow IPC frames per integration step.
Batch mode blocks until completion and returns a summary; the per-step
state values are NOT returned in batch mode unless the request names
dae_vars, whose values come back in traces (use streaming mode for
the five variable groups).
| Field | Type | Required | Description |
|---|---|---|---|
run_id |
string | yes | Server-generated identifier for this TDS run. |
converged |
boolean | yes | true if TDS completed without becoming busted. Numerical instability (e.g., a fault that doesn't clear) surfaces as converged: false with final_t < tf. |
final_t |
number | yes | Last simulation time reached, in seconds. |
callpert_count |
integer | yes | Number of times the per-step TDS.callpert hook fired during the run. Useful as a sanity check that streaming is wired. |
job_id |
string or null | no | Job-registry id mirroring this TDS run. Additive and IDENTICAL to run_id - the two fields alias the same value, with run_id preserved for backward compatibility. GET /sessions/{id}/jobs/{job_id} returns the matching JobRecord (kind tds-batch). null only on legacy responses synthesised outside the job lifecycle. |
traces |
TdsTraces or null | no | The values of the request's dae_vars, every step of the run. null when the request named none. |
controllers |
array of TdsControllerResult or null | no | What each of the request's controllers did, in the order asked, with its samples. null when the request named none. |
TdsControllerCatalogue¶
The controllers a TDS run takes, for the loaded case.
| Field | Type | Required | Description |
|---|---|---|---|
types |
array of string | yes | The kinds of controller: the values type takes. |
coi_available |
boolean | yes | true when the case has a synchronous machine, which the centre-of-inertia frequency (frequency: "coi") is read from. Without one a controller has to read its own bus. |
freq_hz |
number or null | no | The system's nominal frequency, in Hz: what a coi reading deviates from. null with no case loaded. |
base_mva |
number or null | no | The system MVA base. null with no case loaded. |
targets |
array of TdsControllerTarget | yes | The devices a controller can command: those of ANDES's distributed generation models (ESD1, PVD1, EV1, EV2). Empty when the case has none, and with no case loaded. |
TdsControllerResult¶
What one controller of a TDS run did.
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | yes | The kind of controller. One of droop, ffr. |
model |
string | yes | ANDES model of the device it commanded. |
idx |
integer or string | yes | The device's idx, as the case holds it. |
samples |
integer | yes | How many times it read the frequency in this run. Limits: min 0. |
first_action_t |
number or null | no | Simulation time, in seconds, of the first sample at which it commanded a power: for an ffr, when it triggered. null if it never did. |
released_t |
number or null | no | Simulation time, in seconds, at which an ffr let go after its hold. null for a droop, and for an ffr that did not trigger or was still holding when the run ended. |
peak_command |
number | yes | Its command of the largest magnitude, in MW, with its sign. |
final_command |
number | yes | Its command when the run ended, in MW. |
trace |
TdsControllerTrace or null | no | Its samples. Returned by a batch run; null in a stream's done frame, where the device's variables are streamed instead. |
TdsControllerTarget¶
One device of the loaded case a controller can command.
| Field | Type | Required | Description |
|---|---|---|---|
model |
string | yes | The device's ANDES model. |
idx |
integer or string | yes | The device's idx. |
name |
string | yes | The device's name in the case. |
bus |
integer or string or null | no | Idx of the bus it is on. |
in_service |
boolean | yes | false for a device that is switched off: commands do nothing to it. |
p_limit |
number or null | no | The most active power the device delivers, in MW: the smaller of its power limit pmx and its current limit ialim (the power that current carries at rated voltage). A command beyond it is not delivered, and a droop that names no p_max is limited to it. null where the model has neither. |
fn |
number or null | no | The device's nominal frequency, in Hz: what a bus reading deviates from. |
variables |
TdsControllerVariables | yes | ANDES variables to record to see the controller at work. |
TdsControllerTrace¶
What one controller read and commanded at each of its samples.
| Field | Type | Required | Description |
|---|---|---|---|
t |
array of number | yes | Simulation time of each sample, in seconds: the solved instant the controller read, from which its command applies. |
frequency |
array of number | yes | The frequency the controller read at each sample, in Hz. |
command |
array of number | yes | The power the controller commanded from each sample on, in MW, positive discharging: what it adds to the device's own set-point. |
output |
array of number or null | yes | The active power the device was delivering at each sample, in MW, its own set-point included. Where it stays below what the command asks for, the device is at one of its limits. null where the device has no such reading. |
soc |
array of number or null | yes | The device's state of charge at each sample, 0 to 1. null for a device without one (a PVD1). |
truncated |
boolean | yes | true when the run took more samples than a response holds (500000 values over all controllers) and the later ones were left out. Raise period. |
TdsControllerVariables¶
The ANDES variables that show a controller at work on one device: names
to put in a run's dae_vars.
| Field | Type | Required | Description |
|---|---|---|---|
command |
string | yes | The external power signal as the device receives it (Pext), per unit of the system base: what the controllers on it command. |
frequency |
string | yes | The frequency the device measures at its bus (fHz), in Hz. |
active_current |
string | yes | The device's active current (Ipout_y), per unit of the system base; times the bus voltage it is the active power delivered. |
soc |
string or null | no | The device's state of charge (pIG_y); null for a model without one. |
TdsRunRequest¶
Request body for POST /sessions/{id}/tds (batch mode).
Streaming runs use the WebSocket at /ws/{session_id} and are started
by its start_tds frame; this schema is the batch-only surface.
| Field | Type | Required | Description |
|---|---|---|---|
tf |
number | yes | Final simulation time, in seconds. Must be > 0. Limits: above 0. |
h |
number or null | no | Integration step size, in seconds, applied as ANDES TDS.config.tstep. With the default trapezoidal integrator this is the fixed step; None keeps the ANDES default (1/30 s). The qndf integrator picks its own step and ignores it; bound its step with tds_config_overrides.max_step instead. Limits: above 0. |
vars |
array of string or null | no | Optional selector for which variable groups appear as columns in each per-step Arrow record batch on the streaming path. bus_v covers bus voltage magnitudes and angles; gen_state adds generator rotor angle delta and per-unit speed omega for every member of the ANDES SynGen group (GENROU / GENCLS / PLBVFU1); gen_power adds their electrical Pe / Qe; line_flow adds active and reactive power at each line's bus1 terminal; load_pq adds each PQ load's consumption. Unknown values are rejected with 422; an empty list is rejected with 422. The batch path (POST /tds) ignores this field at runtime: it returns the values of dae_vars instead, and accepts this field for symmetry with the WebSocket start_tds config so generated clients can share one request shape. Defaults to ["bus_v", "gen_state"] when omitted on the streaming path. Limits: min items 1. |
dae_vars |
array of string or null | no | ANDES variables to record, by the names dae.x_name and dae.y_name give them (omega GENROU 1, vf GENROU 2); GET /sessions/{id}/dae-variables lists them. A batch run returns their values in traces, at every step ANDES takes, with no scaling. A name that is not a variable of the loaded case is refused with 422 before anything runs. The streaming start_tds frame takes the same field and adds one column per name, named exactly so. Limits: max items 1000. |
integrator |
string | no | DAE integrator. "trapezoidal" (default) maps to ANDES's fixed-step Implicit Trapezoidal Method (ss.TDS.config.method = "trapezoid"). "qndf" selects the variable-order, variable-step QNDF (NDF) method and forces fixt = 0 so ANDES enables LTE-driven step control. Combine integrator="qndf" with the Auto preset (rtol=1e-3, atol=1e-6, max_step=0.05) by passing the values via tds_config_overrides. One of trapezoidal, qndf. Default "trapezoidal". |
controllers |
array of DroopController or FfrController or null | no | Controllers that act while the run goes: each reads the frequency once a sample period and sets the power of a battery or another distributed generation device, on top of the device's own set-point. Two kinds, picked by type: droop (power in proportion to the frequency deviation beyond a dead band) and ffr (a fixed power, once, for a set time when the frequency leaves a threshold or moves too fast). Powers are in MW, positive discharging, and frequencies in Hz. GET /sessions/{id}/tds/controllers lists the devices that can be named. A controller that names a device the case does not have is refused with 422 before anything runs. What each did comes back in the result's controllers; when the run ends the devices' inputs are as they were. A later run that names the same controllers and goes on from where this one stopped (a larger tf) keeps their state, so an ffr that has fired does not fire again. After a reload or a restored snapshot they start afresh, and it can. The streaming start_tds frame takes the same field. Sweeps do not take controllers. Limits: max items 32. |
tds_config_overrides |
object (names to number) or null | no | Optional adaptive-integrator tolerance overrides. Supported keys are rtol (→ ss.TDS.config.reltol), atol (→ ss.TDS.config.abstol) and max_step (→ ss.TDS.config.dtmax), or the name of any ss.TDS.config field. An unknown key is refused with 422. So is a value that ANDES would take and then misbehave on: tstep must be finite and greater than 0, max_step (dtmax) finite and not negative (0 lets ANDES choose), fixt 0 or 1, and every other value a finite number. The tolerances have no effect when integrator="trapezoidal" (the fixed-step path ignores reltol/abstol and uses h for stepping). |
TdsTraceSeries¶
One recorded ANDES variable of a batch run.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | The variable, named as in dae_vars. |
values |
array of number or null | yes | Its value at each time in traces.t, as ANDES stores it. null for a value that is not a number (a diverged step). |
TdsTraces¶
The ANDES variables a batch run was asked to record (dae_vars).
| Field | Type | Required | Description |
|---|---|---|---|
t |
array of number | yes | Simulation time of each recorded step, in seconds. |
variables |
array of TdsTraceSeries | yes | One series per requested variable, in the order asked. |
truncated |
boolean | yes | true when the run took more steps than a response holds (500000 values in all) and the later steps were left out. Raise h or ask for fewer variables. |
ToggleSpec¶
Status toggle on a device - used for line trips, generator trips, etc.
Maps to ss.add('Toggle', model=..., dev=..., t=...). Toggling sets the
target device's status to its complement at time t (closed→open or
open→closed).
| Field | Type | Required | Description |
|---|---|---|---|
kind |
"toggle" |
no | Discriminator: this spec creates an ANDES Toggle device. Default "toggle". |
model |
string | yes | ANDES model class name whose device is being toggled. Examples: 'Line', 'GENROU', 'PV'. |
dev_idx |
integer or string | yes | ANDES idx of the device within model to toggle. |
t |
number | yes | Time the toggle fires, in seconds. |
TopologyEntry¶
One element in a topology summary.
| Field | Type | Required | Description |
|---|---|---|---|
idx |
integer or string | yes | ANDES idx of the element (its public identifier in ANDES). Used as the stable handle in subsequent operations (e.g., Fault.bus references this idx). |
name |
string | yes | Human-readable name of the element. |
kind |
string | yes | ANDES model class name (e.g., Bus, Line, GENROU, PV, Slack, PQ). |
params |
object (names to number or integer or string or boolean) | no | Flat dict of model-input parameters for this element (e.g., for a Bus: Vn rated voltage in kV, vmax/vmin voltage limits, area, zone; for a Line: r, x, b, g, tap, phi; for a generator: Sn rated MVA, Vn, bus, plus model-specific params). The Inspector Properties tab in the v0.1 UI consumes this dict; absent params (None or unavailable on a given model) are omitted. |
job_id |
string or null | no | Job-registry id mirroring the mutation that produced this entry. Populated only when this TopologyEntry is the top-level response of an edit / PMU-add / profile-add routine; null for nested entries inside a TopologySummary. |
TopologyParamMeta¶
One parameter row in a model's add/edit form schema.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | ANDES parameter name (e.g., Vn). |
kind |
string | yes | Form-input kind. string and number map to text/number inputs; bus_idx renders as a dropdown of existing buses; gen_idx a dropdown of existing static generators; syn_idx a dropdown of existing synchronous machines (GENROU/GENCLS) for an exciter/governor's machine link; bool is a checkbox. One of string, number, bus_idx, gen_idx, syn_idx, bool. |
required |
boolean | no | Whether the field is required when adding a new element. Optional fields collapse under the form's Show advanced disclosure. Default false. |
unit |
string or null | no | Display unit suffix (kV, pu, MVA, MWs/MVA, rad). Rendered inline next to numerical inputs. |
TopologySchema¶
Per-model parameter metadata, used by the web client's polymorphic form generator.
Returned from GET /api/topology/schema. Mirrors the wrapper-side
_PARAMS_BY_MODEL table - adding a new model on the server
automatically expands the form picker.
| Field | Type | Required | Description |
|---|---|---|---|
models |
object (names to array of TopologyParamMeta) | yes | Mapping from ANDES model class name to ordered parameter metadata. Order is the rendering order in the form. |
TopologySummary¶
Substrate's structural view of the loaded case.
state reflects whether ss.setup() has been committed. Some
fields on individual elements are only populated after setup.
| Field | Type | Required | Description |
|---|---|---|---|
state |
string | yes | pre-setup if disturbances can still be added; committed after PF or TDS has triggered ss.setup(). Once committed, callers must POST /sessions/{id}/reload to add more disturbances. One of pre-setup, committed. |
buses |
array of TopologyEntry | yes | Bus elements. |
lines |
array of TopologyEntry | yes | Line elements. |
transformers |
array of TopologyEntry | yes | Transformer elements split out from the ANDES Line bucket via the tap != 1.0 OR phi != 0.0 heuristic. Pure transmission lines remain in lines; off-nominal-tap and phase-shifting branches move here. |
generators |
array of TopologyEntry | yes | Generator elements (PV, Slack, GENROU, GENCLS, etc.). |
loads |
array of TopologyEntry | yes | Load elements - both static (PQ) and dynamic (ZIP). |
shunts |
array of TopologyEntry | no | Shunt elements (capacitors and reactors). Modeled as ANDES Shunt devices; rendered with the IEC 60617 shunt-cap or shunt-reactor icon depending on the sign of b. |
controllers |
array of TopologyEntry | no | Dynamic controller devices: exciters (IEEEX1, ESDC2A, SEXS), governors (IEEEG1, TGOV1), the IEEEST PSS, and the REGCA1 renewable-converter model. Surfaces the seven Unit-8 whitelist additions so the disturbance editor can populate device pickers when the case includes them. An ESD1 battery is listed here as well: like REGCA1 it takes over a static generator (its gen) in a time-domain run. Empty for cases that carry no dynamics addfile (stock IEEE 14 .raw alone). |
freq_hz |
number or null | no | System nominal frequency in Hz, as the case sets it: the header of a PSS/E RAW file, or the _config section of an xlsx or json file. A MATPOWER file, and any other case that sets none, keeps ANDES's default of 60. A per-unit rotor speed omega times this is the speed in Hz. null when the configuration has no usable value. |
base_mva |
number or null | no | System MVA base, as the case sets it: the header of a PSS/E RAW file, baseMVA of a MATPOWER file, or the _config section of an xlsx or json file. Any other case, and a blank system, keeps ANDES's default of 100. A power in per unit on the system base times this is the power in MW or MVAr. A device with its own rating Sn gives some values per unit of that instead; an ESD1 battery reads alike on both only when its Sn equals this. null when the configuration has no usable value. |
buses_without_vn |
array of integer or string | no | Idx of the buses whose rated voltage (Vn in the bus's params) the case file does not give: it is absent, blank or zero there, and ANDES fills in 110 kV. That 110 is not the bus's voltage base, so a client must not use it to turn a per-unit voltage into kV. Empty when every bus has a rated voltage. A bus whose Vn has been edited since the case was loaded is no longer listed. |
events |
array of CaseEvent | no | Timed events the next time-domain run applies besides the disturbances a client commits through POST /sessions/{id}/disturbances: the Fault, Toggle and Alter devices the case's files define (the bundled kundur_full.xlsx trips Line_8 at 2 s), and the disturbances a bundle import or snapshot restore replayed. A client that says what a run will do must count these. A device that cannot act (switched off with u = 0, or a time below zero) is not listed. Empty when there are none. |
undo |
EditStep or null | no | The edit POST /sessions/{id}/undo-last-edit would take back: the last element added, changed or deleted since the case was loaded. null when there is none. Edits are taken back while state is pre-setup. |
redo |
EditStep or null | no | The edit POST /sessions/{id}/redo-edit would put back: the one taken back last. null when there is none, which is the case after any new edit. |
job_id |
string or null | no | Job-registry id mirroring the routine that produced this topology snapshot: case load / reload, element delete / undo / redo, or blank-system create. null when the summary is a plain read (GET /topology). |
UploadProfileResponse¶
Wire shape of POST /sessions/{id}/profiles/upload.
| Field | Type | Required | Description |
|---|---|---|---|
profile_path |
string | yes | Absolute path of the written xlsx on the substrate's workspace. Pass this verbatim as profile_path on the follow-up POST /profiles call. |
bytes_written |
integer | yes | Size of the on-disk xlsx in bytes. Reported back so the UI can confirm the upload completed end-to-end. Limits: min 0. |
job_id |
string or null | no | Job-registry id mirroring the profile-upload routine (kind profile-upload). null on legacy responses. |
UploadedWorkspaceFile¶
Response shape for POST /workspace/files: the file as it now sits in
the workspace, as the lister would report it.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | File name relative to the workspace root (no directory components; the lister does not recurse). |
size_bytes |
integer | yes | File size in bytes as reported by os.stat. Limits: min 0. |
modified_iso |
string | yes | Last-modified time in ISO 8601 format with timezone (UTC). Computed from stat.st_mtime at list time. |
format |
string | yes | Detected file format from the extension. Matches one of the ANDES-supported formats; non-matching files are excluded by the lister. One of xlsx, raw, dyr, json, m. |
replaced |
boolean | yes | true when the upload replaced a file of the same name (overwrite=true), false when it created a new one. |
ValidationError¶
| Field | Type | Required | Description |
|---|---|---|---|
loc |
array of string or integer | yes | |
msg |
string | yes | |
type |
string | yes | |
input |
any | no | |
ctx |
object | no |
VersionInfo¶
Response shape for GET /version: the packages this server runs on.
| Field | Type | Required | Description |
|---|---|---|---|
tensa |
string | yes | Installed tensa version (the one in the OpenAPI info.version). |
andes |
string | yes | Installed ANDES version, or unknown when its package metadata is missing. |
WorkspaceFile¶
One entry in the workspace file lister response.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | File name relative to the workspace root (no directory components; the lister does not recurse). |
size_bytes |
integer | yes | File size in bytes as reported by os.stat. Limits: min 0. |
modified_iso |
string | yes | Last-modified time in ISO 8601 format with timezone (UTC). Computed from stat.st_mtime at list time. |
format |
string | yes | Detected file format from the extension. Matches one of the ANDES-supported formats; non-matching files are excluded by the lister. One of xlsx, raw, dyr, json, m. |
WorkspaceFileList¶
Response shape for GET /workspace/files.
| Field | Type | Required | Description |
|---|---|---|---|
files |
array of WorkspaceFile | yes | Workspace files matching the supported extensions, sorted alphabetically by name. Hidden files (dotfiles) and symlinks are excluded; subdirectories are not recursed. |