This workflow corresponds to n8n.io template #16468 — 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 →
{
"id": "7BvmpMUEf7fRqYpm",
"meta": {
"aiBuilderAssisted": true
},
"name": "SAP B1 OData Sync to Google Sheets",
"tags": [],
"nodes": [
{
"id": "69a2acfe-f90c-4b28-bd2b-45f5575d8929",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
48,
688
],
"parameters": {
"width": 480,
"height": 864,
"content": "## SAP B1 OData Sync to Google Sheets\n\n### How it works\n\nThis workflow runs on a daily schedule to synchronize SAP Business One OData records into Google Sheets. It logs in to SAP B1, fetches two pages of records in parallel, extracts and merges them, then maps the fields into a consistent sheet format. Records with valid email addresses are upserted into Google Sheets, while records without email addresses are logged as skipped before the valid path logs out of SAP B1.\n\n### Setup steps\n\n- Configure the schedule trigger with the desired daily run time and timezone.\n- Replace the SAP B1 Service Layer placeholder URLs with the correct login, record-fetch, and logout endpoints.\n- Add SAP B1 authentication details or credentials required by the HTTP Request nodes, including company database, username, and password/session handling as needed.\n- Configure the Google Sheets credential, spreadsheet ID, target sheet/range, and upsert key columns.\n- Review the extraction code nodes to match the exact SAP OData response structure and pagination format.\n\n### Customization\n\nAdjust the number of fetch/extract branches if more SAP OData pages are needed, change the mapped fields in the Transform & Map Fields node, or modify the email validation rule before writing to Google Sheets."
},
"typeVersion": 1
},
{
"id": "a618b35d-9a1c-4bf9-953e-5ab6fec07440",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
608,
816
],
"parameters": {
"color": 7,
"width": 384,
"height": 320,
"content": "## Schedule and SAP login\n\nStarts the daily synchronization and establishes an SAP B1 session before data retrieval begins."
},
"typeVersion": 1
},
{
"id": "58f177e4-32b0-4071-8799-ce7900a6bbf5",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1040,
736
],
"parameters": {
"color": 7,
"width": 672,
"height": 528,
"content": "## Fetch and merge records\n\nFetches two spatially parallel SAP record pages, extracts their record arrays with code, and appends both results into one combined stream."
},
"typeVersion": 1
},
{
"id": "97071d54-4ee0-4168-931c-f2178a6612e9",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1760,
816
],
"parameters": {
"color": 7,
"width": 432,
"height": 320,
"content": "## Map and validate fields\n\nTransforms the merged SAP records into the target field structure and branches records based on whether they contain a valid email address."
},
"typeVersion": 1
},
{
"id": "abe37149-d64d-40ce-be5f-886ac06a13a3",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
2240,
688
],
"parameters": {
"color": 7,
"width": 432,
"height": 560,
"content": "## Write or log results\n\nHandles the final output cluster: valid records are upserted to Google Sheets and followed by SAP logout, while records missing email information are marked as skipped with a reason."
},
"typeVersion": 1
},
{
"id": "046a90d9-e9c0-4833-b95f-909b21ecbcfe",
"name": "Run Daily SAP Sync",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
656,
976
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 24
}
]
}
},
"typeVersion": 1.3
},
{
"id": "2f30c6ad-2a89-4644-b1d1-64a50df3b683",
"name": "Post SAP Login",
"type": "n8n-nodes-base.httpRequest",
"position": [
848,
976
],
"parameters": {
"url": "<__PLACEHOLDER_VALUE__https://your-sap-server:50000/b1s/v1/Login__>",
"method": "POST",
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{
"name": "CompanyDB",
"value": "<__PLACEHOLDER_VALUE__SBODEMOGB__>"
},
{
"name": "UserName",
"value": "<__PLACEHOLDER_VALUE__manager__>"
},
{
"name": "Password",
"value": "<__PLACEHOLDER_VALUE__your-password__>"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "b27da326-3f23-4fb3-a288-101d6d20291e",
"name": "Fetch SAP Page 1 Records",
"type": "n8n-nodes-base.httpRequest",
"position": [
1088,
864
],
"parameters": {
"url": "<__PLACEHOLDER_VALUE__https://your-sap-server:50000/b1s/v1/BusinessPartners__>",
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
},
"sendQuery": true,
"sendHeaders": true,
"queryParameters": {
"parameters": [
{
"name": "$top",
"value": "20"
},
{
"name": "$skip",
"value": "0"
},
{
"name": "$select",
"value": "CardCode,CardName,CardType,Balance,Phone1,EmailAddress"
},
{
"name": "$orderby",
"value": "CardCode asc"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Cookie",
"value": "=B1SESSION={{ $('Post SAP Login').item.json.SessionId }}; ROUTEID=.node1"
},
{
"name": "Prefer",
"value": "odata.maxpagesize=20"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "50c7ab62-03b7-40b4-a25f-9ba9575a3db9",
"name": "Parse Page 1 Records",
"type": "n8n-nodes-base.code",
"position": [
1328,
864
],
"parameters": {
"jsCode": "\nconst records = $input.first().json.value || [];\nreturn records.map(r => ({ json: r }));\n"
},
"typeVersion": 2
},
{
"id": "1d8ca860-d112-45a8-a369-8298c4d3821c",
"name": "Merge Records from Both Pages",
"type": "n8n-nodes-base.merge",
"position": [
1568,
976
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "f9a56de3-8285-4f64-a08c-a9c776a57c8a",
"name": "Fetch SAP Page 2 Records",
"type": "n8n-nodes-base.httpRequest",
"position": [
1088,
1088
],
"parameters": {
"url": "<__PLACEHOLDER_VALUE__https://your-sap-server:50000/b1s/v1/BusinessPartners__>",
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
},
"sendQuery": true,
"sendHeaders": true,
"queryParameters": {
"parameters": [
{
"name": "$top",
"value": "20"
},
{
"name": "$skip",
"value": "20"
},
{
"name": "$select",
"value": "CardCode,CardName,CardType,Balance,Phone1,EmailAddress"
},
{
"name": "$orderby",
"value": "CardCode asc"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Cookie",
"value": "=B1SESSION={{ $('Post SAP Login').item.json.SessionId }}; ROUTEID=.node1"
},
{
"name": "Prefer",
"value": "odata.maxpagesize=20"
}
]
}
},
"executeOnce": true,
"typeVersion": 4.3
},
{
"id": "44212607-33f6-4926-9d83-b2803a1269d3",
"name": "Parse Page 2 Records",
"type": "n8n-nodes-base.code",
"position": [
1328,
1088
],
"parameters": {
"jsCode": "\nconst records = $input.first().json.value || [];\nreturn records.map(r => ({ json: r }));\n"
},
"typeVersion": 2
},
{
"id": "efe86309-80a9-4cbc-84be-14a0b63483ba",
"name": "Set Customer Data Fields",
"type": "n8n-nodes-base.set",
"position": [
1808,
976
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "1",
"name": "Customer Code",
"type": "string",
"value": "={{ $json.CardCode }}"
},
{
"id": "2",
"name": "Customer Name",
"type": "string",
"value": "={{ $json.CardName }}"
},
{
"id": "3",
"name": "Type",
"type": "string",
"value": "={{ $json.CardType === 'C' ? 'Customer' : $json.CardType === 'S' ? 'Supplier' : 'Lead' }}"
},
{
"id": "4",
"name": "Balance (SAR)",
"type": "number",
"value": "={{ $json.Balance }}"
},
{
"id": "5",
"name": "Phone",
"type": "string",
"value": "={{ $json.Phone1 }}"
},
{
"id": "6",
"name": "Email",
"type": "string",
"value": "={{ $json.EmailAddress }}"
},
{
"id": "7",
"name": "Last Synced",
"type": "string",
"value": "={{ $now.toISO() }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "e97f02bc-febe-4130-a355-54ca8adf0e7a",
"name": "Check Valid Email",
"type": "n8n-nodes-base.if",
"position": [
2048,
976
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": false,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"id": "email-check",
"operator": {
"type": "string",
"operation": "notEmpty"
},
"leftValue": "={{ $json.Email }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "5e5e2d33-233c-4bfc-b57b-273f25507ec7",
"name": "Upsert Customer to Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
2288,
864
],
"parameters": {
"columns": {
"value": {},
"schema": [],
"mappingMode": "autoMapInputData",
"matchingColumns": [
"Customer Code"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": "={{ \"SAP_BusinessPartners\" }}",
"documentId": "={{ \"your-google-sheet-id-here\" }}"
},
"typeVersion": 4.5
},
{
"id": "71320247-884e-4aaa-8674-b39798c5c372",
"name": "Post SAP Logout",
"type": "n8n-nodes-base.httpRequest",
"position": [
2528,
864
],
"parameters": {
"url": "<__PLACEHOLDER_VALUE__https://your-sap-server:50000/b1s/v1/Logout__>",
"method": "POST",
"options": {
"response": {
"response": {
"responseFormat": "text"
}
}
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Cookie",
"value": "=B1SESSION={{ $('Post SAP Login').item.json.SessionId }}; ROUTEID=.node1"
}
]
}
},
"executeOnce": true,
"typeVersion": 4.3
},
{
"id": "897bcc8a-c5d9-4b33-b5a3-c651f8c6ccbd",
"name": "Log Skips Without Email",
"type": "n8n-nodes-base.set",
"position": [
2288,
1088
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "1",
"name": "skipped_code",
"type": "string",
"value": "={{ $json[\"Customer Code\"] }}"
},
{
"id": "2",
"name": "skipped_name",
"type": "string",
"value": "={{ $json[\"Customer Name\"] }}"
},
{
"id": "3",
"name": "reason",
"type": "string",
"value": "Missing email address"
}
]
}
},
"typeVersion": 3.4
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"availableInMCP": true,
"executionOrder": "v1"
},
"versionId": "e8319938-cdca-4dba-bedc-e461257fc0aa",
"connections": {
"Post SAP Login": {
"main": [
[
{
"node": "Fetch SAP Page 1 Records",
"type": "main",
"index": 0
},
{
"node": "Fetch SAP Page 2 Records",
"type": "main",
"index": 0
}
]
]
},
"Check Valid Email": {
"main": [
[
{
"node": "Upsert Customer to Sheets",
"type": "main",
"index": 0
}
],
[
{
"node": "Log Skips Without Email",
"type": "main",
"index": 0
}
]
]
},
"Run Daily SAP Sync": {
"main": [
[
{
"node": "Post SAP Login",
"type": "main",
"index": 0
}
]
]
},
"Parse Page 1 Records": {
"main": [
[
{
"node": "Merge Records from Both Pages",
"type": "main",
"index": 0
}
]
]
},
"Parse Page 2 Records": {
"main": [
[
{
"node": "Merge Records from Both Pages",
"type": "main",
"index": 1
}
]
]
},
"Fetch SAP Page 1 Records": {
"main": [
[
{
"node": "Parse Page 1 Records",
"type": "main",
"index": 0
}
]
]
},
"Fetch SAP Page 2 Records": {
"main": [
[
{
"node": "Parse Page 2 Records",
"type": "main",
"index": 0
}
]
]
},
"Set Customer Data Fields": {
"main": [
[
{
"node": "Check Valid Email",
"type": "main",
"index": 0
}
]
]
},
"Upsert Customer to Sheets": {
"main": [
[
{
"node": "Post SAP Logout",
"type": "main",
"index": 0
}
]
]
},
"Merge Records from Both Pages": {
"main": [
[
{
"node": "Set Customer Data Fields",
"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 workflow runs daily to sync SAP Business One Service Layer OData Business Partners to Google Sheets, handling SAP’s 20-record page limit, mapping fields into a sheet-friendly format, filtering out records without email addresses, and upserting rows to avoid duplicates. Runs…
Source: https://n8n.io/workflows/16468/ — 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.
This workflow monitors customer health by combining payment behavior, complaint signals, and AI-driven feedback analysis. It runs on daily and weekly schedules to evaluate risk levels, escalate high-r
Code Postgres. Uses httpRequest, splitInBatches, postgres, hubspot. Scheduled trigger; 23 nodes.
Sync Asana project tasks to a Google Sheet mirror. Uses httpRequest, googleSheets. Scheduled trigger; 19 nodes.
Continuous monitoring: Real-time surveillance of supplier performance, financial health, and operational status Risk scoring: AI-powered assessment of supplier risks across multiple dimensions (financ
Regulatory monitoring: Continuously tracks changes in laws, regulations, and compliance requirements across multiple jurisdictions Contract analysis: AI-powered review of existing contracts to identif