> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scalacomputing.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Simulations

> Simulation execution and results

Simulation execution and results

## Endpoints

| Method | Path | Description |
| - | - | - |
| GET | `/api/v1/simulations` | List simulations |
| POST | `/api/v1/simulations` | Start simulation |
| POST | `/api/v1/simulations/compare` | Compare simulations |
| GET | `/api/v1/simulations/{sim_id}` | Get simulation status |
| DELETE | `/api/v1/simulations/{sim_id}` | Delete simulation and free storage |
| POST | `/api/v1/simulations/{sim_id}/terminate` | Terminate simulation |
| GET | `/api/v1/simulations/{sim_id}/results` | Get simulation results |
| GET | `/api/v1/simulations/{sim_id}/results/download-url` | Generate presigned download URL for result file |
| GET | `/api/v1/simulations/{sim_id}/results/data` | Get computed summary data for simulation results |
| GET | `/api/v1/simulations/{sim_id}/logs` | Get simulation logs |

***

## List simulations

GET `/api/v1/simulations`

Retrieves a paginated list of simulations with optional filtering by workspace, status, name search, and creation date. Results are sorted by creation date (newest first) by default.

### Parameters

| Name | In | Type | Required | Description |
| - | - | - | - | - |
| `limit` | query | integer | No | Maximum number of items to return (default: 100, max: 100) |
| `next` | query | string | No | Opaque cursor token from previous response's `nextCursor` for pagination |
| `workspaceId` | query | string | No | Filter by workspace ID (format: `workspace_xxx`) |
| `status` | query | string | No | Filter by simulation status. Supports comma-separated values for OR logic (e.g., `running,completed,failed`). Valid values: `validating`, `provisioning`, `running`, `completed`, `failed`, `terminated`, `invalid`. Invalid values are silently ignored for forward compatibility. |
| `search` | query | string | No | Full-text search on simulation name (case-insensitive, max 100 characters) |
| `createdAfter` | query | string | No | Filter by creation date - items created on or after this time (ISO 8601, inclusive) |
| `createdBefore` | query | string | No | Filter by creation date - items created before this time (ISO 8601, exclusive) |
| `sort` | query | string | No | Sort order: a single `field:direction` pair (e.g., `created_at:desc`). Sortable fields: `name`, `created_at`, `status`. Default: `created_at:desc`. Compound (multi-field) sorts are not supported and return 400, because a cursor cannot express them. |

### Responses

**200** - List of simulations

```json theme={null}
{
  "simulations": [
    {
      "id": "sim_abc123xyz",
      "workspaceId": "workspace_def456",
      "configurationId": "config_ghi789",
      "configurationVersion": 1,
      "name": "my-network-simulation",
      "status": "running",
      "createdAt": "2024-01-15T10:30:00Z"
    }
  ],
  "pagination": {
    "count": 1,
    "hasMore": true,
    "nextCursor": "eyJjcmVhdGVkIjoiMjAyNC0wMS0xNVQxMDozMDowMFoifQ=="
  }
}
```

**400** - Bad Request - Invalid query parameters (e.g., malformed cursor, invalid workspaceId format, search query too long, a compound sort, or a cursor minted under a different sort)

```json theme={null}
{
  "error": {
    "message": "Invalid workspaceId format: expected 'workspace_' prefix"
  }
}
```

***

## Start simulation

POST `/api/v1/simulations`

Creates and starts a new simulation based on the specified configuration. The simulation will begin in `validating` status, then progress through `provisioning` to `running`. Poll the GET endpoint to monitor progress.

### Request Body

| Field | Type | Required | Description |
| - | - | - | - |
| `workspaceId` | string | No | - |
| `configurationId` | string | Yes | - |
| `configurationVersion` | integer | No | - |
| `name` | string | Yes | Simulation name. SECURITY: this value is interpolated into command strings and Slurm entrypoints executed on cluster nodes, so it is restricted to letters, digits, '-' and '*' (1–255 characters), and must start with a letter or digit (no whitespace, other punctuation, or non-ASCII characters, and no leading '-' or '*'). |
| `duration` | string | Yes | - |
| `checkpointing` | CheckpointingConfig | No | - |
| `checkpointing.enabled` | boolean | No | - |
| `checkpointing.interval` | string | No | - |

