Product teams should be thinking differently about documents.Read blog post.
Anvil Logo
Products
Industries
Resources
Developers
Engineering

How to create a compliant monthly financial statement

Author headshot
By Ben Ogle

Financial institutions are required to provide customers with a statement of transactions each month. This post will outline the kinds of companies that need to send statements, describe the information required on a monthly PDF statement, and show how to generate Electronic Fund Transfer Act (EFTA) / Regulation E compliant statements using HTML, CSS, and React.

Back to all articles
How to create a compliant monthly financial statement

Every month your bank sends you a statement, usually in PDF form, outlining all the transactions you made in that month. It shows your balance at the beginning and end of the month, that deposited birthday card check from your Aunt Jill 🤑, other deposits & withdrawals, and metadata such as the physical locations where you used an ATM. You've probably noticed that all other financial services you use — credit cards, investment platforms, etc. — also provide monthly statements with similar information in a similar format. A statement might look like this:

html css and react monthly financial statement pdf An example monthly statement we will generate with HTML and CSS below

What gives? Why do all these companies issue statements? Because of regulation. Financial institutions are required to provide you a statement each month under the Electronic Fund Transfer Act (EFTA) / Regulation E (12 CFR Part 1005 to be specific). In this post, we'll dig into a few details in the EFTA, then show you how to generate compliant monthly statement PDFs with HTML, CSS, and React.

The EFTA / Regulation E

The EFTA / Regulation E governs electronic transfers of assets made by "financial institutions." To the EFTA, a "financial institution" is any company that allows a customer to make electronic fund transfers defined as:

The term "electronic fund transfer" or "EFT" means any transfer of funds that is initiated through an electronic terminal, telephone, computer, or magnetic tape for the purpose of ordering, instructing, or authorizing a financial institution to debit or credit a consumer's account.

When the EFTA was passed in 1978, likely only a small percentage of institutions were making "electronic fund transfers" within this definition. In the modern world, and especially on the internet, every meaningful asset transaction is electronic and happens through an "electronic terminal." This applies to every online bank, investment platform, money transfer app, retirement product, and anything else dealing with other people's assets.

What about cryptocurrency? Turns out even crypto companies fall into the "financial institution" category based on a recent ruling in NY (Rider v. Uphold HQ Inc.). This ruling is New York-only for now, though it's safe to say that, long-term, all crypto companies will be viewed as "financial institutions" in the eyes of the EFTA.

