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

> ## Agent Instructions
> Cluster API calls are made as a signed-in person with an OIDC bearer token. There are no API keys, and service-account tokens are refused (Business returns 401, Platform returns 403).
> Platform takes the organization as the query parameter businessOrgId on most cluster routes, but as organizationId on /clusters/{clusterId}/ssh-access and /clusters/{clusterId}/kubeconfig.
> The Business API uses snake_case. The Platform API uses camelCase, except /ssh-access and /machines, which use snake_case.
> Business write requests need Idempotency-Key and Audit-Reason headers.
> Storage capacity can grow but cannot shrink, including disk and PVC resizing. Each purchase adds capacity.
> A cluster's storage can be Ceph, WEKA, or both, or NFS on its own. The Ceph quota, the purchased bytes, and Slurm's default 100 GiB shared-volume request are three different quantities.
> Organization permissions cover every cluster the organization owns. A Kubernetes resource grant shares one cluster or namespace, possibly with someone outside the organization, and lets them read that cluster and fetch its kubeconfig. A grant does not give Slurm SSH, Slurm configuration, or organization storage inventory access. Slurm SSH requires organization membership and clusters.ssh.
> The SSH login name is <cluster-id>.<username>. The gateway supports shells, commands, SFTP (including modern scp), and forwarding to loopback ports on the login node. Legacy scp and rsync need their programs on the login node. Remote forwarding and non-loopback destinations are refused.
> Use POST /me/ssh-keys for personal key registration. POST /organizations/{orgID}/ssh-keys is a deprecated alias and requires no membership. Read the preferred shell from GET /me as user.login_shell; update it with PUT /me/login-preferences.
> GET /clusters/{clusterId}/ssh-access returns 200 with ready and reason, even when access is not ready. ready: true does not mean compute nodes or Slurm accounting are ready. To confirm a key or shell change reached a cluster, require observation_current: true and compare ssh_key_set_generation with generation from GET /me/ssh-keys, and shell with user.login_shell from GET /me.
> Adding or removing a login account restarts the cluster's login nodes, Slurm controller, and accounting service, then its compute nodes one at a time; jobs running on a restarting node end. An account is added or removed when a person with an active key gains or loses SSH access, or a person with SSH access registers their first key or revokes their last. Other key changes and shell changes restart no nodes.

# Slurm configuration

> Read and replace a cluster's Slurm configuration and the organization default.

For what each setting does and how to change it safely, see [Configure Slurm](/clusters/slurm-configuration).

