Data moves between your systems, and the numbers agree.

Etalon collects from banks, advertising accounts, trackers and internal tools, keeps one canonical copy of the records, checks that the figures agree across systems, and delivers the result where it is needed — another system, a warehouse, a dashboard, a Slack message.

Banking Advertising Attribution Anything else raw payload canonical row agreed figure Your systems Warehouse Files Alerts Banking Advertising Attribution Anything else raw payload canonical row agreed figure Your systems Warehouse Files Alerts

Collect, agree, deliver.

Collect

Scheduled pulls, signed webhooks and file drops land every record in one place, with the raw payload kept next to the parsed row.

Agree

Sources are matched on the keys they share. The difference between two systems becomes a column you can sort, filter and alert on.

Deliver

The same records go onward: into another system through its API, into a warehouse, into a spreadsheet, into a Slack message at nine in the morning.

Four systems. Four numbers.

Advertising account 12,480.00
delivered spend
Bank 12,655.20
settled to the card
Accounting 11,900.00
recognised cost
Attribution 1,204
attributed installs

Illustrative figures

Each of those numbers is correct inside the system that produced it. The advertising account counts what it delivered, the bank counts what it settled, the tracker counts what it attributed, the books count what was recognised.

No system owns the number that spans all four. Once a month somebody exports four files, lines them up by hand and reports the result, then does the same work again in thirty days, because none of it was written down anywhere a machine can read.

That number lives in Etalon and stays current.

Five stages, the same for every source.

A bank statement, an advertising account and a task tracker travel the same path. Only the connector is written per source.

Connect credentials, sealed 01 Pull leased, backed off 02 Canonicalise typed row + raw 03 Agree diff as a column 04 Deliver API, files, alerts 05
  1. 01

    Connect

    Credentials are entered once, sealed with authenticated encryption and kept inside your own instance. OAuth sources refresh themselves and persist the rotated token, so a connection made in March is still live in December.

  2. 02

    Pull

    Every connection carries its own schedule in the database and is claimed under a lease before anything is fetched. Two processes can run side by side and each account is still pulled once.

  3. 03

    Canonicalise

    Each record lands as a typed row beside the payload it came from. Everything is kept, so any figure on any screen opens down to the exact response the source returned.

  4. 04

    Agree

    Two sources are joined on account and period, campaign and day, order and payment. The gap between them is stored, watched and reported like any other measure.

  5. 05

    Deliver

    Rows are pushed into the systems that need them, exported on a schedule, rendered as a pivot in the browser and announced in Slack when a figure crosses a threshold you set.

Anything with an interface can be a source.

Etalon connects through whatever a system offers: a REST API, an OAuth application, a signed webhook, a scheduled file drop, or a login and a monthly statement that somebody downloads. The categories below are the shapes we meet most often; which providers sit inside them is decided by your stack.

Banking

APIOAuthFileManual

Cards and wallets

APIFile

Crypto and exchanges

API

Advertising accounts

OAuthAPI

Attribution and mobile

APIFile

Product analytics

OAuthAPI

Accounting and ERP

APIFile

CRM, tasks, forms

APIWebhook

Anything with an interface

Custom

We build the connector

Building the integration is part of the service. You name the system, we write the connector into your instance for a fixed fee, and from that day it is scheduled, monitored and alerted like everything else in the pipeline.

Ask about a source ↗

Records go back out to the systems that need them.

Etalon writes the same records forward, on a schedule or the moment they land, and gives every delivery the retry and alerting it gives a pull.

Another system

Records are written through its own API, mapped to its objects and idempotent on retry.

Warehouse or database

A schema you can query directly, kept current on the same schedule as the pull.

Files

XLSX and CSV on a schedule, to a bucket or an inbox, matching what the screen shows.

Your endpoint

A signed webhook per event, with delivery retried and dead-lettered like everything else.

Slack

Cards on an event, threshold alerts, a morning digest of what moved overnight.

#finance-alerts 09:00

Spend and settlement disagree

Paid social+175.20

Periodthis month

2 sources compared · opened from the reconciliation view

outbound webhook
POST /your-endpoint   X-Etalon-Signature: sha256=…

{
  "event": "record.upserted",
  "source": "advertising",
  "occurred_at": "2026-07-31T09:00:00Z",
  "record": {
    "account": "paid-social",
    "campaign": "prospecting",
    "day": "2026-07-30",
    "spend": "1284.40",
    "currency": "USD"
  },
  "delivery": { "attempt": 1, "idempotency_key": "a7f1…" }
}

