# SSH keys

The keys installed on new instances.

Source: https://docs.pantechdynamics.com/api/ssh-keys

Images have no password login, so give every new instance an SSH key. Register your own public key, or have a key pair generated. Its private key is returned once and never again.

Endpoints:

- `GET /public/v1/ssh-keys`: List SSH keys
- `POST /public/v1/ssh-keys`: Add or generate an SSH key
- `GET /public/v1/ssh-keys/{ssh_key_id}`: Get an SSH key
- `DELETE /public/v1/ssh-keys/{ssh_key_id}`: Delete an SSH key

## The SSH key object



- `id` (string, required): e.g. `sshk_...`.
- `name` (string, required): Its name, unique among your SSH keys.
- `fingerprint` (string, required): The key's SHA256 fingerprint.
- `public_key` (string, required): The OpenSSH public key.
- `created_at` (string or null): When it was created (RFC 3339, UTC).
## List SSH keys

```http
GET /public/v1/ssh-keys
```

The SSH keys you can install on new instances.

Scope: `read`.

Example:

```sh
curl "https://api.pantechdynamics.com/public/v1/ssh-keys" \
  -H "Authorization: Bearer $PANTECH_API_KEY"
```

Response `200`:

```json
{
  "data": [
    {
      "id": "sshk_06gk3x9tq7m2v8r4y1c5d0zp8w",
      "name": "web-1",
      "fingerprint": "SHA256:Qm8vWv3n7rC1bK0pXcFZ9yS2t4uJ6hLdA5gE8iRqTzo",
      "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExample deploy@ci",
      "created_at": "2026-10-03T09:30:00Z"
    }
  ],
  "next_cursor": null
}
```

Errors:

- `401`: `UNAUTHENTICATED`: the request has no API key, or the key is mistyped, revoked or expired, or its creator has left the organization. Send `Authorization: Bearer PAN_…` with a valid key; create one in the console under Organization › API keys.
- `403`: `INSUFFICIENT_SCOPE`: the API key lacks the scope this endpoint needs (`read` for GET, `write` for changes; an AI app's key also needs `delete` for a destructive call). Use a key with that scope, or reconnect the AI app with "Manage and delete" access.
`FORBIDDEN`: the member who created the key may not do this in the organization. Use a key created by an owner or admin.
`AI_APPS_DISABLED`: the organization has turned AI app access off, and this request was made with an AI app's key or sent by Pantech's MCP server (`Pantech-Client: mcp/…`). An owner can turn it on in the console under Organization › AI apps.
- `429`: `RATE_LIMITED`: this API key, verified user or organization used its request budget for the current window, or this address exceeded an IP/failed-auth limit. Wait `Retry-After` seconds, then retry. For authenticated quota denials, `RateLimit-Scope` identifies the denying quota and `RateLimit-Reset` reports its remaining window in seconds.
- `503`: `SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.
## Add or generate an SSH key

```http
POST /public/v1/ssh-keys
```

Send `public_key` to register your own OpenSSH public key. Leave it out to have a key pair generated: the private key is returned in this response only and never stored. Returns `201` at once; there is no operation to follow.

**Idempotency:** a retry with the same `Idempotency-Key` is not replayed yet. If a request may have gone through, list your SSH keys before retrying: a second attempt with the same name returns `409 SSH_KEY_NAME_TAKEN`, and a generated private key is never shown again.

Scope: `write`. Send an `Idempotency-Key` header.

Body:

- `name` (string, required): 1 to 255 characters, unique among your SSH keys. At most 255 characters.
- `public_key` (string): One OpenSSH public key line, e.g. `ssh-ed25519 AAAA… deploy@ci`. Leave out to have a key pair generated; its private key is then returned once.

Example:

```sh
curl -X POST "https://api.pantechdynamics.com/public/v1/ssh-keys" \
  -H "Authorization: Bearer $PANTECH_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "deploy"
  }'
```

Response `201`:

```json
{
  "id": "sshk_06gk3x9tq7m2v8r4y1c5d0zp8w",
  "name": "web-1",
  "fingerprint": "SHA256:Qm8vWv3n7rC1bK0pXcFZ9yS2t4uJ6hLdA5gE8iRqTzo",
  "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExample deploy@ci",
  "created_at": "2026-10-03T09:30:00Z",
  "private_key": "-----BEGIN OPENSSH PRIVATE KEY-----\n…\n-----END OPENSSH PRIVATE KEY-----"
}
```

Errors:

- `400`: `IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.
`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.
`INVALID_REQUEST_BODY`: the body is not a single valid JSON object. Send one JSON object with the fields documented for this endpoint.
- `401`: `UNAUTHENTICATED`: the request has no API key, or the key is mistyped, revoked or expired, or its creator has left the organization. Send `Authorization: Bearer PAN_…` with a valid key; create one in the console under Organization › API keys.
- `403`: `INSUFFICIENT_SCOPE`: the API key lacks the scope this endpoint needs (`read` for GET, `write` for changes; an AI app's key also needs `delete` for a destructive call). Use a key with that scope, or reconnect the AI app with "Manage and delete" access.
`FORBIDDEN`: the member who created the key may not do this in the organization. Use a key created by an owner or admin.
`AI_APPS_DISABLED`: the organization has turned AI app access off, and this request was made with an AI app's key or sent by Pantech's MCP server (`Pantech-Client: mcp/…`). An owner can turn it on in the console under Organization › AI apps.
- `409`: `SSH_KEY_NAME_TAKEN`: you already have an SSH key with this name. Choose a different name.
`SSH_KEY_ALREADY_EXISTS`: this public key is already registered. Use the existing key.
- `413`: `REQUEST_TOO_LARGE`: the body is larger than 64 KiB. Send a smaller request.
- `422`: `VALIDATION_FAILED`: a field is invalid. Each entry of `errors` names the `field` and its `code`:
`name` `REQUIRED` or `INVALID_NAME`: send a name of 1 to 255 characters.
`public_key` `INVALID_SSH_PUBLIC_KEY`: send one OpenSSH public key line, such as `ssh-ed25519 AAAA… comment`.
`UNKNOWN_FIELD`: the body has a field this endpoint does not take (named in `field`). Remove it or fix its spelling.
- `429`: `RATE_LIMITED`: this API key, verified user or organization used its request budget for the current window, or this address exceeded an IP/failed-auth limit. Wait `Retry-After` seconds, then retry. For authenticated quota denials, `RateLimit-Scope` identifies the denying quota and `RateLimit-Reset` reports its remaining window in seconds.
- `503`: `SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.
## Get an SSH key