* [Read a cluster's Slurm configuration](#read-a-clusters-slurm-configuration): `GET /clusters/{clusterId}/scheduler-configuration`
* [Replace a cluster's Slurm configuration](#replace-a-clusters-slurm-configuration): `PUT /clusters/{clusterId}/scheduler-configuration`
* [Read the organization default](#read-the-organization-default): `GET /organizations/{orgId}/scheduler-configuration`
* [Replace the organization default](#replace-the-organization-default): `PUT /organizations/{orgId}/scheduler-configuration`

These endpoints apply to clusters that run Slurm. They accept only people, not service accounts.

## The configuration object

Every field is optional. A field that has never been set is omitted.

| Field | Type | Description |
| - | - | - |
| `slurmPartitions` | string | Partition definitions for `slurm.conf`. Replaces the generated partitions. Cluster only. |
| `slurmExtraConfig` | string | Lines appended to `slurm.conf`. |
| `cgroupExtraConfig` | string | Lines appended to `cgroup.conf`. |
| `gresConf` | string | Contents of `gres.conf`. Replaces the generated file. Cluster only. |
| `prolog` | object | Prolog scripts, keyed by file name. Each must start with `#!`. |
| `epilog` | object | Epilog scripts, keyed by file name. Each must start with `#!`. |
| `controllerEtc` | object | Extra files in the controller's `/etc/slurm`, keyed by file name. |
| `loginS6Packages` | string | Script run when a login node starts. |
| `computeS6Packages` | string | Script run when a compute node starts. Changing it restarts every compute node and ends running jobs. |

For the organization default, `slurmPartitions` and `gresConf` are not accepted.

## Read a cluster's Slurm configuration

```http theme={null}
GET /clusters/{clusterId}/scheduler-configuration
```

**API:** Platform. **Permission:** `clusters.configure`.

### Parameters

| Name | In | Type | Required | Description |
| - | - | - | - | - |
| `clusterId` | path | string | yes | Cluster ID. |
| `businessOrgId` | query | string | yes | Organization ID. |

### Response

A [configuration object](#the-configuration-object).

### Example

```sh theme={null}
andromeda call platform GET "/clusters/$CLUSTER_ID/scheduler-configuration?businessOrgId=$ORG_ID"
```

```json theme={null}
{
  "slurmExtraConfig": "MaxJobCount=20000\n",
  "prolog": {"10-gpu-check.sh": "#!/bin/sh\nnvidia-smi -L >/dev/null || exit 1\n"}
}
```

### Errors

| Status | Code | When |
| - | - | - |
| 403 | `forbidden` | You lack `clusters.configure`, or you called with a service account. |
| 404 | `not_found` | No cluster with this ID belongs to the organization. |
| 422 | `invalid_request` | `businessOrgId` is missing. |

## Replace a cluster's Slurm configuration

```http theme={null}
PUT /clusters/{clusterId}/scheduler-configuration
```

**API:** Platform. **Permission:** `clusters.configure`.

Replaces the whole configuration with the body. A field you omit is cleared, so read the configuration first and send
it back with your changes.

Sending a configuration identical to the stored one changes nothing. Otherwise the cluster's
`spec.schedulerGeneration` increases and the cluster applies the new configuration. Applying it closes open SSH
sessions on the cluster.

### Parameters

| Name | In | Type | Required | Description |
| - | - | - | - | - |
| `clusterId` | path | string | yes | Cluster ID. |
| `businessOrgId` | query | string | yes | Organization ID. |

### Request body

A [configuration object](#the-configuration-object).

### Response

`200` with the configuration as stored.

### Example

Raise the job limit, and keep the rest of the configuration from
[the read example](#read-a-clusters-slurm-configuration), saved as `slurm.json`:

```sh theme={null}
jq '.slurmExtraConfig = "MaxJobCount=50000\n"' slurm.json |
  andromeda call --data @- \
    platform PUT "/clusters/$CLUSTER_ID/scheduler-configuration?businessOrgId=$ORG_ID"
```

### Errors

| Status | Code | When |
| - | - | - |
| 400 | `invalid_scheduler_config` | A setting failed validation. `message` says which. See [Validation](#validation). |
| 403 | `forbidden` | You lack `clusters.configure`, or you called with a service account. |
| 404 | `not_found` | No cluster with this ID belongs to the organization. |
| 422 | `invalid_request` | `businessOrgId` is missing, or the body is not a configuration object. |

### Validation

| Rule | Example that fails |
| - | - |
| `prolog` and `epilog` scripts start with `#!`. | `{"prolog": {"check.sh": "exit 0"}}` |
| File names contain only letters, digits, `-`, `_`, and `.`. | `{"prolog": {"gpu/check.sh": "#!/bin/sh\ntrue"}}` |
| `controllerEtc` does not contain a generated file: `slurm.conf`, `cgroup.conf`, `gres.conf`, `plugstack.conf`. | `{"controllerEtc": {"slurm.conf": "..."}}` |
| Each script or file is at most 64 KiB. | |
| `prolog`, `epilog`, and `controllerEtc` together are at most 256 KiB. | |

`slurmPartitions`, `slurmExtraConfig`, `cgroupExtraConfig`, `gresConf`, and the package scripts are not validated. An
error in them surfaces on the cluster, not in this response, and can stop `slurmctld`.

## Read the organization default

```http theme={null}
GET /organizations/{orgId}/scheduler-configuration
```

**API:** Platform. **Permission:** `clusters.configure`.

Returns the configuration new clusters in the organization start with. An organization with no default returns `{}`.

### Parameters

| Name | In | Type | Required | Description |
| - | - | - | - | - |
| `orgId` | path | string | yes | Organization ID. |

### Example

```sh theme={null}
andromeda call platform GET "/organizations/$ORG_ID/scheduler-configuration"
```

```json theme={null}
{"loginS6Packages": "#!/bin/sh\napt-get install -y tmux htop\n"}
```

## Replace the organization default

```http theme={null}
PUT /organizations/{orgId}/scheduler-configuration
```

**API:** Platform. **Permission:** `clusters.configure`.

Replaces the whole default. Clusters created afterwards start with it. Existing clusters are not changed.

The body is a [configuration object](#the-configuration-object) without `slurmPartitions` or `gresConf`. The
response is `200` with the default as stored. Validation is the same as for a cluster.

### Example

```sh theme={null}
jq -n '{loginS6Packages: "#!/bin/sh\napt-get install -y tmux htop\n"}' |
  andromeda call --data @- platform PUT "/organizations/$ORG_ID/scheduler-configuration"
```

### Errors

| Status | Code | When |
| - | - | - |
| 400 | `invalid_scheduler_config` | A setting failed validation. |
| 403 | `forbidden` | You lack `clusters.configure`, or you called with a service account. |
| 422 | `invalid_request` | The body contains a field the default does not accept, such as `slurmPartitions` or `gresConf`. |


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