William Shallum

Bank Account Complications

Posted Sep 2 2023, 00:26 by William Shallum

I worked in a team in a previous job that handled sending payments to bank accounts for several countries in APAC. It was your standard bank transfer UI (enter a bank account to send payments to), but there was also an API to enter the same information.

So as to say I’ve learned something on that job, here’s what I found “interesting” about the domain. I have avoided naming individual banks below.

1. No fixed list

Some countries don’t have a public list of banks or a well known addressing scheme. IDK what banks there are in the US, but at least they have universally agreed-on routing numbers and you can rely on the end user to understand what that is. Similarly Australian bank accounts have the BSB number which customers are expected to know (they also have monthly FTP downloads for updates to the list <3).

However, some countries use a drop-down / search as the common UI for picking banks, and they don’t have a list of valid IDs (or even a general agreement on what those IDs should be). Great fun when trying to expose in an API. For an example of this, try finding an official list for Thailand.

Indonesian bank account selection screen

Indonesian bank account selection screen

Yes, you could get around this by e.g. using SWIFT’s Bank Directory data (which you still need to filter properly), but if there’s no generally accepted way of specifying a bank, then most likely your partner has also used an ad-hoc encoding and you’d have to store a mapping to it anyway.

2. Branch code? What branch code?

In some countries knowing the branch code is important, in others less so. Of course it gets bad if you need the branch code to send money out, but your customers don’t know what it is. For an example of this, look at Indonesians getting paid out by PayPal: PayPal wants a 7 digit SKN code (bank + branch) while Indonesians normally never even specify the branch (the usual UI is a bank selector drop-down and an account number field). Lucky there’s a list, hope it’s up to date… (hint: it’s not). Where is the official list anyway? (see also number 1 above)

3. The times they are a-changin'

Some countries upgrade their systems and the new systems have different inputs compared to the old system. However you are sometimes 2 steps removed from the system and still need to support the old way (or the old way is stuck in your API).

As an example, Singapore moved away from bank code and branch code to just bank code and account number in the Interbank Giro upgrade / move to FAST and it has gems like these:

After 23 March 2015, if you are adding a new […banks…] account to make transactions, you will need to provide the full account number, which includes the bank’s old branch code prefixed as the first 3 digits. For example, the full account number of a […] account is ‘000123456789’

This implies that 1) the UI has changed to a bank selector + account number input and 2) some banks relied on the branch code to disambiguate accounts (i.e. account numbers were shorter because they were not globally unique). However, your API is tied to backwards compatibility and still supports people entering bank code, branch code, and account number. Will people in the future even know what a branch code is? Will they input the prefixed number in the bank account number field? Will you strip it out if they do? How would you even detect a prefixed number anyway? Do you know how long the account numbers are at those banks? What if you send money through two different systems, where one has moved to a bank + account system but the other still insists on bank + branch + account?

Day to day annoyances include branch closures / mergers for countries that require a branch code (bonus points for having to hunt down this information in Japanese through a broken link on the bank website). Also new banks popping up / banks getting merged / renamed.

4. More currencies, more fun

Payments of nonlocal currencies are interesting. Technically you can probably send any currency anywhere with a BIC and account number, but some countries (e.g. HK) have local clearing for foreign currencies (e.g. USD / EUR / RMB). Of course, not all banks are part of the local clearing so you better limit the bank codes people can enter. Even for BICs some banks explicitly state that foreign currency transfers are not accepted so you better exclude those as well, unless you enjoy annoying your customers and paying useless fees.

In countries without local clearing you’d have to use international wires. Do you still need the local branch code for international wires? Probably yes, if your bank account number is only 6 digits long — it’s not unique between branches! However some banks use special branch IDs for foreign currency accounts which don’t exist in the national database, so you can’t reuse the same validation code. Also customers from other banks then complain that their bank told them they don’t need branch numbers for international wires — why do you require them as input? "¯\_(ツ)_/¯"


Just use IBANs, people. One long string with everything you need, plus a built-in checksum.