How to capture bank transaction logs in South Africa

"Bank logs" means different things to different people. For a developer it means a structured event stream. For a compliance officer it means an auditable record of every transaction. For an accountant it means a reconcilable ledger. For all of them, the practical question is the same: how do you get a complete, reliable record of what happened in a bank account over time?

This guide covers what bank logs contain, what South African law requires you to keep, and how to capture them without depending on someone manually downloading a statement every month.

What bank transaction logs contain

A complete bank transaction log has at minimum:

  • Date — when the transaction was posted to the account
  • Description — the narrative the bank assigns (merchant name, reference, counterparty)
  • Amount — debit or credit, in ZAR
  • Running balance — the account balance after each transaction
  • Reference number — a unique identifier assigned by the bank

For compliance and reconciliation purposes, the reference number is critical. It is the immutable link between your internal records and the bank's records. Without it, disputes are difficult to resolve.

What South African law requires

The Financial Intelligence Centre Act (FICA) requires covered entities — banks, accountants, estate agents, lawyers, and anyone else designated under the Act — to retain transaction records for at least five years from the date of the last transaction.

Records must be:

  • Readily available for examination by the Financial Intelligence Centre or SARS
  • Sufficient to reconstruct the transaction — amount, parties, date, type
  • Kept in a format that can be produced in evidence if required

South Africa's compliance environment is tightening in 2026. The FIC, FSCA, and Prudential Authority are all in active enforcement mode. "We had it in an email somewhere" is not an acceptable audit trail.

FICA record-keeping is not optional — it applies to any business that handles financial transactions, not just banks. If you're an accountant, lawyer, or property agent, you need retained transaction records going back five years.

Why manual exports fail as a logging strategy

The most common approach for smaller businesses is periodic manual exports: someone logs into internet banking, downloads the last month as a CSV or PDF, and files it.

This breaks in several ways:

Gaps in the record. If the export happens monthly, any transactions that fall near month boundaries — especially anything that posts or reverses after the download — may be missed or duplicated.

Format inconsistency. FNB, Standard Bank, ABSA, and Nedbank all produce slightly different CSV column layouts. A CSV from 2023 may not import cleanly into the same software in 2026 after a bank changes their export format.

No verification. A manually downloaded file has no cryptographic signature and no automated validation. There is no way to prove it has not been edited.

Human dependency. If the person who does the downloads leaves, or forgets, or is on leave — the log has a gap.

How to capture bank logs programmatically

A reliable logging approach runs automatically, stores data in a structured format, and creates an immutable record at the point of capture.

The architecture is straightforward:

Bank account
    ↓ (scheduled sync)
BankLink Pulse
    ↓ (webhook)
Your system
    ↓
Append-only transaction log
    ↓
Compliance archive (5-year retention)

Each sync captures all new transactions since the last run. The webhook payload includes the full transaction detail and the running balance.

{
  "account_number": "62012345678",
  "bank": "fnb",
  "synced_at": "2026-06-10T07:00:00Z",
  "transactions": [
    {
      "id": "txn_9f3c21a",
      "date": "2026-06-09",
      "description": "SUPPLIER PAYMENT REF:INV-2891",
      "amount": -48500.00,
      "running_balance": 102340.00,
      "reference": "FNB2026060901234",
      "type": "debit"
    }
  ]
}

Storing this payload in an append-only table gives you:

  • A timestamp of when BankLink captured the transaction (synced_at)
  • The bank's own reference number
  • The running balance as evidence of account state
  • An immutable record that can be produced in a compliance audit

Building a five-year retention store

For FICA compliance, your log needs to survive for five years and remain queryable. The simplest implementation:

CREATE TABLE bank_transaction_log (
  id            BIGSERIAL PRIMARY KEY,
  captured_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  account_number TEXT NOT NULL,
  bank          TEXT NOT NULL,
  txn_date      DATE NOT NULL,
  description   TEXT NOT NULL,
  amount        NUMERIC(15, 2) NOT NULL,
  balance       NUMERIC(15, 2),
  reference     TEXT,
  raw_payload   JSONB
);

-- Never update or delete rows — append only
CREATE RULE no_update AS ON UPDATE TO bank_transaction_log DO INSTEAD NOTHING;
CREATE RULE no_delete AS ON DELETE TO bank_transaction_log DO INSTEAD NOTHING;

The raw_payload column stores the full JSON from BankLink, so if you ever need to re-process or prove completeness, the original capture is there.

Handling gaps and replays

Automated log capture can miss data if a sync fails — network error, service downtime, or a missed window. Your system should:

  1. Track the synced_at timestamp of every successful sync
  2. Alert if no sync is received within the expected window (e.g., more than 25 hours for a daily Pulse)
  3. On recovery, trigger a manual sync that fetches back 7 days to fill any gap

BankLink Pulses are idempotent — syncing the same transaction twice will return the same data. Your system should use the bank's reference field as a deduplication key, not your own auto-increment ID.

Getting started

BankLink supports FNB transaction capture today, with more banks being added. A Pulse configured with a dashboard destination writes every transaction to the BankLink database and delivers it to your webhook — giving you a live, structured log from the moment you link the account.

Start capturing bank logs → app.banklink.co.za