AutomationFlowsGeneral › Update Google Sheets Finance Records via Webhook

Update Google Sheets Finance Records via Webhook

Original n8n title: Rodopi Dent - Finance Update

Rodopi Dent - Finance UPDATE. Uses googleSheets. Webhook trigger; 10 nodes.

Webhook trigger★★★★☆ complexity10 nodesGoogle Sheets
General Trigger: Webhook Nodes: 10 Complexity: ★★★★☆ Added:

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
{
  "name": "Rodopi Dent - Finance UPDATE",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "finance-update",
        "responseMode": "responseNode",
        "options": {
          "allowedOrigins": "*"
        }
      },
      "id": "webhook-finance-update",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const body = $input.first().json.body;\n\n// Required: id of record to update\nif (!body.id) {\n  return [{\n    json: {\n      success: false,\n      error: '\u041b\u0438\u043f\u0441\u0432\u0430 ID \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u0430',\n      valid: false\n    }\n  }];\n}\n\n// Build update object with only provided fields\nconst updates = {};\n\nif (body.remainingPayment !== undefined) {\n  updates.remainingPayment = parseFloat(body.remainingPayment) || 0;\n}\n\nif (body.amount !== undefined) {\n  updates.amount = parseFloat(body.amount);\n}\n\nif (body.patientAmount !== undefined) {\n  updates.patientAmount = parseFloat(body.patientAmount);\n}\n\nif (body.description !== undefined) {\n  updates.description = body.description;\n}\n\nif (body.paymentMethod !== undefined) {\n  updates.paymentMethod = body.paymentMethod;\n}\n\nif (body.serviceCategory !== undefined) {\n  updates.serviceCategory = body.serviceCategory;\n}\n\nif (body.category !== undefined) {\n  updates.category = body.category;\n}\n\nif (body.patientName !== undefined) {\n  updates.patientName = body.patientName;\n}\n\nreturn [{\n  json: {\n    id: body.id,\n    updates: updates,\n    valid: true\n  }\n}];"
      },
      "id": "prepare-update",
      "name": "Prepare Update",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.valid }}",
              "value2": true
            }
          ]
        }
      },
      "id": "is-valid",
      "name": "Is Valid?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        440,
        0
      ]
    },
    {
      "parameters": {
        "operation": "read",
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "1hv4XAfHhScA40Bm1kQ3I-Ih4SJuCBpOJxTOYDNb167g"
        },
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Finances"
        },
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "id",
              "lookupValue": "={{ $json.id }}"
            }
          ]
        },
        "options": {}
      },
      "id": "find-record",
      "name": "Find Record",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        660,
        -50
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const input = $input.first().json;\nconst prepareNode = $('Prepare Update').first().json;\n\n// Check if record was found\nif (!input.id) {\n  return [{\n    json: {\n      success: false,\n      error: '\u0417\u0430\u043f\u0438\u0441\u044a\u0442 \u043d\u0435 \u0435 \u043d\u0430\u043c\u0435\u0440\u0435\u043d',\n      found: false\n    }\n  }];\n}\n\n// Merge existing record with updates\nconst updates = prepareNode.updates;\nconst merged = { ...input };\n\nObject.keys(updates).forEach(key => {\n  merged[key] = updates[key];\n});\n\nreturn [{\n  json: {\n    ...merged,\n    found: true\n  }\n}];"
      },
      "id": "merge-updates",
      "name": "Merge Updates",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        880,
        -50
      ]
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.found }}",
              "value2": true
            }
          ]
        }
      },
      "id": "record-found",
      "name": "Record Found?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1100,
        -50
      ]
    },
    {
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "1hv4XAfHhScA40Bm1kQ3I-Ih4SJuCBpOJxTOYDNb167g"
        },
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Finances"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "id": "={{ $json.id }}",
            "remainingPayment": "={{ $json.remainingPayment }}",
            "amount": "={{ $json.amount }}",
            "patientAmount": "={{ $json.patientAmount }}",
            "description": "={{ $json.description }}",
            "paymentMethod": "={{ $json.paymentMethod }}",
            "serviceCategory": "={{ $json.serviceCategory }}",
            "category": "={{ $json.category }}",
            "patientName": "={{ $json.patientName }}"
          },
          "matchingColumns": [
            "id"
          ]
        },
        "options": {}
      },
      "id": "update-record",
      "name": "Update Record",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1320,
        -100
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={\n  \"success\": true,\n  \"message\": \"\u0417\u0430\u043f\u0438\u0441\u044a\u0442 \u0435 \u043e\u0431\u043d\u043e\u0432\u0435\u043d\",\n  \"id\": \"{{ $json.id }}\"\n}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Access-Control-Allow-Origin",
                "value": "*"
              }
            ]
          }
        }
      },
      "id": "respond-success",
      "name": "Respond Success",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1540,
        -100
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={\n  \"success\": false,\n  \"error\": \"{{ $json.error || '\u0417\u0430\u043f\u0438\u0441\u044a\u0442 \u043d\u0435 \u0435 \u043d\u0430\u043c\u0435\u0440\u0435\u043d' }}\"\n}",
        "options": {
          "responseCode": "400",
          "responseHeaders": {
            "entries": [
              {
                "name": "Access-Control-Allow-Origin",
                "value": "*"
              }
            ]
          }
        }
      },
      "id": "respond-not-found",
      "name": "Respond Not Found",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1320,
        50
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={\n  \"success\": false,\n  \"error\": \"{{ $json.error }}\"\n}",
        "options": {
          "responseCode": "400",
          "responseHeaders": {
            "entries": [
              {
                "name": "Access-Control-Allow-Origin",
                "value": "*"
              }
            ]
          }
        }
      },
      "id": "respond-error",
      "name": "Respond Error",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        660,
        100
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Prepare Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Update": {
      "main": [
        [
          {
            "node": "Is Valid?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Valid?": {
      "main": [
        [
          {
            "node": "Find Record",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Record": {
      "main": [
        [
          {
            "node": "Merge Updates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Updates": {
      "main": [
        [
          {
            "node": "Record Found?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Record Found?": {
      "main": [
        [
          {
            "node": "Update Record",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond Not Found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Record": {
      "main": [
        [
          {
            "node": "Respond Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "tags": [
    {
      "name": "Rodopi Dent"
    }
  ]
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

Rodopi Dent - Finance UPDATE. Uses googleSheets. Webhook trigger; 10 nodes.

Source: https://github.com/Georgi-Piskov/RODOPI-DENT/blob/f071a84326ea5adf54e4eb20a2ba3e34aac5b728/n8n-workflows/06c-finance-update.json — original creator credit. Request a take-down →

More General workflows → · Browse all categories →

Related workflows

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

General

BARIN ALP - Auth Login. Uses googleSheets. Webhook trigger; 6 nodes.

Google Sheets
General

Rodopi Dent - Finance GET. Uses googleSheets. Webhook trigger; 6 nodes.

Google Sheets
General

BARIN ALP - Objects CRUD. Uses googleSheets, respondToWebhook. Webhook trigger; 9 nodes.

Google Sheets
General

Sia — Portal de Expansão de Terrenos (Principal). Uses chainLlm, lmChatGroq, googleSheets. Webhook trigger; 12 nodes.

Chain Llm, Groq Chat, Google Sheets
General

AI Product Description Writer. Uses openAi, googleSheets. Webhook trigger; 6 nodes.

OpenAI, Google Sheets