For agents
Give an AI agent the BankSync CLI and an API key: a stable JSON contract, machine-readable errors and exit codes, runtime command and schema discovery, and a raw API escape hatch.
5 min read
On this page
The BankSync CLI is a first-class tool for AI agents, not only for humans. A shell tool plus an API key gives an agent everything it needs to read financial data, manage feeds, and trigger syncs, with a contract stable enough to build on. In practice, a well-designed CLI is often a better agent surface than a bespoke API integration: the output is structured, the errors are machine-readable, and the whole command surface is discoverable at runtime.
Give your agent the CLI and a key#
Wire it up
Install the CLI
Drop the standalone binary into the agent's environment with the one-line installer (curl -fsSL https://banksync.io/install.sh | sh). It is self-contained, so the environment needs no Node or other runtime. See installation.Provide a scoped API key
SetBANKSYNC_API_KEYin the agent's environment with a least-privilege key created in Settings > Developers. No interactive login is needed.Let the agent discover the surface
The agent runsbanksync commands --jsonandbanksync schema --jsonto learn every command, flag, entity, and exit code, then calls commands with--json.
The contract an agent can rely on#
Stable JSON envelope
{ "data": ..., "meta": ... }. The agent can always read .data and page with meta.cursor and meta.has_more.Machine-readable errors
No blocking
Runtime discovery
commands --json and schema --json expose the entire surface, so an agent needs no out-of-band docs to act.The JSON envelope#
Ask for JSON with --json (any pipe also triggers it). Every read has the same top-level shape regardless of the command:
{ "data": [ { "id": "txn_1", "date": "2026-03-01", "description": "UBER", "amount": -24.5, "currency": "USD" } ], "meta": { "count": 1, "cursor": "eyJvIjoxMDB9", "has_more": true, "schema_version": "1", "api_version": "v1" }}dataholds raw entity fields (ISO dates, unformatted numbers), never humanized strings.meta.cursorandmeta.has_moredrive pagination; when they are null the endpoint does not paginate.meta.schema_versionis the output-contract version. It is also emitted bycommands --json, so an agent can assert the contract it was built against.
Errors and exit codes#
In JSON mode, an error is a single object on stderr while stdout stays empty:
{ "error": { "code": "rate_limited", "message": "Too many requests.", "status": 429, "hint": "Rate limited. Retrying automatically; slow down or pass --no-retry.", "retry_after": 60 }}The process exit code classifies the failure so an agent can react programmatically:
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Generic or unexpected error (including 5xx) |
| 2 | Invalid usage or bad request (400) |
| 3 | Unauthenticated or forbidden (401 or 403) |
| 4 | Resource not found (404) |
| 5 | Conflict (409) |
| 6 | Semantic validation failed (422) |
| 7 | Rate limited (429) |
| 8 | Provider does not support this capability (501) |
| 9 | Backend unavailable or consent required (503) |
An agent that gets exit code 3 knows to check the credential; a 5 on a sync means it should retry with --force; a 7 means back off.
Discover the whole surface at runtime#
An agent does not need to read documentation to act. Two commands expose everything, and neither emits telemetry.
Command catalog#
banksync commands --json returns the entire command tree, plus the exit-code map and the output-contract version:
banksync commands --json{ "cli": "banksync", "output_contract_version": "1", "api_version": "v1", "exit_codes": { "0": "Success", "3": "Unauthenticated or forbidden (401/403)", "5": "Conflict (409)" }, "commands": [ { "id": "transactions list", "summary": "List transactions for a bank or a single account, resolving names or partial ids.", "aliases": ["tx"], "args": [{ "name": "bid", "required": false, "description": "Bank id or name." }], "flags": [ { "name": "from", "type": "option", "required": false, "description": "Start date YYYY-MM-DD." }, { "name": "all", "type": "boolean", "required": false, "description": "Fetch all pages (follows the cursor)." } ] } ]}The agent enumerates command ids, required args, flag names, types, and enum options directly from this output, then constructs a call.
Entity schema#
banksync schema --json lists the entities, and banksync schema <entity> --json returns the default columns (the selectable dot-paths for --fields):
banksync schema --jsonbanksync schema transaction --json{ "data": { "entity": "transaction", "default_columns": ["date", "description", "amount", "currency", "category", "pending"] }, "meta": { "count": 1 }}Known entities include bank, account, balance, transaction, trade, holding, order, loan, feed, job, enrichment, integration, and institution.
Stream large reads with NDJSON#
For a large pull, -o ndjson emits one raw entity per line, which an agent can consume incrementally without buffering the whole response:
banksync tx list --bank amex --all -o ndjsonEach line is a complete JSON object, ideal for streaming into a processing loop.
The raw API escape hatch#
Any endpoint that does not yet have a dedicated command is reachable through banksync api, which reuses the same auth, retries, and output path. It takes an HTTP method and path, an optional body (inline JSON, @file, or - for stdin), and repeatable --query params:
banksync api GET /v1/banksbanksync api GET /v1/feeds --query dataType=transactionsecho '{"name":"My rule"}' | banksync api POST /v1/enrichments --data -In a machine format, the raw response body is echoed verbatim, so an agent sees exactly what the API returned. This future-proofs the surface: an agent is never blocked by a missing command.
Non-interactive guarantees#
Deterministic and quiet by default
When stdout is not a terminal, the CLI emits JSON, never prompts, disables color and spinners, and
sends any notice to stderr, so stdout is byte-clean for parsing. You can force this posture
explicitly with --no-input, --json, and --quiet. Destructive commands still require --yes,
which prevents an agent from deleting or cancelling by accident.
A worked example#
An agent asked to summarize spending would typically:
# 1. Confirm the credential and workspacebanksync whoami --json
# 2. Find the bank by namebanksync banks list --json | jq -r '.data[] | select(.name|test("Amex";"i")) | .id'
# 3. Pull the quarter's transactions as a streambanksync tx list --bank amex --from 2026-01-01 --to 2026-03-31 --all -o ndjson
# 4. On exit code 3, stop and report an auth problem; on 7, back off and retryEach step is structured input and structured output, with a clear exit code, so the agent can chain steps and recover from failure on its own.
Next steps#
- Scripting and CI: the same guarantees for shell automation.
- Output formats: the envelope, NDJSON, and TOON.
- Telemetry: what usage data is collected and how to disable it.
- MCP server guide: the same data exposed to agents over the Model Context Protocol.
Use this page with your AI assistant
Every BankSync doc is available as plain Markdown for agents and LLMs.