Unified.to
All articles

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 🎉

All articles