Case study · Electronic payments

Building a custom ISO 20022 payment file in NetSuite

A client's bank would only accept payments in its own ISO 20022 variant, which NetSuite doesn't produce on its own. We built the format inside their account: four payment rails in one file, structured remittance on every line, and no add-on license to carry.

Custom build ISO 20022 Electronic payments SuiteScript
The situation

Their bank would take a file, in its own format

A client wanted to get off cheques and start paying vendors electronically. Their bank was happy to accept a payment file. The catch was which file.

ISO 20022 sounds like something you just comply with. In practice every bank runs its own dialect: the clearing codes it expects, how it wants a virtual card told apart from an ACH credit, what belongs in the remittance block, which fields it will quietly drop on the floor. The published standard gives you a schema. Everything that decides whether the file is accepted lives in the bank's own implementation guide, and a bit of it you only learn from the first file they reject.

The client also paid vendors four different ways. Most by ACH, some by wire, some on virtual cards, and a stubborn handful who still wanted a cheque. All of it had to come out of one run.

Why build it

NetSuite handles the common formats, not every one

Native electronic payment support covers a set of common formats. This bank's wasn't one of them, which leaves two ways forward: license an add-on that handles custom formats and pay for it monthly, or build the format itself.

It's a well-specified document going to one bank, so we built it. It runs in the client's own account, in their own scripts, and it's covered by the work we already do for them. Nothing recurring is attached to it. That wasn't the point of the project, but it's the part their CFO remembers.

The build

Four rails, one file

One payment run produces a single ISO 20022 document covering everything due, with each payment shaped according to how it's actually being sent.

ACH

Service level and local instrument codes set per vendor, including the distinction between paying a business and paying an individual.

Wire

Full creditor address, IBAN where there is one, and the right national clearing code for the destination country instead of a US default.

Virtual card

Its own instrument block, the vendor's remittance email carried through, and the merchant identifier the bank routes on.

Cheque

Still supported, because every real AP ledger has a few. Cheque instructions and mailing address travel in the same file as the rest.

Wrapped around the file is the part AP actually touches: a screen showing what's pending, what it totals and which vendors it covers, then one button. The run goes off in the background, reports progress as it works, writes a numbered batch record, attaches the generated file to it, marks the payments processed, and emails a summary of what went out. Vendors it had to skip are listed by name, so a missing bank detail surfaces the same day instead of three weeks later.

The engineering

Three problems nobody writes down

01

Remittance the vendor can actually use

When a payment lands as one undifferentiated sum, somebody at the vendor has to work out which invoices it covers. When they can't, they call your AP team. Remittance detail isn't a courtesy, it's the difference between a quiet week and a queue of phone calls.

Every bill goes across as its own structured remittance entry: invoice number, invoice date, amount due, any discount taken, and what was actually remitted. PO numbers go along where the bill carries one. Credits travel as credit notes with negative amounts, so the arithmetic on the vendor's side ties out on its own.

02

The bills that aren't on the payment

This one isn't obvious until you hit it. A bill fully covered by a vendor credit never appears on the payment's apply list, because no cash moved and there's nothing to apply. The payment doesn't know it exists. The vendor still expects to see it, though, and without it their AR and your AP disagree about an invoice that is in fact closed.

So the run goes looking. It takes the bills it does have, finds the credits applied to them, follows each credit through to whatever other bills it settled, and pulls those onto the remittance as well. It never appears on a requirements list. It turns up about six weeks in, in an email from a vendor's accounts receivable clerk.

03

Staying under the governance ceiling

NetSuite caps how much work any one script is allowed to do. A payment covering several hundred bills will run straight through that ceiling, and it doesn't stop cleanly. You get a half-written file, which is worse than no file at all.

Each payment is sized up before processing, and anything large is split into chunks that run independently and get reassembled before the document is written, with credit totals merged across the split rather than counted twice. None of that is visible from the AP screen. It's still one payment and one button.

Where it landed

Vendors paid electronically, in the bank's own format

AP runs the batch themselves and gets told what went out and what didn't. Nobody is cutting a cheque unless they meant to, and a vendor missing bank details gets named in the summary that afternoon rather than turning up as a question three weeks later.

The format itself sits in the client's account, which matters more than it sounds. Banks revise these specs. When this one does, it's a change we make, not a ticket we file and wait on.

The wider pattern

Most of what we build starts here

Payment files are one example. The shape recurs: the platform covers the common case well, your process sits a little outside it, and the options come down to changing the process, paying for an add-on, or having someone build the missing piece properly.

We do the third one. Same story behind the cross-subsidiary cash application work and behind BankSync.

Tell us what you're trying to do

A bank spec, an awkward workflow, a process held together by a spreadsheet. We'll tell you what it would take to build.

Get in touch