---
title: "Wallet Automation | 0xArchive Docs"
description: "Automate wallet-based signup, SIWE auth, API key creation, and x402 billing flows from scripts that start with a wallet."
canonical_url: "https://www.0xarchive.io/docs/wallet-automation/"
markdown_url: "https://www.0xarchive.io/docs/wallet-automation.md"
route: "/docs/wallet-automation"
robots: "index, follow"
generated_from: "prerendered_html"
---

# Wallet Automation

SIWE signup, wallet-managed keys, and x402 billing for scripts that run from a wallet.

Starts with SIWE challenge Returns Fresh API keys Billing x402 on Base

[Runbook](https://www.0xarchive.io/docs/wallet-automation/#runbook)

[Key endpoints](https://www.0xarchive.io/docs/wallet-automation/#wallet-automation-endpoints)

Wallet automation covers SIWE signup, wallet-managed keys, and x402 billing.

Dashboard-managed `X-API-Key` is still the simplest option. Use [SIWE](https://eips.ethereum.org/EIPS/eip-4361) and [x402](https://www.x402.org/) when the code itself owns signup, key lifecycle, or payment without a browser session.

## Where wallet auth fits

Wallet auth solves a specific job: the code owns signup, keys, or billing.

Use this if

### The code owns signup, keys, or billing

This is the right fit when a script has to create an account, list or revoke keys, or upgrade tiers without the dashboard.

Skip it if

### A normal API key already solves the job

Dashboard-managed keys are simpler. Use wallet auth when you need wallet ownership, not just because it exists.

## Runbook

Go from SIWE challenge to live API key, then add x402 if you need a paid tier.

1. 1 0xArchive Get a SIWE challenge POST /auth/web3/challenge with the agent's wallet address. Returns a message to sign. `POST /v1/auth/web3/challenge`
2. 2 Wallet Sign the SIWE message locally The private key never leaves the wallet runtime. Only the signature is sent over the wire. `personal_sign`
3. 3 0xArchive Create the account and first key Submit the signed message to /web3/signup and receive an API key you can use immediately. `POST /v1/web3/signup`
4. 4 operator Call a live route with X-API-Key Use the returned key on the same REST, CLI, or AI-client paths as any dashboard-managed key. `GET /v1/hyperliquid/summary/BTC`
5. 5 0xArchive Request an x402 quote when needed POST /web3/subscribe with the target tier. The server returns a 402 payment quote with Base USDC details. `POST /v1/web3/subscribe`
6. 6 Wallet Sign the USDC authorization Create the EIP-3009 transferWithAuthorization payload locally, then retry the subscribe call with the payment signature header. `payment-signature header`
7. 7 0xArchive Switch to the returned key Every paid subscribe response returns a fresh API key. Downstream clients and scripts should adopt the new key immediately. `{ api_key, tier, expires_at, tx_hash }`

## Operational jobs

Publicly supported jobs: bootstrap, key lifecycle, and paid-tier changes.

### Bootstrap account + key

Goal Create the account and get the first usable API key from a wallet alone. Command or route `POST /v1/auth/web3/challenge -> sign message -> POST /v1/web3/signup` Expected output A live api_key and tier are returned immediately. Next step Use the key with REST, CLI, or AI Clients exactly as you would a dashboard-managed key.

[Open AI Clients](https://www.0xarchive.io/docs/ai-clients/)

### List or revoke keys

Goal Inspect active keys or invalidate one without opening the dashboard. Command or route `POST /v1/web3/keysPOST /v1/web3/keys/revoke` Expected output Current key inventory or a revoked key ID you can audit downstream. Next step Rotate scripts and clients to the surviving key before the revoked one is used again.

[Open Authentication](https://www.0xarchive.io/docs/authentication/#wallet-auth)

### Upgrade or renew with x402

Goal Move to Build or Pro, renew the current tier, or queue a lower tier after expiry rules are applied. Command or route `POST /v1/web3/subscribe -> receive 402 -> sign EIP-3009 authorization -> retry with payment-signature` Expected output A fresh api_key, updated tier, expiry, and tx_hash prove the change. Next step Adopt the returned key in AI Clients or CLI so the upgraded entitlement is the one actually in use.

[Open CLI](https://www.0xarchive.io/docs/cli/)

## Code examples

Get signup and first-key creation working first. Add x402 after that.

TypeScript signup

TypeScript

```
import { privateKeyToAccount } from 'viem/accounts';
import { createWalletClient, http } from 'viem';
import { mainnet } from 'viem/chains';

const API = 'https://api.0xarchive.io/v1';
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);

// Step 1: Get SIWE challenge
const { message, nonce } = await fetch(`${API}/auth/web3/challenge`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ address: account.address }),
}).then(r => r.json());

// Step 2: Sign and submit
const signature = await account.signMessage({ message });
const { api_key, tier } = await fetch(`${API}/web3/signup`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ message, signature }),
}).then(r => r.json());

console.log(`API key: ${api_key} (tier: ${tier})`);
```

Python signup

Python

```
from eth_account import Account
from eth_account.messages import encode_defunct
import requests, os

API = "https://api.0xarchive.io/v1"
account = Account.from_key(os.environ["PRIVATE_KEY"])

# Step 1: Get SIWE challenge
resp = requests.post(f"{API}/auth/web3/challenge",
    json={"address": account.address})
data = resp.json()

# Step 2: Sign and submit
sig = account.sign_message(
    encode_defunct(text=data["message"]))
resp = requests.post(f"{API}/web3/signup",
    json={"message": data["message"],
           "signature": sig.signature.hex()})
result = resp.json()
print(f"API key: {result['api_key']} (tier: {result['tier']})")
```

x402 subscribe

Python

```
# Step 1: Request pricing (returns 402)
resp = requests.post(f"{API}/web3/subscribe",
    json={"tier": "build"})
# resp.status_code == 402
payment_info = resp.json()["payment"]
# { amount: "49000000", asset: "USDC", network: "eip155:8453",
#   pay_to: "0x...", asset_address: "0x8335..." }

# Step 2: Sign EIP-3009 transferWithAuthorization
# (see x402 spec for full signing flow)
# Then retry with payment header:
resp = requests.post(f"{API}/web3/subscribe",
    headers={"payment-signature": base64_payment},
    json={"tier": "build"})
result = resp.json()
# { api_key: "0xa_live_...", tier: "build",
#   expires_at: "2026-04-06T...", tx_hash: "0x..." }
```

## Endpoints

| Method | Path | Description |
| --- | --- | --- |
| `POST` | `/v1/auth/web3/challenge` | Get a SIWE nonce to sign (10 min TTL) |
| `POST` | `/v1/web3/signup` | Create account + first API key from a signed SIWE message |
| `POST` | `/v1/web3/keys` | List active API keys for the wallet |
| `POST` | `/v1/web3/keys/revoke` | Revoke an API key by ID with a fresh signed request |
| `POST` | `/v1/web3/subscribe` | Subscribe to Build/Pro via x402 (USDC on Base) and return a fresh API key |

## Pricing

SIWE signup is free. Paid tiers are optional and activate through x402.

| Tier | Price | Duration | Payment |
| --- | --- | --- | --- |
| Free | $0 | Unlimited | SIWE signup only |
| Build | $49 USDC | 30 days | x402 (USDC on Base) |
| Pro | $199 USDC | 30 days | x402 (USDC on Base) |

## Renewals and tier changes

A script can call /web3/subscribe at any time. The server decides whether the purchase renews, upgrades, or queues.

| Scenario | Example | Behavior |
| --- | --- | --- |
| Same-tier renewal | Build (15 days left) → Buy Build again | Extends from current expiry. New expiry = old expiry + 30 days (45 days total remaining). A new API key is returned. |
| Upgrade to higher tier | Build (15 days left) → Buy Pro | Applies immediately. Remaining Build days carry forward: new expiry = old expiry + 30 days. Unused credits from Build are added as bonus credits on Pro. A new API key is returned. |
| Lower-tier purchase (active plan) | Pro (15 days left) → Buy Build | Queued. You keep Pro for remaining 15 days, then automatically transition to Build for 30 days. A new API key is returned. |
| Purchase after expiry | Build (expired) → Buy Build or Pro | Applies immediately. New period starts from now for 30 days. A new API key is returned. |
| Free → Paid | Free → Buy Build | Applies immediately. 30-day subscription starts from now. A new API key is returned. |

The `expires_at` field always reflects the updated post-purchase state. Every purchase returns a fresh API key.

## Security

Keep the security model boring and explicit: fresh signatures, local private keys, domain validation, and no session tokens.

- **No reusable sessions** — every request requires a fresh SIWE signature, so the server does not mint a reusable auth token.
- **Single-use nonces** — challenge nonces are consumed atomically, address-bound, and expire after 10 minutes.
- **Domain-locked validation** — SIWE messages are validated against the server domain to reduce replay risk.
- **Private key stays local** — only signatures and payment payloads cross the network.
- **Shared auth guardrails** — wallet endpoints still sit behind the auth rate limiter, so scripts must handle retries and failures conservatively.

### Where to use wallet auth next

[AI Clients Drop the returned API key into Claude Code or MCP.](https://www.0xarchive.io/docs/ai-clients/)

[CLI Use the same key in shell scripts, cron, CI, or incident tooling.](https://www.0xarchive.io/docs/cli/)

[REST API docs Open route details, parameters, credits, and schemas.](https://www.0xarchive.io/docs/rest-api/)