Pivots, charts and exports over the same tables.

Rows nest as far as the data goes, columns are periods you can regroup by day, week, month or quarter, and every subtotal is computed inside the database over the full set of rows. Any cell opens down to the records behind it.

Spend by channel and campaign

Month Week Day
Channel / campaign Apr May Jun Total
Paid search 18,42019,98021,340 59,740
Brand 4,1204,2604,510 12,890
Generic 9,88010,64011,300 31,820
Competitor 4,4205,0805,530 15,030
Paid social 22,14020,86024,410 67,410
Prospecting 14,98013,42016,900 45,300
Retargeting 7,1607,4407,510 22,110
Affiliate 6,3006,7406,120 19,160
Total 46,86047,58051,870 146,310

Spend and cost per acquisition

Spend Cost per acquisition
JanFebMarAprMayJun

Illustrative figures

Views are written down

A report is a file with its query, axes and measures. It is reviewed and versioned with the rest of your code, and the same definition backs the screen, the export and the digest.

Exports match the screen

XLSX and CSV carry the filters that were applied when you clicked, so the file mailed to a board member holds the figures the dashboard showed.

Share what you choose

A view can be granted to a person with a row filter attached, or published as a link with its configuration frozen.

Or query it yourself

The canonical tables are ordinary Postgres. Point your own tool at a read-only role and work with the data directly.

Every pull is leased, retried and accounted for.

claim pull commit deliver dead letter backoff, retry attempts exhausted

Each connection is claimed with a database lock and a short lease before anything is fetched, then rearmed in the same transaction. Two instances can run side by side and every account is still pulled once. A deploy in the middle of a run costs one retry.

Failures back off and retry on their own. When the attempts are spent the work moves to a dead-letter queue and raises an alarm, so a dropped webhook or a missing statement is visible the same day.

Alerting is streak-gated. One blocked request is retried without an alert, two consecutive failures on the same account raise one, and the recovery closes it. Heartbeats go out on a timer and an external watchdog checks that they arrive, so a pipeline that dies quietly is caught as well.

Built in Rust, top to bottom.

Connectors, scheduler, reconciliation, reporting and the web interface are one Rust program. One process to deploy and one to watch; reports are computed in Postgres next to the data, and a pull that runs every few minutes keeps running for years.

One binary

The whole service compiles to a single statically linked executable with no runtime and no garbage collector.

Cold start under a second

A deploy or a restart is back in service within a second, which is what makes an instance per client practical.

Tens of megabytes at rest

It idles on the smallest instance your cloud sells and spends its day waiting on slow upstreams.

Thousands of records a second

Parsing and upserting are bounded by the database, and the database is right next to it.

Decimal money

Amounts are exact decimals from the wire to the screen, through every sum, rate and conversion.

Async I/O

One process holds hundreds of open connections while a bank takes its time answering.

Least privilege, by construction.

Credentials stay in your instance

Tokens are sealed with authenticated encryption under a master key held in the environment and opened only for the request that needs them.

Reporting connects read-only

Reports connect through roles without write permission, inside read-only transactions. A view has no way to touch a ledger.

Access is per view, per row

People are granted individual views, optionally with a row filter the server applies to every query they run.

Every run is logged

Each run is recorded with its outcome, duration and record counts, kept as long as you need it and pruned on a policy.

What comes with an instance.

  • Access grants per view
  • Audit log of every run
  • Backfill on demand
  • Chart tiles
  • Currency conversion at event date
  • Dead-letter queue
  • Drill-down to the raw payload
  • Encrypted credential store
  • Filters and parameters
  • Grain switching by day, week, month
  • Heartbeats and external watchdog
  • Idempotent writes downstream
  • Multi-entity, multi-currency
  • OAuth token rotation
  • Pivot subtotals in the database
  • Prepared-statement binding
  • Retention policies
  • Rolling re-pull windows
  • Row-level filters
  • Scheduled exports
  • Share links
  • Signed inbound webhooks
  • Slack digests and alerts
  • XLSX and CSV export

Three ways in.

Close the month with the numbers already agreed

Several legal entities, several countries, accounts across banks, cards and crypto. Balances and movements arrive on their own, transfers between your own accounts are recognised as transfers, and the closing figure is reconciled against the bank while the month is still running. By the time the month closes, the reconciliation has already run every day of it.

Tell us what your stack looks like.

Send the list of systems you run and what should flow between them. We will come back with what connects today, what we build for you, and how long it takes.