```json theme={null}
{
  "configurationId": "config_def456",
  "configurationVersion": 1,
  "name": "production-network-test",
  "duration": "1h",
  "checkpointing": {
    "enabled": true,
    "interval": "10m"
  }
}
```

### Responses

**201** - Simulation started successfully

```json theme={null}
{
  "id": "string",
  "workspaceId": "string",
  "configurationId": "string",
  "configurationVersion": 1,
  "name": "string",
  "status": "validating",
  "createdAt": "2024-01-15T10:30:00Z",
  "startedAt": "2024-01-15T10:30:00Z",
  "completedAt": "2024-01-15T10:30:00Z",
  "failureReason": "string",
  "terminationRequestedAt": "2024-01-15T10:30:00Z",
  "metrics": {
    "simulatedTime": "string",
    "eventsProcessed": 1,
    "throughput": "string"
  },
  "transportStats": [
    "uet"
  ],
  "networkTiers": [
    "ssw"
  ],
  "appliedMappingFile": {
    "id": "string",
    "name": "string",
    "deleted": true
  }
}
```

**400** - Bad Request; no simulation is created. Code VALIDATION\_ERROR when the simulation parameters are invalid. Code LAUNCH\_CONFIG\_INVALID when the configuration could not be prepared for the simulator: the message says why, and resubmitting it unchanged fails again.

**402** - Payment Required - the platform's credit balance is exhausted. Add credits before launching simulations.

**404** - Configuration or workspace not found

**409** - Conflict; no simulation is created. Code CONFLICT when a simulation with this name already exists in the workspace: choose another name. Code MAPPING\_FILE\_DELETED\_REFERENCE when the Chakra mapping file attached to the configuration has been deleted: the message names the file. Detach it, or attach another mapping file, and create the simulation again.

**422** - No simulation is created. Code UNPROCESSABLE\_ENTITY when the configuration is not validated: it must have status `validated` before starting a simulation. Code LAUNCH\_REJECTED when the simulator rejected the configuration: resubmitting it unchanged fails again.

**503** - Service Unavailable - the simulation service could not start the simulation. No simulation is created, so the request can be retried.

***

## Compare simulations

POST `/api/v1/simulations/compare`

Compares two to four simulations and returns aligned summaries, per-metric deltas and a diff context. The result is returned inline as JSON rather than as a presigned download envelope.

### Request Body

| Field | Type | Required | Description |
| - | - | - | - |
| `simulationIds` | array\[string] | Yes | - |
| `tier` | string | Yes | - |

```json theme={null}
{
  "simulationIds": [
    "string"
  ],
  "tier": "all"
}
```

### Responses

**200** - Comparison result

```json theme={null}
{
  "simulations": [
    {
      "simulationId": "string",
      "summaryByMetric": "..."
    }
  ],
  "deltas": [
    {
      "metric": "nd-stats",
      "fieldPath": "string",
      "baseline": null,
      "comparisonValues": [
        "..."
      ],
      "percentChange": [
        "..."
      ]
    }
  ],
  "diffContext": {
    "changedParams": [
      "..."
    ],
    "heldConstant": [
      "string"
    ]
  },
  "confidence": "singleChange"
}
```

**400** - Invalid request body (simulationIds count outside 2..4, malformed simulation id, or unknown tier)

**404** - Simulation not found, or its workspace has been deleted

**500** - Internal server error

***

## Get simulation status

GET `/api/v1/simulations/{sim_id}`

Retrieves detailed information about a specific simulation, including its current status, timing information, and metrics (if available).

### Parameters

| Name | In | Type | Required | Description |
| - | - | - | - | - |
| `sim_id` | path | string | Yes | Simulation ID in `sim_xxx` format (base32-encoded UUID with prefix) |

