Getting Started with FreshBooks NodeJS SDK - Expenses & Invoices
Tags: freshbooks, node, accounting, freshbooksapi
Published: 2021-10-21 14:08:02

Getting Started with FreshBooks NodeJS SDK - Expenses & Invoices
In this tutorial, we’ll be looking into the FreshBooks NodeJs SDK and how simple and easy it is to create, update and fetch Invoices, Expenses, Clients, Items, Payments, Projects, Time Entries etc. We have done all the heavy-lifting making it super convenient for you!

We have handled http calls, http retries, Idempotency, consistent request and response structures and many more.This way you get to focus on your business logic rather than figuring out how the FreshBooks API works. 

Prerequisites 
1. A FreshBooks Developer account. If you don't have one, you can create one here.
2. Authenticate yourself on the FreshBooks API using Oauth2.0. No idea how to do that? No problem, we have an excellent tutorial here.
3. Basic knowledge of Async, Await and Node.js.
4. A code editor (e.g. VS Code, Sublime, Atom etc.)

Let's get started!
Install the FreshBooks Nodejs SDK

In your Node project directory, install the FreshBooks NodeJs Client via npm or yarn
```
npm install @freshbooks/api 
```
```
yarn install @freshbooks/api
```


Get your FreshBooks Client ID

Login to the FreshBooks Dashboard, click on the Settings/Gear Icon, then click on Developer Portal. Select your Oauth App and then note the Client ID (you’ll need it). 
(By the way, this tutorial assumes you have created an existing Oauth App in the past and understand the dynamics of FreshBooks Authentication. If you haven’t, then this tutorial on how to create one.)






Instantiate the FreshBooks Client 
Using the block of code, we can instantiate the FreshBooks Client:
```	
import { Client } from '@freshbooks/api';
import winston from 'winston'; // This is optional

//This logger is also optional
const logger = winston.createLogger({
   level: 'error',
   transports: [
       new winston.transports.File({ filename: 'error.log', level: 'error' }),
       new winston.transports.File({ filename: 'combined.log' }),
   ],
});


// Get CLIENT ID from STEP 2 ABOVE
const clientId = '<CLIENT ID>';

// Get token from authentication or helper function or configuration
const token = '<BEARER TOKEN>';

// Instantiate new FreshBooks API client
const freshBooksClient = new Client(token, {
   clientId
}, logger);
```

Set a value for your Client ID and your Bearer Token. This tutorial assumes you have a helper function that helps generate the bearer tokens and refresh tokens from the /auth/oauth/token endpoints. If you don’t, you can check out authentication tutorial

Confirm Instantiation 
Using the function below, we can confirm the instantiations works
```
const confirmClientInstantiation = async () => {
   try {
       const { data: { firstName, roles } } = await    freshBooksClient.users.me()
       accountId = roles[0].accountId;
       logger.info(`Hello ${firstName}`)
       return {
           firstName,
           accountId
       }
   } catch ({ code, message }) {
       // Handle error if API call failed
       logger.error(`Error fetching user: ${code} - ${message}`)
       return {
           error: {
               code, message
           }
       }
   }
}
console.log(await confirmClientInstantiation());
```
 

If everything works as expected you should see a response similar to the below when you invoke the function. It also returns some useful information (especially the accountid. Store in a variable as you’ll need it in other method calls).

```
{ firstName: 'John', accountId: 'Zz2EMMR' }
```

If there is something wrong, you will receive a response that looks like this:

```
{
  error: {
    code: 'unauthenticated',
    message: 'This action requires authentication to continue.'
  }
}
```


Create A Client
If everything works as expected, you should be able to create a Client, an Invoice, etc. 
For simplicity, we'll create a Client. Once we do that, this same Client will be created immediately on the FreshBooks dashboard
 we will create a Client and the same client created immediately on the FreshBooks Dashboard
```
const createAClient = async () => {
   let client =
   {
       fName: "John",
       lName: "Doe",
       email: 'no-reply@example.com',
   }
   console.log(accountId)
   try {
       const { ok, data } = await freshBooksClient.clients.create(client, accountId)
       return ok && { data };
   } catch ({ code, message }) {
       return {
           error: { code, message }
       }
   }
}

console.log(await createAClient())
```



List Expenses
We should also be able to list Expenses using the sample block below:
```
//Fetch Expenses
const fetchExpenses = async () => {
   try {
       const { ok, data } = await freshBooksClient.expenses.list(accountId);
       return ok && data
   } catch ({ code, message }) {
       console.error(`Error fetching expenses for accountid:  ${accountId}. The response message got was ${code} - ${message}`)
   }
}

console.log(await fetchExpenses());
```














If everything checks out, you should get a list of expenses These expenses are  also listed on the FreshBooks Dashboard

```
{
  expenses: [
    {
       …
      id: '7538415',
      taxAmount2: null,
      taxAmount1: null,
      visState: 0,
      status: 0,
      vendor: 'FreshBooks Payments',
      notes: 'CC Payment Transaction Fee Invoice: #2021-09',
      updated: 2021-04-17T06:45:36.000Z,
      ...
    }
  ] 
```




Conclusion
This implementation simply scratched the surface of the possibilities of the Node.js SDK as there are several use cases that can be achieved with it.