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

# SDKs

> Use the Python and TypeScript SDKs to manage Arct Cloud resources.

The Python and TypeScript SDKs cover all 22 public API operations. Source, examples and changelogs are in [ArctCloud/sdk](https://github.com/ArctCloud/sdk). The Python package also includes `arct` and `python -m arct` for terminal automation; see the [CLI installation guide](/api-reference/cli.md), including the macOS/Linux shell installer.

## Install the Preview

| SDK | Preview version | Runtime |
| - | - | - |
| Python, `arct-cloud` | `0.1.0rc3` | Python 3.11+ |
| TypeScript / JavaScript, `@arct-cloud/sdk` | `0.1.0-rc.4` | Node.js 22+, ESM |

Install an exact preview from [PyPI](https://pypi.org/project/arct-cloud/0.1.0rc3/) or [npm](https://www.npmjs.com/package/@arct-cloud/sdk):

```bash Python theme={null}
python -m pip install "arct-cloud==0.1.0rc3"
```

```bash TypeScript / JavaScript theme={null}
npm install --save-exact @arct-cloud/sdk@0.1.0-rc.4
```

### Install from Source

With Git installed, clone the source into your project directory:

```bash theme={null}
git clone https://github.com/ArctCloud/sdk.git arct-sdk
```

```bash Python theme={null}
python -m pip install ./arct-sdk/python
```

```bash TypeScript / JavaScript theme={null}
npm --prefix arct-sdk/typescript ci
npm --prefix arct-sdk/typescript run build
npm install ./arct-sdk/typescript
```

The TypeScript commands build the local package before adding it to your application. Keep that checkout while using a local file dependency.

## Authenticate and Read Resources

Create a token in [Settings > API Tokens](/account/api-tokens.md). Choose **Read only** for queries and **Read & write** for mutations. Supply it through your environment or secret manager:

```bash macOS / Linux theme={null}
export ARCT_TOKEN="arct_your_token_here"
```

```powershell Windows theme={null}
$env:ARCT_TOKEN = "arct_your_token_here"
```

Explicit `token=` in Python or `{ token }` in TypeScript overrides `ARCT_TOKEN`. Both SDKs use `https://api.arct.cloud/v1` by default. Keep tokens server-side; never embed them in browser code.

**Python**

```python theme={null}
from arct import Arct

with Arct() as client:
    print(client.account.get().id)
    for server in client.servers.list(location="fra"):
        print(server.id, server.hostname, server.status)
    page = client.images.list_page(location="fra", page=1, per_page=20)
    print(page.pagination.total)
```

**Async Python**

```python theme={null}
import asyncio
from arct import AsyncArct

async def main():
    async with AsyncArct() as client:
        print((await client.account.get()).id)
        async for server in client.servers.list(location="fra"):
            print(server.id, server.hostname, server.status)
        page = await client.images.list_page(location="fra", page=1, per_page=20)
        print(page.pagination.total)

asyncio.run(main())
```

**TypeScript / JavaScript**

```javascript theme={null}
import { Arct } from '@arct-cloud/sdk';

const client = new Arct();
console.log((await client.account.get()).id);
for await (const server of client.servers.list({ location: 'fra' })) {
  console.log(server.id, server.hostname, server.status);
}
const page = await client.images.listPage({ location: 'fra', page: 1, perPage: 20 });
console.log(page.pagination.total);
```

`list()` lazily retrieves every page, using 100 items per page by default and preserving filters. Python `list_page()` and TypeScript `listPage()` return one page with its pagination metadata. Page-number results can change while resources are being added or removed. See [Pagination](/api-reference/pagination.md).

## Create and Wait for a Server

> [!WARNING]
>
> Creation charges the saved card and requires a `read_write` token. SDK methods do not prompt. Review the location, plan and billing period before running a creation example.

Replace `PLAN_ID` with a plan `slug` from `plans.list()` and `TARGET_PLAN` with the target resize plan. Choose a compatible image for the same location and a saved public key matching your local private key. These examples use the saved key name `my-laptop`; add your public key in [SSH Keys](/compute/virtual-machines/ssh-keys.md) first.

**Python**

```python theme={null}
from arct import Arct

with Arct() as client:
    location, plan = "fra", "PLAN_ID"
    image = next(
        image for image in client.images.list(location=location)
        if "ubuntu" in image.name.lower()
        and (not image.allowed_plans or plan in image.allowed_plans)
    )
    key = next(key for key in client.ssh_keys.list() if key.name == "my-laptop")
    result = client.servers.create(
        hostname="web-1", location=location, plan=plan,
        image_id=image.id, ssh_key_ids=[key.id], billing_period="monthly",
    )
    server = client.servers.wait_until(result, "running", timeout=600)
    print(f"ssh -i ~/.ssh/id_ed25519 {server.login_user}@{server.ipv4}")
```

**TypeScript / JavaScript**

```javascript theme={null}
import { Arct } from '@arct-cloud/sdk';

const client = new Arct();
const location = 'fra';
const plan = 'PLAN_ID';
const images = await Array.fromAsync(client.images.list({ location }));
const image = images.find(image => image.name.toLowerCase().includes('ubuntu') &&
  (image.allowed_plans.length === 0 || image.allowed_plans.includes(plan)));
const keys = await Array.fromAsync(client.sshKeys.list());
const key = keys.find(key => key.name === 'my-laptop');
if (!image || !key) throw new Error('Select a compatible image and saved SSH key.');
const result = await client.servers.create({
  hostname: 'web-1', location, plan, image_id: image.id,
  ssh_key_ids: [key.id], billing_period: 'monthly',
});
const server = await client.servers.waitUntil(result, 'running', { timeoutMs: 600_000 });
console.log(`ssh -i ~/.ssh/id_ed25519 ${server.login_user}@${server.ipv4}`);
```

Run the printed [SSH command](/compute/virtual-machines/connect-ssh.md) using the private key matching the selected public key. Creation returns HTTP `201` with an order and a server that may still be provisioning or `null`. Waiters resolve acknowledged delayed creations and return the final server. Pre-orders can outlive the default 600-second deadline.

Python async resource calls use the same arguments with `await`; `list()` remains an async iterator. Use `async with AsyncArct()` to close the client.

Keep the original `result`: waiting does not overwrite its order or one-time password. Passwords are masked in normal representations and JSON. Deliberately unwrap a non-null password with Python `result.password.get_secret_value()` or TypeScript `result.password.getSecretValue()` only when needed. Omitted `ssh_key_ids` uses saved keys; an explicit empty array requests password access where supported. See [Creating Servers](/api-reference/creating-servers.md#login-password).

### Lifecycle and Completion

| Operation | Python | TypeScript |
| - | - | - |
| Start / stop / restart | `servers.start(id)`, `stop(id)`, `restart(id)` | Same method names |
| Reinstall | `servers.reinstall(id, image_id=...)` | `servers.reinstall(id, { image_id })` |
| Wait for status | `servers.wait_until(result, "running")` | `servers.waitUntil(result, 'running')` |
| Resize options / resize | `servers.resize_options(id)`, `resize(id, plan=...)` | `servers.resizeOptions(id)`, `resize(id, { plan })` |
| Schedule deletion | `servers.delete(id, at_period_end=True)` | `servers.delete(id, { atPeriodEnd: true })` |
| Cancel scheduled deletion | `servers.cancel_deletion(id)` | `servers.cancelDeletion(id)` |

Start, stop, restart and reinstall return accepted HTTP `202` responses. Pass the **original action result** to a waiter: a bare server ID checks current status, while the original restart/reinstall result retains transition tracking. An initial stale `running` observation cannot prove those operations completed; a missed transition can time out as unverified.

Waiters poll every 5 seconds by default. Python uses `timeout` in seconds; TypeScript uses `timeoutMs` in milliseconds. Timeouts expose `last_state` in Python or `lastState` in TypeScript. Cancellation stops waiting and does not cancel an accepted remote operation. Cancel an async Python task or pass an `AbortSignal` in the final TypeScript request/wait options.

### Resize Safely

Stop the server and wait for `stopped` before resizing. `resize()` obtains an eligible quote and sends its exact `amount_due_today` as `expected_amount`. To retain an already reviewed quote, supply that amount explicitly. A `price_changed` conflict requires a new decision; it is never silently re-quoted.

Python `servers.wait_resize(id, resize_result)` and TypeScript `servers.waitUntil(id, 'stopped', { plan: 'TARGET_PLAN' })` check resize completion. HTTP `200 applied` and `202 pending_payment` are distinct. A pending payment may need dashboard action. Start the server only after the requested plan is confirmed applied; resizing and waiting never start it automatically.

Python monetary responses use `Decimal`. TypeScript monetary responses are JavaScript numbers, while automatic resize quoting preserves the original numeric text. Use a decimal string for an explicit TypeScript amount. Explicit Python `expected_amount=None` or TypeScript `expected_amount: null` opts out of price protection and accepts the current API price.

## Errors and Retry Safety

Both SDKs export `APIError` and typed errors including `AuthenticationError`, `PaymentRequiredError`, `PermissionDeniedError`, `NotFoundError`, `ConflictError`, `ValidationError`, `RateLimitError`, `ChargeUnknownError`, `UncertainOperationError`, `WaitTimeoutError` and `OperationFailedError`.

API errors expose `status`, `code` and redacted `details`; validation errors also expose `fields`. Unknown error codes fall back to their HTTP status class. See the [error reference](/api-reference/errors.md) for codes.

* Reads and eligible creation failures have at most three total attempts; creation retries retain the identical body and hostname. Other uncertain mutations are not blindly repeated.
* `429` honors `Retry-After` within the operation deadline. Local scheduling complements the server's [rate limits](/api-reference/rate-limits.md).
* `details.order_intent_id` or `409 payment_pending` raises `ChargeUnknownError` without retrying. Keep support identifiers and verify billing before another purchase.
* A lost response or a matching hostname cannot prove a successful order or recover its one-time password. `UncertainOperationError` requires reconciliation before repeating the action.

## Available Resources and Limits

Resources are `account`, `servers`, `locations`, `plans`, `images`, `invoices`, and Python `ssh_keys` / TypeScript `sshKeys`. They cover the endpoints listed in this API reference; new response fields and enum strings are accepted.

You can enable automatic backups **during server creation** with Python `enable_backups=True` or TypeScript `enable_backups: true`, where the selected plan supports them. There are no backup/snapshot management endpoints or SDK management methods. Use the [dashboard](/compute/virtual-machines/backups-snapshots.md) for backup and snapshot management. Token issuance/revocation, cards, invoice payment, password resets and VNC also remain dashboard operations.


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