### Responses

**200** - Simulation details

```json theme={null}
{
  "id": "string",
  "workspaceId": "string",
  "configurationId": "string",
  "configurationVersion": 1,
  "name": "string",
  "status": "validating",
  "createdAt": "2024-01-15T10:30:00Z",
  "startedAt": "2024-01-15T10:30:00Z",
  "completedAt": "2024-01-15T10:30:00Z",
  "failureReason": "string",
  "terminationRequestedAt": "2024-01-15T10:30:00Z",
  "metrics": {
    "simulatedTime": "string",
    "eventsProcessed": 1,
    "throughput": "string"
  },
  "transportStats": [
    "uet"
  ],
  "networkTiers": [
    "ssw"
  ],
  "appliedMappingFile": {
    "id": "string",
    "name": "string",
    "deleted": true
  }
}
```

**404** - Simulation not found

***

## Delete simulation and free storage

DELETE `/api/v1/simulations/{sim_id}`

\[Feature-gated: enable\_simulation\_delete] Permanently deletes a simulation and all associated data including results, logs, and checkpoints. This action cannot be undone. Running simulations must be terminated before deletion. This endpoint is only available on deployments where the enable\_simulation\_delete feature flag is enabled; callers may receive 404 on deployments where the flag is off.

### Parameters

| Name | In | Type | Required | Description |
| - | - | - | - | - |
| `sim_id` | path | string | Yes | Simulation ID in `sim_xxx` format |

### Responses

**200** - Simulation scheduled for deletion

```json theme={null}
{
  "id": "string",
  "status": "string",
  "message": "string"
}
```

**400** - Invalid simulation ID format

**404** - Simulation or workspace not found

***

## Terminate simulation

POST `/api/v1/simulations/{sim_id}/terminate`

Initiates termination of a simulation. There is no status pre-check: a simulation that has already finished is accepted and keeps its status; otherwise it transitions to `terminated`. Results generated up to the termination point will be available.

### Parameters

| Name | In | Type | Required | Description |
| - | - | - | - | - |
| `sim_id` | path | string | Yes | Simulation ID in `sim_xxx` format |

### Responses

**200** - Simulation termination initiated

```json theme={null}
{
  "id": "string",
  "workspaceId": "string",
  "configurationId": "string",
  "configurationVersion": 1,
  "name": "string",
  "status": "validating",
  "createdAt": "2024-01-15T10:30:00Z",
  "startedAt": "2024-01-15T10:30:00Z",
  "completedAt": "2024-01-15T10:30:00Z",
  "failureReason": "string",
  "terminationRequestedAt": "2024-01-15T10:30:00Z",
  "metrics": {
    "simulatedTime": "string",
    "eventsProcessed": 1,
    "throughput": "string"
  },
  "transportStats": [
    "uet"
  ],
  "networkTiers": [
    "ssw"
  ],
  "appliedMappingFile": {
    "id": "string",
    "name": "string",
    "deleted": true
  }
}
```

**202** - Termination dispatched for a simulation whose workspace has been deleted. Returned without a body: workspace deletion revokes the simulation's details, so the acknowledgement carries no SimulationDetails payload. Also returned when the backend refuses the request with a 4xx, whose message would describe the revoked simulation; a backend 5xx is reported as itself.

**400** - Bad Request - Invalid simulation ID format, or a scala-go simulation has no platform link and cannot be terminated. An orchestrator-backed simulation carries no link and is terminated through the gateway, so it never reaches this refusal

**404** - Simulation not found

**500** - Internal Server Error - A fault a retry cannot clear: the gateway or broker refused central's own request or credentials, or the termination event could not be built

**503** - Service Unavailable - The termination transport is unavailable

***

## Get simulation results

GET `/api/v1/simulations/{sim_id}/results`

Retrieves results for a completed simulation including summary metrics, dashboard URL, and downloadable result files (pcap, traces, etc.).

### Parameters

