Skip to main content

Record and reconcile bill payments

Record and reconcile bill payments in the SMB's accounting software

Overview

Finally, your SMB customer will make a payment from your application, which you should then record and reconcile back to the SMB's accounting software. A bill payment represents an allocation of money within any of your customer's accounts payable (AP) accounts.

We built async Bill Pay to handle a wide range of bill pay scenarios, for example:

  • A payment made against a bill, e.g. a credit card payment, cheque payment, or cash payment
  • An allocation of a supplier's credit note to a bill or a refund
  • A bill payment made directly to an AP account, e.g. an overpayment or a prepayment

We have summarized the approaches to bill payments and reconciliation available to you on the diagram:

A diagram of all bill payment options that Bill Pay supports

Manage payment accounts

Your SMB customers may have multiple bank accounts they can use to pay for a bill. In your application, enable them to select or create the account the payment should originate from.

Foreign currency payments

To facilitate payments in a foreign currency, you can:

  • Convert the payment to the currency of the account.
  • Create a new account in the payment currency.

Use the Get create/update bank account model endpoint to view the list of the company's currently enabled currencies. It can return:

  • Single value: the account's base currency in platforms that only support the base currency
  • Multiple values: several currencies enabled by the SMB user in their accounting software
  • No values: empty array for platforms where any and all currencies can be selected

Retrieve accounts

If your SMB customer is making payments from an existing bank account, retrieve a list of their accounts and allow them to map payment methods against each one.

Use the List accounts endpoint and filter by isBankAccount=true to return a list of valid bank accounts.

const accountsListResponse = await payablesClient.accounts.list({
companyId: companyId,
query: 'isBankAccount=true'
});

Create account

If the SMB customer plans to make payments from a new payment method or account that you provide, create the new account in their accounting software. The account will contain their transactions, making the SMB's payment reconciliation workflows easier.

You can also use the Get create bank account model or Get create account model endpoints first to check integration-specific requirements for account creation, or read more about creating data with Codat.

Create account in Sage Intacct

For Sage Intacct, use the Create account endpoint to reflect that account in the customer's accounting software.

const accountCreateResponse = await payablesClient.accounts.create({
accountPrototype: {
name: "BillPay Debit Account"
fullyQualifiedName: "BillPay Debit Account",
fullyQualifiedCategory: "Asset.Current",
nominalCode: "610",
currency: "USD",
status: AccountStatus.Active,
type: AccountType.Asset,
currentBalance: 0,
},
companyId: companyId,
connectionId: connectionId
});
Create account in other integrations

To create a new bank account in MYOB, Xero, QuickBooks Online, or NetSuite use the Create bank account endpoint.

Xero doesn't support the creation of credit accounts.

const accountCreateResponse = await payablesClient.accounts.create({
account: {
accountName: "BillPay Debit Account",
accountType: AccountType.Debit,
accountNumber: "80088008",
currency: "USD",
balance: 0,
availableBalance: 0,
},
companyId: companyId,
connectionId: connectionId
});

Choosing an account type

Use the following accountType values that correspond to the payment methods you provide.

