---
name: nodexo-rental
description: Rent and manage Nodexo GPUs through the public API using x402 payments, SSH keys, and recovery tokens.
---

# Nodexo Rental

Use this skill when an agent needs to inspect Nodexo inventory, rent a GPU, connect by SSH, extend a rental, add or remove SSH keys, or terminate a rental.

The public renter API is the web app backend at `https://nodexo.ai/api/*`. Do not call validator control routes directly. Miners and monitors call validators directly with their own signed protocol, but renters and agents use `/api/*`.

## Required Inputs

For an x402 rental:

- `api_base`: API base URL. Default to `https://nodexo.ai/api`. Override it
  only for an explicit private test deployment.
- `gpu_model`: Requested GPU model or unambiguous substring, for example `A6000`, `RTX A6000`, `4090`, or `H100`.
- `gpu_count`: Number of GPUs in one executor. Default `1`.
- `hours`: x402 rental duration from `1` to `168`.
- `image`: Docker image. Default `ubuntu:22.04`.
- `ssh_pub_key`: Public SSH key to inject into the rental container.
- x402-capable EVM wallet on the required network, currently USDC on Base.

For a credit-balance rental:

- `api_key`: Account API key from Account settings. It starts with `vc_`.
- The account must have a positive credit balance.
- `gpu_model`, `gpu_count`, `image`, and `ssh_pub_key` use the same fields as x402.
- Do not send `hours`; credit rentals are metered and run until terminated or the account balance is exhausted.

For management after creation:

- `rental_id`: ID returned by rental creation.
- `recovery_token`: Bearer token returned by rental creation, unless the caller uses an authenticated account session or account API key.

Never expose private keys, wallet seed phrases, API keys, or recovery tokens in logs. Treat `api_key` and `recovery_token` as bearer secrets.

## Preferred CLI

Prefer the installed `nodexo` CLI when it is available. Public renter commands are routed through the web app API; validator-direct/admin behavior is explicit.

```bash
nodexo --api-url https://nodexo.ai/api inventory
nodexo --api-url https://nodexo.ai/api marketplace
nodexo --api-url https://nodexo.ai/api quote --gpu A6000 --duration 1h --ssh-key ~/.ssh/id_ed25519.pub
```

Preview payment requirements without paying:

```bash
nodexo --api-url https://nodexo.ai/api quote \
  --gpu A6000 \
  --duration 1h \
  --ssh-key ~/.ssh/id_ed25519.pub
```

Create a real x402 rental:

```bash
export NODEXO_EVM_PRIVATE_KEY=0x...
nodexo --api-url https://nodexo.ai/api rent \
  --gpu A6000 \
  --duration 1h \
  --ssh-key ~/.ssh/id_ed25519.pub \
  --save ./rental.json
```

The CLI automatically:

1. Fetches inventory from `/api/inventory`.
2. Selects a rentable matching offer.
3. Computes the maximum x402 authorization from `price_usdc_per_hour * hours`.
4. Signs the x402 `upto` authorization.
5. Retries `POST /api/rent` with the generated payment header.
6. Prints `rental_id`, `recovery_token`, and the SSH command.

## Direct HTTP Flow

First inspect inventory:

```bash
curl -fsS "$API_BASE/inventory"
curl -fsS "$API_BASE/tiers"
curl -fsS "$API_BASE/instances"
```

Use `/api/inventory` for renter decisions. Select an offer where:

- `rentable` is `true`
- `available > 0`
- `state` is `available`
- `price_usdc_per_hour` is acceptable

Start with an unsigned rental request:

```bash
curl -i "$API_BASE/rent" \
  -H 'content-type: application/json' \
  -d '{
    "payment_mode": "x402",
    "gpu_model": "NVIDIA RTX A6000",
    "gpu_count": 1,
    "hours": 1,
    "image": "ubuntu:22.04",
    "ssh_pub_key": "ssh-ed25519 AAAA..."
  }'
```

Expected unsigned response:

- HTTP status `402`
- JSON body with x402 payment requirements
- `PAYMENT-REQUIRED` response header

Then use an x402 client to sign the requirements and retry the same request with an x402 payment header. The web app accepts either:

- `x-payment: <signed-x402-payment>`
- `payment-signature: <signed-x402-payment>`

Successful rental response:

```json
{
  "rental_id": "4d1c836fb43175269bd29eadaad280eb",
  "connection": {
    "ssh_host": "185.216.22.76",
    "ssh_port": 20000,
    "ssh_user": "root"
  },
  "gpu": {
    "model": "NVIDIA RTX A6000",
    "count": 1,
    "vram_gb": 47
  },
  "ttl_seconds": 3600,
  "recovery_token": "...",
  "payment": {
    "scheme": "upto",
    "status": "authorized",
    "max_authorized_usdc": 0.06
  }
}
```

After success, persist at least:

- `rental_id`
- `recovery_token`
- `ssh_host`
- `ssh_port`
- `ssh_user`
- SSH private key path that matches `ssh_pub_key`
- `created_at` and requested `hours`

Connect:

```bash
ssh -p <ssh_port> <ssh_user>@<ssh_host>
```

## Management

Preferred CLI:

