API Reference

ClawBloc provides a REST API for programmatic file uploads to Arweave with optional Solana hash verification. Authenticate with an API key and start uploading.

Authentication

All API endpoints require authentication. Pass your API key in one of two ways:

Option 1: x-api-key header
curl -H "x-api-key: cb_sk_your_key_here" \
  https://clawbloc.com/api/v1/uploads
Option 2: Authorization header
curl -H "Authorization: Bearer cb_sk_your_key_here" \
  https://clawbloc.com/api/v1/uploads

Generate API keys from your dashboard. Keys start with cb_sk_ and are shown only once at creation.

Upload File

POST/api/v1/upload

Upload a file to Arweave. Optionally register the hash on Solana or mint an Agent NFT.

Request Body (multipart/form-data)

FieldTypeRequiredDescription
filebinaryYesThe file to upload (max 100 MB)
tierstringNoraw | hash_registry | agent_nft (default: raw)
agent_namestringNoRequired for agent_nft tier
encryptedbooleanNoSet to true if file was client-side encrypted (Basic/Pro only)
payment_txstringNoSolana TX signature for pay-per-upload
curl
curl -X POST https://clawbloc.com/api/v1/upload \
  -H "x-api-key: cb_sk_your_key_here" \
  -F "file=@./memory.json" \
  -F "tier=hash_registry"
Response (200)
{
  "id": "a1b2c3d4-...",
  "file_name": "memory.json",
  "file_hash": "sha256:abc123...",
  "file_size_bytes": 1234,
  "tier": "hash_registry",
  "status": "complete",
  "arweave_tx_id": "AbCdEf...",
  "arweave_url": "https://arweave.net/AbCdEf...",
  "solana_hash_tx": "5xKm9...",
  "nft_mint_address": null,
  "encrypted": false,
  "cost_lamports": 60000,
  "payment_tx": null
}

Note: cost_lamports is denominated in micro-USDC (6 decimals). Divide by 1,000,000 to get the USDC amount.

Client-Side Encryption

ClawBloc supports optional client-side AES-256-GCM encryption for uploads. Files are encrypted in your browser before leaving your device — the encryption key is derived from your wallet signature and is never stored anywhere.

How It Works

  1. Your wallet signs the message ClawBloc Encryption Key v1
  2. The signature is SHA-256 hashed to produce a 256-bit AES key
  3. The file is encrypted with AES-256-GCM using a random 12-byte IV
  4. The IV is prepended to the ciphertext and uploaded to Arweave
  5. To decrypt, the same wallet signs the same message to re-derive the key

Upload with encryption (API)

curl
curl -X POST https://clawbloc.com/api/v1/upload \
  -H "x-api-key: cb_sk_your_key_here" \
  -F "file=@./encrypted-data.bin" \
  -F "tier=hash_registry" \
  -F "encrypted=true"

When using the API directly, you must encrypt the file yourself before uploading and pass encrypted=true. The dashboard handles this automatically.

PropertyDetail
AlgorithmAES-256-GCM
IV size12 bytes (96-bit), random per file
Key derivationSHA-256(wallet_signature)
Key storageNone — derived on demand
AvailabilityBasic and Pro plans only

Important: If you lose access to your wallet, encrypted files cannot be decrypted. There is no recovery mechanism — only the original signing wallet can derive the decryption key.

List Uploads

GET/api/v1/uploads

List your uploads with pagination and optional status filtering.

Query Parameters

ParamDefaultDescription
limit20Results per page (max 100)
offset0Number of results to skip
statusallFilter: complete, failed, pending, uploading, processing
curl
curl "https://clawbloc.com/api/v1/uploads?limit=10&status=complete" \
  -H "x-api-key: cb_sk_your_key_here"
Response (200)
{
  "data": [
    {
      "id": "a1b2c3d4-...",
      "file_name": "memory.json",
      "file_hash": "sha256:abc123...",
      "file_size_bytes": 1234,
      "tier": "raw",
      "status": "complete",
      "arweave_tx_id": "AbCdEf...",
      "arweave_url": "https://arweave.net/AbCdEf...",
      "solana_hash_tx": null,
      "nft_mint_address": null,
      "cost_lamports": 60000,
      "created_at": "2026-03-01T00:00:00Z"
    }
  ],
  "total": 42,
  "limit": 10,
  "offset": 0
}

