
## SSH credentials

`GET /v1/infra/servers/:id/ssh`

Returns the SSH connection credentials. Full SSH access (with a password, private key, and public key) is returned only for servers in `OPEN` mode. For `BLACKHOLE`, all SSH fields are `null`: the server is closed behind the iptables firewall, and direct SSH is impossible. Instead of SSH, for BLACKHOLE use the [Deploy API](/docs/infra/deploy) — `/exec`, `/upload`, `/logs`. Rate limit: up to 10 requests per minute per server.

## Parameters

| Parameter | In | Type | Req. | Description |
|----------|---|-----|:-----:|----------|
| `id` | path | string (UUID) | yes | Server ID |

## Examples

### curl — personal key

```bash
curl -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/ssh
```

### curl — OAuth application

```bash
curl -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/ssh
```

### JavaScript — personal key

```javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/ssh`,
  { headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
)
const { data } = await res.json()

if (data.mode === 'OPEN') {
  console.log('Command:', data.sshCommand)
  console.log('Password:', data.sshPassword)  // if it was issued
} else {
  console.log(data.note)  // BLACKHOLE — use the Deploy API
}
```

### JavaScript — OAuth application

```javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/ssh`,
  {
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
    },
  }
)
```

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | Always `true` on success |
| `data.mode` | string | `OPEN` or `BLACKHOLE` |
| `data.ip` | string | Public IP of the server |
| `data.sshDirect` | boolean | `true` for `OPEN` (SSH works by IP), `false` for `BLACKHOLE` (closed behind the firewall) |
| `data.sshUser` | string \| null | SSH user: `ubuntu` or `root`. `null` for BLACKHOLE |
| `data.sshPort` | number \| null | SSH port: `22`. `null` for BLACKHOLE |
| `data.sshPassword` | string \| null | Password. For BLACKHOLE always `null`. For OPEN — the password if the server generated one when switching to OPEN |
| `data.sshPrivateKey` | string \| null | OpenSSH private key (ed25519). Returned for an OPEN server when the platform generated it |
| `data.sshPublicKey` | string \| null | Public key (ed25519) — the matching public part for `sshPrivateKey` |
| `data.sshCommand` | string \| null | Ready-to-copy command: `ssh ubuntu@IP`. For BLACKHOLE — `null` |
| `data.appUrl` | string | The application's HTTPS address (present only for BLACKHOLE, where SSH is unavailable) |
| `data.note` | string | Explanation for BLACKHOLE: "BLACKHOLE servers do not expose SSH. Use the Deploy API…" |

## Response example

OPEN server:

```json
{
  "success": true,
  "data": {
    "mode": "OPEN",
    "ip": "111.88.251.211",
    "sshUser": "ubuntu",
    "sshPort": 22,
    "sshPassword": "Oi9owBO6zMbueGmM75J9hg",
    "sshPrivateKey": "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmU…\n-----END OPENSSH PRIVATE KEY-----\n",
    "sshPublicKey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM0JAP1EMGh0CkT7RkZ26pTSa4X1FsWXe61cB5Fiqqjz vibe-generated",
    "sshCommand": "ssh ubuntu@111.88.251.211",
    "sshDirect": true
  }
}
```

BLACKHOLE server:

```json
{
  "success": true,
  "data": {
    "mode": "BLACKHOLE",
    "ip": "93.77.184.167",
    "sshDirect": false,
    "sshPassword": null,
    "sshPrivateKey": null,
    "sshPublicKey": null,
    "sshCommand": null,
    "appUrl": "https://app-abc12345.vibecode.bitrix24.com",
    "note": "BLACKHOLE servers do not expose SSH. Use the Deploy API (exec/upload/logs) instead."
  }
}
```

## Error response example

404 — the server does not exist:

```json
{
  "success": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "Server not found"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header was not provided |
| 401 | `INVALID_API_KEY` | Invalid or expired API key |
| 404 | `NOT_FOUND` | The server does not exist, was deleted, or belongs to another API key |
| 429 | `RATE_LIMITED` | The rate limit was exceeded (up to 10 requests per minute per server) or the platform's overall rate limit |

The full list of common API errors — [Errors](/docs/errors).

## Known specifics

- **Each BLACKHOLE → OPEN switch generates a new password.** Old passwords (if any) become invalid. The same applies on the reverse cycle BLACKHOLE → OPEN → BLACKHOLE → OPEN: on every entry into OPEN, the platform generates a fresh `sshPassword`. The password is also returned in the response to [`PATCH /mode`](./mode.md) — you can save it from there.
- **`sshPrivateKey` and `sshPublicKey` are returned only for keys generated by the platform.** If, when creating the server via [`POST /v1/infra/servers`](/docs/infra/servers/create), you passed your own `sshPublicKey`, the platform did not generate a private key — the `sshPrivateKey` field in the response will be `null`. Use your own private key on the client side.
- **`sshCommand` is a ready "copy-paste" for AI agents and scripts.** It is not a separate launch command — just `ssh ubuntu@IP`. Authentication via password or key is a separate step on the SSH client side.
- **A separate limit — 10 requests per minute per server** exists precisely because of the sensitivity of the returned data. The platform's overall limit is higher, but `/ssh` is throttled more strictly.

## See also

- [Switch mode](./mode.md) — `PATCH /v1/infra/servers/:id/mode` — switch to OPEN/BLACKHOLE.
- [Execute command](/docs/infra/deploy/exec) — `POST /v1/infra/servers/:id/exec` — the SSH equivalent for BLACKHOLE.
- [Upload file](/docs/infra/deploy/upload) — `POST /v1/infra/servers/:id/upload` — the scp equivalent for BLACKHOLE.
- [Access policy](./access-policy.md) — who sees the application via HTTPS.
