> For the complete documentation index, see [llms.txt](https://docs.clawcloud.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.clawcloud.co/reference/api-reference.md).

# API reference

{% hint style="warning" %}
This page documents **our internal HTTP API**.

A **public API** will be available later, on demand.
{% endhint %}

### Version

* **Version:** `1.3.0`
* **Last updated:** Feb 3, 2026

### Changelog

#### Version 1.3.0 (Feb 3, 2026)

**🔒 Security enhancements**

**ECC encryption**

* All wallet private keys and SSH keys now use **ECIES** with **secp256k1** (same curve as Ethereum).
* Format: `ecc:<ephemeralPubKey>:<iv>:<authTag>:<ciphertext>`.
* Forward secrecy via ephemeral key agreement.
* Backward compatible with existing unencrypted keys.

**SQL injection prevention**

* All database queries use prepared statements with strict input validation.
* Pattern matching for agent IDs, addresses, token IDs.
* Automatic sanitization of user inputs.
* Detection and blocking of SQL injection patterns.

**Advanced rate limiting**

* Per-IP, per-endpoint tracking.
* Auto-ban after **10 violations within 1 hour**.
* Configurable limits with `X-RateLimit-*` headers.
* Manual ban/unban capabilities for administrators.

**Input validation**

* Comprehensive validation layer.
* Regex pattern matching for all inputs.
* Length validation (agent IDs, addresses, etc.).
* Type checking and range validation.
* XSS prevention for display values.

**⚡ Provisioning updates**

**RunPod integration (Tiers 4-7)**

* Tier 4: NVIDIA GeForce RTX 4090
* Tier 5: NVIDIA A100 40GB PCIe
* Tier 6: NVIDIA A100 80GB PCIe
* Tier 7: NVIDIA H100 PCIe
* Docker image support with PyTorch 2.1 and CUDA 11.8.
* Automated SSH configuration.

**Vultr integration (Tiers 0-3)**

* Tier 0: 1vCPU, 1GB RAM
* Tier 1: 1vCPU, 2GB RAM
* Tier 2: 2vCPU, 4GB RAM
* Tier 3: 4vCPU, 8GB RAM
* Cloud-init automation.
* Firewall pre-configuration.

**SSH key management**

* RSA 4096-bit key generation per VM.
* Automated public key deployment.
* ECC-encrypted private key storage.
* One-time credential delivery.

**📊 Logging & monitoring**

**Security audit logging**

* SQL injection attempts logged to `security.log`.
* Rate limit violations tracked with IP.
* Authentication failures recorded.
* All events timestamped with ISO 8601 format.

**Structured logging**

* JSON-formatted logs for all events.
* Separate logs: `combined.log`, `error.log`, `security.log`.
* Automatic log rotation (5MB max, 5 files).
* Debug mode for development environments.

**💰 Payment protocol**

**x402 support (beta)**

* HTTP-native cryptocurrency payments.
* Routes: `/x402/vm-credentials`, `/x402/purchase-compute`.
* Network: Base Sepolia (testnet) or Base Mainnet.
* Pay-per-request model for API access.
* Integration with the x402.org facilitator.

**🔧 Infrastructure**

**Provider redundancy**

* Vultr for VMs (US East, US West, Europe, Asia regions).
* RunPod for GPUs (community cloud network).
* Automatic failover and retry logic.

**Error handling**

* Failed provisioning logged to `failed_provisionings` table.
* Retry logic with exponential backoff.
* Detailed error messages for debugging.

**📝 Database schema**

New tables:

* `failed_provisionings`: Tracks provisioning failures.
* Enhanced `vms` table with `vm_type` and `instance_id` columns.
* `agent_wallets`: ECC-encrypted wallet storage.

**Breaking changes**

None. Fully backward compatible with v1.0.0.

**Migration notes**

* Existing wallets remain accessible.
* No API endpoint changes.
* New security features auto-enabled.
* Rate limits apply to all clients (see updated limits below).

**Updated rate limits (v1.3.0)**

Endpoint limits:

* `/health`: unlimited
* `/tiers`: `100 requests / 1 minute`
* `/credentials/:tokenId`: `30 requests / 1 hour`
* `/vms/:address`: `30 requests / 1 minute`
* `/status/:tokenId`: `100 requests / 1 minute`
* `/agents/generate-wallet`: `3 requests / 1 minute`
* `/admin/*` (authenticated): `20 requests / 1 minute`

Auto-ban policy:

* 10+ violations within 1 hour results in automatic IP ban (1 hour duration).

**Security best practices (v1.3.0)**

* **API keys:** Store admin API keys securely. Never commit to version control.
* **Signatures:** Generate fresh signatures for each request.
* **Rate limits:** Implement exponential backoff on `429` responses.
* **SSL/TLS:** Always use HTTPS endpoints in production.
* **Key rotation:** Rotate admin API keys periodically (every 90 days recommended).

#### Version 1.0.0 (Feb 2, 2026)

* Initial release.
* Basic VM provisioning.
* NFT-based access control.
* Wallet signature authentication.

### Base URLs

* **Primary:** `https://api.clawcloud.co`
* **Alternative:** `https://clawcloud-backend-railway-production.up.railway.app`

### Overview

ClawCloud provides decentralized cloud infrastructure where AI agents can:

* Purchase VMs with **USDC** on **Base**.
* Receive ownership as **ERC-721 NFTs**.
* Access provisioned VMs via **SSH**.
* Manage compute resources autonomously.

Purchases happen on-chain. This API surfaces provisioning state and VM access.

#### On-chain context

* **Network:** Base Mainnet
* **Contract:** `0xF708741D37C420518852c6A15aB658066951c852`
* **USDC (Base):** `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`

### Authentication

Most endpoints are public. Sensitive endpoints use **wallet signature auth**.

#### Bearer token format

Send a wallet signature as:

* `Authorization: Bearer {signature}`

#### Message format

Sign this exact message:

* `"ClawCloud Access Request: {tokenId}"`

Example:

* Message: `"ClawCloud Access Request: 42"`
* Sign with the wallet that owns NFT `#42`.

### Endpoints

#### Health check

Check API status and connectivity.

* **Method:** `GET`
* **Path:** `/health`
* **Auth:** none
* **Rate limit:** none

{% code title="Response (200)" %}

```json
{
  "status": "ok",
  "service": "clawcloud-api"
}
```

{% endcode %}

{% code title="cURL" %}

```bash
curl https://api.clawcloud.co/health
```

{% endcode %}

#### Get tiers

Retrieve VM tier configurations and pricing (derived from the contract).

* **Method:** `GET`
* **Path:** `/tiers`
* **Auth:** none
* **Rate limit:** `100/minute` per IP

{% code title="Response (200)" %}

```json
{
  "tiers": [
    {
      "tier": 0,
      "name": "CPU-Basic-1vCPU-1GB",
      "pricePerDay": "0.50",
      "pricePerMonth": "15.00",
      "active": true
    },
    {
      "tier": 1,
      "name": "CPU-Standard-2vCPU-4GB",
      "pricePerDay": "1.00",
      "pricePerMonth": "30.00",
      "active": true
    }
  ]
}
```

{% endcode %}

Fields:

* `tier` (number). Tier index (`0-7`).
* `name` (string). VM spec name.
* `pricePerDay` (string). Price in USDC per day.
* `pricePerMonth` (string). Price in USDC for 30 days.
* `active` (boolean). Tier availability.

{% code title="cURL" %}

```bash
curl https://api.clawcloud.co/tiers
```

{% endcode %}

#### Get VM credentials

Retrieve SSH credentials for a VM you own.

* **Method:** `GET`
* **Path:** `/credentials/:tokenId`
* **Auth:** required (Bearer signature)
* **Rate limit:** `30/hour` per IP

Path params:

* `tokenId` (required). NFT token ID.

Headers:

* `Authorization: Bearer {signature}`

{% code title="Response (200) — VM ready" %}

```json
{
  "tokenId": "42",
  "host": "rentals-xxxxx.ssh.deployments.targon.com",
  "username": "root",
  "privateKey": null,
  "tier": 4,
  "type": "gpu-external",
  "expiresAt": "2026-02-05T00:00:00.000Z",
  "instructions": "ssh rentals-xxxxx.ssh.deployments.targon.com"
}
```

{% endcode %}

{% code title="Response (202) — provisioning" %}

```json
{
  "status": "provisioning",
  "message": "VM is being provisioned. Try again in 2-3 minutes."
}
```

{% endcode %}

Status codes:

* `200` VM ready
* `202` provisioning in progress
* `401` invalid or missing signature
* `403` not the owner, or NFT expired
* `404` VM not found

Fields:

* `tokenId` (string). NFT token ID.
* `host` (string). SSH hostname or IP.
* `username` (string). Usually `root`.
* `privateKey` (string|null). Present for GCP VMs. `null` for GPU external.
* `tier` (number). Tier (`0-7`).
* `type` (string). `gcp` or `gpu-external`.
* `expiresAt` (string). ISO 8601 timestamp.
* `instructions` (string). SSH command.

{% code title="cURL" %}

```bash
SIGNATURE="0x..." # wallet signature
TOKEN_ID="42"

curl -H "Authorization: Bearer $SIGNATURE" \
  https://api.clawcloud.co/credentials/$TOKEN_ID
```

{% endcode %}

#### List user VMs

List all VMs owned by a wallet address.

* **Method:** `GET`
* **Path:** `/vms/:address`
* **Auth:** none
* **Rate limit:** `30/minute` per IP

Path params:

* `address` (required). Wallet address (`0x...`).

{% code title="Response (200)" %}

```json
{
  "address": "0x1234567890123456789012345678901234567890",
  "count": 3,
  "vms": [
    {
      "token_id": 42,
      "tier": 4,
      "vm_type": "gpu-external",
      "ssh_host": "rentals-xxxxx.ssh.deployments.targon.com",
      "status": "running",
      "created_at": "2026-02-01T12:00:00.000Z",
      "expires_at": "2026-02-05T12:00:00.000Z"
    }
  ]
}
```

{% endcode %}

Fields:

* `address` (string). Queried wallet.
* `count` (number). VM count.
* `vms` (array). VM objects.

VM object:

* `token_id` (number). NFT token ID.
* `tier` (number). Tier (`0-7`).
* `vm_type` (string). `gcp` or `gpu-external`.
* `ssh_host` (string). SSH hostname.
* `status` (string). `provisioning`, `running`, `terminated`, `expired`.
* `created_at` (string). ISO 8601 timestamp.
* `expires_at` (string). ISO 8601 timestamp.

{% code title="cURL" %}

```bash
ADDRESS="0x1234567890123456789012345678901234567890"
curl https://api.clawcloud.co/vms/$ADDRESS
```

{% endcode %}

#### Get VM status

Get public status for a VM.

* **Method:** `GET`
* **Path:** `/status/:tokenId`
* **Auth:** none
* **Rate limit:** `100/minute` per IP

{% code title="Response (200)" %}

```json
{
  "tokenId": "42",
  "status": "running",
  "tier": 4,
  "type": "gpu-external",
  "expiresAt": "2026-02-05T12:00:00.000Z",
  "owner": "0x1234567890123456789012345678901234567890"
}
```

{% endcode %}

{% code title="cURL" %}

```bash
curl https://api.clawcloud.co/status/42
```

{% endcode %}

### Smart contract

Contract address (Base Mainnet):

* `0xF708741D37C420518852c6A15aB658066951c852`

Key functions:

* `purchaseVM(uint8 tier, uint16 durationDays)`
* `isTokenValid(uint256 tokenId) view returns (bool)`
* `ownerOf(uint256 tokenId) view returns (address)`
* `getTierConfig(uint8 tier) view returns (uint256, bool, string)`

Purchase flow:

1. Read tier price via `getTierConfig()`.
2. Calculate total cost: `price * durationDays`.
3. Approve USDC: `usdc.approve(contract, totalCost)`.
4. Purchase: `purchaseVM(tier, durationDays)`.
5. Wait \~2–3 minutes for provisioning.
6. Fetch SSH credentials via `GET /credentials/:tokenId`.

Event:

* `VMPurchased(tokenId, buyer, tier, durationDays, purchaseDate, totalCost)`

### Response codes

Success:

* `200` OK
* `202` Accepted

Client errors:

* `400` Bad Request
* `401` Unauthorized
* `403` Forbidden
* `404` Not Found
* `429` Too Many Requests

Server errors:

* `500` Internal Error
* `502` Bad Gateway
* `503` Service Unavailable

### Rate limits

Limits (per IP):

* `/health`: unlimited
* `/tiers`: `100/minute`
* `/credentials/:tokenId`: `30/hour`
* `/vms/:address`: `30/minute`
* `/status/:tokenId`: `100/minute`
* `/agents/generate-wallet`: `3/minute`
* `/admin/*` (authenticated): `20/minute`

Auto-ban policy:

* **10+ violations within 1 hour** results in an automatic IP ban.
* Ban duration: **1 hour**.

Headers (returned when rate-limited):

* `X-RateLimit-Limit`
* `X-RateLimit-Remaining`
* `X-RateLimit-Reset`

{% code title="Response (429)" %}

```json
{
  "error": "Rate limit exceeded",
  "retryAfter": 42
}
```

{% endcode %}

Best practices:

* Cache tier pricing. It changes rarely.
* Use exponential backoff on `429`.
* Read and respect rate limit headers.
* Store admin API keys securely. Never commit them.
* Rotate admin API keys periodically (every 90 days recommended).
* Always use HTTPS in production.
* Generate fresh signatures per request.

### Examples

#### Check available tiers

{% code title="cURL" %}

```bash
curl https://api.clawcloud.co/tiers | jq
```

{% endcode %}

<details>

<summary>Purchase a VM (ethers.js)</summary>

```javascript
const { ethers } = require('ethers');

// Setup
const provider = new ethers.JsonRpcProvider('https://mainnet.base.org');
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);

const contractAddress = '0xF708741D37C420518852c6A15aB658066951c852';
const usdcAddress = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';

// Contract ABIs
const contractABI = [
  'function purchaseVM(uint8 tier, uint16 durationDays) returns (uint256)',
  'function getTierConfig(uint8 tier) view returns (uint256, bool, string)'
];

const usdcABI = [
  'function approve(address spender, uint256 amount) returns (bool)'
];

const contract = new ethers.Contract(contractAddress, contractABI, wallet);
const usdc = new ethers.Contract(usdcAddress, usdcABI, wallet);

// Get pricing
const tier = 4;
const days = 7;
const [pricePerDay] = await contract.getTierConfig(tier);
const totalCost = pricePerDay * BigInt(days);

// Approve USDC
const approveTx = await usdc.approve(contractAddress, totalCost);
await approveTx.wait();

// Purchase VM
const purchaseTx = await contract.purchaseVM(tier, days);
const receipt = await purchaseTx.wait();

// Get token ID from event
const event = receipt.logs.find(
  log => log.topics[0] === contract.interface.getEvent('VMPurchased').topicHash
);
const tokenId = ethers.toNumber(event.topics[1]);

console.log(`VM purchased! Token ID: ${tokenId}`);
```

</details>

<details>

<summary>Get VM credentials (ethers.js)</summary>

```javascript
const tokenId = 42;

// Sign authentication message
const message = `ClawCloud Access Request: ${tokenId}`;
const signature = await wallet.signMessage(message);

// Call API
const response = await fetch(
  `https://api.clawcloud.co/credentials/${tokenId}`,
  {
    headers: {
      'Authorization': `Bearer ${signature}`
    }
  }
);

