AutomationFlowsData & Sheets › Automate Expense Reporting From Airtable to Quickbooks

Automate Expense Reporting From Airtable to Quickbooks

ByIntuz @intuz on n8n.io

It seamlessly connects an Airtable base, where expenses are submitted, to your QuickBooks account, eliminating manual data entry and ensuring financial records are always up-to-date. Accountants & Bookkeepers Small Business Owners Finance Teams Operations Managers Trigger on New…

Event trigger★★★★☆ complexity20 nodesAirtable TriggerAirtableHTTP Request
Data & Sheets Trigger: Event Nodes: 20 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #7324 — we link there as the canonical source.

This workflow follows the Airtable → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "WCAyzxSt6yCROjq8",
  "name": "Automate Expense Reporting from Airtable to QuickBooks",
  "tags": [],
  "nodes": [
    {
      "id": "92e68aed-1a03-478b-89d4-5d94e98b3db0",
      "name": "Airtable Trigger",
      "type": "n8n-nodes-base.airtableTrigger",
      "position": [
        -120,
        1120
      ],
      "parameters": {
        "baseId": {
          "__rl": true,
          "mode": "id",
          "value": "appT0dprL0zCSuG45"
        },
        "tableId": {
          "__rl": true,
          "mode": "id",
          "value": "{YOUR_AIRTABLE_TABLE_ID}"
        },
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerField": "Created",
        "authentication": "airtableTokenApi",
        "additionalFields": {}
      },
      "typeVersion": 1
    },
    {
      "id": "0b1822e8-1fcf-4ef0-872d-ec3b50d0ef9d",
      "name": "Search records",
      "type": "n8n-nodes-base.airtable",
      "position": [
        240,
        1120
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "{YOUR_AIRTABLE_BASE_ID}",
          "cachedResultUrl": "https://airtable.com/{YOUR_AIRTABLE_BASE_ID}",
          "cachedResultName": "airtable_expenses_dummy.csv"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "{YOUR_AIRTABLE_TABLE_ID}",
          "cachedResultUrl": "https://airtable.com/{YOUR_AIRTABLE_BASE_ID}/{YOUR_AIRTABLE_TABLE_ID}",
          "cachedResultName": "expense management"
        },
        "options": {},
        "operation": "search"
      },
      "typeVersion": 2.1
    },
    {
      "id": "6bd50650-7226-48ad-afe3-c2493e6c50f8",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        700,
        1120
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "dd2d7985-b436-4213-a3b9-56916c8f59b4",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Status }}",
              "rightValue": "Approved"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2d50d1e9-8c4c-4dff-91cb-d39d0c1d0237",
      "name": "No Operation, do nothing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1580,
        1580
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "5edab364-f81e-47e3-8da4-601b84b3ac19",
      "name": "Download File",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1560,
        780
      ],
      "parameters": {
        "url": "={{ $json['Receipt URL'] }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file",
              "outputPropertyName": "=Receipt"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "84784657-8fad-4e60-aa32-bdf75255ac2f",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        2800,
        760
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "02450b3c-81fa-4159-a910-730365a05dfd",
      "name": "Update record",
      "type": "n8n-nodes-base.airtable",
      "position": [
        3840,
        760
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "{YOUR_AIRTABLE_BASE_ID}",
          "cachedResultUrl": "https://airtable.com/{YOUR_AIRTABLE_BASE_ID}",
          "cachedResultName": "airtable_expenses_dummy.csv"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "{YOUR_AIRTABLE_TABLE_ID}",
          "cachedResultUrl": "https://airtable.com/{YOUR_AIRTABLE_BASE_ID}/{YOUR_AIRTABLE_TABLE_ID}",
          "cachedResultName": "expense management"
        },
        "columns": {
          "value": {
            "id": "={{ $('Search records').item.json.id }}",
            "Status": "Done"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "id",
              "defaultMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Receipt URL",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Receipt URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Amount",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Amount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Date",
              "type": "dateTime",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Memo",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Memo",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "QBO Vendor ID",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "QBO Vendor ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "QBO Expense Account ID",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "QBO Expense Account ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "QBO Payment Account ID",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "QBO Payment Account ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Category",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Created",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "Created",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Receipt Type",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Receipt Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Customer",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Customer",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update"
      },
      "typeVersion": 2.1
    },
    {
      "id": "cb4a1747-f86b-427a-8325-113315392775",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        1300
      ],
      "parameters": {
        "color": 3,
        "width": 500,
        "height": 300,
        "content": "### Step 1: Airtable Trigger \ud83d\udea6\ud83d\udccb\n\nThis node triggers the workflow whenever there is a change in the **Created** column, effectively activating when new data is added.\n\nWhy this step is important:\n\n- \u23f0 Automatically starts the workflow on new entries.\n- \ud83d\udcc8 Monitors real-time changes for timely processing.\n- \ud83d\udd04 Ensures your automation responds instantly to new Airtable data.\n\nIt\u2019s the step that keeps your workflow synced with your Airtable updates. \ud83d\udd14\u2728\n"
      },
      "typeVersion": 1
    },
    {
      "id": "d3c122f4-ce1a-4968-b57a-f8fa3ad261eb",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        60,
        780
      ],
      "parameters": {
        "width": 460,
        "height": 300,
        "content": "### Step 2: Airtable Search Records \ud83d\udd0d\ud83d\udccb\n\nThis node searches and retrieves all records from a specific Airtable table.\n\nWhy this step is important:\n\n- \ud83d\udd0e Gathers complete data from the table for processing.\n- \ud83d\udcca Enables further filtering, updating, or analysis within the workflow.\n- \ud83d\uddc2\ufe0f Provides a snapshot of all relevant records at once.\n\nIt\u2019s the step that collects your data foundation for the automation ahead. \ud83e\uddf1\u2728\n"
      },
      "typeVersion": 1
    },
    {
      "id": "2bc54880-2d88-41e6-9327-37dd97da3689",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        500,
        1280
      ],
      "parameters": {
        "color": 4,
        "width": 500,
        "height": 340,
        "content": "### Step 3: Status Check (If Node) \u2705\u274c\n\nThis node checks whether the **Status** field is set to **Approved**.\n\n- **True:** Status is Approved; workflow continues.\n- **False:** Status is not Approved; workflow can exit or take alternate action.\n\nWhy this step is important:\n\n- \u2714\ufe0f Ensures only approved items proceed in the workflow.\n- \ud83d\uded1 Prevents processing of unapproved or incomplete records.\n- \ud83d\udd04 Maintains workflow accuracy and efficiency.\n\nIt\u2019s the decision point that filters records based on their approval status. \ud83d\udea6\u2728\n"
      },
      "typeVersion": 1
    },
    {
      "id": "111d0402-84f5-4f09-b78d-b5b9ead43713",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1420,
        1260
      ],
      "parameters": {
        "width": 440,
        "height": 300,
        "content": "### Graceful Exit (No-Op Node) \ud83d\uded1\u2728\n\nThis **No Operation** node acts as a graceful exit for items whose **Status** is not Approved.\n\nWhy this step is important:\n\n- \ud83d\udee1\ufe0f Prevents further processing of unapproved records.\n- \ud83d\udd04 Ensures the workflow ends cleanly without errors.\n- \ud83e\uddf9 Maintains clear and organized workflow logic.\n\nIt\u2019s the safe stopping point that quietly ends the flow when no action is needed. \ud83d\udeaa\u2705\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b9847915-663e-4ec6-b815-71b09d28e687",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1360,
        440
      ],
      "parameters": {
        "color": 6,
        "width": 480,
        "height": 300,
        "content": "### Step 4: Download File from Receipt URL (HTTP Request) \ud83d\udce5\ud83d\udcbb\n\nThis node sends an **HTTP Request** to download the file from the provided **Receipt URL**.\n\nWhy this step is important:\n\n- \ud83d\udcc4 Retrieves the actual file (e.g., invoice, receipt) for further processing.\n- \ud83d\udd17 Ensures the workflow has access to the necessary document.\n- \u26a1 Enables downstream nodes to work with the downloaded file.\n\nIt\u2019s the step that pulls the file into your workflow for processing or storage. \ud83d\uddc2\ufe0f\u2728\n"
      },
      "typeVersion": 1
    },
    {
      "id": "6c6f6ede-b978-4351-abe3-cc6226ebc746",
      "name": "QBO-Create Expense",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2220,
        460
      ],
      "parameters": {
        "url": "https://sandbox-quickbooks.api.intuit.com/v3/company/{YOUR_QUICKBOOKS_COMPANY_ID}/purchase",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"PaymentType\": \"Cash\",\n  \"TxnDate\": \"{{$json['Date']}}\",\n  \"PrivateNote\": \"{{$json['Memo']}}\",\n  \"AccountRef\": { \"value\": \"{{$json['QBO Payment Account ID']}}\" },\n  \"EntityRef\": { \"type\": \"Vendor\", \"value\": \"{{$json['QBO Vendor ID']}}\" },\n  \"Line\": [\n    {\n      \"Amount\": {{$json['Amount']}},\n      \"DetailType\": \"AccountBasedExpenseLineDetail\",\n      \"AccountBasedExpenseLineDetail\": {\n        \"AccountRef\": { \"value\": \"{{$json['QBO Expense Account ID']}}\" }\n      }\n    }\n  ]\n}\n",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "quickBooksOAuth2Api"
      },
      "typeVersion": 4.2
    },
    {
      "id": "d6f91071-2044-4c56-b940-962a63765b60",
      "name": "QBO-Upload File",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3320,
        760
      ],
      "parameters": {
        "url": "https://sandbox-quickbooks.api.intuit.com/v3/company/{YOUR_QUICKBOOKS_COMPANY_ID}/upload?minorversion=65",
        "method": "POST",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendBody": true,
        "contentType": "multipart-form-data",
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "file_content_01",
              "parameterType": "formBinaryData",
              "inputDataFieldName": "Receipt"
            }
          ]
        },
        "nodeCredentialType": "quickBooksOAuth2Api"
      },
      "typeVersion": 4.2
    },
    {
      "id": "b12dc68f-ef24-42a7-801c-54d03e729b67",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2060,
        100
      ],
      "parameters": {
        "color": 5,
        "width": 440,
        "height": 300,
        "content": "**Step 5 - Create Expense in QuickBooks (QBO) \ud83d\udcb8\ud83e\uddfe**\n\nThis node uses the **Create Expense** operation to add an expense in QuickBooks based on data from Airtable.\n\nWhy this step is important:\n\n- \ud83d\udcca Automatically records expenses from your Airtable data.\n- \ud83d\udd17 Links expenses to the correct accounts and vendors in QuickBooks.\n- \u26a1 Streamlines bookkeeping and financial tracking.\n\nIt\u2019s the step that turns raw expense data into an official QuickBooks record. \u2705\u2728\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e0617428-57bd-4fd6-b4cd-afec5931f363",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2640,
        920
      ],
      "parameters": {
        "width": 480,
        "height": 340,
        "content": "### Step 6: Merge Expense and File Data Node \ud83d\udd17\ud83d\udcc2\n\nThis node merges data from the **Create Expense** node and the **Download File** node.\n\nWhy this step is important:\n\n- \ud83d\udd04 Combines expense details with the corresponding file (receipt or invoice).\n- \ud83d\udcca Ensures all relevant information is packaged together for the next steps.\n- \u2699\ufe0f Maintains data integrity and prepares a unified dataset for further processing.\n\nIt\u2019s the step that consolidates expense and file data for smooth workflow continuation. \ud83e\udd1d\u2728\n"
      },
      "typeVersion": 1
    },
    {
      "id": "21f9dc2b-852c-43eb-9600-beb33c567bf7",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3120,
        500
      ],
      "parameters": {
        "color": 3,
        "width": 480,
        "height": 240,
        "content": "### Step 7: Upload File to QuickBooks (QBO Upload) \ud83d\udce4\ud83e\uddfe\n\nThis node uses the **Upload File** operation to attach the downloaded file (e.g., receipt or invoice) to QuickBooks.\n\nWhy this step is important:\n- \ud83d\udd17 Ensures proper documentation for bookkeeping and auditing.\n- \u26a1 Automates file management within QuickBooks, saving time and reducing errors.\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "5e7976bb-8812-407b-b79e-a67f2462e07c",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3680,
        940
      ],
      "parameters": {
        "color": 4,
        "width": 480,
        "height": 300,
        "content": "### Step 8: Update Airtable Record Status \u270f\ufe0f\u2705\n\nThis node updates the **Status** column of the Airtable records to **Done**.\n\nWhy this step is important:\n\n- \ud83d\udd04 Marks the completion of the workflow for each record.\n- \ud83d\udccb Provides clear visibility on processed items.\n- \u26a1 Ensures Airtable reflects the latest workflow status.\n\nIt\u2019s the step that closes the loop by updating the record\u2019s status to indicate successful processing. \ud83c\udfc1\u2728\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f270dc7e-492a-4f23-9f65-f4658c3aedde",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -180,
        20
      ],
      "parameters": {
        "color": 3,
        "width": 600,
        "height": 440,
        "content": "### Prerequisites \u2699\ufe0f\ud83d\udd17\n\n- Create and connect your **Airtable** account using a **Personal Access Token**.\n- Create a table with the following columns:\n  - **Status**\n  - **Receipt URL**\n  - **Amount**\n  - **Date**\n  - **Memo**\n  - **QBO Vendor ID**\n  - **QBO Expense Account ID**\n  - **QBO Payment Account ID**\n  - **Category**\n  - **Receipt Type**\n  - **Customer**\n- Connect your oauth2 Quickbooks credentials\n- Add your company id in the QBO nodes\nThese configurations ensure your Airtable is ready for seamless integration with QuickBooks and the workflow. \u2705\u2728\n"
      },
      "typeVersion": 1
    },
    {
      "id": "a356ca74-915c-4349-9d68-c1a03cdc58f8",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1500,
        1800
      ],
      "parameters": {
        "width": 440,
        "height": 300,
        "content": "### Get in Touch\n\nPlease feel free to reachout to us, if you need any help in settin up this workflow.\n\nWe can also help customize workflow pet the use-case. \n\nReach out us at: getstarted@intuz.com\n\nWebsite: https://www.intuz.com/\n\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "71973fac-b373-4884-b5d0-f70497f5c2cb",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Download File",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "QBO-Upload File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download File": {
      "main": [
        [
          {
            "node": "QBO-Create Expense",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Search records": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "QBO-Upload File": {
      "main": [
        [
          {
            "node": "Update record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Airtable Trigger": {
      "main": [
        [
          {
            "node": "Search records",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "QBO-Create Expense": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

It seamlessly connects an Airtable base, where expenses are submitted, to your QuickBooks account, eliminating manual data entry and ensuring financial records are always up-to-date. Accountants & Bookkeepers Small Business Owners Finance Teams Operations Managers Trigger on New…

Source: https://n8n.io/workflows/7324/ — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Data & Sheets

Upload Bulk Records From Csv Airtable Interfaces. Uses airtable, httpRequest, stickyNote, spreadsheetFile. Event-driven trigger; 17 nodes.

Airtable, HTTP Request, Spreadsheet File +1
Data & Sheets

This workflow is a supporting automation to a common Airtable situation, that as of this writing, has no direct solution but has great demand.

Airtable, HTTP Request, Spreadsheet File +1
Data & Sheets

This template is ideal for solo store owners, eCommerce marketers, automation beginners, or anyone using Shopify and Gmail who wants to recover lost revenue without coding.

HTTP Request, Gmail, Twilio +3
Data & Sheets

This guide will walk you through setting up your n8n workflow. By the end, you'll have a fully automated system for managing your recruitment pipeline.

Google Calendar Trigger, Slack, HTTP Request +4
Data & Sheets

This workflow is perfect for recruiters, HR professionals, and startup founders who receive job applications by email and want to automate the process of parsing, matching, and evaluating resumes. If

Gmail Trigger, Airtable, HTTP Request +2