Building an invoicing integration for accounting using Unified
August 22, 2025
Using Unified.to, you can build accounting and invoicing products that work with your customers preferred accounting platforms. With our wide range of integrations you can connect to dozens of platforms like Xero, QuickBooks, Freshbooks and more.
In this guide, we will show you how to create and list invoices using Unified's typescript SDK, including all related objects (contacts, accounts, line items, etc.). The same approach works for any accounting integration supported by Unified.to.
Prerequisites
- Node.js (v18+)
- Unified.to account with an accounting integration enabled (e.g., Xero, QuickBooks)
- Unified.to API key
- Your customer's connection ID for an accounting integration
Step 1: Setting up your project
mkdir accounting-demo
cd accounting-demo
npm init -y
npm install @unified-api/typescript-sdk dotenv
Add your credentials to .env:
UNIFIED_API_KEY=your_unified_api_key
CONNECTION_ACCOUNTING=your_customer_accounting_connection_id
Step 2: Initialize the SDK
import 'dotenv/config';
import { UnifiedTo } from '@unified-api/typescript-sdk';
const { UNIFIED_API_KEY, CONNECTION_ACCOUNTING } = process.env;
const sdk = new UnifiedTo({
security: { jwt: UNIFIED_API_KEY! },
});
Step 3: Get Your Customer's Connection ID
Before you can create or list invoices, your customer must authorize your application to access their accounting platform. You can easily do this with Unified's pre-build embedded authorization components.
Once authorized, you'll receive a connection ID for that customer's integration.
Store this connection ID securely and use it in all API calls for that customer.
Step 4: Creating an Invoice
To create an invoice, you'll typically need to reference related objects such as contacts, accounts (revenue accounts), and line items.
// 1. Create a contact (customer)
const contactResult = await sdk.accounting.createAccountingContact({
connectionId: CONNECTION_ACCOUNTING,
accountingContact: {
name: "Acme Corp",
email: "billing@acme.com",
},
});
const contactId = contactResult.accountingContact?.id;
// 2. Create an invoice with a line item
const invoiceResult = await sdk.accounting.createAccountingInvoice({
connectionId: CONNECTION_ACCOUNTING,
accountingInvoice: {
contactId,
issueDate: new Date().toISOString().split('T')[0], // YYYY-MM-DD
dueDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0], // +7 days
currency: "USD",
lineItems: [
{
description: "Consulting services",
quantity: 10,
unitAmount: 100,
accountId: "revenue", // Use a valid accountId for your connection by first getting a list of accounts
},
],
status: "DRAFT",
},
});
console.log("Created invoice:", invoiceResult.accountingInvoice);
How it works:
- First, create a contact (the customer).
- Then, create an invoice referencing that contact, with one or more line items.
- You may need to look up valid accountId values for your integration (see Unified's account data model).
Step 5: Listing Invoices
You can list all invoices for a customer's accounting connection:
const invoicesResult = await sdk.accounting.listAccountingInvoices({
connectionId: CONNECTION_ACCOUNTING,
limit: 10,
});
console.log("Invoices:", invoicesResult.accountingInvoices);
How it works:
- This fetches the first 10 invoices for the customer's accounting system.
- You can filter, paginate, or sort as needed (see API docs).
Step 6: Data Model
Unified's invoice model is normalized across all supported accounting integrations.
Key fields include:
- id
- contactId
- issueDate
- dueDate
- currency
- lineItems (array of { description, quantity, unitAmount, accountId })
- status (e.g., DRAFT, SENT, PAID)
- ...and more
See the full invoice data model here for all fields and types.
Happy Invoicing 🎉