| Name | In | Type | Required | Description |
| - | - | - | - | - |
| `sim_id` | path | string | Yes | Simulation ID in `sim_xxx` format |
| `next` | query | string | No | Opaque cursor token from previous response's `nextCursor` for pagination |
| `limit` | query | integer | No | Maximum number of items to return (default: 100, min: 1, max: 100) |
| `type` | query | string | No | Filter by result file type (pcap, csv, json, log, state, unknown) |
| `metrics` | query | string | No | Filter by metrics query parameter |
| `sort` | query | string (enum) | No | Field to sort the result files by (default: createdAt) |
| `order` | query | string (enum) | No | Sort direction (default: desc) |

### Responses

**200** - Simulation results

```json theme={null}
{
  "simulationId": "string",
  "duration": "string",
  "summary": {
    "totalPackets": 1,
    "avgLatency": "string",
    "throughput": "string",
    "dropRate": 1.0
  },
  "dashboardUrl": "https://example.com",
  "files": [
    {
      "type": "pcap",
      "name": "string",
      "size": "string",
      "downloadUrl": "https://example.com"
    }
  ],
  "pagination": {
    "count": 1,
    "hasMore": true,
    "nextCursor": "string"
  }
}
```

**400** - Invalid simulation ID format, invalid pagination cursor, limit out of range, or an unrecognized sort or order value

**404** - Simulation not found or results not yet available

**500** - Internal server error

***

## Generate presigned download URL for result file

GET `/api/v1/simulations/{sim_id}/results/download-url`

### Parameters

| Name | In | Type | Required | Description |
| - | - | - | - | - |
| `sim_id` | path | string | Yes | Simulation ID in sim\_xxx format (base32-encoded UUID with prefix) |
| `fileName` | query | string | Yes | Path of the result file to download, relative to the simulation's results prefix. Nested files use their subdirectory path (e.g. "subdir/file.csv"). |
| `metrics` | query | string | No | Reserved for future use. Filter by metrics type (e.g., nd-stats, perf-stats, pfc-stats, post-annotated, logs) |
| `type` | query | string | No | Reserved for future use. File type filter (e.g., zstd) |

### Responses

**200** - File download URL generated

```json theme={null}
{
  "simulationId": "string",
  "fileName": "string",
  "contentType": "string",
  "sizeBytes": 1,
  "checksum": "string",
  "downloadUrl": "https://example.com",
  "expiresAt": "2024-01-15T10:30:00Z"
}
```

**400** - Invalid simulation ID format or missing fileName

**404** - Simulation or file not found

**500** - Internal server error

***

## Get computed summary data for simulation results

GET `/api/v1/simulations/{sim_id}/results/data`

Computes or retrieves cached summary statistics for simulation result CSV files using Polars. Returns a presigned URL to download the zstd-compressed JSON summary. For a run whose status is `completed`, `failed` or `terminated` and whose `completedAt` is at least 60 minutes old, and that has no rows for the requested metric (no data file for it, or only a header-only one), the response is 200 with a summary whose `totalRowsProcessed` is 0 and whose projection fields are absent. The one exception is a `completed` run whose only data for the PFC metric is a header-only shard: its `pfc` projection is present with five zero totals (`totalXoffRx`, `totalXoffTx`, `totalXonRx`, `totalXonTx`, `totalTimePausedUsec`) and `byTier` omitted. A run that is not yet settled, or whose status is `invalid`, keeps 404.

### Parameters

