# Arrakis API guide

The live [OpenAPI document](/openapi.json) is the authoritative schema; [/docs](/docs) is the interactive reference. This guide is an overview, not a generated endpoint inventory or an executed response transcript. The console is at [/console/](/console/).

## Authentication

`POST /v1/tenants` creates a tenant and returns a single-use `bootstrap_secret` alongside its id, name and creation time. The secret is returned once, stored hashed and expires after 24 hours. Without a bearer, `POST /v1/tokens` requires `tenant_id` and `bootstrap_secret`. Missing, incorrect, expired and used secrets all fail with 401. Success consumes the secret.

With a bearer, token issuance requires `manage`. Requested scopes must be a subset of the caller's scopes; the default is `read`. Identity linking to an existing tenant also requires `manage`. Use `Authorization: Bearer $ARRAKIS_TOKEN` on protected requests. The API derives the tenant from the credential.

Tokens can carry `spend_limit_usd` (positive), `max_rental_hours` (integer at least one), and a future `expires_at`. An expired token receives 401. Child tokens cannot exceed a parent's remaining spend cap or maximum rental duration. Keep account-management credentials separate from agent tokens.

## Main routes

| Method | Path | Purpose |
|---|---|---|
| GET | `/healthz` | Public liveness |
| GET | `/v1/market/summary` | Public live price and availability summary |
| POST | `/v1/tenants` | Create a tenant and obtain its bootstrap secret |
| POST | `/v1/tokens` | Exchange bootstrap secret, or mint with a manage-scoped bearer |
| GET / DELETE | `/v1/tokens`, `/v1/tokens/{id}` | List or revoke credentials; see live schema for required scopes |
| GET | `/v1/gpus` | Search capacity |
| POST | `/v1/instances` | Create a billable rental; requires rent scope |
| GET | `/v1/instances`, `/v1/instances/{id}` | Read your instances |
| POST | `/v1/instances/{id}/terminate` | Terminate your rental |
| POST | `/v1/instances/{id}/schedule-removal` | Set `removal_scheduled_at` |
| GET | `/v1/billing/balance`, `/v1/billing/ledger` | Inspect funds and ledger |
| POST | `/v1/billing/deposits` | Request a deposit; does not credit funds |
| GET | `/v1/metering/usage` | Inspect recorded usage |
| POST | `/mcp` | Remote MCP using the caller's bearer credential |

Templates, SSH keys, volumes and other operations are documented in the live OpenAPI schema. Capabilities depend on the chosen host; unsupported operations fail explicitly.

## Search and prices

`GET /v1/gpus` supports GPU type and count, memory, price, country and other filters documented in OpenAPI. `max_price_per_gpu_hour` is a per-GPU ceiling, not a whole-machine price. Inspect the returned machine's price before renting.

The public summary shape is `{updated_at, stale, gpus_available, machines, families}`. Each family contains `gpu_type`, `gpu_model`, `min_price_per_gpu_hour`, `available_gpus`, `machines` and `max_vram_gb`. This is a response shape, not a captured response. Unverified and zero prices are excluded. The summary is cached for 60 seconds; on market failure a last-good snapshot can be served for up to ten minutes with `stale: true`. Without a usable snapshot it returns 503.

## Rental safety

Use a returned node id, your public SSH key, a stable `idempotency_key` and `termination_hours` on creation. Capped tokens must provide a shutdown window within their maximum duration. A rental commits the machine's hourly price multiplied by that duration against the token's cap. A cap-exceeding request receives 402; missing a required shutdown window receives 422. Reusing the same retry key returns the same machine rather than another rental.

Pending deposit requests do not change the spendable balance. Only an operator-confirmed deposit credits funds. Tenant credentials cannot write arbitrary billing charges. Do not rely on an empty balance to terminate an existing machine.

## Agent and CLI access

[Connect through MCP](/docs/mcp.md) or follow the [agent walkthrough](/docs/agent-walkthrough.md). The CLI is generated from the same OpenAPI contract as the console. Run it from an Arrakis checkout with `uv run arrakis --help`; a public package-install workflow is not promised here.
