Skip to content

BPAY biller registration and inbound BPAY

ID MOD-136
System SD04
Repo bank-payments
Build status Deployed
Deployed Yes
Last commit 22c7a6053efe82886e736158dea6ef33222a5e76

Purpose

MOD-136 enables the bank's business customers to be registered as BPAY billers so that members of the public can pay them from any Australian bank using a BPAY biller code and customer reference number (CRN). The inbound payment flows through the BPAY scheme via the bank's sponsor bank relationship, arrives as part of a daily settlement file, and is credited automatically to the registered biller's nominated account. This is the complement to MOD-119 (outbound BPAY): MOD-119 handles customers paying bills; MOD-136 handles customers receiving bill payments.

Scope

Australia only. The module is inactive by default and is enabled via the payments.bpay.inbound.enabled feature flag at the tenant level. NZ customers do not have access to this feature; BPAY is an Australian-only payment scheme.

BPAY biller registration process

Registration is a back-office–initiated workflow. To register a business customer as a BPAY biller:

  1. The back-office team collects the required information from the customer: entity name, nominated account (the account to which inbound payments are credited), CRN format specification (Luhn, regex, or length-only), and the desired biller name as it will appear on payers' bank statements.
  2. A biller registration request is submitted to the sponsor bank, including the biller name, nominated account BSB and account number, and CRN validation configuration.
  3. The sponsor bank registers the biller with BPAY Pty Ltd. This process typically takes 3–5 business days from submission.
  4. Once the sponsor bank returns the assigned biller code, the payments.bpay_billers record is updated from pending_registration to active and the biller code is recorded.

No inbound payments may be credited to a biller whose status is pending_registration. The biller record is created in the system at the point of submission so that the back-office can track progress, but the biller code is not yet assigned at that stage.

CRN format configuration

Each biller defines the format rules used to validate the customer reference number presented on inbound payments:

Validation type Description
luhn CRN passes a Luhn check digit algorithm — the standard BPAY validation method
regex CRN is validated against a biller-specific regular expression (e.g. 8–12 digits with a specific prefix)
none No CRN validation applied — any non-empty string is accepted

The validation type and any format parameters are stored in crn_format and crn_validation_type. CRNs failing validation on receipt are quarantined (see FR-606).

Inbound payment processing

The sponsor bank delivers a daily settlement file containing all inbound BPAY payments received on behalf of this bank's registered billers. The processing flow is:

  1. File ingestion — the settlement file is received from the sponsor bank (SFTP or API, depending on sponsor bank capability) and each line item is written to payments.bpay_inbound_payments with status received.
  2. CRN validation — each payment's CRN is validated against the registered biller's CRN format. Items that fail validation are set to returned and reported to the operations queue.
  3. Credit posting — valid items are posted as credits to the biller's nominated account via MOD-001. The BPAY payment date (as indicated in the settlement file) and scheme reference are recorded on the ledger transaction.
  4. Notification — a payment received notification is dispatched to the biller via MOD-063 within 60 seconds of the posting completing.
  5. Reconciliation — the complete batch is reconciled against the sponsor bank's BPAY settlement file via MOD-081 (see FR-608).

Same-day crediting applies to all payments included in the sponsor bank's daily settlement file.

Data model

