This workflow corresponds to n8n.io template #14205 — we link there as the canonical source.
This workflow follows the Google Sheets → 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 →
{
"nodes": [
{
"id": "a2b55cbc-dbef-4d25-8261-d08d4c230542",
"name": "Run Enrichment",
"type": "n8n-nodes-base.manualTrigger",
"position": [
0,
624
],
"parameters": {},
"typeVersion": 1
},
{
"id": "d3d2ab75-19ec-4bb5-b257-315dcdf998b7",
"name": "Template Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
-224
],
"parameters": {
"color": 4,
"width": 560,
"height": 816,
"content": "## Enrich Google Sheets via API \u2014 Rate-Limited Batches\n\nThis template reads rows from a Google Sheet, calls any external API to enrich each row, and writes results back, in rate-limited batches to avoid hitting API rate limits.\n\n## Who it's for\nDevelopers, marketers, and operations teams who need to enrich spreadsheet data (leads, products, URLs) via any REST API without triggering rate-limit errors.\n\n## How it works\n1. **Read rows** from your input Google Sheet tab\n2. **Split into batches** (default: 5 rows per batch)\n3. **Call your API** for each row in the batch\n4. **Wait 1 second** between batches (rate-limit pause)\n5. **Check the response** route success and errors separately\n6. **Write enriched fields** back to the matching row on success\n7. **Capture errors** with row identifier on failure\n\n## Requirements\n- Google Sheets OAuth2 credential\n- HTTP Header Auth credential (for your API key)\n\n## How to set up\n1. Connect your **Google Sheets OAuth2** credential to both Sheet nodes\n2. Set your **Sheet ID** and **Tab name** in the Read Rows node\n3. Set your **API endpoint URL** in the Call API node\n4. Connect your **Header Auth** credential in the Call API node\n5. Update the **Update Row** node with the column(s) to write back\n6. Adjust **batch size** and **wait duration** using the sticky notes below"
},
"typeVersion": 1
},
{
"id": "b45cc002-3be0-4516-a28e-4ef8056692a9",
"name": "Batch Config Instructions",
"type": "n8n-nodes-base.stickyNote",
"position": [
640,
0
],
"parameters": {
"color": 7,
"width": 380,
"height": 364,
"content": "## Batch Size & Rate Limit Config\n\n**SplitInBatches node** (`Batch Rows`)\n\u2192 Open the node and set `Batch Size`\n\u2192 Default: **5 rows per batch**\n\u2192 Increase for fast APIs (e.g. 20)\n\u2192 Decrease for strict rate limits (e.g. 1)\n\n**Wait node** (`Rate Limit Pause`)\n\u2192 Default: **1 second** between batches\n\u2192 Change `Amount` to match your API's rate limit\n\u2192 Example: 2s for 30 req/min APIs"
},
"typeVersion": 1
},
{
"id": "049bb248-f6ad-4540-9cd1-6e865abfa1cf",
"name": "API Credential Instructions",
"type": "n8n-nodes-base.stickyNote",
"position": [
1040,
0
],
"parameters": {
"color": 6,
"width": 588,
"height": 364,
"content": "## API Credential Setup\n\n**Call API node** (`Call API`)\n1. Open the node\n2. Set `URL` to your API endpoint\n Example: `https://api.example.com/enrich`\n3. Set `Method` (GET or POST)\n4. Under **Authentication**, select `Header Auth`\n5. Create a new **Header Auth** credential:\n - Name: `X-API-Key` (or whatever header your API requires)\n - Value: your API key\n\n**Google Sheets nodes**\n- Both Sheet nodes need the same **Google Sheets OAuth2** credential\n- Grant access to the spreadsheet in Google Drive"
},
"typeVersion": 1
},
{
"id": "0bb2bc15-b3bd-4839-996b-bae7f494daee",
"name": "Read Rows",
"type": "n8n-nodes-base.googleSheets",
"position": [
240,
624
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "b397055b-fc8f-4931-9ff5-72117ed053e0",
"name": "Batch Rows",
"type": "n8n-nodes-base.splitInBatches",
"position": [
480,
624
],
"parameters": {
"options": {},
"batchSize": 5
},
"typeVersion": 3
},
{
"id": "b6e027b5-2ce6-4a76-bdb5-38c408ef23d9",
"name": "Call API",
"type": "n8n-nodes-base.httpRequest",
"position": [
720,
624
],
"parameters": {
"url": "https://api.example.com/enrich",
"options": {
"response": {
"response": {
"fullResponse": true
}
}
},
"sendQuery": true,
"authentication": "predefinedCredentialType",
"queryParameters": {
"parameters": [
{
"name": "id",
"value": "={{ $json.id }}"
}
]
},
"nodeCredentialType": "httpHeaderAuth"
},
"typeVersion": 4.3
},
{
"id": "deede1f3-59ea-4d10-bce6-b452a0eb05c9",
"name": "Rate Limit Pause",
"type": "n8n-nodes-base.wait",
"position": [
960,
624
],
"parameters": {
"amount": 1
},
"typeVersion": 1.1
},
{
"id": "ceb03f84-025e-4d4a-8da8-293e0d987bc9",
"name": "API Success?",
"type": "n8n-nodes-base.if",
"position": [
1200,
624
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-0001",
"operator": {
"type": "number",
"operation": "equals"
},
"leftValue": "={{ $json.statusCode }}",
"rightValue": 200
}
]
}
},
"typeVersion": 2
},
{
"id": "6cf9dc4c-579f-4b21-9be1-51bd8d41c043",
"name": "Update Row",
"type": "n8n-nodes-base.googleSheets",
"position": [
1440,
512
],
"parameters": {
"columns": {
"value": {
"row_number": "={{ $('Batch Rows').item.json.row_number }}",
"enriched_field": "={{ $json.body.result }}",
"enrichment_status": "success"
},
"schema": [],
"mappingMode": "defineBelow",
"matchingColumns": [
"row_number"
]
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "name",
"value": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.5
},
{
"id": "ba0f3f22-39f4-4ccb-96d9-b5960eb9d8aa",
"name": "Capture Error",
"type": "n8n-nodes-base.set",
"position": [
1440,
752
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "err-0001",
"name": "row_id",
"type": "string",
"value": "={{ $('Batch Rows').item.json.id }}"
},
{
"id": "err-0002",
"name": "error_status",
"type": "number",
"value": "={{ $json.statusCode }}"
},
{
"id": "err-0003",
"name": "error_message",
"type": "string",
"value": "API call failed \u2014 status {{ $json.statusCode }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "15ccf54b-cebb-4fb7-8cd7-1cf044ab2e3b",
"name": "Merge Results",
"type": "n8n-nodes-base.merge",
"position": [
1680,
624
],
"parameters": {},
"typeVersion": 3
}
],
"connections": {
"Call API": {
"main": [
[
{
"node": "Rate Limit Pause",
"type": "main",
"index": 0
}
]
]
},
"Read Rows": {
"main": [
[
{
"node": "Batch Rows",
"type": "main",
"index": 0
}
]
]
},
"Batch Rows": {
"main": [
[],
[
{
"node": "Call API",
"type": "main",
"index": 0
}
]
]
},
"Update Row": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 0
}
]
]
},
"API Success?": {
"main": [
[
{
"node": "Update Row",
"type": "main",
"index": 0
}
],
[
{
"node": "Capture Error",
"type": "main",
"index": 0
}
]
]
},
"Capture Error": {
"main": [
[
{
"node": "Merge Results",
"type": "main",
"index": 1
}
]
]
},
"Merge Results": {
"main": [
[
{
"node": "Batch Rows",
"type": "main",
"index": 0
}
]
]
},
"Run Enrichment": {
"main": [
[
{
"node": "Read Rows",
"type": "main",
"index": 0
}
]
]
},
"Rate Limit Pause": {
"main": [
[
{
"node": "API Success?",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
• Reads all rows from a Google Sheet • Splits them into configurable batches (default: 5 rows per batch) • Calls any external REST API once per row (GET or POST, Header Auth) • Waits 1 second between batches to stay within API rate limits • Routes responses: writes enriched data…
Source: https://n8n.io/workflows/14205/ — 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.
TrackCollect_deeper. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 80 nodes.
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.
PCN. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 60 nodes.
Product Ad Machine. Uses googleDrive, googleSheets, httpRequest, @ffmpeg-micro/n8n-nodes-ffmpeg-micro. Event-driven trigger; 60 nodes.
Basic AI SEO KW Research n8n DataForSEO Gumroad 030125. Uses googleSheets, googleDrive, httpRequest. Event-driven trigger; 56 nodes.