```bash
export NODEXO_RENTAL_RECOVERY_TOKEN=...

nodexo --api-url "$API_BASE" rental-info "$RENTAL_ID"
nodexo --api-url "$API_BASE" ssh-config "$RENTAL_ID"
nodexo --api-url "$API_BASE" connect "$RENTAL_ID"
nodexo --api-url "$API_BASE" rental-extend "$RENTAL_ID" --hours 4
nodexo --api-url "$API_BASE" rental-key add "$RENTAL_ID" --ssh-key ~/.ssh/id_ed25519.pub
nodexo --api-url "$API_BASE" rental-end "$RENTAL_ID"
```

`connect` and `ssh-config` use the public `/api/rentals/{id}` route and the
recovery token by default. Do not use validator-direct mode for renter agents.

Account API keys can also manage saved SSH public keys:

```bash
export NODEXO_API_KEY=vc_...

nodexo --api-url "$API_BASE" account-ssh-keys list
nodexo --api-url "$API_BASE" account-ssh-keys add --ssh-key ~/.ssh/id_ed25519.pub --label workstation
nodexo --api-url "$API_BASE" account-ssh-keys remove --key-id <id>
```

Get status:

```bash
curl -fsS "$API_BASE/rentals/$RENTAL_ID" \
  -H "authorization: Bearer $RECOVERY_TOKEN"
```

Terminate:

```bash
curl -fsS -X DELETE "$API_BASE/rentals/$RENTAL_ID" \
  -H "authorization: Bearer $RECOVERY_TOKEN"
```

Extend an x402 rental:

```bash
curl -i "$API_BASE/rentals/$RENTAL_ID/extend" \
  -H "authorization: Bearer $RECOVERY_TOKEN" \
  -H 'content-type: application/json' \
  -d '{ "payment_mode": "x402", "hours": 4 }'
```

The first extend response is also HTTP `402`. Sign it with x402 and retry.

Add an SSH key:

```bash
curl -fsS -X POST "$API_BASE/rentals/$RENTAL_ID/ssh-keys" \
  -H "authorization: Bearer $RECOVERY_TOKEN" \
  -H 'content-type: application/json' \
  -d '{ "ssh_pub_key": "ssh-ed25519 AAAA..." }'
```

Remove an SSH key:

```bash
curl -fsS -X DELETE "$API_BASE/rentals/$RENTAL_ID/ssh-keys" \
  -H "authorization: Bearer $RECOVERY_TOKEN" \
  -H 'content-type: application/json' \
  -d '{ "ssh_pub_key": "ssh-ed25519 AAAA..." }'
```

## Error Handling

- `402`: Payment required or payment verification failed. If the response contains insufficient-funds detail, the wallet needs more USDC on the required network.
- `401` or `403`: Missing or invalid session/recovery token, or attempting to call an internal validator route.
- `404`: Rental is unknown or no longer active.
- `409`: Idempotent request is already in progress. Retry with backoff.
- `429`: Rate limited. Retry with backoff.
- `502` with `provision_failed`: Payment authorization was not settled; retry after inventory recovers.
- `503`: Validator or inventory is temporarily unavailable. Retry with backoff.

On any provisioning failure, do not assume a rental exists unless the response includes `rental_id` and SSH connection details.

## Credit Rentals

Credit rentals use an account API key and debit the account balance while the
machine runs. Create the API key in Account settings, then pass it as a bearer
token. The raw key is shown only once.

Check balance:

```bash
curl -fsS "$API_BASE/credits" \
  -H "authorization: Bearer $NODEXO_API_KEY"
```

List saved account SSH keys:

```bash
curl -fsS "$API_BASE/account/ssh-keys" \
  -H "authorization: Bearer $NODEXO_API_KEY"
```

Create a metered rental:

```bash
curl -fsS -X POST "$API_BASE/rent" \
  -H "authorization: Bearer $NODEXO_API_KEY" \
  -H 'content-type: application/json' \
  -d '{
    "payment_mode": "credits",
    "gpu_model": "NVIDIA RTX A6000",
    "gpu_count": 1,
    "image": "ubuntu:22.04",
    "ssh_pub_key": "ssh-ed25519 AAAA...",
    "storage_gb": 30,
    "memory_gb": 16,
    "idempotency_key": "agent-job-001"
  }'
```

Use the same API key for account-owned rental status, termination, and SSH-key
updates:

```bash
curl -fsS "$API_BASE/rentals/$RENTAL_ID" \
  -H "authorization: Bearer $NODEXO_API_KEY"
```

Recovery tokens still work and should be saved with the rental response so the
rental can be managed even if the API key is revoked.

## Agent Checklist

Before renting:

1. Confirm inventory has a rentable matching offer.
2. Confirm the wallet can spend the maximum requested amount.
3. Confirm the SSH public key is valid and belongs to an accessible private key.
4. Use `hours <= 168` for x402.

After renting:

1. Save `rental_id` and `recovery_token` securely.
2. Print or return the SSH command.
3. Poll `GET /api/rentals/{id}` until status is active and SSH details are present.
4. If the rental is no longer needed, terminate it explicitly.

Final output to a calling agent should include:

```json
{
  "ok": true,
  "rental_id": "...",
  "recovery_token": "...",
  "ssh_command": "ssh -p 20000 root@185.216.22.76",
  "gpu": "1x NVIDIA RTX A6000",
  "hours": 1,
  "max_authorized_usdc": 0.06
}
```