-- Registered BPAY billers
CREATE TABLE payments.bpay_billers (
    biller_id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    account_id             UUID NOT NULL REFERENCES core.accounts(account_id),
    biller_code            TEXT UNIQUE,          -- null until sponsor bank assigns code
    biller_name            TEXT NOT NULL,
    crn_format             TEXT,                 -- regex or length spec; null for luhn/none
    crn_validation_type    TEXT NOT NULL DEFAULT 'luhn' CHECK (crn_validation_type IN (
                               'luhn', 'regex', 'none'
                           )),
    status                 TEXT NOT NULL DEFAULT 'pending_registration' CHECK (status IN (
                               'pending_registration',
                               'active',
                               'suspended',
                               'deregistered'
                           )),
    registered_at          TIMESTAMPTZ,          -- null until active
    scheme_reference       TEXT,                 -- BPAY Pty Ltd registration reference
    created_at             TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Inbound BPAY payments received via the sponsor bank settlement file
CREATE TABLE payments.bpay_inbound_payments (
    inbound_id             UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    biller_id              UUID NOT NULL REFERENCES payments.bpay_billers(biller_id),
    crn                    TEXT NOT NULL,
    payer_bank_code        TEXT,                 -- originating bank identifier from settlement file
    amount                 NUMERIC(18,2) NOT NULL,
    payment_date           DATE NOT NULL,        -- value date from settlement file
    settlement_batch_reference TEXT NOT NULL,
    posting_id             UUID,                 -- reference to MOD-001 ledger entry
    status                 TEXT NOT NULL DEFAULT 'received' CHECK (status IN (
                               'received',
                               'posted',
                               'reconciled',
                               'returned'
                           )),
    created_at             TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX ON payments.bpay_inbound_payments (biller_id);
CREATE INDEX ON payments.bpay_inbound_payments (settlement_batch_reference);
CREATE INDEX ON payments.bpay_inbound_payments (payment_date);

biller_code is nullable at creation — it is populated only once the sponsor bank returns the assigned code and the biller moves to active. scheme_reference is the BPAY Pty Ltd registration confirmation reference returned by the sponsor bank.

Key operations

Biller registration. Back-office creates a payments.bpay_billers record with status pending_registration and submits the registration request to the sponsor bank. When the sponsor bank confirms the assigned biller code, the record is updated to active with the biller code and registered_at timestamp.

CRN validation on receipt. For each item in the settlement file, the CRN is checked against the biller's crn_validation_type. Luhn validation applies the standard Luhn algorithm. Regex validation applies the pattern in crn_format. Items failing either check are set to returned; the payer's bank is notified via the BPAY scheme return mechanism, and the item is added to the operations exception queue.

Inbound credit posting. Valid items are posted via MOD-001 as credits to the biller's nominated account. The posting_id is written back to bpay_inbound_payments and status advances to posted.

Settlement reconciliation. After all items in a settlement batch are processed, MOD-081 reconciles the processed totals against the sponsor bank's BPAY settlement file — comparing item count and total credit amount per biller. Discrepancies are flagged to the operations queue and status remains posted rather than advancing to reconciled until the discrepancy is resolved.

Return handling. CRN validation failures result in a scheme return to the payer's bank via the sponsor bank. The return is recorded in bpay_inbound_payments with status returned. Returns that cannot be matched to a biller (e.g. unrecognised biller code) are escalated to the operations queue immediately.

Requirements

FR-605 — System shall manage the BPAY biller registration lifecycle — from back-office initiation of a new biller registration request (capturing biller name, account, CRN format) through to sponsor bank scheme registration confirmation; the biller record must remain in pending_registration status until the sponsor bank confirms the biller code has been assigned; no inbound payments may be credited to a biller in pending_registration status.

FR-606 — System shall validate the CRN on each inbound BPAY payment against the registered biller's CRN format specification (Luhn check, regex, or length-only as configured); CRNs that fail validation must be quarantined with status returned and reported to the operations queue within 60 minutes; the payer's bank must be notified via the scheme return mechanism.

FR-607 — System shall post each valid inbound BPAY receipt as a credit to the registered biller's account via MOD-001 on the day of receipt (same-day settlement for payments included in the sponsor bank's daily settlement file), record the BPAY payment date and scheme references on the transaction, and dispatch a payment received notification to the biller via MOD-063 within 60 seconds of posting.

FR-608 — System shall reconcile each inbound BPAY settlement batch against the sponsor bank's BPAY settlement file via MOD-081, identifying any discrepancy between expected and received totals per biller, and must flag unmatched items to the operations queue within 2 hours of the settlement file being received; unreconciled items must not remain open beyond end of the following business day without an escalation.


Module dependencies

Depends on

Module Title Required? Contract Reason
MOD-001 Double-entry posting engine Required Inbound BPAY payment credits are posted via the double-entry engine.
MOD-081 Payment reconciliation engine Required Inbound BPAY settlement batches are reconciled against the sponsor bank's BPAY settlement file via the payment reconciliation engine.
MOD-063 Notification orchestration Required Biller notification of inbound payments is dispatched via notification orchestration. MOD-063's catch-all rule on bank.payments.* already covers the three new BPAY-inbound events; no new handoff required.
MOD-103 Neon database platform bootstrap Required Neon database and schema provisioned by MOD-103 must exist before this module can read or write Postgres.
MOD-104 AWS shared infrastructure bootstrap Required AWS shared infrastructure provisioned by MOD-104 (IAM role, EventBridge bus, SNS, KMS) is required before this module can be deployed.
MOD-157 External provider stub service Required Sponsor BPAY clearing URL (bank-payments/{stage}/clearing/bpay/base-url) is published by MOD-157; reused from MOD-119 for inbound biller-registration submission and webhook.

Required by

(No modules in this wiki currently declare a dependency on this module.)


Policies satisfied

Policy Title Mode How
PAY-001 Payment Operations Policy AUTO Inbound BPAY payments are credited to the biller's account automatically upon receipt from the sponsor bank settlement file; no manual processing step for standard inbound payments.
REP-005 Data Quality & Assurance Policy LOG All BPAY biller registrations, inbound payment receipts, and reconciliation outcomes are logged for payment data quality and regulatory reporting.
PAY-002 Settlement Risk Policy LOG Biller registration events and inbound payment transactions are logged to the payment audit trail.
CON-005 Fee & Pricing Transparency Policy AUTO Biller is notified of each inbound BPAY receipt within 60 seconds via MOD-063 — timely disclosure of payment received (j-1 ruling; CON-001 is a stretch fit for this mechanism).

Capabilities satisfied

(No capabilities mapped)


Part of SD04 — Payments Processing Platform Compiled 2026-05-22 from source/entities/modules/MOD-136.yaml