Log in with your browser
atoa login opens the dashboard, you approve, done. No token to copy-paste.Test webhooks locally
atoa webhooks trigger PAYMENTS_STATUS fires a fake event at your sandbox URL — no real payment needed.Two credential types
Shell completion
Prerequisites
- Node.js 20 or later — verify with
node --version - An Atoa merchant account and a desktop browser on the same machine (login is browser-based). No account yet? Run
atoa signup, or see the Getting Started guide.
Installation
- npm
- yarn
- pnpm
~/.atoa/auth/, readable only by
your user account.First-time setup
Pair the CLI with your Atoa account through your browser:atoa business use <id> afterwards). A profile is created, named after your business.
atoa login requires an interactive terminal (TTY) and a desktop browser
on the same machine — there is no headless/CI login path (see
CI / automation).atoa signup walks you through account creation (email + one-time code) and business onboarding — no prior login needed.
Confirm you’re logged in
The dual-credential model
The CLI holds two independent credential types per profile:atoa login always creates the login session. The SDK key is optional — add it whenever you need the payments/data commands:
atoa keys create requires an admin role on the business. The apiSecret is stored locally under ~/.atoa/auth/, so the CLI picks it up automatically on later commands.
Which login does each command need?
atoa get/post/delete authenticate with the SDK key, not
the browser session — they’re for calling the payments API directly, so
atoa keys create must have been run first.Environments and profiles
A single machine can hold credentials for many businesses (profiles) and both environments (sandbox + production). The CLI keeps them separate so you can’t accidentally run a production refund while testing locally.Per-profile settings
CLI state is stored entirely under profiles. To change which env a profile defaults to, useatoa profile set. To wipe everything, use atoa reset.
Inspect state
Change the default env on a profile
Reset everything
Core workflows
Create a payment
paymentRequestId, the customer-facing paymentLink, and a qrCodeUrl.
Check payment status (poll until terminal)
--poll keeps polling every 5 seconds until the status is no longer PENDING, up to 3 minutes.
List recent transactions
Refund a payment
Manage customers and saved cards
Account management
These run on your browser login — no SDK key needed.Switch the active business
If your account owns several businesses, account commands operate on one at a time:Manage login sessions
Everyatoa login registers a device session server-side. Audit and revoke them:
SDK key lifecycle
Team, onboarding & business setup
Staff and roles
atoa staff add and atoa staff invite are the same command under two names — both create
the staff member and notify them.
atoa staff update or atoa roles update with no arguments on a terminal and the CLI
prompts for each field with the current value already filled in — press Enter to keep it.
--permission takes permission ids, and atoa roles permissions is where they come from —
every other view shows only names, so start there when scripting a role. Each row also carries a
requires list, which is why a role can end up with more permissions than you asked for.
KYB (Know Your Business) verification
link
commands open the browser for you and print the URL as well, so there’s something to fall back on
if no browser can be launched.
Bank accounts
atoa bank add with no flags on a terminal and it walks you through it — pick your bank, enter
the details, confirm. Your first bank account is set as the primary automatically.
The primary account is where Atoa settles your payments. Pass --setPrimary on a later account to
move settlement to it — this also re-points any store currently linked to the previous account.
If a one-time code is required, atoa bank add sends it and exits with code 9. Re-run the same command with
--otp to complete it:
Stores
Allstores subcommands need a browser login:
Google Business listing
Pair a store with its Google Business listing so reviews flow back to Atoa:placeId from those results. The listing’s name and address are
stored exactly as the CLI sends them and are never looked up from the id, so --placeId on its own
exits with code 3 — the search is what supplies them. Pass the same --search text to both commands.
Linking a store that already has a listing replaces it — there’s no warning, so check with
--dryRun first. atoa google unlink reverses it.
atoa google search works on any account. link, unlink and locations need the Google
Review add-on and exits with code 8 without it — atoa addons list shows your plan’s limits. Once the
plan allows it, locations still exits with code 4 until the merchant connects their Google Business
account, which happens in the dashboard rather than the CLI.Direct Debit
Atoa collects your subscription fees by Direct Debit. A business can hold one mandate — once it’s active, setup refuses rather than creating a second one.--acceptMandate:
--addressLine2 is optional. The name is the account holder’s own, not the business’s —
the mandate is signed by an individual — and it’s capped at 20 characters here.
Notification preferences
on, off, or unavailable — Atoa doesn’t send every channel for
every topic, and an unavailable channel can’t be switched on.
Add-on plans
Checkout branding and SMS sender name
Onboard a brand-new account
--acceptTerms records acceptance of the Privacy Policy
and Terms of Service; --marketing is a separate opt-in.
--startNew creates a second business rather than resuming an existing signup.
--businessStructure is Limited Company or Charity. --industry and --monthlyTurnover are
server-defined lists that vary by environment, so the values above are illustrative — pass the
option’s name and, if it doesn’t match, the CLI exits with code 3 listing every valid one to choose from.
atoa signup is the one command that needs no prior login — it creates
the account and logs you in as part of the flow.Payment links
Create a hosted checkout link (browser login;--storeId is required):
--amount is in GBP (e.g. 10.50 for £10.50), not pence.Idempotency — duplicate-charge protection
The CLI auto-generates a freshIdempotency-Key: <uuidv4> header on every POST/PUT/PATCH, so a network blip on the response never double-charges a customer. You don’t need to think about this for interactive use.
For CI / scripted retries — where one logical operation may run more than once (a job restarts) — pass a stable --idempotencyKey so a re-run produces the same key and the server deduplicates:
atoa payments create, atoa refunds create, atoa card-on-file charge, and the generic atoa post. Every other POST still sends an auto-generated key, so all retries are safe by default.
Trigger test webhook events
The CLI can fire a synthetic webhook payload at your registered sandbox URL — same shape as production — without you actually creating a real payment.atoa webhooks create. Inspect the request on your endpoint (e.g. webhook.site) to verify your signature-check, routing logic, and response shape work end-to-end.
Supported events
Customising the dispatched body
--env production,
the CLI warns you and proceeds with your active profile’s sandbox key
anyway — this prevents accidentally driving fake events at your live customers.Using the CLI in CI
atoa login needs an interactive browser, so a CI runner cannot log in itself. Instead, provision credentials on a workstation once, then hand the files to the runner:
- On a workstation:
atoa login, plusatoa keys createif the job hits SDK/data commands. - Copy
~/.atoa/auth/to a location the runner can read. - Point the runner at it with
ATOA_HOME(credentials live in$ATOA_HOME/.atoa/auth/).
--output json for machine-readable output (the default is a human-readable table) and --dryRun to resolve the request without sending it. --yes is required on destructive commands in a non-TTY context.
--output does more than pick a format — it also puts the CLI into non-interactive
mode, so no prompt is ever opened. A command that would have asked for a value reports the
missing flag by name and exits with code 3 instead. This is what makes the CLI safe to drive
from an AI agent: it never blocks on a prompt the agent cannot see, and a missing value comes back
as a named flag the agent can supply on the next run.Exit codes
The CLI uses POSIX-style exit codes so pipelines can branch on the failure mode:Environment variables
Generic HTTP verbs
When you need to hit an endpoint the CLI doesn’t yet wrap (or you want full control over the request body), use the raw verbs. They authenticate with the SDK key, so runatoa keys create first:
How -d and --data work
These are two different ways to build the request body. Pick whichever fits the call:
atoa post /api/webhook/merchant --data @webhook.json reads webhook.json from the directory you ran the command in, takes its contents as the JSON request body, and POSTs it to /api/webhook/merchant. Example file:
-d and --data are mutually meaningful — they both contribute to the same
body. If you pass both, --data wins and -d fields are ignored. Use one or
the other per command.Passing nested objects and arrays
Some API fields aren’t a single string or number — they’re objects (e.g.authentication, consumerDetails) or arrays (e.g. paymentMethod, storeIds). How you pass these depends on which kind of command you’re using.
On typed commands (e.g. atoa payments create)
Use the command’s own named flags. Quote complex values so the shell passes them to the CLI intact:
.exe / .cmd programs, so the bash-style '{"key":"value"}'
doesn’t survive intact. Use backslash-escaped double quotes inside the
single quotes instead:"Jane Doe"), wrap the whole
backslash-escaped JSON in an extra pair of outer double-quotes so Windows
doesn’t split at the space:On generic verbs (e.g. atoa post /api/...)
The generic verbs accept any JSON body. Three ways to specify it:
{, ", and spaces pass through
untouched.PowerShell: same rule, but escape any inner single quote by
doubling it ('It''s urgent' → It's urgent).--env, --output, --dryRun, --verbose). Useful for:
- New endpoints that haven’t gained a typed wrapper yet
- Debugging —
--verboseprints the redacted request line so you can see exactly what was sent - CI scripts where you want explicit control over the exact body sent
Shell completion
Enable TAB-completion of commands, flags, profile names, and IDs:- bash
- zsh
- PowerShell
<TAB> mid-command:
Command reference
Authentication & account setup
Authentication & account setup
Business, sessions & SDK keys
Business, sessions & SDK keys
Team, KYB & bank accounts
Team, KYB & bank accounts
Add-on plans
Add-on plans
Direct Debit
Direct Debit
Google Business listing
Google Business listing
Notifications & branding
Notifications & branding
Payment links
Payment links
Profiles
Profiles
Payments
Payments
Customers, Cards & Card-on-File
Customers, Cards & Card-on-File
Refunds
Refunds
Webhooks
Webhooks
Bank Feed (Open Banking)
Bank Feed (Open Banking)
Payouts
Payouts
Utilities
Utilities
--help is authoritative):
Troubleshooting
401 or 'No profile is configured' on every command
401 or 'No profile is configured' on every command
atoa login for a login session,
atoa keys create for an SDK key. See the dual-credential
model.'Timed out acquiring lock on …/session.json.lock'
'Timed out acquiring lock on …/session.json.lock'
atoa process is mid-write. If none is running (e.g. one crashed),
remove the stale lockfile:'Refusing to read …/session.json: insecure permissions' (POSIX)
'Refusing to read …/session.json: insecure permissions' (POSIX)
chmod 600 ~/.atoa/auth/session.json.atoa webhooks trigger says 'No webhook subscription configured'
atoa webhooks trigger says 'No webhook subscription configured'
TAB completion doesn't work
TAB completion doesn't work
-
Re-source your shell config after install (e.g.
source ~/.bashrc, or open a new PowerShell window). -
Confirm completion is registered:
-
For PowerShell specifically, make sure you ran
| Out-String | Invoke-Expressionafteratoa completion pwsh— the script must be evaluated, not just printed.
Want to nuke everything and start fresh
Want to nuke everything and start fresh
Need Help?
Contact our team at[email protected] or use chat support on the Dashboard.