This workflow corresponds to n8n.io template #7291 — 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 →
{
"id": "wnHdgRqker2FalaJ",
"name": "My workflow 23",
"tags": [],
"nodes": [
{
"id": "989dcbdc-5d15-45df-bb0e-db6049c537e2",
"name": "Airtable Trigger",
"type": "n8n-nodes-base.airtableTrigger",
"position": [
60,
1780
],
"parameters": {
"baseId": {
"__rl": true,
"mode": "id",
"value": "{YOUR_AIRTABLE_BASE_ID}"
},
"tableId": {
"__rl": true,
"mode": "id",
"value": "{YOUR_AIRTABLE_TABLE_ID}"
},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"triggerField": "Created",
"authentication": "airtableTokenApi",
"additionalFields": {}
},
"typeVersion": 1
},
{
"id": "45863a72-e832-448e-88e6-edb6ee1c8908",
"name": "IF - Status Check",
"type": "n8n-nodes-base.if",
"position": [
1580,
1580
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.Status }}",
"value2": "Approved for Invoicing"
}
]
}
},
"typeVersion": 1
},
{
"id": "43c615f1-777f-43da-8274-2b9ecce18aa0",
"name": "IF - Customer Exists?",
"type": "n8n-nodes-base.if",
"position": [
3020,
1340
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.Id ?? \"\" }}",
"operation": "isEmpty"
}
]
}
},
"typeVersion": 1,
"alwaysOutputData": false
},
{
"id": "2cb49f5e-08f7-46ea-afab-217e98908a14",
"mode": "append",
"name": "Merge QBO Customer",
"type": "n8n-nodes-base.merge",
"position": [
4320,
1540
],
"parameters": {},
"typeVersion": 1
},
{
"id": "60920472-77b6-4243-89b0-f162f6e900d9",
"name": "Stripe - Find Customer",
"type": "n8n-nodes-base.stripe",
"position": [
5800,
1020
],
"parameters": {
"resource": "customer",
"customerId": "={{ $('Search records').item.json['Stripe Customer ID'] || \"\"}}"
},
"typeVersion": 1
},
{
"id": "bd0adf89-499a-40ee-9e37-648ae0aad30d",
"name": "IF - Stripe Customer Exists?",
"type": "n8n-nodes-base.if",
"position": [
7220,
1160
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.DisplayName }}",
"operation": "isNotEmpty"
}
]
}
},
"typeVersion": 1
},
{
"id": "ea27b7d1-4e6e-4620-b402-b0b8e0db436d",
"name": "Stripe - Create Customer",
"type": "n8n-nodes-base.stripe",
"position": [
7960,
980
],
"parameters": {
"name": "={{ $json.DisplayName }}",
"resource": "customer",
"operation": "create",
"additionalFields": {
"email": "={{ $json.PrimaryEmailAddr.Address }}"
}
},
"typeVersion": 1
},
{
"id": "901e1828-f5e5-4801-83a0-53fce11f4ea0",
"mode": "append",
"name": "Merge Stripe Customer",
"type": "n8n-nodes-base.merge",
"position": [
8520,
1380
],
"parameters": {},
"typeVersion": 1
},
{
"id": "4c99441c-1f72-49d6-b421-62e3c2c72b28",
"name": "QuickBooks - Find Customer",
"type": "n8n-nodes-base.quickbooks",
"position": [
2360,
1160
],
"parameters": {
"limit": 500,
"filters": {
"query": "=WHERE DisplayName = '{{ $json['Client Name'] }}'\n\n"
},
"operation": "getAll"
},
"typeVersion": 1,
"alwaysOutputData": false
},
{
"id": "497c8d82-1916-4ac6-acd2-7fdc561d3919",
"name": "Create an invoice",
"type": "n8n-nodes-base.quickbooks",
"position": [
13120,
1420
],
"parameters": {
"Line": [
{
"Qty": "={{ $('Update Quickbooks and Stripe Customer Ids').item.json.fields.Quantity }}",
"Amount": "={{ $json.Amount }}",
"itemId": "={{ $json.Id }}",
"DetailType": "SalesItemLineDetail",
"Description": "={{ $json.Description }}"
}
],
"resource": "invoice",
"operation": "create",
"CustomerRef": "={{ $('Update Quickbooks and Stripe Customer Ids').item.json.fields['QuickBooks Customer ID'] }}",
"additionalFields": {}
},
"typeVersion": 1
},
{
"id": "b1330d78-6e36-4296-98b0-0312804e955d",
"name": "Create a customer",
"type": "n8n-nodes-base.quickbooks",
"position": [
3680,
1100
],
"parameters": {
"operation": "create",
"displayName": "={{ $('IF - Status Check').item.json['Client Name'] }}",
"additionalFields": {
"PrimaryEmailAddr": "={{ $('IF - Status Check').item.json['Client Email'] }}"
}
},
"typeVersion": 1
},
{
"id": "8b371200-572e-4995-b7d7-d496751342f4",
"name": "Search records",
"type": "n8n-nodes-base.airtable",
"position": [
800,
1360
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "{YOUR_AIRTABLE_BASE_ID}",
"cachedResultUrl": "https://airtable.com/{YOUR_AIRTABLE_BASE_ID}",
"cachedResultName": "{YOUR_AIRTABLE_BASE_NAME}"
},
"table": {
"__rl": true,
"mode": "list",
"value": "{YOUR_AIRTABLE_TABLE_ID}",
"cachedResultUrl": "https://airtable.com/{YOUR_AIRTABLE_BASE_ID}/{YOUR_AIRTABLE_TABLE_ID}",
"cachedResultName": "{YOUR_AIRTABLE_TABLE_NAME}"
},
"options": {},
"operation": "search"
},
"typeVersion": 2.1
},
{
"id": "d56e433c-447b-406f-8467-a8c5de082d5b",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-100,
1920
],
"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": "44f16735-21cb-4a35-bb97-45bf8ec79469",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
620,
1040
],
"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": "430acba9-f9ad-424f-888e-a239968e9bbf",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1360,
1220
],
"parameters": {
"color": 5,
"width": 500,
"height": 300,
"content": "### Step 3: Status Check (If Node) \u2705\u274c\n\nThis node checks whether the **Status** field is set to **'Approved for Invoicing'**.\n\n- **True:** Continues with the workflow.\n- **False:** Gracefully exits the workflow.\n\nWhy this step is important:\n\n- \u2714\ufe0f Ensures only approved records proceed for invoicing.\n- \ud83d\uded1 Prevents processing of draft or already invoiced data.\n- \ud83d\udd04 Maintains workflow efficiency and accuracy."
},
"typeVersion": 1
},
{
"id": "5d2740d4-c4fc-4290-914c-bcbff9202b1c",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
2200,
2080
],
"parameters": {
"color": 3,
"width": 520,
"height": 300,
"content": "### Graceful Exit (No-Op Node) \ud83d\uded1\u2728\n\nThis **No Operation** node acts as a graceful exit point for items whose status is **not** 'Approved for Invoicing'.\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 Keeps workflow logic clear and organized.\n\nIt\u2019s the safe landing spot that quietly ends the flow when no action is needed. \ud83d\udeaa\u2705\n"
},
"typeVersion": 1
},
{
"id": "12d6c762-e245-4203-b91d-a03ad0c39c5a",
"name": "Exit from workflow",
"type": "n8n-nodes-base.noOp",
"position": [
2400,
1920
],
"parameters": {},
"typeVersion": 1
},
{
"id": "d3de759a-8382-4127-867f-84afbc9fb1b6",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
2180,
800
],
"parameters": {
"color": 4,
"width": 460,
"height": 320,
"content": "### Step 4: Find Customer in QuickBooks \ud83d\udd0d\ud83d\udc64\n\nThis node uses the **Find Customer** operation to search for a customer in QuickBooks based on the **Display Name** parameter.\n\nWhy this step is important:\n\n- \ud83d\udd0e Quickly locates existing customers by their display name.\n- \u2705 Helps avoid duplicate customer records.\n- \ud83d\udccb Ensures accurate linking of invoices and estimates to the right customer.\n\nIt\u2019s the step that verifies customer existence to maintain clean and organized data. \ud83e\uddf9\u2728\n"
},
"typeVersion": 1
},
{
"id": "2aa200ff-342e-4a9b-b46d-956dc31ea3e1",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
2820,
1480
],
"parameters": {
"color": 6,
"width": 580,
"height": 340,
"content": "### Step 5: Customer Existence Check (If Node) \u2753\u2705\u274c\n\nThis node checks whether a customer exists in QuickBooks.\n\n- **False:** Customer exists; workflow continues without creating a new customer.\n- **True:** Customer does **not** exist; triggers creation of a new customer before continuing.\n\nWhy this step is important:\n\n- \ud83d\udd04 Directs the workflow to create a customer only when needed.\n- \ud83d\udee1\ufe0f Prevents duplicate customer entries.\n- \u2699\ufe0f Ensures smooth, logical progression of the automation.\n\nIt\u2019s the decision point that manages customer creation intelligently. \ud83d\udd00\u2728\n"
},
"typeVersion": 1
},
{
"id": "054ac6a9-7198-49d3-8005-8291e2b99de1",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
3480,
780
],
"parameters": {
"color": 4,
"width": 480,
"height": 300,
"content": "Create Customer in QuickBooks \u2795\ud83d\udc64\n\nThis node uses the **Create Customer** operation to add a new customer to QuickBooks using details from Airtable.\n\nWhy this step is important:\n\n- \ud83c\udd95 Adds new customers automatically when they don\u2019t exist.\n- \ud83d\udce5 Keeps your QuickBooks customer database current and accurate.\n- \ud83d\udd17 Links customer records to subsequent invoices or estimates.\n\nIt\u2019s the step that fills gaps in your customer list, ensuring seamless data flow. \u270d\ufe0f\u2728\n"
},
"typeVersion": 1
},
{
"id": "e656e242-fcd7-4f4b-b8c7-1093e6873c9d",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
4160,
1180
],
"parameters": {
"width": 500,
"height": 300,
"content": "### Step 6: Merge Customer Data Node \ud83d\udd17\ud83d\udcca\n\nThis node merges data from existing customers with newly created customer records.\n\nWhy this step is important:\n\n- \ud83d\udd04 Combines customer information into a single dataset.\n- \ud83d\udccb Ensures continuity and completeness of customer details.\n- \u2699\ufe0f Prepares unified data for downstream workflow steps.\n\nIt\u2019s the step that brings together all customer data for seamless processing. \ud83e\udd1d\u2728\n"
},
"typeVersion": 1
},
{
"id": "43640cbe-d8c0-4d46-a8be-71ed26deaf88",
"name": "If - Stripe Customer Id",
"type": "n8n-nodes-base.if",
"position": [
5100,
1180
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "0e0b7c72-589a-4d76-9201-cbc4cfdc9c70",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $('Search records').item.json['Stripe Customer ID'] }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "e7fd405d-2dca-453d-ad16-086d855393e0",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
4840,
800
],
"parameters": {
"color": 3,
"width": 600,
"height": 340,
"content": "### Step 7: Stripe Customer ID Check (If Node) \ud83d\udd0d\ud83d\udcb3\n\nThis node checks whether the **Stripe Customer ID** already exists for users in Airtable.\n\n- **True:** Stripe Customer ID exists; proceeds to find the customer.\n- **False:** Stripe Customer ID does not exist; continues with the workflow to create or update as needed.\n\nWhy this step is important:\n\n- \u2705 Prevents duplicate Stripe customer entries.\n- \ud83d\udd04 Directs the workflow along the correct path based on Stripe data.\n- \u2699\ufe0f Maintains data integrity across systems.\n\nIt\u2019s the decision point that manages Stripe customer handling efficiently. \ud83d\udd00\u2728\n"
},
"typeVersion": 1
},
{
"id": "d8810872-3110-450d-a87e-a68c6acec976",
"name": "Sticky Note9",
"type": "n8n-nodes-base.stickyNote",
"position": [
5540,
680
],
"parameters": {
"color": 5,
"width": 580,
"height": 300,
"content": "Find Customer in Stripe \ud83d\udd0d\ud83d\udcb3\n\nThis node uses the **Find Customer** operation to search for a customer in Stripe based on the **Stripe Customer ID**.\n\nWhy this step is important:\n\n- \ud83d\udd0e Quickly locates the customer record in Stripe.\n- \u2705 Ensures accurate synchronization between your systems.\n- \ud83d\udccb Prevents duplicate customer creation in Stripe.\n\nIt\u2019s the step that verifies Stripe customer existence to maintain clean and consistent billing data. \ud83e\uddf9\u2728\n"
},
"typeVersion": 1
},
{
"id": "0af13885-0000-48a4-9a1a-5ca0695d4329",
"name": "Merge - Stripe Customers",
"type": "n8n-nodes-base.merge",
"position": [
6320,
1460
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "66ce007d-361a-44d1-b397-c8bf354bc62a",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
6180,
1620
],
"parameters": {
"color": 6,
"width": 480,
"height": 300,
"content": "### Step 8: Merge Stripe Customer Data Node \ud83d\udd17\ud83d\udcb3\n\nThis node merges data from the **If Node** decision with the newly retrieved customer data from the **Stripe - Find Customer** node.\n\nWhy this step is important:\n\n- \ud83d\udd04 Combines decision results with fresh customer information.\n- \ud83d\udcca Ensures unified data for further processing in the workflow.\n- \u2699\ufe0f Maintains data consistency across Stripe and Airtable.\n\nIt\u2019s the step that integrates conditional logic with actual customer details for smooth automation. \ud83e\udd1d\u2728\n"
},
"typeVersion": 1
},
{
"id": "642cf14a-238f-4525-bc6c-a4d88ad2ff25",
"name": "Sticky Note11",
"type": "n8n-nodes-base.stickyNote",
"position": [
7020,
780
],
"parameters": {
"color": 3,
"width": 540,
"height": 340,
"content": "### Step 9: Stripe Customer Existence Check (If Node) \ud83d\udd0d\u2705\u274c\n\nThis node checks whether a Stripe customer exists based on the **name**.\n\n- **True:** Customer does **not** exist; proceeds to create a new customer.\n- **False:** Customer exists; continues with the workflow without creating.\n\nWhy this step is important:\n\n- \u2705 Prevents duplicate Stripe customer creation.\n- \ud83d\udd04 Directs workflow to create customers only when necessary.\n- \u2699\ufe0f Ensures clean and accurate Stripe customer data.\n\nIt\u2019s the decision gate that manages Stripe customer creation smartly. \ud83d\udd00\u2728\n"
},
"typeVersion": 1
},
{
"id": "fe468b60-5f78-4a61-9262-a0c24e2054e8",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
7740,
640
],
"parameters": {
"width": 500,
"height": 320,
"content": "Create Customer in Stripe \u2795\ud83d\udcb3\n\nThis node uses the **Create Customer** operation to add a new customer in Stripe using the **name** and **email address** from Airtable.\n\nWhy this step is important:\n\n- \ud83c\udd95 Automatically adds new customers to Stripe when they don\u2019t exist.\n- \ud83d\udce7 Uses accurate customer details from Airtable for Stripe records.\n- \ud83d\udd17 Ensures Stripe customer data is up-to-date and linked correctly.\n\nIt\u2019s the step that expands your Stripe customer base seamlessly from Airtable data. \u270d\ufe0f\u2728\n"
},
"typeVersion": 1
},
{
"id": "84f2c126-13e0-4999-95ed-c62155473934",
"name": "Sticky Note13",
"type": "n8n-nodes-base.stickyNote",
"position": [
8320,
1540
],
"parameters": {
"color": 5,
"width": 520,
"height": 300,
"content": "### Step 10: Merge New Stripe Customer Data Node \ud83d\udd17\ud83d\udcb3\n\nThis node merges data from the previous **If Node** with the newly created Stripe customer data.\n\nWhy this step is important:\n\n- \ud83d\udd04 Combines decision results with fresh customer creation data.\n- \ud83d\udcca Provides a unified dataset for downstream processing.\n- \u2699\ufe0f Ensures consistency and completeness of customer information.\n\nIt\u2019s the step that integrates newly created Stripe customer details seamlessly into the workflow. \ud83e\udd1d\u2728\n"
},
"typeVersion": 1
},
{
"id": "d72208de-119a-4cc7-8f41-c04e8534fdf5",
"name": "Search records by email",
"type": "n8n-nodes-base.airtable",
"position": [
9260,
1080
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "{YOUR_AIRTABLE_BASE_ID}",
"cachedResultUrl": "https://airtable.com/{YOUR_AIRTABLE_BASE_ID}",
"cachedResultName": "{YOUR_AIRTABLE_BASE_NAME}"
},
"table": {
"__rl": true,
"mode": "list",
"value": "{YOUR_AIRTABLE_TABLE_ID}",
"cachedResultUrl": "https://airtable.com/{YOUR_AIRTABLE_BASE_ID}/{YOUR_AIRTABLE_TABLE_ID}",
"cachedResultName": "{YOUR_AIRTABLE_TABLE_NAME}"
},
"options": {},
"operation": "search",
"filterByFormula": "={Client Email} = \"{{ $json.email }}\""
},
"typeVersion": 2.1,
"alwaysOutputData": true
},
{
"id": "0dc8e7c1-e027-4641-9618-357f72d67039",
"name": "Sticky Note14",
"type": "n8n-nodes-base.stickyNote",
"position": [
9060,
760
],
"parameters": {
"color": 6,
"width": 480,
"height": 300,
"content": "### Step 11: Search Records in Airtable \ud83d\udd0d\ud83d\udccb\n\nThis node searches for complete records in the Airtable table based on the **email address** from the previous merge node.\n\nWhy this step is important:\n\n- \ud83d\udd0e Retrieves full user data linked to the email.\n- \ud83d\udcca Ensures accurate and updated information for the workflow.\n- \u2699\ufe0f Enables precise matching and further processing.\n\nIt\u2019s the step that pulls detailed Airtable records to keep your automation data-rich and reliable. \ud83d\udcda\u2728\n"
},
"typeVersion": 1
},
{
"id": "62d46511-8cf8-4160-a242-bea2e4e81086",
"name": "Update Quickbooks and Stripe Customer Ids",
"type": "n8n-nodes-base.airtable",
"position": [
9980,
1400
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "{YOUR_AIRTABLE_BASE_ID}",
"cachedResultUrl": "https://airtable.com/{YOUR_AIRTABLE_BASE_ID}",
"cachedResultName": "{YOUR_AIRTABLE_BASE_NAME}"
},
"table": {
"__rl": true,
"mode": "list",
"value": "{YOUR_AIRTABLE_TABLE_ID}",
"cachedResultUrl": "https://airtable.com/{YOUR_AIRTABLE_BASE_ID}/{YOUR_AIRTABLE_TABLE_ID}",
"cachedResultName": "{YOUR_AIRTABLE_TABLE_NAME}"
},
"columns": {
"value": {
"id": "={{ $json.id }}",
"Stripe Customer ID": "={{ $('Merge Stripe Customer').item.json.id }}",
"QuickBooks Customer ID": "={{ $('Merge QBO Customer').item.json.Id }}"
},
"schema": [
{
"id": "id",
"type": "string",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "id",
"defaultMatch": true
},
{
"id": "Deal Name",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Deal Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Client Name",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Client Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Client Email",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Client Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "options",
"display": true,
"options": [
{
"name": "Approved for Invoicing",
"value": "Approved for Invoicing"
},
{
"name": "Draft",
"value": "Draft"
},
{
"name": "Invoiced",
"value": "Invoiced"
}
],
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Line Items JSON",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Line Items JSON",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "QuickBooks Customer ID",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "QuickBooks Customer ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Stripe Customer ID",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Stripe Customer ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Stripe Payment Link",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Stripe Payment Link",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "QuickBooks Invoice #",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "QuickBooks Invoice #",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update"
},
"typeVersion": 2.1
},
{
"id": "5cbaa7bd-1ef6-49d8-8b61-fef3f2d3090c",
"name": "Sticky Note15",
"type": "n8n-nodes-base.stickyNote",
"position": [
9780,
1580
],
"parameters": {
"width": 520,
"height": 300,
"content": "### Step 12: Update Records in Airtable \u270f\ufe0f\ud83d\udd04\n\nThis node updates the Airtable records to add or modify the **QuickBooks Customer ID** and **Stripe Customer ID** for the corresponding users.\n\nWhy this step is important:\n\n- \ud83c\udd95 Keeps Airtable data synchronized with QuickBooks and Stripe.\n- \ud83d\udd17 Ensures accurate linking of customer IDs across platforms.\n- \ud83d\udd04 Maintains data integrity for future workflows and reports.\n\nIt\u2019s the step that closes the loop by updating your source data with key customer identifiers. \u2705\u2728\n"
},
"typeVersion": 1
},
{
"id": "cdd5c85d-1168-4b4e-ab95-b17132f0bd10",
"name": "Generate Payment Links",
"type": "n8n-nodes-base.httpRequest",
"position": [
10700,
1080
],
"parameters": {
"url": "https://api.stripe.com/v1/payment_links",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "form-urlencoded",
"authentication": "predefinedCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "line_items[0][price]",
"value": "={{ $json.fields['Stripe Price Id'] }}"
},
{
"name": "line_items[0][quantity]",
"value": "={{ $json.fields.Quantity }}"
}
]
},
"nodeCredentialType": "stripeApi"
},
"typeVersion": 4.2
},
{
"id": "86d2ad6f-2501-4885-9f61-40563bcd132a",
"name": "Sticky Note16",
"type": "n8n-nodes-base.stickyNote",
"position": [
10500,
760
],
"parameters": {
"color": 3,
"width": 520,
"height": 300,
"content": "### Step 13: Generate Stripe Payment Link (HTTP Request) \ud83d\udd17\ud83d\udcb3\n\nThis node sends a **POST** HTTP request with the **Stripe Price ID** and **quantity** from Airtable to generate a ready-to-pay link.\n\nWhy this step is important:\n\n- \ud83d\uded2 Creates a payment link dynamically based on order details.\n- \ud83d\udd17 Enables easy and secure customer checkout.\n- \u26a1 Automates payment initiation directly from your data.\n\nIt\u2019s the step that turns order info into a clickable payment link, simplifying the checkout process. \ud83d\udd25\u2728\n"
},
"typeVersion": 1
},
{
"id": "cce1f3fd-3731-41ea-8b6c-b1b6872f571c",
"name": "Get all Quickbook products",
"type": "n8n-nodes-base.httpRequest",
"position": [
11440,
1400
],
"parameters": {
"url": "https://quickbooks.api.intuit.com/v3/company/{YOUR_QUICKBOOKS_COMPANY_ID}/query?query=SELECT%20*%20FROM%20Item",
"options": {},
"authentication": "predefinedCredentialType",
"nodeCredentialType": "quickBooksOAuth2Api"
},
"typeVersion": 4.2
},
{
"id": "e4819fee-6591-45cf-b9e7-000ec6ba07e4",
"name": "Sticky Note17",
"type": "n8n-nodes-base.stickyNote",
"position": [
11240,
1580
],
"parameters": {
"width": 540,
"height": 280,
"content": "### Step 14: Fetch All Products from QuickBooks (HTTP Request) \ud83d\udce6\ud83d\udd0d\n\nThis node sends an HTTP request to retrieve all products from QuickBooks.\n\nWhy this step is important:\n\n- \ud83d\udccb Gathers the full product catalog for reference or processing.\n- \ud83d\udd04 Keeps your workflow updated with the latest product information.\n- \u2699\ufe0f Enables product data integration across your automation.\n\nIt\u2019s the step that pulls your product inventory into the workflow for seamless management. \ud83d\udce6\u2728\n"
},
"typeVersion": 1
},
{
"id": "29e7df5d-6b99-44a4-8493-d3c2aec66353",
"name": "Sticky Note18",
"type": "n8n-nodes-base.stickyNote",
"position": [
12060,
760
],
"parameters": {
"color": 6,
"width": 540,
"height": 300,
"content": "### Step 15: Filter Products by Airtable Data (Code Node) \u2699\ufe0f\ud83d\udd0d\n\nThis node runs custom code to filter and return only the product details that exist in Airtable.\n\nWhy this step is important:\n\n- \ud83c\udfaf Narrows down the product list to relevant items.\n- \ud83d\udd04 Improves workflow efficiency by processing only necessary data.\n- \ud83d\udccb Ensures accuracy by matching QuickBooks products with Airtable records.\n\nIt\u2019s the step that refines your product data for targeted automation. \ud83e\uddf9\u2728\n"
},
"typeVersion": 1
},
{
"id": "b6e2c9d4-502b-44e6-b907-8eab05c7561e",
"name": "Filter and Return product details",
"type": "n8n-nodes-base.code",
"position": [
12260,
1100
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const airtableProductName = $('Update Quickbooks and Stripe Customer Ids').item.json.fields['Quickbooks Product Name'];\nconst quantity = $('Update Quickbooks and Stripe Customer Ids').item.json.fields.Quantity;\n\nconst quickBooksProducts = $json.QueryResponse.Item;\n\nconst matchingProduct = quickBooksProducts.find(product => product.Name === airtableProductName);\n\nif (matchingProduct) {\n const unitPrice = matchingProduct.UnitPrice || 0;\n const amount = unitPrice * (quantity || 0);\n\n return {\n json: {\n Id: matchingProduct.Id,\n Description: matchingProduct.Description,\n Amount: amount,\n }\n };\n} else {\n return {\n json: {\n Id: null,\n Description: null,\n Amount: 0,\n }\n };\n}\n"
},
"typeVersion": 2
},
{
"id": "4e309a57-bebd-4a0e-871f-1f66e7119099",
"name": "Sticky Note19",
"type": "n8n-nodes-base.stickyNote",
"position": [
12960,
1620
],
"parameters": {
"color": 4,
"width": 480,
"height": 300,
"content": "### Step 16: Create Invoice in QuickBooks \ud83e\uddfe\u2728\n\nThis node uses the **Create Invoice** operation to generate an invoice in QuickBooks based on data from previous nodes.\n\nWhy this step is important:\n\n- \ud83d\udcc4 Converts collected data into a formal invoice.\n- \ud83d\udd17 Links invoices to the correct customers and products.\n- \u26a1 Automates billing and record-keeping processes.\n\nIt\u2019s the step that issues the official invoice, completing the sales cycle. \u2705\u2728\n"
},
"typeVersion": 1
},
{
"id": "52c262a3-df12-47a4-bc8a-73eaaea82ec8",
"name": "Update Stripe Payment Link and Quickbooks Invoice #",
"type": "n8n-nodes-base.airtable",
"position": [
13840,
1100
],
"parameters": {
"base": {
"__rl": true,
"mode": "list",
"value": "{YOUR_AIRTABLE_BASE_ID}",
"cachedResultUrl": "https://airtable.com/{YOUR_AIRTABLE_BASE_ID}",
"cachedResultName": "{YOUR_AIRTABLE_BASE_NAME}"
},
"table": {
"__rl": true,
"mode": "list",
"value": "{YOUR_AIRTABLE_TABLE_ID}",
"cachedResultUrl": "https://airtable.com/{YOUR_AIRTABLE_BASE_ID}/{YOUR_AIRTABLE_TABLE_ID}",
"cachedResultName": "{YOUR_AIRTABLE_TABLE_NAME}"
},
"columns": {
"value": {
"id": "={{ $('Update Quickbooks and Stripe Customer Ids').item.json.id }}",
"Status": "Invoiced",
"Stripe Payment Link": "={{ $('Generate Payment Links').item.json.url }}",
"QuickBooks Invoice #": "=INV-{{ $json.DocNumber }}"
},
"schema": [
{
"id": "id",
"type": "string",
"display": true,
"removed": false,
"readOnly": true,
"required": false,
"displayName": "id",
"defaultMatch": true
},
{
"id": "Deal Name",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Deal Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Client Name",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Client Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Client Email",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Client Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "options",
"display": true,
"options": [
{
"name": "Approved for Invoicing",
"value": "Approved for Invoicing"
},
{
"name": "Draft",
"value": "Draft"
},
{
"name": "Invoiced",
"value": "Invoiced"
}
],
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Line Items JSON",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Line Items JSON",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "QuickBooks Customer ID",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "QuickBooks Customer ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Stripe Customer ID",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Stripe Customer ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Stripe Payment Link",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Stripe Payment Link",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "QuickBooks Invoice #",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "QuickBooks Invoice #",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Stripe Price Id",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Stripe Price Id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Quantity",
"type": "number",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Quantity",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Quickbooks Product Name",
"type": "string",
"display": true,
"removed": true,
"readOnly": false,
"required": false,
"displayName": "Quickbooks Product Name",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update"
},
"typeVersion": 2.1
},
{
"id": "cba338d9-dbad-4cf8-becc-609892ba96dc",
"name": "Sticky Note20",
"type": "n8n-nodes-base.stickyNote",
"position": [
13640,
740
],
"parameters": {
"color": 5,
"width": 480,
"height": 320,
"content": "### Step 17: Update Airtable Records \u270f\ufe0f\ud83d\udd04\n\nThis node updates Airtable records with the newly created **Stripe Payment Link** and **QuickBooks Invoice #**.\n\nWhy this step is important:\n\n- \ud83d\udd17 Keeps Airtable synchronized with payment and invoice details.\n- \ud83d\udccb Provides easy access to transaction information within Airtable.\n- \u26a1 Enhances tracking and reporting accuracy.\n\nIt\u2019s the step that ensures your source data reflects the latest billing status. \ud83d\udcc8\u2728\n"
},
"typeVersion": 1
},
{
"id": "e8125d20-5e72-443c-82ca-9f444ff91e1d",
"name": "Workflow Completed",
"type": "n8n-nodes-base.noOp",
"position": [
14660,
1420
],
"parameters": {},
"typeVersion": 1
},
{
"id": "b3e74b53-f2e4-4c37-adb0-008766c0c21e",
"name": "Sticky Note21",
"type": "n8n-nodes-base.stickyNote",
"position": [
14500,
1560
],
"parameters": {
"color": 4,
"width": 500,
"height": 300,
"content": "### Step 18: Workflow Completion (No-Op Node) \u2705\ud83c\udf89\n\nThis **No Operation** node marks the successful completion of the entire workflow.\n\nWhy this step is important:\n\n- \ud83c\udfaf Signifies a clean and error-free end to the process.\n- \ud83d\udee1\ufe0f Prevents unintended actions after workflow completion.\n- \ud83d\udd04 Helps maintain clear workflow structure and readability.\n\nIt\u2019s the final step that confirms your automation ran smoothly from start to finish. \ud83c\udfac\u2728\n"
},
"typeVersion": 1
},
{
"id": "75b2998f-2369-425a-b88b-f8e7383861f1",
"name": "Sticky Note22",
"type": "n8n-nodes-base.stickyNote",
"position": [
-60,
40
],
"parameters": {
"color": 3,
"width": 620,
"height": 680,
"content": "### Prerequisites \u2699\ufe0f\ud83d\udd17\n\n#### AIRTABLE\n- Create and connect your Airtable account using a **Personal Access Token**.\n- Create a table with the following columns:\n - **Deal Name** - Short representation of each record.\n - **Client Name** - Name of the client/customer.\n - **Client Email** - Email of the client/customer.\n - **Status** - Status of the deal (Draft, Approved for Invoicing, Invoiced).\n - **QuickBooks Customer ID** - ID of the client in QuickBooks.\n - **Stripe Customer ID** - ID of the client in Stripe.\n - **Stripe Payment Link** - Payment link from Stripe.\n - **QuickBooks Invoice #** - Invoice number from QuickBooks.\n - **Stripe Price Id** - Price ID of the product selected by the client in Stripe.\n - **Quantity** - Quantity of the product selected by the client.\n - **QuickBooks Product Name** - Name of the product from QuickBooks.\n - **Created** - Created timestamp.\n\n- Select the base and table in the **Airtable Trigger** node.\n- Connect and select the same base and table in all required Airtable nodes.\n\n#### QUICKBOOKS\n- Create and connect credentials using **OAuth2 authorization** in QuickBooks.\n- Use the same credentials across all QuickBooks nodes.\n- Add your company ID in the URL in the **Get all Quickbook products** node\n\n#### STRIPE\n- Generate and connect your Stripe account using the **Secret Key**.\n- Use these credentials in all required Stripe nodes.\n"
},
"typeVersion": 1
},
{
"id": "d88adcf9-9557-4759-9638-bfdd2f6e00b8",
"name": "Sticky Note23",
"type": "n8n-nodes-base.stickyNote",
"position": [
14500,
900
],
"parameters": {
"width": 360,
"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": "e10a1c5b-b5c4-4861-a1b7-8cf52907b464",
"connections": {
"Search records": {
"main": [
[
{
"node": "IF - Status Check",
"type": "main",
"index": 0
}
]
]
},
"Airtable Trigger": {
"main": [
[
{
"node": "Search records",
"type": "main",
"index": 0
}
]
]
},
"Create a customer": {
"main": [
[
{
"node": "Merge QBO Customer",
"type": "main",
"index": 0
}
]
]
},
"Create an invoice": {
"main": [
[
{
"node": "Update Stripe Payment Link and Quickbooks Invoice #",
"type": "main",
"index": 0
}
]
]
},
"IF - Status Check": {
"main": [
[
{
"node": "QuickBooks - Find Customer",
"type": "main",
"index": 0
}
],
[
{
"node": "Exit from workflow",
"type": "main",
"index": 0
}
]
]
},
"Merge QBO Customer": {
"main": [
[
{
"node": "If - Stripe Customer Id",
"type": "main",
"index": 0
}
]
]
},
"IF - Customer Exists?": {
"main": [
[
{
"node": "Create a customer",
"type": "main",
"index": 0
}
],
[
{
"node": "Merge QBO Customer",
"type": "main",
"index": 1
}
]
]
},
"Merge Stripe Customer": {
"main": [
[
{
"node": "Search records by email",
"type": "main",
"index": 0
}
]
]
},
"Generate Payment Links": {
"main": [
[
{
"node": "Get all Quickbook products",
"type": "main",
"index": 0
}
]
]
},
"Stripe - Find Customer": {
"main": [
[
{
"node": "Merge - Stripe Customers",
"type": "main",
"index": 1
}
]
]
},
"If - Stripe Customer Id": {
"main": [
[
{
"node": "Stripe - Find Customer",
"type": "main",
"index": 0
}
],
[
{
"node": "Merge - Stripe Customers",
"type": "main",
"index": 0
}
]
]
},
"Search records by email": {
"main": [
[
{
"node": "Update Quickbooks and Stripe Customer Ids",
"type": "main",
"index": 0
}
]
]
},
"Merge - Stripe Customers": {
"main": [
[
{
"node": "IF - Stripe Customer Exists?",
"type": "main",
"index": 0
}
]
]
},
"Stripe - Create Customer": {
"main": [
[
{
"node": "Merge Stripe Customer",
"type": "main",
"index": 0
}
]
]
},
"Get all Quickbook products": {
"main": [
[
{
"node": "Filter and Return product details",
"type": "main",
"index": 0
}
]
]
},
"QuickBooks - Find Customer": {
"main": [
[
{
"node": "IF - Customer Exists?",
"type": "main",
"index": 0
}
]
]
},
"IF - Stripe Customer Exists?": {
"main": [
[
{
"node": "Stripe - Create Customer",
"type": "main",
"index": 0
}
],
[
{
"node": "Merge Stripe Customer",
"type": "main",
"index": 1
}
]
]
},
"Filter and Return product details": {
"main": [
[
{
"node": "Create an invoice",
"type": "main",
"index": 0
}
]
]
},
"Update Quickbooks and Stripe Customer Ids": {
"main": [
[
{
"node": "Generate Payment Links",
"type": "main",
"index": 0
}
]
]
},
"Update Stripe Payment Link and Quickbooks Invoice #": {
"main": [
[
{
"node": "Workflow Completed",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This is the ultimate sales-to-cash automation. When a deal in Airtable is marked "Approved for Invoicing," this workflow intelligently syncs customer data across QuickBooks and Stripe (creating them if they don't exist), generates an official QuickBooks invoice, creates a Stripe…
Source: https://n8n.io/workflows/7291/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Automated Stripe Payment to QuickBooks Sales Receipt
Generating Stripe invoices through the API can be tricky since it requires four steps to generate and send it via email to the customer.
Automatically processes vendor invoices received by email, creates QuickBooks bills with full details, and attaches the original PDF. Small/medium businesses using QuickBooks Online Bookkeepers proces
How It Works Trigger: Watches for new emails in Gmail with PDF/image attachments. OCR: Sends the attachment to OCR.space API (https://ocr.space/OCRAPI) to extract invoice text. Parsing: Extracts key f
Tired of the standard, boring invoices from QuickBooks Online? This workflow completely automates the process of creating beautiful, custom-branded PDF invoices and emailing them directly to your clie