```http
GET /public/v1/ssh-keys/{ssh_key_id}
```

One SSH key.

Scope: `read`.

Path parameters:

- `ssh_key_id`: The resource's id.

Example:

```sh
curl "https://api.pantechdynamics.com/public/v1/ssh-keys/sshk_06gk3x9tq7m2v8r4y1c5d0zp8w" \
  -H "Authorization: Bearer $PANTECH_API_KEY"
```

Response `200`:

```json
{
  "id": "sshk_06gk3x9tq7m2v8r4y1c5d0zp8w",
  "name": "web-1",
  "fingerprint": "SHA256:Qm8vWv3n7rC1bK0pXcFZ9yS2t4uJ6hLdA5gE8iRqTzo",
  "public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExample deploy@ci",
  "created_at": "2026-10-03T09:30:00Z"
}
```

Errors:

- `401`: `UNAUTHENTICATED`: the request has no API key, or the key is mistyped, revoked or expired, or its creator has left the organization. Send `Authorization: Bearer PAN_…` with a valid key; create one in the console under Organization › API keys.
- `403`: `INSUFFICIENT_SCOPE`: the API key lacks the scope this endpoint needs (`read` for GET, `write` for changes; an AI app's key also needs `delete` for a destructive call). Use a key with that scope, or reconnect the AI app with "Manage and delete" access.
`FORBIDDEN`: the member who created the key may not do this in the organization. Use a key created by an owner or admin.
`AI_APPS_DISABLED`: the organization has turned AI app access off, and this request was made with an AI app's key or sent by Pantech's MCP server (`Pantech-Client: mcp/…`). An owner can turn it on in the console under Organization › AI apps.
- `404`: `RESOURCE_NOT_FOUND`: no SSH key with this id in your organization, or the id is not a SSH key id (`sshk_…`). Check the id.
- `429`: `RATE_LIMITED`: this API key, verified user or organization used its request budget for the current window, or this address exceeded an IP/failed-auth limit. Wait `Retry-After` seconds, then retry. For authenticated quota denials, `RateLimit-Scope` identifies the denying quota and `RateLimit-Reset` reports its remaining window in seconds.
- `503`: `SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.
## Delete an SSH key

```http
DELETE /public/v1/ssh-keys/{ssh_key_id}
```

Deletes an SSH key. Instances that already have it keep it in their `authorized_keys`; remove it there yourself.

**Idempotency:** a retry is not replayed. Once the key is deleted, a repeat returns `404`; treat that as done.

**Scope:** `write`. Destructive: an AI app's key also needs `delete`.

Scope: `write`. Send an `Idempotency-Key` header.

Path parameters:

- `ssh_key_id`: The resource's id.

Example:

```sh
curl -X DELETE "https://api.pantechdynamics.com/public/v1/ssh-keys/sshk_06gk3x9tq7m2v8r4y1c5d0zp8w" \
  -H "Authorization: Bearer $PANTECH_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```

Response `204`: Deleted.

Errors:

- `400`: `IDEMPOTENCY_KEY_REQUIRED`: the `Idempotency-Key` header is missing. Send a new unique value, such as a UUID, with every write.
`INVALID_IDEMPOTENCY_KEY`: the `Idempotency-Key` header is longer than 255 characters. Use a shorter value.
- `401`: `UNAUTHENTICATED`: the request has no API key, or the key is mistyped, revoked or expired, or its creator has left the organization. Send `Authorization: Bearer PAN_…` with a valid key; create one in the console under Organization › API keys.
- `403`: `INSUFFICIENT_SCOPE`: the API key lacks the scope this endpoint needs (`read` for GET, `write` for changes; an AI app's key also needs `delete` for a destructive call). Use a key with that scope, or reconnect the AI app with "Manage and delete" access.
`FORBIDDEN`: the member who created the key may not do this in the organization. Use a key created by an owner or admin.
`AI_APPS_DISABLED`: the organization has turned AI app access off, and this request was made with an AI app's key or sent by Pantech's MCP server (`Pantech-Client: mcp/…`). An owner can turn it on in the console under Organization › AI apps.
- `404`: `RESOURCE_NOT_FOUND`: no SSH key with this id in your organization, or the id is not a SSH key id (`sshk_…`). Check the id.
- `429`: `RATE_LIMITED`: this API key, verified user or organization used its request budget for the current window, or this address exceeded an IP/failed-auth limit. Wait `Retry-After` seconds, then retry. For authenticated quota denials, `RateLimit-Scope` identifies the denying quota and `RateLimit-Reset` reports its remaining window in seconds.
- `503`: `SERVICE_UNAVAILABLE`: request quota storage is unavailable. Wait a few seconds, then retry.
