Satchel MCP docs

Sandbox reference

The sandbox API endpoints, seeded data, in-memory store semantics, and the documented known simplifications.

The sandbox (app/api/sandbox/*) is a synthetic implementation of the same API contract the real FintechLab Client Office API serves — same endpoint paths, same DTO field names, same enums, same auth flow. It exists so the MCP tools have something real to run against before a live credential ever enters the picture.

Endpoints

EndpointPurpose
POST /tokenAuthenticate with X-Username / X-Password; returns an API token (also echoed in the X-Auth-Token response header).
GET /accountsList accounts, with balances.
GET /cardsList cards.
GET /transactions?page=&records=List transactions, paginated.
GET /transactions/{id}A single transaction's full detail.
POST /transfer/internalMove money between the customer's own accounts (write demo — see below).

These are the same six operations the MCP tools call; there is nothing in the sandbox that the tools don't exercise.

Seeded data

Each sandbox instance seeds a small, fictional dataset: a handful of accounts across a few currencies, a couple of cards, and roughly 35–40 transactions spread across a few weeks — groceries, salary, subscriptions, transfers, an ATM withdrawal, a refund — enough variety for satchel_financial_summary's merchant grouping and subscription detection to have something real to find.

In-memory store semantics

Sandbox state lives entirely in server process memory. It reseeds on every restart — there is no database and nothing to migrate. A shape change to the seed data or DTOs bumps an internal store-version marker specifically so a running dev server picks up the new shape on its next restart instead of silently continuing to serve a stale one.

The one exception is sandbox API keys issued through the landing page's waitlist flow, which persist to a local JSON file (gitignored) so a key survives a server restart — keys are not yet revocable server-side.

The write demo

POST /transfer/internal is a real write within the sandbox's own state: a successful call mutates account balances and prepends a matching pair of transactions to the ledger, so a follow-up read reflects it immediately. This is the sandbox side of satchel_move_money — see that page for the tool-level gating (SATCHEL_ALLOW_WRITES) that has to be enabled before this endpoint is ever called at all.

Known simplifications

The sandbox matches the real swagger on everything that matters for building against it: auth flow, endpoint paths, DTO field names, enums (payment_state, payment_type, payment_role, account_type), unsigned money, and the real transfer request/response shapes. A short list of things are deliberately simplified for the MVP — documented here, not hidden, and each one disappears the moment you flip to live:

  • create_time is served as a plain ISO-8601 string, not the real swagger's more verbose LocalDateTime object.
  • Cross-currency transfers through satchel_move_money settle at a flat 1:1 rate, with no FX conversion or exchange_id validation.
  • Card locator fields use network names (mastercard / visa) rather than the real API's prepaid / debit product-type enum.
  • Sandbox state is in-memory and resets on restart; waitlist-issued sandbox keys are not yet revocable server-side.

Flipping to live (see Overview) means the real gateway supplies the real thing for every item above — none of these are architectural limits, only sandbox-fidelity trade-offs for the MVP.

On this page