---
title: "For agents"
description: "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."
section: "CLI"
canonical: "https://banksync.io/docs/cli/for-agents"
---

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**

1. **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.
2. **Provide a scoped API key** — Set BANKSYNC\_API\_KEY in the agent's environment with a least-privilege key created in Settings > Developers. No interactive login is needed.
3. **Let the agent discover the surface** — The agent runs banksync commands --json and banksync schema --json to learn every command, flag, entity, and exit code, then calls commands with --json.

## The contract an agent can rely on

- **Stable JSON envelope** — Every read returns { "data": ..., "meta": ... }. The agent can always read .data and page with meta.cursor and meta.has\_more.
- **Machine-readable errors** — Failures print one JSON object on stderr and set a stable exit code, so the agent branches on failure without parsing prose.
- **No blocking** — In any non-interactive context the CLI never prompts. A missing argument is an error, not a hang.
- **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:

```json
{
  "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"
  }
}
```

- `data` holds raw entity fields (ISO dates, unformatted numbers), never humanized strings.
- `meta.cursor` and `meta.has_more` drive pagination; when they are null the endpoint does not paginate.
- `meta.schema_version` is the output-contract version. It is also emitted by `commands --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:

```json
{
  "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:

```bash
banksync commands --json
```

```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`):

```bash
banksync schema --json
banksync schema transaction --json
```

```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:

```bash
banksync tx list --bank amex --all -o ndjson
```

Each 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:

```bash
banksync api GET /v1/banks
banksync api GET /v1/feeds --query dataType=transactions
echo '{"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:

```bash
# 1. Confirm the credential and workspace
banksync whoami --json

# 2. Find the bank by name
banksync banks list --json | jq -r '.data[] | select(.name|test("Amex";"i")) | .id'

# 3. Pull the quarter's transactions as a stream
banksync 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 retry
```

Each 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](/docs/cli/scripting-and-ci): the same guarantees for shell automation.
- [Output formats](/docs/cli/output-formats): the envelope, NDJSON, and TOON.
- [Telemetry](/docs/cli/telemetry): what usage data is collected and how to disable it.
- [MCP server guide](/docs/mcp/overview): the same data exposed to agents over the Model Context Protocol.