const data = await response.json();

if (response.status === 202) {
  console.log('VM still provisioning, try again in 2 minutes');
} else if (response.ok) {
  console.log('SSH Command:', data.instructions);
  console.log('Host:', data.host);
  console.log('Expires:', data.expiresAt);
}
```

</details>

<details>

<summary>Complete agent flow (Python)</summary>

```python
from web3 import Web3
from eth_account.messages import encode_defunct
import requests
import time

# Setup
w3 = Web3(Web3.HTTPProvider('https://mainnet.base.org'))
account = w3.eth.account.from_key(PRIVATE_KEY)

contract_address = '0xF708741D37C420518852c6A15aB658066951c852'
usdc_address = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'

# Purchase VM
tier = 4
days = 7

# Get price
contract = w3.eth.contract(address=contract_address, abi=CONTRACT_ABI)
price_per_day, active, name = contract.functions.getTierConfig(tier).call()
total_cost = price_per_day * days

# Approve USDC
usdc = w3.eth.contract(address=usdc_address, abi=USDC_ABI)
approve_tx = usdc.functions.approve(contract_address, total_cost).build_transaction({
  'from': account.address,
  'nonce': w3.eth.get_transaction_count(account.address)
})
signed = account.sign_transaction(approve_tx)
w3.eth.send_raw_transaction(signed.rawTransaction)

# Purchase
purchase_tx = contract.functions.purchaseVM(tier, days).build_transaction({
  'from': account.address,
  'nonce': w3.eth.get_transaction_count(account.address)
})
signed = account.sign_transaction(purchase_tx)
tx_hash = w3.eth.send_raw_transaction(signed.rawTransaction)
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)

# Get token ID from event
token_id = receipt['logs'][0]['topics'][1]
print(f"Purchased VM! Token ID: {int(token_id.hex(), 16)}")

# Wait for provisioning
time.sleep(180)

# Get credentials
message = f"ClawCloud Access Request: {token_id}"
signed_message = account.sign_message(encode_defunct(text=message))
signature = signed_message.signature.hex()

response = requests.get(
  f"https://api.clawcloud.co/credentials/{token_id}",
  headers={'Authorization': f'Bearer {signature}'}
)

if response.status_code == 200:
  data = response.json()
  print(f"SSH: {data['instructions']}")
  print(f"Expires: {data['expiresAt']}")
else:
  print(f"Error: {response.json()}")
```

</details>

### Support

* Contract explorer: `https://basescan.org/address/0xF708741D37C420518852c6A15aB658066951c852`


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.clawcloud.co/reference/api-reference.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
