# wallet.prim.sh Agent wallets. Generate keys, hold USDC on Base, and pay any x402 invoice. Base URL: https://wallet.prim.sh Auth: x402 (USDC on Base Sepolia). GET /, GET /pricing, GET /v1/metrics are free. Chain: Base Sepolia (eip155:84532) during beta. Install: curl -fsSL https://wallet.prim.sh/install.sh | sh Limits: Max wallets per owner: 100 --- ## Quick Start 1. POST /v1/wallets with EIP-191 signature → register wallet (free) 2. POST faucet.prim.sh/v1/faucet/usdc → get 10 test USDC 3. Call any paid endpoint → receive 402 → sign payment → resend ## Tips - Wallet registration is free — no x402 payment required. - The signed message must be: Register
with prim.sh at - Timestamp must be within 5 minutes of server time (ISO 8601 UTC). - Use @x402/fetch or any x402-compatible client to handle payments automatically. - Pause a wallet to temporarily block spending without deactivating it. --- ## x402 Payment 1. Make request. Server returns 402 with Payment-Required header. 2. Sign EIP-3009 transferWithAuthorization. 3. Retry with Payment-Signature header (base64-encoded signed authorization). Error envelope: {"error": {"code": "", "message": ""}} Error codes: not_found forbidden insufficient_balance wallet_paused policy_violation duplicate_request invalid_request not_implemented --- ## Endpoints ### GET / Health check. Free. Response (200): service string "wallet.sh" status string "ok" --- ### GET /pricing Machine-readable pricing for all endpoints. Free. Response (200): service string "wallet.prim.sh" currency string "USDC" network string "eip155:8453" routes array Route pricing list .method string HTTP method .path string URL path .price_usdc string Price in USDC (decimal string) .description string Human-readable description --- ### GET /v1/metrics Operational metrics. Uptime, request counts, latency percentiles, error rates. Free. Response (200): service string "wallet.prim.sh" uptime_s number Seconds since last restart requests object Request counts and latencies by endpoint payments object Payment counts by endpoint errors object Error counts by status code --- ### POST /v1/wallets Register a wallet via EIP-191 signature Free. No x402 required. Sign message: Register
with prim.sh at Request: address string required Ethereum address to register (0x... 42 chars, checksummed). signature string required EIP-191 signature over "Register
with prim.sh at ". timestamp string required ISO 8601 UTC timestamp used in the signed message. Must be within 5 minutes of server time. chain string optional Chain identifier. Default "base". label string optional Human-readable label for this wallet. Response (201): address string Registered Ethereum address. chain string Chain identifier. label string | null Label if provided, null otherwise. registered_at string ISO 8601 timestamp when the wallet was registered. created_at string ISO 8601 timestamp when the record was created. Errors: 400 invalid_request Missing fields or invalid signature format 403 forbidden Signature does not match address 409 duplicate_request Wallet already registered --- ### GET /v1/wallets List registered wallets owned by the calling wallet Price: $0.001 Query params: limit integer optional 1-100, default 20 after string optional Cursor from previous response Response (200): WalletListResponse Errors: 402 payment_required x402 payment needed 403 forbidden No wallet address in payment 429 rate_limited Too many requests --- ### GET /v1/wallets/:address Get full wallet details including balance, policy, and status Price: $0.001 Path params: address string required address parameter Response (200): address string Ethereum address. chain string Chain identifier. balance string USDC balance as a decimal string. funded boolean Whether the wallet has ever been funded. paused boolean Whether the wallet is currently paused. created_by string Address that registered this wallet (or self). policy SpendingPolicy | null Spending policy, null if none configured. created_at string ISO 8601 timestamp when the wallet was created. Errors: 402 payment_required x402 payment needed 403 forbidden Caller does not own this wallet 404 not_found Wallet not found --- ### DELETE /v1/wallets/:address Permanently deactivate a wallet. Irreversible. Pending fund requests cancelled. Price: $0.01 Path params: address string required address parameter Response (200): address string Deactivated Ethereum address. deactivated boolean Always true on success. deactivated_at string ISO 8601 timestamp of deactivation. Errors: 402 payment_required x402 payment needed 403 forbidden Caller does not own this wallet 404 not_found Wallet not found --- ### POST /v1/wallets/:address/fund-request Request USDC funding for a wallet. A human operator can approve or deny. Price: $0.001 Path params: address string required address parameter Request: amount string required Requested USDC amount as a decimal string (e.g. "10.00"). reason string required Human-readable reason for the funding request. Response (200): id string Fund request ID (e.g. "fr_abc123"). wallet_address string Wallet address the request is for. amount string Requested USDC amount as a decimal string. reason string Reason provided by the requester. status FundRequestStatus Current status of the fund request. created_at string ISO 8601 timestamp when the request was created. Errors: 400 invalid_request Missing amount or reason 402 payment_required x402 payment needed 403 forbidden Caller does not own this wallet 404 not_found Wallet not found --- ### GET /v1/wallets/:address/fund-requests List all fund requests for a wallet Price: $0.001 Path params: address string required address parameter Query params: limit integer optional 1-100, default 20 after string optional Cursor from previous response Response (200): FundRequestListResponse Errors: 402 payment_required x402 payment needed 403 forbidden Caller does not own this wallet 404 not_found Wallet not found --- ### POST /v1/fund-requests/:id/approve Approve a pending fund request. Returns the address to send USDC to. Price: $0.01 Path params: id string required id parameter Response (200): id string Fund request ID. status "approved" Always "approved" on success. funding_address string Send USDC to this address to fulfill the request. amount string Approved USDC amount as a decimal string. chain string Chain identifier for the funding transaction. approved_at string ISO 8601 timestamp when the request was approved. Errors: 402 payment_required x402 payment needed 403 forbidden Caller not authorized to approve 404 not_found Fund request not found 409 duplicate_request Already approved or denied --- ### POST /v1/fund-requests/:id/deny Deny a pending fund request Price: $0.001 Path params: id string required id parameter Request: reason string optional Reason for denial. Response (200): id string Fund request ID. status "denied" Always "denied" on success. reason string | null Denial reason if provided, null otherwise. denied_at string ISO 8601 timestamp when the request was denied. Errors: 402 payment_required x402 payment needed 403 forbidden Caller not authorized to deny 404 not_found Fund request not found 409 duplicate_request Already approved or denied --- ### GET /v1/wallets/:address/policy Get the spending policy for a wallet Price: $0.001 Path params: address string required address parameter Response (200): wallet_address string Wallet address this policy applies to. max_per_tx string | null Max USDC per transaction, null = no limit. max_per_day string | null Max USDC per day, null = no limit. allowed_primitives string[] | null Allowed primitive hostnames (e.g. ["store.prim.sh"]), null = all allowed. daily_spent string USDC spent today as a decimal string. daily_reset_at string ISO 8601 timestamp when the daily counter resets. Errors: 402 payment_required x402 payment needed 403 forbidden Caller does not own this wallet 404 not_found Wallet not found --- ### PUT /v1/wallets/:address/policy Update spending policy for a wallet. All fields optional. Pass null to remove a limit. Price: $0.005 Path params: address string required address parameter Request: maxPerTx string | null optional Max USDC per transaction. Pass null to remove the limit. maxPerDay string | null optional Max USDC per day. Pass null to remove the limit. allowedPrimitives string[] | null optional Allowed primitive hostnames. Pass null to allow all. Response (200): wallet_address string Wallet address this policy applies to. max_per_tx string | null Max USDC per transaction, null = no limit. max_per_day string | null Max USDC per day, null = no limit. allowed_primitives string[] | null Allowed primitive hostnames (e.g. ["store.prim.sh"]), null = all allowed. daily_spent string USDC spent today as a decimal string. daily_reset_at string ISO 8601 timestamp when the daily counter resets. Errors: 400 invalid_request Invalid JSON body or field values 402 payment_required x402 payment needed 403 forbidden Caller does not own this wallet 404 not_found Wallet not found --- ### POST /v1/wallets/:address/pause Pause operations for a wallet. Temporarily halts spending without deactivating. Price: $0.001 Path params: address string required address parameter Request: scope PauseScope optional Scope to pause. "all" | "send" | "swap". Default "all". Response (200): wallet_address string Wallet address that was paused. paused boolean Always true on success. scope PauseScope Scope that was paused. paused_at string ISO 8601 timestamp when the wallet was paused. Errors: 400 invalid_request Invalid scope value 402 payment_required x402 payment needed 403 forbidden Caller does not own this wallet 404 not_found Wallet not found --- ### POST /v1/wallets/:address/resume Resume operations for a paused wallet Price: $0.001 Path params: address string required address parameter Request: scope PauseScope optional Scope to resume. "all" | "send" | "swap". Default "all". Response (200): wallet_address string Wallet address that was resumed. paused boolean Always false on success (wallet is unpaused). scope PauseScope Scope that was resumed. resumed_at string ISO 8601 timestamp when the wallet was resumed. Errors: 400 invalid_request Invalid scope value 402 payment_required x402 payment needed 403 forbidden Caller does not own this wallet 404 not_found Wallet not found --- ## Ownership All resources scoped to the wallet address extracted from the x402 payment signature. Wallet registration uses EIP-191 signature for ownership proof.