Automate Google Sheets Workflows with n8n and SheetsAPI
Build self-hosted automation workflows in n8n using SheetsAPI - fetch rows, add data, paginate, and chain with 400+ other nodes.
n8n is an open-source, self-hostable workflow automation tool with 400+ integrations. Unlike Zapier or Make, n8n runs on your own infrastructure, so your data stays in your environment. SheetsAPI exposes your Google Sheet as a clean REST endpoint - making it an ideal n8n data source or destination.
Prerequisites
- n8n running locally (
npx n8n) or on your server - A Google Sheet with a header row
- A SheetsAPI account and a
YOUR_USER_KEYkey from the dashboard
1. Create an HTTP Request credential
- In n8n, go to Credentials → Add credential.
- Choose Header Auth.
- Name it
SheetsAPI. - Key:
Authorization, Value:Bearer sk_your_api_key_here. - Save.
For public sheets (no API key required), skip this step and leave the HTTP Request node unauthenticated.
2. Fetch rows from a sheet
- Add an HTTP Request node.
- Method: GET.
- URL:
https://sheetsapi.gkit.mreshank.com/api/spreadsheets/YOUR_USER_KEY/Products - Authentication: Predefined Credential Type → Header Auth →
SheetsAPI. - Query Parameters:
limit:20sort:name
- Response Format: JSON.
- Execute the node - the response is available as
{{ $json.data }}in downstream nodes.
3. Iterate over rows with the Split In Batches node
To process each product row individually:
- Connect an Item Lists → Split Out node (or Split In Batches) after the HTTP Request.
- Field To Split Out:
data. - Each item flowing through downstream nodes is now one row from your sheet:
{{ $json.name }},{{ $json.price }},{{ $json.category }}
4. Add a row via POST
To write back to your sheet - for example, from a webhook trigger:
- Add an HTTP Request node.
- Method: POST.
- URL:
https://sheetsapi.gkit.mreshank.com/api/spreadsheets/YOUR_USER_KEY/Orders - Authentication:
SheetsAPI(Header Auth). - Body Content Type: JSON.
- Body:
{ "customer": "{{ $json.customer_name }}", "amount": "{{ $json.total }}", "status": "pending" }
5. Paginate all rows
Use a Loop Over Items (or Split In Batches) pattern with an offset counter:
Using a Code node for controlled pagination
// Code node: Build paginated requests
const LIMIT = 100;
const userKey = "YOUR_USER_KEY";
const apiKey = "sk_your_api_key_here";
const all = [];
let offset = 0;
let total = Infinity;
while (offset < total) {
const url = `https://sheetsapi.gkit.mreshank.com/api/spreadsheets/${userKey}/Products?limit=${LIMIT}&offset=${offset}`;
const resp = await fetch(url, {
headers: { Authorization: `Bearer ${apiKey}` },
});
const json = await resp.json();
all.push(...json.data);
total = json.meta.total;
offset += LIMIT;
}
return all.map((item) => ({ json: item }));This Code node returns all rows as individual n8n items ready for downstream processing.
6. Search and filter
Pass search and sort as query parameters:
https://sheetsapi.gkit.mreshank.com/api/spreadsheets/YOUR_USER_KEY/Products?search=category:electronics&sort=-price&limit=50
In n8n, set these as Query Parameters on the HTTP Request node:
search:category:{{ $json.category }}sort:-pricelimit:50
7. Example: Typeform submission → Google Sheet row
| Node | Type | Action |
|---|---|---|
| 1 | Webhook | Receive Typeform POST |
| 2 | HTTP Request | POST to SheetsAPI /Submissions |
| 3 | Gmail | Send confirmation email |
Workflow JSON (import into n8n):
{
"nodes": [
{
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"parameters": { "path": "typeform-submissions", "httpMethod": "POST" }
},
{
"name": "Add to Sheet",
"type": "n8n-nodes-base.httpRequest",
"parameters": {
"method": "POST",
"url": "https://sheetsapi.gkit.mreshank.com/api/spreadsheets/YOUR_USER_KEY/Submissions",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "httpHeaderAuth",
"jsonParameters": true,
"bodyParametersJson": "={{ JSON.stringify({ name: $json.body.answers[0].text, email: $json.body.answers[1].email }) }}"
}
}
]
}8. Error handling
Enable Continue on Fail on your HTTP Request node to avoid stopping the entire workflow on a single failure. Then add an IF node:
- Condition:
{{ $json.statusCode }}is not200 - True branch: log error or send a Slack notification
- False branch: continue processing
For rate limit responses (429), add a Wait node:
- After the HTTP Request node, add IF →
{{ $json.statusCode }} === 429. - True branch → Wait node → 10 seconds → loop back to retry.
Query parameter reference
| Parameter | Example | Description |
|---|---|---|
limit | 100 | Rows per page (max 500) |
offset | 0 | Pagination offset |
search | status:active | Filter field:value |
sort | name or -price | Ascending / descending |
fields | name,price | Return only named columns |
Summary
| Task | n8n approach |
|---|---|
| Fetch rows | HTTP Request (GET) + JSON Response |
| Iterate rows | Split Out node on data field |
| Add row | HTTP Request (POST) with JSON body |
| Pagination | Code node with while loop |
| Error handling | Continue on Fail + IF node |
| Rate limits | IF node + Wait + retry |
n8n's visual editor makes it easy to chain SheetsAPI with any of its 400+ other integrations - send emails, post to Slack, update CRMs, trigger CI pipelines - all without writing a server.