Payment methodAccount type
Automated Clearing House (ACH) or Real-Time Payments (RTP) networksDebit
Cheque/check paymentsDebit
Electronic bank transferDebit
BACS (Bankers' Automated Clearing System)Debit
Commercial/business credit cardCredit
BNPL (Buy Now, Pay Later)Credit

Single bill payment

If your SMB customer is making a payment to pay off a single bill in full, use the Create bill payments endpoint and include the following properties in the request:

PropertyDetails
totalAmountAlways positive value that indicates the amount of the bill that was paid
linesArray that contains one element with the following:
  • amount equal to the totalAmount of the payment
  • links array that must contain one element
linksArray that contains one element with the following:
  • type of link, in this case a Bill
  • id of the bill that was paid
  • amount with value of -totalAmount to indicate the full amount is allocated to the bill

In case of partial payments, use the same endpoint and adjust the amount values according to the amount of the partial payment.

Bill payment tips

When paying a bill, check the following:

  • supplierRef.id is the same id as the supplierRef.id on the bill.
  • accountRef.id is the payment account indicated during mapping.
  • totalAmount is the same as the amountDue on the bill.
  • date is the date that the payment is made to the supplier.

For example, review the bill mapped from Xero in the dropdown below and see how it can be paid using the Create bill payments in the subsequent code snippets.

Bill mapped from Xero
{
"id": "59978bef-af2f-4a7e-9728-4997597c0980",
"reference": "RPT445-1",
"supplierRef": {
"id": "dec56ceb-65e9-43b3-ac98-7fe09eb37e31",
"supplierName": "PowerDirect"
},
"purchaseOrderRefs": [],
"issueDate": "2023-02-09T00:00:00",
"dueDate": "2023-02-19T00:00:00",
"currency": "GBP",
"currencyRate": 1,
"lineItems": [
{
"description": "Monthly electricity",
"unitAmount": 129.38,
"quantity": 1,
"discountAmount": 0,
"subTotal": 129.38,
"taxAmount": 6.47,
"totalAmount": 135.85,
"discountPercentage": 0,
"accountRef": {
"id": "d50842c3-af67-4233-b8c9-df3180f5b7bd"
},
"taxRateRef": {
"id": "RRINPUT",
"name": "5% (VAT on Expenses)",
"effectiveTaxRate": 5
},
"trackingCategoryRefs": [],
"isDirectCost": false
}
],
"withholdingTax": [],
"status": "Open",
"subTotal": 129.38,
"taxAmount": 6.47,
"totalAmount": 135.85,
"amountDue": 135.85,
"modifiedDate": "2023-04-17T14:51:35Z",
"sourceModifiedDate": "2021-01-03T21:56:20",
"paymentAllocations": [],
"metadata": {
"isDeleted": false
}
}
const billPaymentResponse = await payablesClient.billPayments.create({
billPayment: {
supplierRef: {
id: "dec56ceb-65e9-43b3-ac98-7fe09eb37e31"
},
accountRef: {
id: "bd9e85e0-0478-433d-ae9f-0b3c4f04bfe4"
},
totalAmount: 135.85,
currency: "GBP",
currencyRate: 1,
date: "2023-04-17T00:00:00",
lines: [
{
amount: 135.85,
links: [
{
id: "59978bef-af2f-4a7e-9728-4997597c0980",
type: BillPaymentLineLinkType.Bill,
amount: -135.85,
currencyRate: 1,
},
],
},
]
},
companyId: companyId,
connectionId: connectionId,
});

Multiple bill payment

Your SMB customer may want pay multiple bills from a single supplier using one payment. Use the Create bill payments endpoint to do so and include a lines array with multiple elements for each bill and its respective amount.

Integration-specific examples
{
"supplierRef": {
"id": "dec56ceb-65e9-43b3-ac98-7fe09eb37e31"
},
"accountRef": {
"id": "bd9e85e0-0478-433d-ae9f-0b3c4f04bfe4"
},
"totalAmount": 244.45,
"currency": "GBP",
"currencyRate": 1,
"date": "2023-04-17T00:00:00",
"lines": [
{
"amount": 135.85,
"links": [
{
"type": "Bill",
"id": "59978bef-af2f-4a7e-9728-4997597c0980",
"amount": -135.85,
"currencyRate": 1
}
]
},
{
"amount": 108.6,
"links": [
{
"type": "Bill",
"id": "2175c381-d323-4e20-8c94-7680ea7f85d3",
"amount": -108.6,
"currencyRate": 1
}
]
}
]
}

Batch bill payment

In some accounting software (for example, Xero) your SMB customer can make a batch payment. It allows them to pay multiple bills from multiple suppliers in a single payment.

To do this with async Bill Pay, use the Create bill payments endpoint and leave the supplierRef parameter blank.

const billPaymentResponse = await payablesClient.billPayments.create({
billPayment: {
accountRef: {
id: "d96ffd74-2394-4666-81c4-eebb76e51e21"
},
totalAmount: 6,
date: "2022-09-06T00:00:00",
lines: [
{
amount: 1,
links: [
{
id: "0394819c-b784-454d-991c-c4711b9aca12",
type: BillPaymentLineLinkType.Bill,
amount: -1,
},
],
},
{
amount: 2,
links: [
{
id: "428e3e38-e8fb-4c56-91b5-dd09dc2e6505",
type: BillPaymentLineLinkType.Bill,
amount: -2,
},
],
},
{
amount: 3,
links: [
{
id: "76129542-2b2f-482f-b2b3-e612d9c1ba08",
type: BillPaymentLineLinkType.Bill,
amount: -3,
},
],
},
]
},
companyId: companyId,
connectionId: connectionId,
});

Bill credit note

If your customer receives a credit note from their supplier, they can use it to partially or fully offset the balance of any outstanding bills from the same supplier. You can reflect that with Bill Pay as follows:

  1. Create a bill credit note.
  2. Allocate the credit note to a bill.

Create a credit note

Start by creating a credit note using our Create bill credit note endpoint.

const billCreditNoteCreateResponse = await payablesClient.billCreditNotes.create({
billCreditNote: {
billCreditNoteNumber: "JMY-1987",
supplierRef: {
id: "3a0d40a2-2698-4cf5-b7b2-30133c632ab6",
supplierName: "Swanston Security"
},
withholdingTax: [],
totalAmount: 25.44,
totalDiscount: 0,
subTotal: 25.44,
totalTaxAmount: 4.24,
discountPercentage: 0,
remainingCredit: 0,
status: BillCreditNoteStatus.Submitted,
issueDate: "2023-02-09T00:00:00",
currency: "GBP",
currencyRate: 1,
lineItems: [
{
description: "Refund as agreed due to window break when guard absent",
unitAmount: 21.2,
quantity: 1,
discountAmount: 0,
subTotal: 21.2,
taxAmount: 4.24,
totalAmount: 25.44,
accountRef: {
id: "f96c9458-d724-47bf-8f74-a9d5726465ce"
},
discountPercentage: 0,
taxRateRef: {
id: "INPUT2",
name: "20% (VAT on Expenses)",
effectiveTaxRate: 20
},
trackingCategoryRefs: []
}
]
},
companyId: companyId,
connectionId: connectionId,
});
Integration-specific examples
{
"billCreditNoteNumber": "JMY-1987",
"supplierRef": {
"id": "3a0d40a2-2698-4cf5-b7b2-30133c632ab6",
"supplierName": "Swanston Security"
},
"withholdingTax": [],
"totalAmount": 25.44,
"totalDiscount": 0,
"subTotal": 25.44,
"totalTaxAmount": 4.24,
"discountPercentage": 0,
"remainingCredit": 0,
"status": "Submitted",
"issueDate": "2023-02-09T00:00:00",
"currency": "GBP",
"currencyRate": 1,
"lineItems": [
{
"description": "Refund as agreed due to window break when guard absent",
"unitAmount": 21.2,
"quantity": 1,
"discountAmount": 0,
"subTotal": 21.2,
"taxAmount": 4.24,
"totalAmount": 25.44,
"accountRef": {
"id": "f96c9458-d724-47bf-8f74-a9d5726465ce"
},
"discountPercentage": 0,
"taxRateRef": {
"id": "INPUT2",
"name": "20% (VAT on Expenses)",
"effectiveTaxRate": 20
},
"trackingCategoryRefs": []
}
]
}

Allocate credit note to a bill

Now that you have the credit note, offset its balance against outstanding bills. Create a bill payment and include the credit note in the links array.

In some accounting software, you can combine a credit note and a partial payment to pay off the full balance of a bill.

const billPaymentResponse = await payablesClient.billPayments.create({
billPayment: {
supplierRef: {
id: "3a0d40a2-2698-4cf5-b7b2-30133c632ab6"
},
accountRef: {
id: "94b02f61-f95f-4873-b5b7-651ff9707325"
},
totalAmount: 0.00,
currency: "GBP",
currencyRate: 1,
date: "2023-05-09T00:00:00",
lines: [
{
amount: 45.00,
links: [
{
id: "59978bef-af2f-4a7e-9728-4997597c0980",
type: BillPaymentLineLinkType.Bill,
amount: -25.44,
},
{
id: "ee8bec08-2be8-40ba-acd0-d53d5df11235",
type: BillPaymentLineLinkType.CreditNote,
amount: 25.44,
},
],
},
]
},
companyId: companyId,
connectionId: connectionId,
});
Integration-specific examples
Considerations

With Xero, you can only fully allocate a billCreditNote to a bill using a billPayment. If you want to also use a partial payment, two separate transactions should be created.

{
"supplierRef": {
"id": "3a0d40a2-2698-4cf5-b7b2-30133c632ab6"
},
"accountRef": {
"id": "94b02f61-f95f-4873-b5b7-651ff9707325"
},
"totalAmount": 0,
"currency": "GBP",
"date": "2023-05-09T00:00:00",
"lines": [
{
"amount": 45,
"links": [
{
"type": "Bill",
"id": "8e65df54-4bbd-41f3-b241-8da2588be341",
"amount": -25.44
},
{
"type": "CreditNote",
"id": "ee8bec08-2be8-40ba-acd0-d53d5df11235",
"amount": 25.44
}
]
}
]
}

Delete bills and payments

In certain scenarios, your SMB customer may want to delete an existing bill or a bill payment - for example, if they made a mistake or no longer want to process the bill.

Use the Delete bill and Delete bill payment endpoints to support these requirements, and check them in our OAS for the most up-to-date integration coverage.

Delete bills

const billDeleteResponse = await payablesClient.bills.delete({
companyId: companyId,
connectionId: connectionId,
billId: billId,
});

Delete bill payments

const billPaymentDeleteResponse = await payablesClient.billPayments.delete({
companyId: companyId,
connectionId: connectionId,
billPaymentId: billPaymentId,
});
Recap

This concludes the bill pay process supported by our asynchronous Bill Pay solution. You have provided your customer with their suppliers, bills, and bank accounts and enabled them to choose relevant payment methods. You have reflected the bill payments in their accounting system.

As a result, the customer will see these bills marked as paid in their software and their accounts payable liability and supplier balances reduced.


Was this page useful?
👏
👍
🤔
👎
😭