| Name | In | Type | Required | Description |
| - | - | - | - | - |
| `sim_id` | path | string | Yes | Simulation ID in sim\_xxx format (base32-encoded UUID with prefix) |
| `metric` | query | string (enum) | Yes | Metric type to summarize. `rank-analysis` is published but returns 501 Not Implemented until its compute path ships. `uet-transport-stats` and `roce-transport-stats` are published: both serve `timeSeries` and return 501 for `summary` and `sampled` until those compute paths ship. |
| `mode` | query | string (enum) | No | Output mode (default: summary). `timeSeries` is served for `nd-stats`, `pfc`, `uet-transport-stats` and `roce-transport-stats` and returns 501 Not Implemented for the other metrics; `sampled` is published but returns 501 Not Implemented until its compute path ships. `utilizationBins` (a binned distribution of link utilization over time) is offered for `nd-stats` only: every other metric returns 400 with error code `UNSUPPORTED_COMBINATION`, a permanent answer that must not be retried, and for `nd-stats` the response's `file` presigns a `UtilizationBinsDocument`. `uplinkFairness` (uplink port fairness per switch over time) is offered for `nd-stats` only in the same way: every other metric returns 400 with error code `UNSUPPORTED_COMBINATION`, and for `nd-stats` the response's `file` presigns an `UplinkFairnessDocument`. `completionTimeBins` (a binned distribution of completion times over time) is offered on the Performance projection: `perf` returns the envelope whose presigned URL serves a `CompletionTimeBinsDocument`; `chakra-perf` returns 404 Not Found, as a run with no result shards does, because this shape does not bin its completions; and every other metric returns 400 with error code `UNSUPPORTED_COMBINATION`, a permanent answer that must not be retried. |
| `tier` | query | string (enum) | No | Tier filter for network device results (default: all) |
| `nodeId` | query | array | No | Filter to these node ids. Comma-separated on the wire. An empty list is not accepted — omit the parameter instead. |
| `ifid` | query | array | No | Filter to these interface ids. Comma-separated on the wire. An empty list is not accepted — omit the parameter instead. |
| `nicType` | query | string | No | Filter to a NIC class. |
| `metricName` | query | array | No | Filter to these metric names. Comma-separated on the wire; values may not contain commas. An empty list is not accepted — omit the parameter instead. |
| `application` | query | array | No | Filter to these application names. Comma-separated on the wire; values may not contain commas. An empty list is not accepted — omit the parameter instead. |
| `priority` | query | array | No | Filter to these PFC priorities. Comma-separated on the wire. An empty list is not accepted — omit the parameter instead. |
| `uldl` | query | string (enum) | No | Filter to uplink or downlink direction. |
| `preset` | query | string (enum) | No | Rank-analysis grouping preset (only consumed when metric=rank-analysis). Omit to get the server default, `balanced`. Carries no schema `default`: a schema default makes generated clients send the value on every request, which lists it in X-Ignored-Params on every mode and metric that does not consume it. |
| `tolerance` | query | number | No | Dimensionless multiplier on the per-dimension tolerance bands (only consumed when metric=rank-analysis). Omit to get the server default, 0.0. Carries no schema `default`: a schema default makes generated clients send the value on every request, which lists it in X-Ignored-Params on every mode and metric that does not consume it. |
| `outlierThreshold` | query | number | No | Outlier deviation-score fraction (only consumed when metric=rank-analysis). Omit to get the server default, 0.10. Carries no schema `default`: a schema default makes generated clients send the value on every request, which lists it in X-Ignored-Params on every mode and metric that does not consume it. |

### Responses

**200** - Summary data with presigned download URL. For a run whose status is `completed`, `failed` or `terminated` and whose `completedAt` is at least 60 minutes old, and that has no rows for the requested metric (no data file for it, or only a header-only one), this is a summary whose `totalRowsProcessed` is 0 and whose projection fields are absent. The one exception is a `completed` run whose only data for the PFC metric is a header-only shard: its `pfc` projection is present with five zero totals (`totalXoffRx`, `totalXoffTx`, `totalXonRx`, `totalXonTx`, `totalTimePausedUsec`) and `byTier` omitted. A run that is not yet settled, or whose status is `invalid`, keeps 404.

```json theme={null}
{
  "simulationId": "string",
  "metric": "nd-stats",
  "mode": "summary",
  "tier": "all",
  "file": {
    "name": "string",
    "size": 1,
    "contentType": "string",
    "downloadUrl": "https://example.com",
    "expiresAt": "2024-01-15T10:30:00Z"
  },
  "metadata": {
    "cached": true,
    "computedAt": "2024-01-15T10:30:00Z",
    "rowsProcessed": 1,
    "computeTimeMs": 1
  }
}
```

