# Upload attachment Source: https://docs.0.finance/api-reference/endpoint/create Upload files to Vercel Blob for transactions ## POST `/api/upload` Uploads a file and returns a public blob URL. Requires a signed-in user session. Optional type for attachments (e.g. `offramp`). Optional transaction ID for attachment scoping. ### Request ```bash theme={null} curl -X POST "https://0.finance/api/upload?transactionType=offramp&transactionId=uuid" \ -H "Cookie: your-session-cookie" \ -F "file=@invoice.pdf" ``` ### Response ```json theme={null} { "url": "https://.../invoice.pdf", "filename": "invoice.pdf", "contentType": "application/pdf", "fileSize": 83921 } ``` File size limit is 10MB. Allowed types: PDF, images, and text files. # Register primary Safe Source: https://docs.0.finance/api-reference/endpoint/delete Attach a Safe to a user after onboarding ## POST `/api/user/safes/register-primary` Registers a user’s primary Safe after Privy authentication. Requires a Privy access token in the `Authorization` header. ```bash cURL theme={null} curl -X POST "https://0.finance/api/user/safes/register-primary" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"safeAddress":"0x..."}' ``` ```json Success theme={null} { "message": "Primary safe registered successfully.", "data": { "id": "uuid", "safeAddress": "0x...", "safeType": "primary" } } ``` This endpoint is used during onboarding to link the user’s primary Safe on Base. # Health check Source: https://docs.0.finance/api-reference/endpoint/get Verify the API is up ## GET `/api/health` Use this endpoint for uptime checks and local verification. ### Request ```bash theme={null} curl https://0.finance/api/health ``` ### Response ```json theme={null} { "status": "ok", "timestamp": "2026-01-12T00:00:00.000Z", "message": "Server is running" } ``` # Privy webhook Source: https://docs.0.finance/api-reference/endpoint/webhook User lifecycle events from Privy ## POST `/api/webhooks/auth` Receives Privy webhook events. This endpoint expects an HMAC signature in `x-privy-signature`. ```bash cURL theme={null} curl -X POST "https://0.finance/api/webhooks/auth" \ -H "x-privy-signature: " \ -H "Content-Type: application/json" \ -d '{"type":"user.created","data":{"email":"user@example.com"}}' ``` ```json Success theme={null} { "received": true } ``` The signature is verified against `PRIVY_WEBHOOK_SECRET`. # API Overview Source: https://docs.0.finance/api-reference/introduction Direct HTTP access to 0 Finance Most users should use the [CLI](/cli/installation) or [MCP server](/mcp/overview) instead of calling the API directly. ## API surfaces 0 Finance exposes two API surfaces: 1. **CLI API** — API-key authenticated endpoints at `/api/cli` 2. **Dashboard API** — Session/webhook authenticated endpoints at `/api/*` *** ## CLI API (API keys) ### Base URL ``` https://www.0.finance/api/cli ``` For local development: ``` http://localhost:3050/api/cli ``` ### Authentication Include your API key in the `Authorization` header: ```bash theme={null} curl https://www.0.finance/api/cli/balance \ -H "Authorization: Bearer sk_live_xxx" ``` Get your API key from [Settings → API Keys](https://www.0.finance/settings). ### Admin authentication Admin-only endpoints require the `x-admin-token` header: ```bash theme={null} curl https://www.0.finance/api/cli/users \ -X POST \ -H "Authorization: Bearer sk_live_xxx" \ -H "x-admin-token: adm_xxx" \ -H "Content-Type: application/json" \ -d '{ "email": "user@example.com" }' ``` ### Response format Endpoints return JSON objects. Errors return `{ "error": "..." }`. Example error: ```json theme={null} { "error": "Unauthorized: invalid or missing API key" } ``` *** ## CLI endpoint map ### Auth & balance | Method | Endpoint | Description | | ------ | ------------------ | ---------------------------------- | | GET | `/api/cli/whoami` | Workspace metadata for the API key | | GET | `/api/cli/balance` | Spendable (idle + earning) balance | ### Bank accounts | Method | Endpoint | Description | | ------ | ------------------------ | ------------------------ | | GET | `/api/cli/bank-accounts` | List saved bank accounts | | POST | `/api/cli/bank-accounts` | Create a bank account | ### Bank transfers | Method | Endpoint | Description | | ------ | ----------------------------------------------- | ----------------------------------------- | | POST | `/api/cli/bank-transfers/proposals` | Propose a bank transfer | | GET | `/api/cli/bank-transfers/proposals` | List proposals (`include_completed=true`) | | POST | `/api/cli/bank-transfers/proposals/:id/dismiss` | Dismiss a proposal | ### Invoices | Method | Endpoint | Description | | ------ | ---------------------------- | --------------------------------- | | POST | `/api/cli/invoices` | Create an invoice | | GET | `/api/cli/invoices` | List invoices (`status`, `limit`) | | GET | `/api/cli/invoices/:id` | Get invoice details | | PATCH | `/api/cli/invoices/:id` | Update an invoice | | POST | `/api/cli/invoices/:id/send` | Send an invoice | ### Transactions | Method | Endpoint | Description | | ------ | --------------------------- | ------------------------------------- | | GET | `/api/cli/transactions` | List transactions (`status`, `limit`) | | GET | `/api/cli/transactions/:id` | Get transaction details | ### Attachments | Method | Endpoint | Description | | ------ | -------------------------- | ---------------------------------------------------------------- | | POST | `/api/cli/attachments` | Upload an attachment | | GET | `/api/cli/attachments` | List attachments (`transaction_id`, `transaction_type`, `limit`) | | DELETE | `/api/cli/attachments/:id` | Remove an attachment | ### Payment details | Method | Endpoint | Description | | ------ | -------------------------------- | ------------------------------ | | GET | `/api/cli/payment-details` | Get IBAN/ACH receiving details | | POST | `/api/cli/payment-details/share` | Email receiving details | ### Crypto transfers | Method | Endpoint | Description | | ------ | ------------------------------------------------- | ------------------------------------------------ | | POST | `/api/cli/crypto-transfers/proposals` | Propose a crypto transfer | | GET | `/api/cli/crypto-transfers/proposals` | List crypto proposals (`include_completed=true`) | | POST | `/api/cli/crypto-transfers/proposals/:id/dismiss` | Dismiss a crypto proposal | ### Savings & vaults | Method | Endpoint | Description | | ------ | ------------------------------ | ------------------------------------------------- | | GET | `/api/cli/vaults` | List supported vaults | | POST | `/api/cli/savings/deposits` | Propose a vault deposit | | POST | `/api/cli/savings/withdrawals` | Propose a vault withdrawal | | GET | `/api/cli/savings/proposals` | List savings proposals (`include_completed=true`) | | GET | `/api/cli/savings/positions` | Idle/earning balance and vault positions | ### Admin endpoints | Method | Endpoint | Description | | ------ | ---------------------------- | ---------------------------------------------- | | POST | `/api/cli/users` | Provision a user (creates workspace + API key) | | GET | `/api/cli/users/:id` | Fetch user + profile by Privy DID | | POST | `/api/cli/users/:id/wallets` | Pregenerate wallets for a user | | POST | `/api/cli/api-keys` | Create an API key for a workspace | *** ## CLI query parameters ### Invoices * `status`: `db_pending`, `pending`, `paid`, `canceled` * `limit`: number ### Transactions * `status`: `pending`, `completed`, `failed` * `limit`: number ### Proposals * `include_completed`: `true` or `false` *** ## CLI examples ### Check balance ```bash theme={null} curl https://www.0.finance/api/cli/balance \ -H "Authorization: Bearer sk_live_xxx" ``` Response: ```json theme={null} { "idle_balance": "3200.00", "earning_balance": "4220.50", "spendable_balance": "7420.50", "safe_address": "0x954A329e1e59101DF529CC54A54666A0b36Cae22", "chain": "base" } ``` ### Create invoice ```bash theme={null} curl https://www.0.finance/api/cli/invoices \ -X POST \ -H "Authorization: Bearer sk_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "recipient_email": "client@example.com", "amount": 1000, "currency": "USD", "description": "Consulting services" }' ``` ### Propose transfer ```bash theme={null} curl https://www.0.finance/api/cli/bank-transfers/proposals \ -X POST \ -H "Authorization: Bearer sk_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "amount_usdc": "1000", "destination_currency": "usd", "saved_bank_account_id": "ba_xxx", "reason": "Contractor payment" }' ``` Transfers create proposals that require dashboard approval before executing. *** ## Dashboard endpoints (session/webhook) These endpoints are used by the web app and internal services: * **Health check:** `/api/health` * **Upload:** `/api/upload` (requires a signed-in user session) * **Register primary Safe:** `/api/user/safes/register-primary` * **Privy webhooks:** `/api/webhooks/auth` (HMAC signed) See the endpoint pages in the API sidebar for request/response details. *** ## MCP server The MCP server at `/api/mcp` wraps the CLI API for AI agents. See [MCP Overview](/mcp/overview) for details. # Installation Source: https://docs.0.finance/cli/installation Install and configure the 0 Finance CLI ## Install with curl ```bash theme={null} curl -fsSL https://zerofinance.ai/install | bash ``` This installs Bun if needed, then installs `agent-bank` globally. ## Install with Bun ```bash theme={null} bun add -g agent-bank ``` Verify the installation: ```bash theme={null} zero --version ``` The CLI binary is `zero` (alias: `zero-bank`). *** ## Run from the repo The CLI lives in `packages/cli` and can be run directly from source: ```bash theme={null} bun install bun --cwd packages/cli run dev -- auth connect --no-browser ``` Use `zero --debug auth whoami` to print the resolved base URL. *** ## Authenticate ### Step 1: Get your API key 1. Log in to [0.finance](https://www.0.finance) 2. Go to **Settings → API Keys** 3. Click **Create API Key** 4. Copy the key (it starts with `sk_live_` or `sk_test_`) Store your API key securely. It provides full access to your workspace. ### Step 2: Connect the CLI **Option A: Browser connect (recommended)** ```bash theme={null} zero auth connect ``` This opens a secure connection page on [www.0.finance](http://www.0.finance) and stores the API key for you. If the automatic handoff fails, the page shows a copyable key for manual paste. **Option B: API key** ```bash theme={null} zero auth login --api-key sk_live_your_api_key_here ``` This stores your credentials in `~/.zero-finance/config.json`. ### Step 3: Verify ```bash theme={null} zero auth whoami ``` ```json theme={null} { "workspace_id": "ws_xxx", "workspace_name": "My Company", "key_id": "key_xxx", "key_name": "Production Key", "align_customer_id": "align_xxx" } ``` *** ## Configuration The CLI stores configuration in `~/.zero-finance/config.json`: ```json theme={null} { "apiKey": "sk_live_xxx", "baseUrl": "https://www.0.finance" } ``` ### Custom base URL For self-hosted deployments or local development: ```bash theme={null} zero auth login --api-key sk_test_xxx --base-url http://localhost:3050 ``` The base URL should be the root (e.g. `https://www.0.finance`), not `.../api/cli`. The CLI will normalize if you include `/api/cli`. *** ## Log out Remove stored credentials: ```bash theme={null} zero auth logout ``` *** ## Next steps Complete command reference with examples. Your first CLI command. Functionality coverage and smoke-test results. # CLI Reference Source: https://docs.0.finance/cli/reference Complete reference for all zero CLI commands ## Overview The `zero` CLI provides full access to 0 Finance from your terminal. All commands output JSON for easy scripting and piping. ```bash theme={null} zero [subcommand] [options] ``` You can also use the alias `zero-bank`. Transfers, savings actions, and crypto moves create proposals that require dashboard approval. *** ## Authentication ### `zero auth connect` Open the browser to connect the CLI and store the API key automatically. ```bash theme={null} zero auth zero auth connect zero login ``` | Option | Required | Description | | -------------- | -------- | -------------------------------------------- | | `--base-url` | No | Base URL (default: `https://www.0.finance`) | | `--no-browser` | No | Print URL instead of opening a browser | | `--manual` | No | Skip callback and paste the API key manually | ### `zero auth login` Store your API key and configure the CLI manually. ```bash theme={null} zero auth login --api-key sk_live_xxx zero auth login --api-key sk_live_xxx --base-url https://custom.0.finance ``` | Option | Required | Description | | ------------ | -------- | ----------------------------------------------- | | `--api-key` | Yes | Your workspace API key | | `--base-url` | No | API base URL (default: `https://www.0.finance`) | ### `zero auth whoami` Show the current workspace context. ```bash theme={null} zero auth whoami ``` ### `zero auth logout` Remove stored credentials. ```bash theme={null} zero auth logout ``` *** ## Configuration ### `zero config show` Show the current config path, base URL, and key prefix. ```bash theme={null} zero config show ``` ### `zero config set` Update stored configuration values. ```bash theme={null} zero config set --base-url http://localhost:3050 zero config set --api-key sk_live_xxx ``` *** ## Debugging Use `--debug` to see request URLs and the base URL being used. ```bash theme={null} zero --debug auth whoami ``` *** ## Balance ### `zero balance` Show your spendable, earning, and idle USDC balances on Base. ```bash theme={null} zero balance ``` **Output:** ```json theme={null} { "idle_balance": "3200.00", "earning_balance": "4220.50", "spendable_balance": "7420.50", "safe_address": "0x954A329e1e59101DF529CC54A54666A0b36Cae22", "chain": "base" } ``` Use `zero savings positions` to include vault-level breakdowns. *** ## Bank Accounts ### `zero bank accounts list` List all saved bank accounts. ```bash theme={null} zero bank accounts list ``` ### `zero bank accounts create` Create a saved bank account from a JSON file. ```bash theme={null} zero bank accounts create --json ./account.json ``` **account.json (IBAN example):** ```json theme={null} { "account_name": "Acme EUR", "bank_name": "Commerzbank", "account_holder_type": "business", "account_holder_business_name": "Acme Corp", "country": "DE", "city": "Berlin", "street_line_1": "Friedrichstr. 1", "postal_code": "10117", "account_type": "iban", "iban_number": "DE89370400440532013000", "bic_swift": "COBADEFFXXX", "is_default": true } ``` For US accounts, set `account_type` to `"us"` and include `account_number` and `routing_number`. For individual accounts, provide `account_holder_first_name` and `account_holder_last_name`. *** ## Bank Transfers ### `zero bank transfers propose` Propose a bank transfer for approval. ```bash theme={null} zero bank transfers propose \ --amount 1000 \ --currency usd \ --bank-account-id ba_xxx \ --reason "Contractor payment for January" ``` | Option | Required | Description | | ------------------- | -------- | ------------------------------------- | | `--amount` | Yes | Amount in USDC | | `--currency` | Yes | Destination currency (`usd` or `eur`) | | `--bank-account-id` | Yes | Saved bank account ID | | `--reason` | No | Reason for the transfer | IBAN accounts require `--currency eur`. US bank accounts require `--currency usd`. Transfers create proposals that require approval in the dashboard before executing. Transfers require completed KYC. If KYC is missing, the command returns an error asking the user to complete verification. ### `zero bank proposals list` List pending transfer proposals. ```bash theme={null} zero bank proposals list zero bank proposals list --include-completed ``` | Option | Description | | --------------------- | --------------------------- | | `--include-completed` | Include completed proposals | ### `zero bank proposals dismiss` Dismiss a transfer proposal. ```bash theme={null} zero bank proposals dismiss --proposal-id prop_xxx ``` *** ## Invoices ### `zero invoices create` Create a new invoice. ```bash theme={null} zero invoices create \ --recipient-email client@example.com \ --recipient-name "Acme Corp" \ --amount 2500 \ --currency USD \ --description "Q1 consulting services" \ --due-date 2026-02-15 \ --notes "Payment terms: Net 30" ``` | Option | Required | Description | | ------------------- | -------- | ------------------------------ | | `--recipient-email` | Yes | Client's email address | | `--recipient-name` | No | Client's name | | `--amount` | Yes | Invoice amount | | `--currency` | Yes | Currency code (USD, EUR, etc.) | | `--description` | Yes | Line item description | | `--due-date` | No | Due date (YYYY-MM-DD) | | `--notes` | No | Additional notes | ### `zero invoices list` List invoices with optional filters. ```bash theme={null} zero invoices list zero invoices list --status pending --limit 10 ``` | Option | Description | | ---------- | -------------------------------------------------------------- | | `--status` | Filter by status (`db_pending`, `pending`, `paid`, `canceled`) | | `--limit` | Maximum number of results | ### `zero invoices get` Get a specific invoice. ```bash theme={null} zero invoices get --invoice-id inv_xxx ``` ### `zero invoices update` Update an existing invoice. ```bash theme={null} zero invoices update \ --invoice-id inv_xxx \ --amount 3000 \ --description "Updated scope" ``` | Option | Required | Description | | ------------------- | -------- | ---------------------- | | `--invoice-id` | Yes | Invoice ID | | `--recipient-email` | No | Update recipient email | | `--recipient-name` | No | Update recipient name | | `--amount` | No | Update amount | | `--currency` | No | Update currency | | `--description` | No | Update description | ### `zero invoices send` Send an invoice to the recipient. ```bash theme={null} zero invoices send --invoice-id inv_xxx ``` *** ## Transactions ### `zero transactions list` List transaction history. ```bash theme={null} zero transactions list zero transactions list --status completed --limit 50 ``` | Option | Description | | ---------- | --------------------------------------------------- | | `--status` | Filter by status (`pending`, `completed`, `failed`) | | `--limit` | Maximum number of results | ### `zero transactions get` Get transaction details. ```bash theme={null} zero transactions get --transaction-id tx_xxx ``` *** ## Attachments ### `zero attachments add` Attach a file to a transaction. ```bash theme={null} zero attachments add \ --transaction-id tx_xxx \ --transaction-type offramp \ --file ./receipt.pdf ``` | Option | Required | Description | | -------------------- | -------- | ----------------------------------------- | | `--transaction-id` | Yes | Transaction ID | | `--transaction-type` | Yes | Transaction type (`offramp` or `invoice`) | | `--type` | No | Alias for `--transaction-type` | | `--file` | Yes | Path to file | | `--content-type` | No | MIME type (auto-detected if omitted) | ### `zero attachments list` List attachments. ```bash theme={null} zero attachments list zero attachments list --transaction-id tx_xxx ``` | Option | Description | | -------------------- | --------------------------------------- | | `--transaction-id` | Filter by transaction ID | | `--transaction-type` | Filter by type (`offramp` or `invoice`) | | `--limit` | Maximum number of results | ### `zero attachments remove` Remove an attachment. ```bash theme={null} zero attachments remove --attachment-id att_xxx ``` *** ## Payment Details ### `zero payment-details show` Show payment details for receiving funds (USD ACH + EUR IBAN). ```bash theme={null} zero payment-details show ``` **Output:** ```json theme={null} { "payment_details": { "hasAccounts": true, "accountTier": "full", "hasCompletedKyc": true, "usdAccount": { "type": "us_ach", "currency": "USD", "bankName": "Mercury", "routingNumber": "123456789", "accountNumber": "000123456789", "beneficiaryName": "0 Finance FBO Jane Doe" }, "eurAccount": { "type": "iban", "currency": "EUR", "bankName": "Commerzbank", "iban": "DE89370400440532013000", "bicSwift": "COBADEFFXXX", "beneficiaryName": "0 Finance FBO Jane Doe" }, "workspaceInfo": { "companyName": "Acme Corp", "firstName": "Jane", "lastName": "Doe" } }, "message": "These are the bank account details for receiving payments." } ``` ### `zero payment-details share` Email your payment details to someone. ```bash theme={null} zero payment-details share \ --recipient-email accountant@example.com \ --recipient-name "Jane Smith" ``` *** ## Crypto Transfers ### `zero crypto transfers propose` Propose a crypto transfer. ```bash theme={null} zero crypto transfers propose \ --to 0x742d35Cc6634C0532925a3b844Bc9e7595f... \ --token-address 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \ --amount 100 \ --token-symbol USDC \ --token-decimals 6 \ --chain-id 8453 \ --reason "Partner payment" ``` | Option | Required | Description | | ------------------ | -------- | --------------------------------------------- | | `--to` | Yes | Recipient wallet address | | `--token-address` | Yes | Token contract address | | `--amount` | Yes | Token amount | | `--token-symbol` | No | Token symbol (e.g., USDC) | | `--token-decimals` | No\* | Token decimals (required for non-USDC tokens) | | `--chain-id` | No | Chain ID (defaults to 8453/Base if omitted) | | `--reason` | No | Reason for transfer | If `--token-address` is the Base USDC contract, you can omit `--token-decimals` and it will default to 6. ### `zero crypto proposals list` List crypto transfer proposals. ```bash theme={null} zero crypto proposals list zero crypto proposals list --include-completed ``` | Option | Description | | --------------------- | --------------------------- | | `--include-completed` | Include completed proposals | ### `zero crypto proposals dismiss` Dismiss a crypto proposal. ```bash theme={null} zero crypto proposals dismiss --proposal-id prop_xxx ``` *** ## Savings ### `zero vaults list` List supported yield vaults. ```bash theme={null} zero vaults list ``` ### `zero savings deposits propose` Propose a deposit into a yield vault. ```bash theme={null} zero savings deposits propose \ --vault-address 0x... \ --amount 1000 \ --reason "Earning yield on idle funds" ``` ### `zero savings withdrawals propose` Propose a withdrawal from a yield vault. ```bash theme={null} zero savings withdrawals propose \ --vault-address 0x... \ --amount 500 \ --reason "Need funds for payment" ``` Vault addresses must come from `zero vaults list` (Base USDC vaults). ### `zero savings proposals list` List savings proposals. ```bash theme={null} zero savings proposals list zero savings proposals list --include-completed ``` | Option | Description | | --------------------- | --------------------------- | | `--include-completed` | Include completed proposals | ### `zero savings positions` Show idle balance, earning balance, and vault positions. ```bash theme={null} zero savings positions ``` **Output:** ```json theme={null} { "idle_balance": "420.50", "earning_balance": "2000.00", "spendable_balance": "2420.50", "safe_address": "0x954A329e1e59101DF529CC54A54666A0b36Cae22", "chain": "base", "vault_positions": [ { "vault_address": "0x...", "vault_name": "Morpho USDC", "balance_usd": 2000 } ] } ``` *** ## Admin Commands Admin commands require an admin token. Set `ZERO_FINANCE_ADMIN_TOKEN` or use `--admin-token`. ### `zero users create` Provision a new user. ```bash theme={null} zero users create \ --email user@example.com \ --admin-token adm_xxx ``` | Option | Required | Description | | ---------------- | -------- | ----------------------------------------------- | | `--email` | Yes\* | User email (required if no phone) | | `--phone` | Yes\* | User phone (required if no email) | | `--wallets-json` | No | Path to wallets JSON array | | `--admin-token` | No | Admin token (or set `ZERO_FINANCE_ADMIN_TOKEN`) | ### `zero users show` Get user details. ```bash theme={null} zero users show --user-id did:privy:xxx --admin-token adm_xxx ``` ### `zero users wallets pregenerate` Pregenerate wallets for a user. ```bash theme={null} zero users wallets pregenerate \ --user-id did:privy:xxx \ --wallets-json ./wallets.json \ --admin-token adm_xxx ``` | Option | Required | Description | | ---------------- | -------- | ----------------------------------------------- | | `--user-id` | Yes | Privy user DID | | `--wallets-json` | No | Path to wallets JSON array | | `--admin-token` | No | Admin token (or set `ZERO_FINANCE_ADMIN_TOKEN`) | ### `zero api-keys create` Create an API key for a workspace. ```bash theme={null} zero api-keys create \ --workspace-id ws_xxx \ --created-by did:privy:xxx \ --name "Production API Key" \ --admin-token adm_xxx ``` | Option | Required | Description | | ---------------- | -------- | ----------------------------------------------- | | `--workspace-id` | Yes | Workspace ID | | `--created-by` | Yes | Privy user DID that owns the key | | `--name` | No | Friendly name for the key | | `--expires-at` | No | ISO expiration date (e.g. `2026-12-31`) | | `--admin-token` | No | Admin token (or set `ZERO_FINANCE_ADMIN_TOKEN`) | *** ## Tips ### JSON output All commands output JSON. Pipe to `jq` for formatting: ```bash theme={null} zero balance | jq .spendable_balance ``` ### Scripting Use the CLI in scripts: ```bash theme={null} #!/bin/bash BALANCE=$(zero balance | jq -r .spendable_balance) if (( $(echo "$BALANCE > 10000" | bc -l) )); then zero savings deposits propose \ --vault-address 0x... \ --amount 5000 \ --reason "Auto-deposit excess funds" fi ``` ### Error handling Non-zero exit codes indicate errors. Error messages are printed to stderr: ```bash theme={null} zero invoices get --invoice-id invalid_id || echo "Invoice not found" ``` # null Source: https://docs.0.finance/cli/testing title: 'CLI Functionality & QA' description: 'Capabilities overview and production smoke test log for the zero CLI' *** ## Capabilities overview The zero CLI exposes the same workflows as the dashboard and MCP server: * **Authentication & config**: connect, login, whoami, logout, config show/set. * **Balances & savings**: spendable balance, vault positions, supported vaults. * **Banking**: saved bank accounts, bank transfer proposals. * **Invoices & transactions**: create, update, send, and list invoices; list transactions. * **Attachments**: add/list/remove attachments for invoices or offramps. * **Payment details**: view and share payment details. * **Crypto transfers**: propose and dismiss token transfers. * **Savings proposals**: propose deposits/withdrawals and list proposals. * **Admin provisioning**: users, wallets, and API keys (admin token required). ## Production smoke test (2026-01-13) Tests target `https://www.0.finance` using the provided workspace API key. | Area | Command | Status | Notes | | --------------- | ------------------------------------------------------ | ------- | ---------------------------------------------------------------------------------------------------------- | | Auth | `zero auth login --api-key ` | Passed | Stored key and base URL set to `https://www.0.finance`. | | Auth | `zero auth connect` | Blocked | Browser flow requires interactive callback. | | Auth | `zero auth whoami` | Passed | Workspace: Different AI Inc. | | Auth | `zero auth logout` | Passed | Re-authenticated after test. | | Config | `zero config show` | Passed | Shows config path + base URL. | | Config | `zero config set --base-url https://www.0.finance` | Passed | Confirmed success. | | Balance | `zero balance` | Passed | idle 500.31, earning 15037.38, spendable 15537.69. | | Savings | `zero savings positions` | Passed | Vault: Stable Savings \~15037.38. | | Vaults | `zero vaults list` | Passed | 4 vaults returned. | | Bank | `zero bank accounts list` | Passed | 8 accounts listed. | | Bank | `zero bank accounts create --json ` | Passed | Created `cd1b0df5-0d72-4c4f-908e-e69f0df106f4`. | | Bank | `zero bank transfers propose` | Passed | `transaction_id` 3a460ea9-57de-496d-af41-f95c11def575, `proposal_id` 149baf8d-15e2-40b0-90f4-4940ce9ed309. | | Bank | `zero bank proposals list` | Passed | Pending proposal `149baf8d-15e2-40b0-90f4-4940ce9ed309`. | | Bank | `zero bank proposals dismiss --proposal-id ` | Passed | Dismissed proposal `149baf8d-15e2-40b0-90f4-4940ce9ed309`. | | Invoices | `zero invoices create` | Passed | `invoice_id` 5daa9bc5-ce96-4cf2-b8c2-21372f9af27c. | | Invoices | `zero invoices update --invoice-id ` | Passed | Updated description. | | Invoices | `zero invoices get --invoice-id ` | Passed | Returned invoice payload. | | Invoices | `zero invoices list` | Passed | Returned list (limit 5). | | Invoices | `zero invoices send --invoice-id ` | Passed | Sent invoice to [benjamin.shafii@gmail.com](mailto:benjamin.shafii@gmail.com). | | Transactions | `zero transactions list` | Passed | Returned recent bank transfers. | | Transactions | `zero transactions get --transaction-id ` | Passed | Returned transfer detail payload. | | Attachments | `zero attachments add --transaction-id ` | Passed | `attachment_id` d8bc9918-f3c3-47c0-a380-d0c3a27c019b. | | Attachments | `zero attachments list --transaction-id ` | Passed | Listed invoice attachment. | | Attachments | `zero attachments remove --attachment-id ` | Passed | Removed attachment. | | Payment details | `zero payment-details show` | Passed | Returned USD + EUR account details. | | Payment details | `zero payment-details share --recipient-email ` | Passed | Sent payment details to [benjamin.shafii@gmail.com](mailto:benjamin.shafii@gmail.com). | | Crypto | `zero crypto transfers propose` | Failed | `action_proposals` table missing in prod (migration 0128). | | Crypto | `zero crypto proposals list` | Failed | `action_proposals` table missing in prod. | | Crypto | `zero crypto proposals dismiss --proposal-id ` | Blocked | Requires `action_proposals` table. | | Savings | `zero savings deposits propose` | Failed | `action_proposals` table missing in prod. | | Savings | `zero savings withdrawals propose` | Failed | `action_proposals` table missing in prod. | | Savings | `zero savings proposals list` | Failed | `action_proposals` table missing in prod. | | Admin | `zero users create` | Blocked | Requires admin token. | | Admin | `zero users show` | Blocked | Requires admin token. | | Admin | `zero users wallets pregenerate` | Blocked | Requires admin token. | | Admin | `zero api-keys create` | Blocked | Requires admin token. | ## Known issues * Crypto + savings proposals require the `action_proposals` table in production; migration `0128` is not applied, so these commands return `relation "action_proposals" does not exist`. # Contributing Source: https://docs.0.finance/development Guidelines for contributing to 0 Finance ## Project structure ``` zero-finance/ ├── packages/ │ ├── web/ # Next.js application │ ├── cli/ # agent-bank package │ └── docs/ # Public documentation site ├── scripts/ # Build and deployment scripts └── deployments/ # Contract deployment manifests ``` *** ## Development workflow ### 1. Create a feature branch ```bash theme={null} git checkout -b feat/your-feature-name ``` ### 2. Make changes Follow the existing code style: * TypeScript for all code * Prettier formatting (2 spaces, single quotes) * ESLint rules from `next/core-web-vitals` ### 3. Run quality checks ```bash theme={null} pnpm typecheck pnpm lint pnpm --filter @zero-finance/web test ``` ### 4. Commit and push ```bash theme={null} git add . git commit -m "feat: add your feature" git push -u origin feat/your-feature-name ``` ### 5. Create a pull request PRs should include: * Summary of changes * Testing notes * Screenshots (for UI changes) *** ## Code style ### TypeScript * Prefer `const` over `let` * Use explicit return types for exported functions * Document complex logic with comments ### React * Functional components with hooks * PascalCase for components * camelCase for hooks and utilities ### Tailwind Order classes: layout → spacing → colors ```tsx theme={null} // Good
// Avoid
``` *** ## Database changes Use Drizzle migrations: ```bash theme={null} # Generate migration pnpm --filter @zero-finance/web db:generate # Apply migration pnpm --filter @zero-finance/web db:migrate ``` *** ## Testing the CLI locally Build and link the CLI: ```bash theme={null} cd packages/cli pnpm build pnpm link --global ``` Point to your local server: ```bash theme={null} zero auth login --api-key sk_test_xxx --base-url http://localhost:3050 ``` *** ## Useful scripts | Script | Description | | ----------------- | ---------------------------- | | `pnpm dev` | Start all dev servers | | `pnpm dev:lite` | Start with lite Docker stack | | `pnpm build` | Build all packages | | `pnpm lint` | Run ESLint | | `pnpm typecheck` | Run TypeScript checks | | `pnpm format` | Check Prettier formatting | | `pnpm format:fix` | Fix formatting issues | *** ## Getting help * Check existing issues on [GitHub](https://github.com/different-ai/zero-finance/issues) * Ask in the team Slack/Discord * Review the codebase — most patterns are self-documenting # Introduction Source: https://docs.0.finance/index Manage your finances from the command line with the 0 Finance CLI ## What is 0 Finance? 0 Finance is a bank account built for the AI era: * **Get paid easily** — Create invoices in seconds and receive payments to your personal IBAN or ACH account. * **Spend anywhere** — Use a debit card worldwide with 0% conversion fees. * **Optimize yield** — AI automatically allocates idle funds to the highest-yielding opportunities. Everything is programmable through the **`zero` CLI** (alias: `zero-bank`) — check balances, send invoices, propose transfers, and manage savings from your terminal. *** ## Quick start ```bash theme={null} # Install the CLI curl -fsSL https://zerofinance.ai/install | bash # Or: bun add -g agent-bank # Connect the CLI (opens a browser) zero auth connect # Or: zero auth login --api-key sk_live_xxx # Debug request URLs: # zero --debug auth whoami # Check your balance zero balance # Create and send an invoice zero invoices create \ --recipient-email client@example.com \ --amount 1000 \ --currency USD \ --description "Consulting services" zero invoices send --invoice-id inv_xxx ``` Get up and running with the `zero` CLI in under a minute. Complete command reference with examples. Let AI agents manage your finances with human approval. Direct HTTP API access for custom integrations. *** ## What you can do ### Check your balance ```bash theme={null} zero balance ``` ```json theme={null} { "idle_balance": "3200.00", "earning_balance": "4220.50", "spendable_balance": "7420.50", "safe_address": "0x954A329e1e59101DF529CC54A54666A0b36Cae22", "chain": "base" } ``` ### Create and send invoices ```bash theme={null} # Create an invoice zero invoices create \ --recipient-email client@acme.com \ --recipient-name "Acme Corp" \ --amount 2500 \ --currency USD \ --description "Q1 consulting" # Send it zero invoices send --invoice-id inv_xxx ``` ### Propose a bank transfer ```bash theme={null} # List your saved bank accounts zero bank accounts list # Propose a transfer (requires dashboard approval) zero bank transfers propose \ --amount 1000 \ --currency usd \ --bank-account-id ba_xxx \ --reason "Contractor payment" ``` ### Manage savings ```bash theme={null} # View available vaults zero vaults list # Deposit into a yield vault zero savings deposits propose \ --vault-address 0x... \ --amount 500 \ --reason "Earning yield on idle funds" # Check your positions zero savings positions ``` *** ## How it works 1. **Authenticate** — Use `zero auth connect` (or `zero auth login` with an API key). 2. **Execute commands** — Read operations happen instantly. Transfers and withdrawals create proposals. 3. **Approve in dashboard** — Proposals require human approval before executing. This keeps you in control. The CLI never moves money without your explicit approval in the 0 Finance dashboard. *** ## For AI agents Connect your AI assistant to 0 Finance using the MCP server. Your agent can check balances, create invoices, and propose transfers — but all outbound payments still require your approval. ```json theme={null} { "mcpServers": { "zero-finance": { "command": "npx", "args": ["-y", "mcp-remote", "https://0.finance/api/mcp"], "env": { "API_KEY": "sk_live_xxx" } } } } ``` MCP currently supports bank transfers, invoices, attachments, and payment details. For crypto transfers and savings, use the CLI or HTTP API. See [MCP setup](/mcp/overview) for detailed instructions. *** ## Documentation map | Section | What's inside | | ----------------- | ------------------------------------------------ | | **CLI** | Installation, authentication, command reference | | **MCP** | AI agent setup for Cursor, Claude Code, Windsurf | | **API Reference** | HTTP endpoints for custom integrations | # Claude Code Source: https://docs.0.finance/mcp/claude-code Connect Claude Code to the 0 Finance MCP server ## Prerequisites * [Claude Code](https://claude.ai/code) or Claude Desktop installed * 0 Finance API key from [Settings → API Keys](https://0.finance/settings) *** ## Step 1: Create the config file Create or edit `~/.claude/claude_desktop_config.json`: ```json theme={null} { "mcpServers": { "zero-finance": { "command": "npx", "args": ["-y", "mcp-remote", "https://0.finance/api/mcp"], "env": { "API_KEY": "sk_live_your_api_key_here" } } } } ``` *** ## Step 2: Restart Claude Quit and reopen Claude to load the new MCP server. *** ## Step 3: Verify Ask Claude to check your balance: ``` Check my 0 Finance balance ``` Claude should call `get_balance` and display your USDC balance. *** ## Add to CLAUDE.md For project-specific context, add this to your `CLAUDE.md`: ```markdown theme={null} ## 0 Finance Integration This project uses 0 Finance for payments. When working with finances: - Use `get_balance` before proposing transfers - Transfers require dashboard approval—never claim funds moved - Use `create_invoice` for billing clients - Use `get_payment_details` to share receiving info ``` *** ## Available tools Once connected, Claude has access to all 0 Finance tools: | Tool | Description | | -------------------------- | ------------------------------ | | `get_balance` | Get spendable USDC balance | | `list_saved_bank_accounts` | List saved bank accounts | | `propose_bank_transfer` | Propose an outbound transfer | | `create_invoice` | Create a new invoice | | `send_invoice` | Send invoice to recipient | | `list_invoices` | List invoices | | `get_payment_details` | Get IBAN/ACH receiving details | | `share_payment_details` | Email payment details | See the [full tool list](/mcp/overview#available-tools) for all available tools. *** ## Troubleshooting ### "MCP server not found" 1. Check that `~/.claude/claude_desktop_config.json` exists 2. Verify the JSON is valid (no trailing commas) 3. Restart Claude completely (quit and reopen) ### "Tool execution failed" 1. Verify your API key is valid 2. Check the Claude output for specific error messages 3. Ensure you have network connectivity ### Slow responses The MCP server connects over HTTPS. If responses are slow: 1. Check your internet connection 2. Try a different network 3. The first request may be slower due to npx package download # Cursor Source: https://docs.0.finance/mcp/cursor Connect Cursor to the 0 Finance MCP server ## Prerequisites * [Cursor](https://cursor.sh) installed * 0 Finance API key from [Settings → API Keys](https://0.finance/settings) *** ## Step 1: Create the config file Create or edit `~/.cursor/mcp.json`: ```json theme={null} { "mcpServers": { "zero-finance": { "command": "npx", "args": ["-y", "mcp-remote", "https://0.finance/api/mcp"], "env": { "API_KEY": "sk_live_your_api_key_here" } } } } ``` *** ## Step 2: Restart Cursor Quit and reopen Cursor to load the new MCP server. *** ## Step 3: Verify In a new chat, ask Cursor to check your balance: ``` Check my 0 Finance balance ``` Cursor should call `get_balance` and show your USDC balance. *** ## Add the starter prompt For best results, add this to your Cursor rules (`.cursorrules` or project settings): ```text theme={null} When using 0 Finance tools: - Always call get_balance before proposing transfers - Never claim funds have moved—transfers require dashboard approval - Confirm amounts and recipients before creating proposals ``` *** ## Available tools Once connected, Cursor has access to these tools: | Tool | Description | | -------------------------- | ------------------------------ | | `get_balance` | Get spendable USDC balance | | `list_saved_bank_accounts` | List saved bank accounts | | `propose_bank_transfer` | Propose an outbound transfer | | `create_invoice` | Create a new invoice | | `send_invoice` | Send invoice to recipient | | `list_invoices` | List invoices | | `get_payment_details` | Get IBAN/ACH receiving details | | `share_payment_details` | Email payment details | See the [full tool list](/mcp/overview#available-tools) for all available tools. *** ## Troubleshooting ### "MCP server not found" 1. Check that `~/.cursor/mcp.json` exists and is valid JSON 2. Verify `npx` is available in your PATH 3. Restart Cursor ### "Authentication failed" 1. Verify your API key is correct 2. Check the key hasn't expired in [Settings → API Keys](https://0.finance/settings) 3. Ensure there are no extra spaces in the key ### "Tool call failed" Check the Cursor output panel for error messages. Common issues: * Rate limiting (wait and retry) * Invalid parameters (check the tool documentation) * Network issues (verify internet connection) # MCP for AI Agents Source: https://docs.0.finance/mcp/overview Let AI agents manage your finances with human approval ## What is MCP? The Model Context Protocol (MCP) lets AI assistants connect to external tools and services. The 0 Finance MCP server gives your AI agent access to: * Check balances and transaction history * Manage invoices (create, update, send) * Propose bank transfers for approval * Attach receipts and share payment details All transfers require human approval in the dashboard. Your AI agent can propose actions, but you stay in control. *** ## Quick setup Add this to your MCP client configuration: Add to `~/.cursor/mcp.json`: ```json theme={null} { "mcpServers": { "zero-finance": { "command": "npx", "args": ["-y", "mcp-remote", "https://0.finance/api/mcp"], "env": { "API_KEY": "sk_live_xxx" } } } } ``` Add to `~/.claude/claude_desktop_config.json`: ```json theme={null} { "mcpServers": { "zero-finance": { "command": "npx", "args": ["-y", "mcp-remote", "https://0.finance/api/mcp"], "env": { "API_KEY": "sk_live_xxx" } } } } ``` Add to `~/.codeium/windsurf/mcp_config.json`: ```json theme={null} { "mcpServers": { "zero-finance": { "command": "npx", "args": ["-y", "mcp-remote", "https://0.finance/api/mcp"], "env": { "API_KEY": "sk_live_xxx" } } } } ``` Replace `sk_live_xxx` with your API key from [Settings → API Keys](https://0.finance/settings). *** ## Available tools | Tool | Description | | -------------------------- | ------------------------------ | | `list_saved_bank_accounts` | List saved bank accounts | | `get_balance` | Get spendable USDC balance | | `propose_bank_transfer` | Propose an outbound transfer | | `list_proposals` | List transfer proposals | | `dismiss_proposal` | Dismiss a proposal | | `create_bank_account` | Save a new bank account | | `create_invoice` | Create a new invoice | | `update_invoice` | Update an invoice | | `list_invoices` | List invoices | | `get_invoice` | Get invoice details | | `send_invoice` | Send invoice to recipient | | `list_transactions` | List transaction history | | `get_transaction` | Get transaction details | | `attach_document` | Attach a file to a transaction | | `list_attachments` | List attachments | | `remove_attachment` | Remove an attachment | | `get_payment_details` | Get IBAN/ACH receiving details | | `share_payment_details` | Email payment details | MCP currently focuses on bank transfers and invoices. For crypto transfers and savings actions, use the CLI or HTTP API. *** ## Starter prompt Add this to your AI client's system prompt for best results: ```text theme={null} You are an assistant connected to the 0 Finance MCP server. ## Before proposing transfers 1. Call `get_balance` to check available USDC. 2. Call `list_saved_bank_accounts` to see destination options. ## Transfers - Use `propose_bank_transfer` to create a transfer proposal. - Never claim funds have moved—transfers require user approval in the dashboard. - Use `attach_document` to link invoices or receipts to proposals. ## Invoices - Use `create_invoice` to draft an invoice. - Use `send_invoice` to email it to the recipient. - Use `list_invoices` and `get_invoice` to check status. ## Receiving payments - Use `get_payment_details` to retrieve the user's IBAN/ACH info. - Use `share_payment_details` to email those details to a third party. ## Style - Summarize results clearly. - Ask before taking destructive or high-value actions. - Always confirm amounts and recipients before proposing transfers. ``` *** ## Example conversation **You:** Check my balance and pending invoices **Agent:** > I'll check your balance and invoices. > > **Balance:** 5,420.50 USDC spendable > > **Pending invoices:** > > * INV-001: \$2,500 from Acme Corp (due Jan 20) > * INV-002: \$1,000 from Beta Inc (overdue) **You:** Send a reminder to Beta Inc **Agent:** > I've sent a reminder email to Beta Inc for invoice INV-002 (\$1,000). **You:** Once that's paid, move \$3,000 to my EUR account **Agent:** > I'll propose a transfer of \$3,000 to your EUR account (ending in ...4521). > > ⚠️ This transfer requires your approval in the dashboard before it executes. Would you like me to create the proposal? *** ## Security model 1. **Read operations** — Balance, invoices, transactions execute immediately 2. **Transfer proposals** — Bank transfers require dashboard approval 3. **Immediate actions** — Invoice creation and sending happen instantly 4. **Audit trail** — Every action is logged with the API key used Never share your API key. It provides full read access and can create proposals on your behalf. *** ## Client-specific guides Detailed Cursor setup Claude Desktop setup Windsurf setup # Windsurf Source: https://docs.0.finance/mcp/windsurf Connect Windsurf to the 0 Finance MCP server ## Prerequisites * [Windsurf](https://codeium.com/windsurf) installed * 0 Finance API key from [Settings → API Keys](https://0.finance/settings) *** ## Step 1: Create the config file Create or edit `~/.codeium/windsurf/mcp_config.json`: ```json theme={null} { "mcpServers": { "zero-finance": { "command": "npx", "args": ["-y", "mcp-remote", "https://0.finance/api/mcp"], "env": { "API_KEY": "sk_live_your_api_key_here" } } } } ``` *** ## Step 2: Restart Windsurf Quit and reopen Windsurf to load the new MCP server. *** ## Step 3: Verify In Cascade, ask Windsurf to check your balance: ``` Check my 0 Finance balance ``` Windsurf should call `get_balance` and display your USDC balance. *** ## Available tools Once connected, Windsurf has access to all 0 Finance tools: | Tool | Description | | -------------------------- | ------------------------------ | | `get_balance` | Get spendable USDC balance | | `list_saved_bank_accounts` | List saved bank accounts | | `propose_bank_transfer` | Propose an outbound transfer | | `create_invoice` | Create a new invoice | | `send_invoice` | Send invoice to recipient | | `list_invoices` | List invoices | | `get_payment_details` | Get IBAN/ACH receiving details | | `share_payment_details` | Email payment details | See the [full tool list](/mcp/overview#available-tools) for all available tools. *** ## Troubleshooting ### "MCP server not found" 1. Check that `~/.codeium/windsurf/mcp_config.json` exists 2. Verify the JSON is valid 3. Restart Windsurf ### "Authentication error" 1. Verify your API key in the config 2. Check the key is active in [Settings → API Keys](https://0.finance/settings) ### Cascade not finding tools 1. Make sure you're using Cascade (the AI assistant) 2. Try explicitly asking "Use the 0 Finance tools to check my balance" 3. Restart Windsurf if tools aren't appearing # Development Setup Source: https://docs.0.finance/quickstart Run 0 Finance locally for development This guide is for developers contributing to 0 Finance. If you just want to use the CLI, see [Installation](/cli/installation). ## Prerequisites * Node.js v22.11+ * pnpm * Docker (for local database) *** ## Clone and bootstrap ```bash theme={null} git clone https://github.com/different-ai/zero-finance.git cd zero-finance ./scripts/bootstrap.sh ``` The bootstrap script: 1. Installs Node.js and pnpm if missing 2. Runs `pnpm install` 3. Sets up required tooling *** ## Environment setup Copy the example environment file: ```bash theme={null} cp packages/web/.env.example packages/web/.env.local ``` Ask the team for the required secrets: * `DATABASE_URL` — Postgres connection string * `PRIVY_APP_ID` and `PRIVY_APP_SECRET` — Auth provider * `BRIDGE_API_KEY` — Payment rails * Other service credentials *** ## Start the dev server ```bash theme={null} pnpm dev ``` The web app runs on [http://localhost:3050](http://localhost:3050). *** ## Verify the setup ```bash theme={null} curl http://localhost:3050/api/health ``` Expected response: ```json theme={null} { "status": "ok", "timestamp": "2026-01-12T00:00:00.000Z", "message": "Server is running" } ``` *** ## Alternative: Lite stack For a minimal Docker-based setup: ```bash theme={null} pnpm dev:lite ``` This uses `docker-compose.lite.yml` with local Postgres and mock services. *** ## Quality checks ```bash theme={null} # Type checking pnpm typecheck # Linting pnpm lint # Tests pnpm --filter @zero-finance/web test # Build pnpm --filter @zero-finance/web build ``` *** ## Next steps Test the CLI against your local server. Understand the HTTP API.