Pass-through integration for local government · records are never stored System status1-559-251-7767Sentra familySign in
SentraBridgeIntegration platform
Finance Integration basicsSeptember 16, 2026 · 4 min read

SFTP is not dead: bank files and billing exports

Banks, lockbox processors and billing vendors still deliver files over SFTP. Here is how to read them safely, check every row, and stop someone from re-keying payments.

Every few years someone announces that file transfers are over and everything will be an API. Then the bank sends the daily payment file to an SFTP folder, the same way it has for fifteen years. For most cities, SFTP is still how money arrives.

That isn't a failure to modernize. A file is a clean, auditable handoff between two organizations that don't share systems. The trouble is usually what happens after the file lands.

Where file handoffs go wrong

The typical setup is a script someone wrote years ago, or a person who opens the file each morning and keys it in. Both work until they don't:

  • A file arrives twice, and payments are posted twice.
  • A row has a blank account number, and the whole load fails at 6:05 am.
  • The script's author has left, and nobody knows which folder it reads.
  • The server's identity changes, and nobody notices the script is now talking to something else.

None of these are hard problems. They just need to be handled the same way every time.

Five habits of a good file flow

1. Check who you're talking to

SFTP servers have a host key, a fingerprint that proves the server is the one you expect. A good flow saves that fingerprint when you first connect and refuses to continue if it ever changes. That's called host-key pinning, and it's the difference between "encrypted" and "encrypted to the right party".

2. Only read files once

Read only files that are new since the last good run, and move each file to an archive folder after a successful load. If the run fails, the file stays where it was, so the next run picks it up again. No one has to remember what was already posted.

3. Check every row before it lands

Bank files are mostly clean. Mostly. Before a row goes into the finance database, check it:

  • Trim and upper-case the account number, then require it.
  • Make sure the amount is a number, and within a sensible range.
  • Make sure the date is a real date.

Rows that fail shouldn't stop the whole file. They should go to a person, with the reason.

4. Make loads repeatable

Load with an upsert on a key the bank provides, such as the receipt number. If the same row is ever loaded twice, it updates instead of duplicating. That one choice removes most double-posting risk.

5. Keep the file name with each row

When finance asks where a payment came from, the answer should be "row 41 of utility-payments-2026-09-14.csv", not "the import". Adding the source file name to each record makes that question easy.

What it looks like as a flow

Here is the ready-made bank payments flow in SentraBridge. It runs weekdays at 6 am, reads new CSV files matching utility-payments-*.csv, cleans and checks each row, upserts good rows into a utility_payments table keyed on the receipt, and moves the file to archive. Rows that fail go to finance by email, with a CSV of just those rows attached.

Flow diagram: Load the bank's daily payment file into the city databaseEvery morning, reads new payment CSV files from the bank's SFTP folder, cleans and checks them, loads them into a database table, and archives the files. Bad rows are emailed to finance.Weekdays at 6 amOn a scheduleRead payment filesRead files · SFTPClean and checkApply rulesLoad intoutility_paymentsWrite to database · PostgreSQLEmail bad rows tofinanceSend emailInvalid
Load the bank's daily payment file into the city database · 5 steps · a real SentraBridge template

The rules step has two outputs, Valid and Invalid, so the bad rows take a different wire instead of stopping the run. The email line for each bad row reads like {{source_file}} {{receipt}}: {{rule_errors}}, so finance sees the file, the receipt and the reason.

Not just CSV

Vendors send what they send. A file flow should read the common formats without a custom parser for each:

  • CSV with comma, semicolon, tab or pipe separators, with or without a header row.
  • JSON, including a list inside the file (for example, an inspections array).
  • JSON Lines, one record per line, common in exports from newer systems.
  • XML, where you name the record element, such as payment.

The same is true going the other way. A nightly export of yesterday's 311 requests, written as a dated CSV in an outbox folder, is often the simplest way to feed a billing or work-order system that only takes files.

Flow diagram: Nightly 311 export as a CSV file on SFTPEvery night, writes yesterday's changed Sentra 311 requests to a dated CSV file in an SFTP folder for another system to pick up.Nightly at 11:30 pmOn a scheduleChanged 311 requestsGet records · Sentra 311Columns for the fileMap fieldsWrite CSVWrite file · SFTP
Nightly 311 export as a CSV file on SFTP · 4 steps · a real SentraBridge template

Moving documents, not just rows

Some handoffs are whole documents: permit PDFs, signed agreements, scanned forms. Those can move the same way, downloaded and uploaded in memory with their metadata, without a copy left on a shared drive along the way. See files and documents for the Transfer file step.

Where SentraBridge fits

SentraBridge treats SFTP as a first-class connector, not an afterthought. Host keys are pinned and checked on every connection. Files are read in memory and never stored by SentraBridge; run history keeps the file names, counts and record IDs, not the payment details. You can preview a real file in the data inspector before turning the flow on, and nothing is written during preview.