Bill Payments

Ledgers Tutorial for Bill Payments

Overview

This guide will explain how to use the Ledgers API for a bill pay product. In this example, we will assume you are building a service that allows vendors to invoice and charge buyers. We will demonstrate a simple flow here with 3 events:

  • A vendor invoices a buyer
  • We pull funds from the buyer's bank account
  • We remit funds to the vendor

In order to facilitate these flows and be able to answer these questions, we will set up a ledger that has 4 ledger accounts.

  • Cash in our bank account
  • The balance owed by a given buyer, Beta Corp.
  • The balance owed to a given vendor, Valor Inc.
  • An account tracking the fees we have charged

Setup

First, we will make a ledger.

curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/ledgers \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Bill Pay Ledger",
    "description": "Represents our USD funds and user balances"
  }'

This will return a ledger object with an ID to be used in the following step.

{
    "id": "ad2c1f72-9945-41ee-8cda-c33b33697872",
    "object": "ledger",
    "name": "Bill Pay Ledger",
    "description": "Represents our USD funds and user balances",
    "active": true,
    "metadata": {},
    "live_mode": true,
    "created_at": "2021-11-09T14:59:54Z",
    "updated_at": "2021-11-09T14:59:54Z"
}

Next, we will create the ledger accounts described above. Note that the bank account is normal_balance=debit, as is the buyer account (because it represents a balance owed to us). The vendor account is normal_balance=credit (because it represents a balance owed from us), as is the fees account.

curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/ledger_accounts \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Cash Account",
    "description": "Tracks our cash",
    "normal_balance": "debit",
    "currency": "USD",
    "ledger_id": "ad2c1f72-9945-41ee-8cda-c33b33697872"
  }'
  
curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/ledger_accounts \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Buyer Beta Corp",
    "description": "Tracks amount to be pulled from Beta Corp",
    "normal_balance": "debit",
    "currency": "USD",
    "ledger_id": "ad2c1f72-9945-41ee-8cda-c33b33697872"
  }'
  
  curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/ledger_accounts \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Vendor Valor Inc",
    "description": "Tracks amount to be remitted to Valor Inc",
    "normal_balance": "credit",
    "currency": "USD",
    "ledger_id": "ad2c1f72-9945-41ee-8cda-c33b33697872"
  }'
  
  curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/ledger_accounts \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Fees",
    "description": "Tracks total fees charged",
    "normal_balance": "credit",
    "currency": "USD",
    "ledger_id": "ad2c1f72-9945-41ee-8cda-c33b33697872"
  }'

This will return the ledger accounts you've created.

{
    "id": "e240d17b-6dbe-4c8d-a152-4da7cc496ff0",
    "object": "ledger_account",
    "name": "Cash Account",
    "ledger_id": "ad2c1f72-9945-41ee-8cda-c33b33697872",
    "description": "Tracks our cash",
    "normal_balance": "debit",
    "currency": "USD",
    "currency_exponent": 2,
    "active": true,
    "metadata": {},
    "live_mode": true,
    "created_at": "2021-11-09T15:02:23Z",
    "updated_at": "2021-11-09T15:02:23Z"
}

{
    "id": "d62a028c-4a1c-41f8-b8c7-3c690d22e2f4",
    "object": "ledger_account",
    "name": "Buyer Beta Corp",
    "ledger_id": "ad2c1f72-9945-41ee-8cda-c33b33697872",
    "description": "Tracks amount to be pulled from Beta Corp",
    "normal_balance": "debit",
    "currency": "USD",
    "currency_exponent": 2,
    "active": true,
    "metadata": {},
    "live_mode": true,
    "created_at": "2021-11-09T15:02:23Z",
    "updated_at": "2021-11-09T15:02:23Z"
}

{
    "id": "463237a4-a93d-4396-9be8-5bacb8ceead1",
    "object": "ledger_account",
    "name": "Vendor Valor Inc",
    "ledger_id": "ad2c1f72-9945-41ee-8cda-c33b33697872",
    "description": "Tracks amount to be remitted to Valor Inc",
    "normal_balance": "credit",
    "currency": "USD",
    "currency_exponent": 2,
    "active": true,
    "metadata": {},
    "live_mode": true,
    "created_at": "2021-11-09T15:02:23Z",
    "updated_at": "2021-11-09T15:02:23Z"
}

{
    "id": "d75ebbac-473d-4e33-bb92-11e821a45f63",
    "object": "ledger_account",
    "name": "Fees",
    "ledger_id": "ad2c1f72-9945-41ee-8cda-c33b33697872",
    "description": "Tracks total fees charged",
    "normal_balance": "credit",
    "currency": "USD",
    "currency_exponent": 2,
    "active": true,
    "metadata": {},
    "live_mode": true,
    "created_at": "2021-11-09T15:02:23Z",
    "updated_at": "2021-11-09T15:02:23Z"
}

Using the ledger

Now that the setup is done, you can write to the ledger to record what happens in your business.

First, we can create a ledger transaction to record that Valor has invoiced Beta $1000, on top of which we will charge $10 in fees.

curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/ledger_transactions \
  -H 'Content-Type: application/json' \
  -d '{
    "description": "Invoice 110382",
    "effective_date": "2021-11-10",
    "status": "posted",
    "external_id": "97dbb8b1-e6f2-485e-a0ec-6267e3c60718",
    "ledger_entries": [
      {
        "ledger_account_id": "d62a028c-4a1c-41f8-b8c7-3c690d22e2f4",
        "direction": "debit",
        "amount": 101000
      },
      {
        "ledger_account_id": "463237a4-a93d-4396-9be8-5bacb8ceead1",
        "direction": "credit",
        "amount": 100000
      },
      {
        "ledger_account_id": "d75ebbac-473d-4e33-bb92-11e821a45f63",
        "direction": "credit",
        "amount": 1000
      }
    ]  
  }'

Next, we can create the ledger transaction to record the funding pull from the buyer. This transaction zeros out the buyer's balance with us and adds funds to our bank account.

curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/ledger_transactions \
  -H 'Content-Type: application/json' \
  -d '{
    "description": "Funding pull from Beta Corp",
    "effective_date": "2021-11-15",
    "status": "posted",
    "external_id": "c006a6df-72ff-4cbf-aa4a-c18dde4b05c5",
    "ledger_entries": [
      {
        "ledger_account_id": "d62a028c-4a1c-41f8-b8c7-3c690d22e2f4",
        "direction": "credit",
        "amount": 101000
      },
      {
        "ledger_account_id": "e240d17b-6dbe-4c8d-a152-4da7cc496ff0",
        "direction": "debit",
        "amount": 101000
      }
    ]
  }'

Finally, we can create the ledger transaction to record the remittance to the vendor. This transaction zeros out the vendor's balance with us and removes funds from our bank account.

curl --request POST \
  -u ORGANIZATION_ID:API_KEY \
  --url https://app.moderntreasury.com/api/ledger_transactions \
  -H 'Content-Type: application/json' \
  -d '{
    "description": "Remit to Valor Inc",
    "effective_date": "2021-11-15",
    "status": "posted",
    "external_id": "14a7fd22-8922-498a-b8b3-def4df72d5e4",
    "ledger_entries": [
      {
         "ledger_account_id": "463237a4-a93d-4396-9be8-5bacb8ceead1",
         "direction": "debit",
         "amount": 100000
      },
      {
        "ledger_account_id": "e240d17b-6dbe-4c8d-a152-4da7cc496ff0",
        "direction": "credit",
        "amount": 100000
      }
    ]
  }'