Skip to content
Finanly

Connectors

Every source you run on, one ledger of truth.

Banks, stores, freight and your ledger — each connector an isolated service with its own secrets, all normalized into one canonical model.

A connector is not a logo. It is a service with its own secrets, a contract it must honour, and an audit trail for every run.

8connectors live in production
1credential scope per connector — never shared
0public routes to any connector
24hnightly sync-all cadence, plus on-demand sync

How a connector works

Four rules, every connector.

The internal contract is the same for a bank, a store and a freight forwarder. That is what makes new ones cheap to add — and old ones boring to operate.

  1. 01

    Isolated credential service

    Each connector is its own stateless FastAPI service on the private network. It holds only its own API keys or OAuth tokens; nothing else in the stack can read them.

  2. 02

    Normalized to the canonical schema

    Connectors fetch and normalize — accounts, transactions, payouts, orders, shipments — and return objects. core-api owns persistence, tenancy and authorization.

  3. 03

    Idempotent sync and backfills

    Every side-effect call carries an Idempotency-Key and correlation IDs. Nightly sync-all, on-demand sync, and backfills with explicit ISO-8601 ranges; re-runs never duplicate.

  4. 04

    Audited, tenant-bound

    Calls carry a short-lived internal JWT scoped to one tenant and one connector audience. Sync runs, webhook receipts and exports write audit events.

Ledger connectors

ERPNext today. QuickBooks and Xero by contract.

Ledger connectors implement a capability matrix. ERPNext is the full reference implementation; QuickBooks Online and Xero start with the close MVP set and expand.

capabilityERPNextQuickBooks OnlineXero
ledger.accounts.readFULLMVPMVP
ledger.dimensions.readFULLMVPMVP
ledger.counterparties.readFULLMVPMVP
ledger.postings.createFULLMVPMVP
ledger.invoices.read / create / sendFULLLATERLATER
ledger.reports.balance_sheet / profit_loss / trial_balanceFULLLATERLATER
ledger.metadata.* (custom fields, options, lookups)FULLLATERLATER
ledger.facts.* (sync GL, invoices, parties into canonical store)FULLLATERLATER

FULL = parity with the current close. MVP = the first capability slice for a new ledger. LATER = follows once the MVP slice is stable.

Bring your own

A connector is ~one FastAPI service.

Implement /health, /ready, /capabilities and the sync endpoints from the internal contract; validate the tenant claim; honour Idempotency-Key; redact secrets in logs. core-api does the rest — auth, gating, persistence, audit.

  • Internal JWT with aud = your connector name
  • X-Request-Id, X-Correlation-Id, X-Tenant-Id on every call
  • Return normalized objects; never write to the database
connector-yourbank · internal only
GET  /health            → 200 (liveness)
GET  /ready             → 200 when creds resolve
GET  /capabilities      → ["banking.accounts.read",
                            "banking.transactions.read"]
POST /v1/sync           Idempotency-Key: <stable>
     X-Tenant-Id must equal JWT.tenant_id
     → { accounts:[…], transactions:[…], cursor }

FAQ

Straight answers

Which banks can I connect?

Mercury directly through its API, Wise directly, and any institution Plaid supports through Plaid Link. Balances can be refreshed on demand; transactions sync nightly and on request.

Is QuickBooks Online or Xero supported today?

Not yet. ERPNext is the ledger of record in production today. QuickBooks Online and Xero follow the same capability contract, starting with accounts, dimensions, counterparties and postings.

What does the Shopify connector actually do?

Payouts with fee and refund decomposition, disputes, orders, products, customers with geography, and fulfillment events that become inventory movements and COGS. It is built for the store it reconciles; we don't claim 'any Shopify store' until we've run yours.

And Flexport?

Billing rows from the Reports API reconciled into purchase invoices and payments, plus orders, inventory and inbound shipments that feed landed cost.

Where are the credentials stored?

Inside the connector's own service, resolved from its environment or secret store. core-api can check credential status but never reads the secret. Missing credentials are surfaced on the Integrations page, never silently skipped.

Can I trigger a backfill for a date range?

Yes — from Settings → Integrations, with an explicit start and end date, when manual sync is enabled for your tenant. Backfills are idempotent: re-running a range doesn't duplicate rows.

Do connectors receive webhooks?

Plaid does: core-api exposes a per-tenant, per-integration receiver that verifies the Plaid signature before enqueuing a sync. Stripe billing webhooks are verified the same way. Other connectors are pull-based on a schedule.

What is GA4 doing in a finance tool?

Traffic and conversion context next to revenue — sessions, conversions and channel mix as dimensions in the semantic layer, so 'revenue per session by channel' is a question, not a spreadsheet.

How do I add my own source?

Write a small internal service that implements the connector contract and register it. Ingest connectors return normalized objects; core-api persists and gates. See the contract guide in Support.

Connect your first source in an afternoon.

Private beta. Tell us where to send your access, and which company you close first.