Business Categorization

Now that you've connected your data sources with Hurdlr's Expense Tracking API, you're ready to start leveraging all of the Expense Tracking features that Hurdlr has to offer, including Business & Tax Categorization.

1. How it works

Through Hurdlr's Plaid or MX integration, your user's transactions are pulled into Hurdlr as soon as Plaid makes them available. All of those transactions are then run through Hurdlr's proprietary algorithms, which leverage the user's business type, accountant best practices, and the behavior of similar businesses within the Hurdlr app's 700k+ users. The expense transactions are then categorized in three primary ways:

a) Business Categories: Hurdlr uses categories specific to the user's business, which a non-accountant business owner can understand. For example, an Uber driver's expense might be categorized as "Car Wash".

b) Tax Categories: All expenses are also mapped to a tax category, which ultimately maps to specific line items on the 1040 Schedule C, 1065, and 1120S.

c) Deduction Confidence: Based on the user's business type and many other factors, Hurdlr's algorithms predict whether any given expense is deductible

2. Getting the user's expenses

First, you should retrieve a list of the user's expenses. Be sure to include that user's access_token in the headers.

curl \
  --request GET \
  --url https://sandbox.hurdlr.com/rest/v5/expenses/expenses?lastUpdatedDate=1970-01-01 \
  --header 'Authorization: Bearer ${access_token}' \
  --header 'Content-Type: application/json' \

📘

lastUpdatedDate

On any given endpoint, if you populate the lastUpdatedDate URI parameter, the Hurdlr API will only return the records that have been updated since that date/time. Since users often have many transactions, to optimize performance we recommend setting lastUpdatedDate to the last time that you initiated the same GET request; if this is your first request on behalf of a given user, simply pass in "1970-01-01". The response will contain a lastUpdatedDate, which we recommend you store in your DB, so that you can use that as an input parameter on your subsequent requests.

The response from GET /expenses contains an array of the user's expenses:

{
  "data": [
    {
      "id": 1118496,
      "type": "PENDING",
      "date": "2020-08-27 00:00:00.000",
      "amount": 500.39,
      "categoryId": 13325612,
      "personalCategoryId": 233391,
      "confidence": "QUESTIONABLE",
      "vendorName": "United Airlines",
      "vendorId": 237791,
      "businessId": null,
      "clientId": null,
      "description": "",
      "apiExpenseId": "VDAx5DKlNLhad1r5p6bQtk58X1kwrbC9ddPyK",
      "apiName": "PLAID",
      "apiAccountNo": "0000",
      "apiAccountName": "Plaid Checking",
      "apiInstitutionId": "ins_127989",
      "plaidItemAccountId": 120693,
      "bankDescription": "UNITED AIRLINES X234X CHARGE",
      "lastUpdatedDate": "2020-08-27T01:09:17.000Z"
    }
  ],
  "lastUpdatedDate": "2021-09-01T15:37:40.107Z"
}

On each expense, you may find the following attributes to be of particular interest:

Field

Description

Format

id

Id of the expense record

Numeric

type

Type of expense

Must be one of the following: "PENDING", "BUSINESS", "NOT_BUSINESS"

date

Date that the expense was incurred

yyyy-MM-dd'T'HH:mm:ss.SSSZ

amount

Total value of the expense

Numeric, with 2 decimal places

categoryId

Id of the associated business expense category

Numeric

personalCategoryId

Id of the associated personal expense category

Numeric

confidence

Deduction confidence of the expense transaction

Must be one of the following: "LIKELY", "NOT_LIKELY", "QUESTIONABLE"

vendorName

Name of the vendor that the expense was incurred with

Any string

vendorId

Id of the associated vendor

Numeric

businessId

Id of the business that this was assigned to; only populated if type == "BUSINESS

Numeric

clientId

Id of the client that this was assigned to; optional, only populated if type == "BUSINESS

Numeric

lastUpdatedDate

The last date/time that this record was modified

yyyy-MM-dd'T'HH:mm:ss.SSSZ

Additionally, several attributes to help you or your user identify a bank transaction are listed below:

Field

Description

Format

apiInstitutionId

Id of the institution that the transaction originated from

Any string

apiAccountName

Display name for the user's bank account

Any string

apiAccountNo