Upload Detail

GET/api/v1/uploads/:id

Get full details for a single upload by its ID.

curl
curl https://clawbloc.com/api/v1/uploads/a1b2c3d4-... \
  -H "x-api-key: cb_sk_your_key_here"
Response (200)
{
  "data": {
    "id": "a1b2c3d4-...",
    "file_name": "memory.json",
    "file_hash": "sha256:abc123...",
    "file_size_bytes": 1234,
    "mime_type": "application/json",
    "tier": "hash_registry",
    "status": "complete",
    "arweave_tx_id": "AbCdEf...",
    "arweave_url": "https://arweave.net/AbCdEf...",
    "solana_hash_tx": "5xKm9...",
    "nft_mint_address": null,
    "cost_lamports": 60000,
    "payment_tx": null,
    "error_message": null,
    "created_at": "2026-03-01T00:00:00Z",
    "updated_at": "2026-03-01T00:00:05Z"
  }
}

Delete Failed Uploads

DELETE/api/v1/uploads?status=failed

Delete all failed upload records for your account.

curl
curl -X DELETE "https://clawbloc.com/api/v1/uploads?status=failed" \
  -H "x-api-key: cb_sk_your_key_here"
Response (200)
{
  "deleted": 4,
  "message": "Deleted 4 failed upload(s)"
}

Error Codes

StatusMeaning
400Bad request — missing or invalid parameters
401Unauthorized — invalid or missing API key
402Payment required — upload payment not confirmed
403Forbidden — storage limit exceeded or tier not allowed
404Not found — upload does not exist
409Conflict — duplicate payment transaction
413Payload too large — file exceeds 100 MB
429Too many requests — rate limit exceeded (see Retry-After header)
500Internal server error

Rate Limits

PlanRequests/minStorageAPI KeysUpload Tiers
Free1050 MB1raw
Basic (5 USDC/mo)60500 MB5raw, hash_registry
Pro (50 USDC/mo)1,00050 GBUnlimitedraw, hash_registry, agent_nft

Max file size: 100 MB per upload for all plans.

Code Examples

JavaScript / Node.js

upload.js
const fs = require('fs');

const API_KEY = 'cb_sk_your_key_here';
const BASE_URL = 'https://clawbloc.com/api/v1';

// Upload a file
async function upload(filePath, tier = 'raw') {
  const form = new FormData();
  form.append('file', new Blob([fs.readFileSync(filePath)]));
  form.append('tier', tier);

  const res = await fetch(`${BASE_URL}/upload`, {
    method: 'POST',
    headers: { 'x-api-key': API_KEY },
    body: form,
  });

  return res.json();
}

// List uploads
async function listUploads(limit = 20) {
  const res = await fetch(
    `${BASE_URL}/uploads?limit=${limit}`,
    { headers: { 'x-api-key': API_KEY } }
  );
  return res.json();
}

// Usage
const result = await upload('./memory.json', 'hash_registry');
console.log('Arweave URL:', result.arweave_url);
console.log('Solana TX:', result.solana_hash_tx);

Python

upload.py
import requests

API_KEY = "cb_sk_your_key_here"
BASE_URL = "https://clawbloc.com/api/v1"
HEADERS = {"x-api-key": API_KEY}

# Upload a file
def upload(file_path, tier="raw"):
    with open(file_path, "rb") as f:
        res = requests.post(
            f"{BASE_URL}/upload",
            headers=HEADERS,
            files={"file": f},
            data={"tier": tier},
        )
    return res.json()

# List uploads
def list_uploads(limit=20, status=None):
    params = {"limit": limit}
    if status:
        params["status"] = status
    res = requests.get(
        f"{BASE_URL}/uploads",
        headers=HEADERS,
        params=params,
    )
    return res.json()

# Usage
result = upload("./memory.json", tier="hash_registry")
print("Arweave URL:", result.get("arweave_url"))
print("Solana TX:", result.get("solana_hash_tx"))