Google Sheets Action

Reads and writes a Google Sheets spreadsheet from a flow. Six operations — append a row, update one, append-or-update, read a range, read every row, or create a whole new spreadsheet — with payload fields mapped to columns by header name, so you build live dashboards, logs, and reports without code.

Overview

The Google Sheets Action node writes to (and reads from) a spreadsheet as part of a flow. It authenticates with a Google credential, and which fields the panel shows depends on the operation you pick. The node appears on the canvas with an emerald color.

Event received--▶Webhook delivery--▶Sheets row appended

Configuration

FieldTypeRequiredDescription
namestringYesFriendly label for the Sheets action
spreadsheetIdstringYesThe Google Sheets spreadsheet ID (from the URL)
sheetNamestringYesName of the sheet tab to write to (e.g., "Sheet1")
operationstringYesOne of the six values in Operations. Case matters — the API rejects anything else.
columnMapping{ header: string, valueTemplate: string }[]YesArray of objects mapping header names (from row 1 of the sheet) to payload field templates. Each entry writes to the column that matches the given header.
credentialsobjectYesGoogle service account JSON key. Encrypted at rest.
inputNodes{ nodeType, nodeId }[]YesUpstream nodes that feed this one
isActivebooleanNoEnable or disable without deleting. Default: true.
The spreadsheetId is the long string in the Google Sheets URL between /d/ and /edit. For example, in https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms/edit, the ID is 1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms.

Operations

The Operation dropdown decides what the node does and which fields the panel shows below it. Six values, and the API validates them exactly as written here:

ValueIn the dropdownDoesFields it shows
appendRowAppend RowAdds a new row at the bottomspreadsheet · sheet · columns
updateRowUpdate RowUpdates the row whose match column equals your value+ match column · match value
appendOrUpdateRowAppend or UpdateUpdates if the row exists, appends if it does not+ match column · match value
readRangeRead RangeReads the cells in a range you givespreadsheet · sheet · range
getRowsGet RowsReads every row, using row 1 as the keysspreadsheet · sheet
createSpreadsheetCreate SpreadsheetCreates a new spreadsheetname · save location
Older versions of this page listed append_row and update_cell. Neither is a valid value — the field is validated against the six above and anything else comes back as a 400. If you have a script built from the old text, that is why.

Match column is picked from the spreadsheet's own headers, and match value is a template — typically {{payload.id}}. Together they are what makes appendOrUpdateRow idempotent: run the same flow twice and you get one row, not two.

createSpreadsheet is the only operation that asks for no existing document, and the only one with a Save location — the Drive folder the new file lands in.


Mode — action or AI toolkit

The Mode selector at the top of the panel decides who drives the node:

  • Action — you pick the operation and fill the fields. The node does that one thing every time it runs.
  • AI toolkit — the node stops being a fixed operation and becomes a set of tools an AI Node can call. The model chooses the operation and the arguments; the panel shows a preview of exactly which tools it will expose.
Toolkit mode is opt-in per node, and it is what makes the node appear in an AI Node's tool picker. A node left in Action mode is invisible to agents.

Create a Sheets Action

bashCreate Sheets Action
curl -X POST /api/sheets-actions \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Order Log Sheet",
    "spreadsheetId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
    "sheetName": "Orders",
    "operation": "appendRow",
    "columnMapping": [
      { "header": "Order ID", "valueTemplate": "{{payload.order.id}}" },
      { "header": "Customer", "valueTemplate": "{{payload.customer.name}}" },
      { "header": "Email", "valueTemplate": "{{payload.customer.email}}" },
      { "header": "Total", "valueTemplate": "{{payload.order.total}}" },
      { "header": "Status", "valueTemplate": "{{response.status}}" },
      { "header": "Timestamp", "valueTemplate": "{{payload.timestamp}}" }
    ],
    "credentials": {
      "type": "service_account",
      "project_id": "my-project-123",
      "private_key_id": "key-id",
      "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
      "client_email": "[email protected]",
      "client_id": "123456789",
      "auth_uri": "https://accounts.google.com/o/oauth2/auth",
      "token_uri": "https://oauth2.googleapis.com/token"
    },
    "inputNodes": [{ "nodeType": "webhook", "nodeId": "6642f1a2c3b4d5e6f7890123" }],
    "isActive": true
  }'

Response

json201 Created
{
  "_id": "6646d4e5f6a7b8c9d0123456",
  "name": "Order Log Sheet",
  "spreadsheetId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
  "sheetName": "Orders",
  "operation": "appendRow",
  "columnMapping": [
    { "header": "Order ID", "valueTemplate": "{{payload.order.id}}" },
    { "header": "Customer", "valueTemplate": "{{payload.customer.name}}" },
    { "header": "Email", "valueTemplate": "{{payload.customer.email}}" },
    { "header": "Total", "valueTemplate": "{{payload.order.total}}" },
    { "header": "Status", "valueTemplate": "{{response.status}}" },
    { "header": "Timestamp", "valueTemplate": "{{payload.timestamp}}" }
  ],
  "inputNodes": [{ "nodeType": "webhook", "nodeId": "6642f1a2c3b4d5e6f7890123" }],
  "isActive": true,
  "organizationId": "6640a1b2c3d4e5f6a7890001",
  "createdAt": "2025-05-17T10:00:00.000Z",
  "updatedAt": "2025-05-17T10:00:00.000Z"
}
The credentials field (service account JSON) is encrypted before storage and never returned in API responses. Make sure the service account email has Editor access to the target spreadsheet.