Mask of the user's bank account, often the last 4 digits of the account number

2-4 Alphanumeric characters

plaidItemAccountId

Id of the bank account that this transaction originated from (within Hurdlr's API)

Numeric

apiName

Name of the API that this transaction originated from

Will always be "PLAID", unless you are utilizing one of Hurdlr's other direct integrations

apiExpenseId

Id of the transaction record in Plaid's API

Any string

bankDescription

Transaction description (similar to what will show on the user's bank statement)

Any string

3. Identifying a transaction's business categorization

On each expense transaction, you will see an categoryId field, which maps to one of Hurdlr's business-specific expense categories. To pull a user's business expense categories, you can make the following GET call. Be sure to include that user's access_token in the headers.

curl \
  --request GET \
  --url https://sandbox.hurdlr.com/rest/v5/expenses/categories?lastUpdatedDate=1970-01-01 \
  --header 'Authorization: Bearer ${access_token}' \
  --header 'Content-Type: application/json' \

The response from GET /expenseCategories contains an array of the user's expense categories:

{
  data: [
    {
      "id": 1,
      "name": "Accounting / Tax",
      "taxCategory": {
        "id": 11,
        "name": "LEGAL_AND_PROFESSIONAL_SERVICES",
        "displayName": "Legal and Professional Services",
        "form1040SchedCLineNumber": "17",
        "form1040SchedCDisplayName": "Legal and Professional Services",
        "form1065LineNumber": "20",
        "form1065DisplayName": "Other deductions (attach statement)",
        "form1120SSLineNumber": "19",
        "form1120SDisplayName": "Other deductions (attach statement)",
        "t2125LineNumber": "8860",
        "t2125DisplayName": "Professional fees (includes legal and accounting fees)",
      },
      "hasChilds": false,
      "parentCategoryId": 70,
      "status": "ACTIVE",
      "lastUpdatedDate": "2021-08-13T22:14:23.000Z"
    }
 ],
 "lastUpdatedDate": "2021-08-27T15:37:40.107Z"
}

On each business expense category, you may find the following attributes to be of particular interest:

Field

Description

Format

id

Id of the expense category record

Numeric

name

Name of the business-specific expense category

Any string

The name of each expense category is specific to the user's business type, which will make sense to a non-accountant business owner. For example, an Uber Driver will have an expense category of "Car Wash". Of course, the Hurdlr API also takes care of mapping that to the proper tax categories, without the user having to think about that.

4. Classifying expense transactions

Pending expenses, i.e. expenses with type == "PENDING", are expense transactions that your user has not yet approved. Once they have been approved, they will be included in all the tax estimates, financial reporting, and other features that the Hurdlr API offers.

You should update the following fields on an expense object when approving a pending expense:

Field

Description

Format

id

Id of the pending expense record

Numeric

type

Whether the transaction is being classified as Business or Not Business

Must be one of the following: "BUSINESS", "NOT_BUSINESS"

businessId

Id of the business that this should be assigned to (only used if status=BUSINESS)

Numeric

clientId

Id of the client that this should be assigned to (only used if status=BUSINESS). Optional.

Numeric

categoryId

Id of the business expense category; most times, this will be the same value that came in on the pending expense, but you may want to allow your user to change that category

Numeric

personalCategoryId

Id of the personal expense category

Numeric

description

User-entered description of the expense. Optional.

Any string

To approve the pending expense, simply POST the updated expense's JSON object to the /expense endpoint:

curl \
  --request POST \
  --url https://sandbox.hurdlr.com/rest/v5/expenses/expense \
  --header 'Authorization: Bearer ${access_token}' \
  --header 'Content-Type: application/json' \
  --data '{
    "expense": {
      "id": 1118496,
      "type": "BUSINESS",
      "businessId": 416080,
      "clientId": 805609,
      "date": "2020-08-27 00:00:00.000",
      "amount": 500.39,
      "categoryId": 13325612,
      "personalCategoryId": "233391",
      "vendorId": 237791,
      "description": "Flight to meet with Bill Tanner"
    }
  }'

Of course, users can make mistakes or change their mind, and the Hurdlr API makes it easy for you to allow those updates. To update a classified expense, simply update the expense's JSON object again as needed, and POST it to the /expense endpoint like we did above.