{"schema_version":"1.0","publisher":"Primitive SDKs","canonical_url":"https://test.abhinandan.one/cli-overview/cli-payments","markdown_url":"https://test.abhinandan.one/cli-overview/cli-payments.md","article":{"id":"6c85e5d2-2501-484e-931a-fb591d0cbe6a","article_slug":"cli-payments","parent_article_slug":"cli-overview","parent_article_title":"What is the Primitive CLI?","kind":"guide","published_at":"2026-08-11T18:54:54.948031+00:00","keywords":["primitive payments register-payout-address","primitive payments charge","primitive payments pay-email","primitive payments create-email-challenge","PRIMITIVE_X402_PRIVATE_KEY","primitive payments update-spend-policy"],"meta_description":"Register a payout address, charge or pay an x402 USDC challenge, and manage spend policy from the terminal with the primitive payments-* CLI commands.","og_image_url":null,"source_file_paths":[],"recording_id":null,"replayable":false,"task_name":"x402 Payments from the CLI","category":"CLI","summary":null,"description":"Register a payout address, create and pay x402 USDC challenges (including the email-native flow), and inspect settlements and spend policy directly from the terminal with the primitive payments command group.","content_kind":"repo_page","content_markdown":"The `primitive payments` command group drives the same non-custodial [x402 payment model](x402-payments-overview) as the SDKs, from your shell. Reach for it when you want to register a payout address, request or settle a USDC payment, or inspect settlements and spend policy without writing code, for example scripting a payment into CI, or testing a payment flow before wiring it into a Function.\n\nOne agent registers a payout address and requests a payment with `charge`; the paying agent signs locally with its own wallet key and settles with `pay`. The signing key never leaves your machine, it is read from an environment variable or flag and used only to sign locally. Networks are `base` (mainnet) and `base-sepolia` (testnet); amounts take either a human USDC value (`--amount-usdc 0.01`) or token base units (`--amount 10000`, since USDC has 6 decimals). Your org is resolved automatically from your API key, so payout registration takes no org flag.\n\n<Note>\n\nThis page assumes you already have the CLI installed and authenticated. See [What is the Primitive CLI?](cli-overview) and [Authentication: login, signup, logout, whoami](cli-authentication) if you haven't set that up yet.\n\n</Note>\n\n## Set your wallet key\n\nThe signing commands (`register-payout-address`, `pay`, `pay-email`, `pay-email-step`) need a wallet private key to sign locally. Set it as an environment variable so it never lands in shell history or the process list:\n\n```bash\nexport PRIMITIVE_X402_PRIVATE_KEY=0x...\n```\n\nA `--private-key` flag exists as an escape hatch for scripted use, but the environment variable is preferred.\n\nThe non-signing commands (`charge`, `get-challenge`, `list-payout-addresses`, `get-spend-policy`, `update-spend-policy`) need only your Primitive API key (set via `primitive login` or `PRIMITIVE_API_KEY`); they don't touch the wallet key at all.\n\n## Register a payout address (payee, one time)\n\nDo this once per org before you ever call `charge`. It signs an ownership message locally with your wallet key and proves control of the address; the recovered address becomes your org's default payout destination for that network.\n\n<Steps>\n\n<Step title=\"Export your wallet key\">\n\n```bash\nexport PRIMITIVE_X402_PRIVATE_KEY=0x...\n```\n\n</Step>\n\n<Step title=\"Register the address\">\n\n```bash\nprimitive payments register-payout-address --network base-sepolia --label treasury\n```\n\nThe command prints a human-readable summary by default. Pass `--json` for the raw registration object.\n\n</Step>\n\n</Steps>\n\n<Tip>\n\nYour org id is resolved automatically from your API key, payout registration takes no `--org` flag.\n\n</Tip>\n\n## Create a payment challenge (payee)\n\n`charge` creates an [x402 payment challenge](x402-payments-overview) with a human USDC amount and prints the challenge JSON to stdout, with a one-line summary on stderr:\n\n```bash\nprimitive payments charge --network base-sepolia --amount-usdc 0.01\n```\n\nCapture the challenge JSON to hand to the payer:\n\n```bash\nprimitive payments charge --network base-sepolia --amount-usdc 0.01 > challenge.json\n```\n\n`charge` is the friendly verb that matches the SDKs' `charge()` / `Charge()` and accepts `--amount-usdc`. The lower-level `create-challenge` command takes base-unit `--amount` instead; either creates a challenge.\n\n## Pay a challenge (payer)\n\n`pay` signs and settles the challenge locally, using your wallet key. It reads the challenge inline, from a file, or piped on stdin:\n\n```bash\nprimitive payments pay --challenge-file challenge.json\n```\n\n```bash\ncat challenge.json | primitive payments pay\n```\n\n`pay` prints a human-readable summary by default, and raw JSON with `--json`.\n\n<Warning>\n\n`pay` needs `PRIMITIVE_X402_PRIVATE_KEY` (or `--private-key`) set to your wallet's private key. Anyone with that key can sign payments from your address, keep it out of shell history and CI logs.\n\n</Warning>\n\n## Inspect a challenge or your payout addresses\n\nLook up a challenge by id, or list every payout address registered for your org:\n\n```bash\nprimitive payments get-challenge --id <challenge-id>\nprimitive payments list-payout-addresses\n```\n\n## Email-native payments\n\nThe [email-native x402 payment](x402-payments-overview) flow rides a real email thread instead of an out-of-band challenge id. The payee issues the challenge as an email; the payer signs it into an `interaction.json` payment step and sends it back.\n\n<Steps>\n\n<Step title=\"Payee: issue the challenge over email\">\n\n`create-email-challenge` takes `--amount` in token base units only, unlike `charge` it has no `--amount-usdc`. USDC has 6 decimals, so multiply by 1,000,000: 0.01 USDC is `--amount 10000`.\n\n```bash\nprimitive payments create-email-challenge --from payee@your-domain.example \\\n  --to payer@their-domain.example --amount 10000 --network base-sepolia\n```\n\n</Step>\n\n<Step title=\"Payer: sign and send in one step\">\n\n`pay-email` is the recommended payer path: it signs the challenge locally with your wallet key AND sends the signed `interaction.json` attachment, so you skip the manual sign-then-send dance. `--in-reply-to` is the inbound challenge email you received; it's fetched to address the payment to the payee, with `From` defaulting to the address the challenge was sent to. The send is not threaded under the challenge itself, the payment associates by `interaction_id` instead.\n\n```bash\nprimitive payments pay-email --challenge-file challenge.json \\\n  --in-reply-to <inbound-challenge-email-id> --wait\n```\n\nThe message carries a short default note alongside the attachment; pass `--body` to customize it.\n\n</Step>\n\n</Steps>\n\nFor advanced cases where you need to deliver the signed envelope yourself (for example attaching it with `primitive send --attachment`), sign only without sending:\n\n```bash\nprimitive payments pay-email-step --challenge-file challenge.json > interaction.json\n```\n\n<Tip>\n\nAll four signing commands (`register-payout-address`, `pay`, `pay-email`, `pay-email-step`) accept `--json`. `pay-email` and `pay-email-step` print JSON by default (the send result and the `interaction.json` bytes, respectively); `--json` switches them to a fuller envelope object.\n\n</Tip>\n\n## Read and update the spend policy\n\nThe [spend policy](x402-payments-overview) guards outbound payments with a kill-switch, per-payment and daily caps in token base units, and a payee allowlist. Read the current policy, or update it, the update merges, so omitted fields keep their current value:\n\n```bash\nprimitive payments get-spend-policy\nprimitive payments update-spend-policy --max-per-payment 5000000\n```\n\nFor the full flag list of any command, run:\n\n```bash\nprimitive payments <command> --help\n```\n\n## Next steps\n\n<CardGroup cols={2}>\n\n<Card title=\"x402 Payments Overview\" href=\"x402-payments-overview\">\n\nUnderstand the non-custodial payment model, challenge lifecycle, and spend policy shared by every SDK and the CLI.\n\n</Card>\n\n<Card title=\"Handling Payment and Interaction Webhook Events\" href=\"node-sdk-webhook-events\">\n\nReceive payment.settled and interaction.x402.* webhook events when a challenge you created gets paid.\n\n</Card>\n\n<Card title=\"Charging and Registering Payout Addresses\" href=\"node-sdk-x402-charging\">\n\nSee the equivalent register-payout-address and charge() flow from the Node.js SDK.\n\n</Card>\n\n<Card title=\"What is the Primitive CLI?\" href=\"cli-overview\">\n\nGet oriented on the CLI's command surface and how it relates to the Node SDK and api-core.\n\n</Card>\n\n</CardGroup>","canonical_base_url":"https://test.abhinandan.one","seo_indexing_enabled":true,"last_modified":"2026-08-21T18:22:43.359885+00:00","video_url":null,"voiceover_url":null,"tools_used":[],"demonstrated_by":[],"steps":[],"related_links":[],"intro":null,"prerequisites":[],"verification":[],"troubleshooting":[],"suggest_edit_url":null,"raise_issue_url":"https://github.com/abhi-browzer/primitive-sdks/issues/new?title=Docs+feedback%3A+x402+Payments+from+the+CLI&body=Page%3A+https%3A%2F%2Ftest.abhinandan.one%2Fcli-payments","page_feedback_enabled":true,"verified_ref":null,"verified_at":"2026-08-11T18:38:45.205849+00:00"}}