Update a Sheets Action

bashUpdate Sheets Action
curl -X PATCH /api/sheets-actions/6646d4e5f6a7b8c9d0123456 \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "sheetName": "Orders-2025",
    "columnMapping": [
      { "header": "Order ID", "valueTemplate": "{{payload.order.id}}" },
      { "header": "Customer", "valueTemplate": "{{payload.customer.name}}" },
      { "header": "Email", "valueTemplate": "{{payload.customer.email}}" },
      { "header": "Total", "valueTemplate": "{{payload.order.total}}" },
      { "header": "Currency", "valueTemplate": "{{payload.order.currency}}" },
      { "header": "Status", "valueTemplate": "{{response.status}}" },
      { "header": "Processed At", "valueTemplate": "{{response.body.processedAt}}" },
      { "header": "Timestamp", "valueTemplate": "{{payload.timestamp}}" }
    ]
  }'

Response

json200 OK
{
  "_id": "6646d4e5f6a7b8c9d0123456",
  "name": "Order Log Sheet",
  "spreadsheetId": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms",
  "sheetName": "Orders-2025",
  "operation": "appendRow",
  "columnMapping": [
    { "header": "Order ID", "valueTemplate": "{{payload.order.id}}" },
    { "header": "Customer", "valueTemplate": "{{payload.customer.name}}" },
    { "header": "Email", "valueTemplate": "{{payload.customer.email}}" },
    { "header": "Total", "valueTemplate": "{{payload.order.total}}" },
    { "header": "Currency", "valueTemplate": "{{payload.order.currency}}" },
    { "header": "Status", "valueTemplate": "{{response.status}}" },
    { "header": "Processed At", "valueTemplate": "{{response.body.processedAt}}" },
    { "header": "Timestamp", "valueTemplate": "{{payload.timestamp}}" }
  ],
  "inputNodes": [{ "nodeType": "webhook", "nodeId": "6642f1a2c3b4d5e6f7890123" }],
  "isActive": true,
  "organizationId": "6640a1b2c3d4e5f6a7890001",
  "createdAt": "2025-05-17T10:00:00.000Z",
  "updatedAt": "2025-05-17T11:45:00.000Z"
}

Canvas Integration

On the visual canvas, the Google Sheets Action node uses the type sheets-action and is rendered with an emerald color scheme. Connect it to any webhook node to write data to Google Sheets after deliveries.

The node displays the action name, the spreadsheet name (if available), and the operation type. Edges from webhooks flow into the Sheets action node.

Columns are mapped by header name from row 1 of your spreadsheet. The header value in each mapping entry must exactly match the text in row 1. Column order in the sheet does not matter — the system finds the correct column by header name, so you can reorder or insert columns freely without breaking your mapping.

Payload Examples

Incoming Webhook Payload

jsonEvent payload
{
  "type": "order.completed",
  "timestamp": "2025-05-17T10:30:00Z",
  "customer": {
    "name": "Jane Doe",
    "email": "[email protected]"
  },
  "order": {
    "id": "ORD-9821",
    "total": 149.99,
    "currency": "USD"
  }
}

Resulting Spreadsheet Row

Order IDCustomerEmailTotalStatusTimestamp
ORD-9821Jane Doe[email protected]149.992002025-05-17T10:30:00Z

Column Mapping Array

jsoncolumnMapping field
[
  { "header": "Order ID", "valueTemplate": "{{payload.order.id}}" },
  { "header": "Customer", "valueTemplate": "{{payload.customer.name}}" },
  { "header": "Email", "valueTemplate": "{{payload.customer.email}}" },
  { "header": "Total", "valueTemplate": "{{payload.order.total}}" },
  { "header": "Status", "valueTemplate": "{{response.status}}" },
  { "header": "Timestamp", "valueTemplate": "{{payload.timestamp}}" }
]

Use Cases

Order Tracking Spreadsheet

Append a row for every completed order. Share the spreadsheet with your operations team for a live view of incoming orders without building a custom dashboard.

Webhook Delivery Log

Log every delivery result to a spreadsheet for auditing. Include the event type, delivery status, response body, and timestamp. Use triggerOn: always to capture both successes and failures.

Lead Capture Pipeline

Receive form submission webhooks and append lead information (name, email, company, message) to a shared Google Sheet that your sales team monitors.

Financial Reporting

Capture payment events with amounts, currencies, and customer details in a spreadsheet. Use Google Sheets formulas and charts to build real-time financial reports.

Google Sheets has a limit of approximately 10 million cells per spreadsheet. For high-volume webhooks, consider periodic archival or using a MongoDB Action for long-term storage alongside the Sheets Action for visibility.

API Reference

MethodWebhookDescription
GET/api/sheets-actionsList all Sheets actions for your organization
POST/api/sheets-actionsCreate a new Sheets action
GET/api/sheets-actions/:idGet a single Sheets action by ID
PATCH/api/sheets-actions/:idUpdate a Sheets action
DELETE/api/sheets-actions/:idDelete a Sheets action
Google Sheets Actions are available on Pro and Enterprise plans. Free plans do not include access to Google Sheets integrations.