So while there is a very specific definition of a financial institution (12 CFR 1005.2(i); I'm fun at parties), it is safe to assume that if you are transferring other people's money, cryptocurrency, or other assets in any way, your company is a "financial institution."

Periodic statements

The EFTA covers a number of different rules for financial institutions: disclosures, liabilities, etc. But for the purposes of this post, we're most interested in section 1005.9 which describes periodic statements: you know, those monthly statements that your bank sends you each month.

The gist of 1005.9 is that if you are a financial institution — i.e. your company electronically transfers assets for a customer — you will need to provide a downloadable statement to that customer. Specifically, 1005.9(b) outlines that statements must be issued monthly so long as a transaction has occurred, and quarterly even if there have been no transactions.

Required statement fields

The periodic statements section, 1005.9(b), also specifies a list of fields that must be in each statement and on each transaction line item. You can obviously go nuts giving your customers extra information on your statements, but I'll just describe the minimum requirements below.

General statement information

A few straightforward account details need to be on each statement. If you've ever used a bank, these will be pretty familiar:

  1. The account number
  2. Fees. The amount of any fees assessed against the account during the statement period
  3. Account balances. The balance in the account at the beginning and at the close of the statement period.
  4. Address and telephone number for your company. The address and telephone number to be used for inquiries or notice of errors, preceded by "Direct inquiries to" or similar language.
  5. A telephone number (for your company) the consumer may call to ascertain whether preauthorized transfers to the consumer's account have occurred

Transaction information

Your statements need to have a list of transactions. The policy says the following bits of information need to be shown for each transaction:

  1. The amount of the transfer
  2. The date the transfer was credited or debited to the consumer's account
  3. The type of transfer and type of account to or from which funds were transferred
  4. For a transfer initiated by the consumer at an electronic terminal (except for a deposit of cash or a check, draft, or similar paper instrument), the terminal location
  5. The name of any third party to or from whom funds were transferred

Generating monthly statement PDFs

I'll assume if you've made it this far, your company probably falls under the "financial institution" definition, and will need to generate monthly statements for your customers.

To make this as easy as possible, we've created a EFTA-compliant monthly statement PDF template with both a plain HTML + CSS example, and a React + styled-components example. Check out the template GitHub repository at anvilco/html-pdf-financial-statement-template. Our goal with this template is to give you an easy starting point for your own company's statements, so feel free to fork it and copy code from the repo!

The rest of this post will show how to generate a statement that looks like the statement below. It has all the EFTA required fields, and it even looks pretty good! It's ready to be updated with your company's color palette 🎨

html css and react monthly financial statement pdf The monthly statement we will be generating from HTML and CSS

Setting up

We'll use the Anvil HTML to PDF API to generate statement PDFs. First, you'll need to get your API key by signing up for an Anvil account.

Once logged in, you will be directed to copy the API key from your organization’s API settings page. For more information see the getting started guide.

Generating PDFs from HTML

Generating PDFs is as simple as POSTing your HTML and CSS to the Anvil PDF generation endpoint https://app.useanvil.com/api/v1/generate-pdf. You send HTML and CSS, and the endpoint will respond with your newly generated PDF binary data ✨. Here's a quick curl example to illustrate how simple it is:

curl \
  -X POST \
  -u <YOUR_API_KEY>: \
  -H 'Content-Type: application/json' \
  -d '{ "type": "html", "title": "World", "data": { "html": "<h1>HTML to PDF</h1>", "css": "h1 { color: purple; }" } }' \
  https://app.useanvil.com/api/v1/generate-pdf > html-to.pdf

A curl example generating a PDF with HTML and CSS

For the remaining examples, we'll use the node-anvil API client. Generating PDFs with the node API client is simple as well:

import fs from 'fs'
import Anvil from '@anvilco/anvil'

const apiKey = <YOUR_API_KEY>
const client = new Anvil({ apiKey })

const { statusCode, data, errors } = await client.generatePDF({
  type: 'html',
  title: 'Hello World',
  data: {
    html: '<h1>HTML to PDF</h1>',
    css: 'h1 { color: purple; }',
  },
})

fs.writeFileSync('html-to.pdf', data, { encoding: null })

A JavaScript example generating a PDF with HTML and CSS

If you don't use node, JavaScript, or TypeScript, check out our other language-specific API clients.

Statement PDF from plain HTML & CSS

The monthly statement template contains a plain HTML and CSS files you can use to generate your PDF: statement.html and statement.css.

From the template repository, you can run generate-pdf.js via a simple command:

ANVIL_API_TOKEN=<YOURKEY> yarn generate-pdf:plain-html && open ./generate-plain-html.output.pdf

The basic gist of generate-pdf.js is as follows:

import fs from 'fs'
import Anvil from '@anvilco/anvil'

const apiKey = <YOUR_API_KEY>
const client = new Anvil({ apiKey })

function buildHTMLToPDFPayload () {
  const html = fs.readFileSync('./statement.html').toString()
  const css =
    fs.readFileSync('./statement.css').toString() +
    fs.readFileSync('./statement-pdf.css').toString()
  return {
    type: 'html',
    title: 'HTML Monthly Statement',
    data: {
      html,
      css,
    },
  }
}
const exampleData = buildHTMLToPDFPayload()
const { statusCode, data, errors } = await client.generatePDF(exampleData)
fs.writeFileSync('monthly-statement.pdf', data, { encoding: null })

An example generating a statement PDF with HTML and CSS

Statement PDF from React + styled-components

The monthly statement template also contains a React statement example that is similarly easy to use.

From the template repo, you can run react-pdf/generate-pdf.js via:

ANVIL_API_TOKEN=your_token yarn generate-pdf:react && open ./generate-react.output.pdf

The basic gist to generate the statement from React is:

  • Collect all styles from styled-components
  • Use ReactDOMServer.renderToStaticMarkup to render the statement components to HTML
  • Extract CSS from the collected styles
  • Send generated HTML and CSS to Anvil's PDF generation endpoint
  • Receive bacon PDF
import fs from 'fs'
import Anvil from '@anvilco/anvil'

import React from 'react'
import ReactDOMServer from 'react-dom/server'
import { ServerStyleSheet } from 'styled-components'

const apiKey = <YOUR_API_KEY>
const client = new Anvil({ apiKey })

function buildHTMLToPDFPayload () {
  const sheet = new ServerStyleSheet()
  const html = ReactDOMServer.renderToStaticMarkup(
    sheet.collectStyles(<Statement />)
  )
  const css = sheet.instance.toString()
  return {
    type: 'html',
    title: 'HTML Statement',
    data: {
      html,
      css,
    },
    page: {
      marginLeft: '60px',
      marginRight: '60px',
    },
  }
}

const exampleData = buildHTMLToPDFPayload()
const { statusCode, data, errors } = await client.generatePDF(exampleData)
fs.writeFileSync('monthly-statement-react.pdf', data, { encoding: null })

An example generating a statement PDF from React and styled components

For more general-purpose information on using React to generate PDFs, see the step-by-step guide for creating PDFs with React.

Conclusion

Hopefully you now have a good idea of how the Electronic Fund Transfer Act works. If your company is a financial institution, you will need to provide monthly statements to your customers. The statement template described above should get you started in no time.

Here are a couple links to check out:

If you have any questions, corrections, or want to show us your company's sweet monthly statement PDF, please reach out to us at hello@useanvil.com.

Sign up for a live demo

Request a 30-minute live demo today and we'll get in touch shortly. During the meeting our Sales team will help you find the right solution, including:
  • Simplifying data gathering
  • Streamlining document preparation
  • Requesting e-signatures
  • Building and scaling your business
Want to try Anvil first?Sign up for free
Want to try Anvil first?Sign up for free