**400** - Invalid parameters (bad metric, mode, or tier value), with error code `VALIDATION_ERROR`; or, with error code `UNSUPPORTED_COMBINATION`, a result shape the requested projection does not offer (`mode=utilizationBins` or `mode=uplinkFairness` on any metric but `nd-stats`, or `mode=completionTimeBins` on any metric but `perf` and `chakra-perf`). `UNSUPPORTED_COMBINATION` is permanent for the request and must not be retried; its message names the result shape and the projection, and only it carries `X-Ignored-Params`.

**404** - Simulation not found or no data files available for the specified metric for a simulation that is not yet settled, or is invalid. For `mode=utilizationBins` and `mode=uplinkFairness`, no data files answers 404 whether or not the simulation is settled. For `mode=completionTimeBins`, also a run with no perf result shards, settled or not, and every `metric=chakra-perf` request

**413** - Payload Too Large - The summarized result set exceeds one of the server's size limits: its row count is over the ceiling, summarizing it would exceed the memory budget, or, for `mode=utilizationBins` or `mode=uplinkFairness`, it spans more distinct sample times or more data files than that mode accepts, or, for `mode=uplinkFairness`, its switch uplinks hold more samples than the fold accepts, or, for `mode=completionTimeBins`, it lists more data files than that mode accepts. This condition is permanent for the request and must not be retried.

**500** - Internal server error

**501** - The requested mode or metric is recognized but its compute path has not shipped yet

**503** - Service Unavailable - Several conditions render this status and they differ in whether a retry resolves them; the ones named here are the known ones rather than a closed set. The common one is a transient fault against the results object store on any mode - a network error, throttling, or a 5xx from the dependency - which is retriable: a client that backs off and retries will usually succeed. A second retriable one is a lost cache-write race the server could not recover from: a concurrent request stored the summary object first, and when this request went back to read it the object was no longer there, so a later attempt normally succeeds against the object the next writer stores. The last is a required backend dependency that is not available or not configured, so the simulation's artifact location could not be resolved. Retrying does not help if the dependency is unconfigured. The response body does not distinguish them, so a client should retry with backoff under a bounded attempt count rather than indefinitely.

**504** - Gateway Timeout - Summary computation exceeded the server's time budget. The request may be retried.

***

## Get simulation logs

GET `/api/v1/simulations/{sim_id}/logs`

Retrieves paginated logs from a simulation with optional filtering by log level and component. Logs are returned in chronological order.

### Parameters

| Name | In | Type | Required | Description |
| - | - | - | - | - |
| `sim_id` | path | string | Yes | Simulation ID in `sim_xxx` format |
| `level` | query | string (enum) | No | Filter logs by minimum severity level |
| `component` | query | string | No | Filter logs by component name (e.g., `simulator`, `flownizer`, `annotator`) |
| `since` | query | string | No | Filter logs to entries at or after this time (ISO 8601 / RFC 3339) |
| `limit` | query | integer | No | Maximum number of log entries to return (default: 100, max: 1000). A truncated read may return one entry more than `limit`: the in-band truncation notice does not count against it. |
| `next` | query | string | No | Opaque cursor token from previous response's `nextCursor` for pagination |

### Responses

**200** - Simulation logs

```json theme={null}
{
  "logs": [
    {
      "timestamp": "2024-01-15T10:30:00Z",
      "level": "debug",
      "component": "string",
      "message": "string"
    }
  ],
  "pagination": {
    "count": 1,
    "hasMore": true,
    "nextCursor": "string"
  }
}
```

**400** - Bad Request - Invalid simulation ID format, invalid `since` timestamp, invalid `level` or `component`, or invalid pagination cursor

**404** - Simulation not found

**500** - Internal server error

**503** - Orchestrator database not configured

***


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.