Pause and resume a workflow using callbacks and Google Sheets

Google Sheets is a cloud-basedspreadsheet solution that supports real-time collaboration and provides tools tovisualize, process, and communicate data.

This tutorial demonstrates how to create and deploy a workflow that creates acallback endpoint (or webhook), saves the callback URL to Google Sheets,pauses executing, and then waits for human approval through the Sheetsspreadsheet to restart the workflow.Learn more about using callbacks.

Objectives

In this tutorial, you will:

  1. Create a new folder in Google Drive. This folder is used to store yourspreadsheet and allows the workflow to write to the spreadsheet.
  2. Create a Google Sheets spreadsheet to capture an approval and initiatea callback to a workflow.
  3. UseGoogle Apps Script, acloud-based JavaScript platform that lets you programmatically create, read,and edit Google Workspace products, to trigger the resumption of a pausedworkflow whenever a request is approved through an update to the spreadsheet.
  4. Create and deploy a workflow that calls theGoogle Sheets API connectorto append data to the spreadsheet. The workflow executes, pauses, and thenresumes when a callback is approved through the spreadsheet.Learn more about Workflows connectors.
  5. Test the entire process and confirm that the workflow proceeds as expected.

Costs

In this document, you use the following billable components of Google Cloud:

To generate a cost estimate based on your projected usage, use thepricing calculator.

New Google Cloud users might be eligible for afree trial.

The tutorial also usesGoogle Workspace.Business-grade services that are not included with Google's free consumer appsare billable.

Before you begin

You can run some of the following commands in the Google Cloud console, or byusing the Google Cloud CLI in either your terminal or Cloud Shell.

Security constraints defined by your organization might prevent you from completing the following steps. For troubleshooting information, seeDevelop applications in a constrained Google Cloud environment.

Console

  1. In the Google Cloud console, on the project selector page, select orcreate a Google Cloud project.

    Note: If you don't plan to keep the resources that you create in thisprocedure, create a project instead of selecting an existing project. Afteryou finish these steps, you can delete the project, removing all resourcesassociated with the project.

    Go to project selector

  2. Make sure that billing is enabled for your Google Cloud project. Learn how tocheck if billing is enabled on a project.

  3. Enable the Compute Engine, Sheets, andWorkflows APIs.

    Enable the APIs

  4. Make note of theCompute Engine default service accountas you will associate it with the workflow in this tutorial for testingpurposes. New projects that have enabled the Compute Engine APIhave this service account created with the IAM basicEditor role, and with the following email format:

    PROJECT_NUMBER-compute@developer.gserviceaccount.com

    You can find your project number on theWelcomepage of the Google Cloud console.

    For production environments, we strongly recommendcreating a new service account andgranting it one or more IAM roles that contain theminimum permissions requiredand follow the principle ofleast privilege.

    Note:

    Theiam.automaticIamGrantsForDefaultServiceAccounts organization policy constraint prevents the Editor role from being automatically granted to default service accounts. If you created your organization after May 3, 2024, this constraint is enforced by default.

    We strongly recommend that you enforce this constraint to disable the automatic role grant. If you disable the automatic role grant, you must decide which roles to grant to the default service accounts, and thengrant these roles yourself.

    If the default service account already has the Editor role, we recommend that you replace the Editor role with less permissive roles.To safely modify the service account's roles, usePolicy Simulator to see the impact of the change, and thengrant and revoke the appropriate roles.

gcloud

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, aCloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. Make sure that billing is enabled for your Google Cloud project.Learn how tocheck if billing is enabled on a project.

  3. Enable the Compute Engine, Sheets, andWorkflows APIs.

    gcloudservicesenable\compute.googleapis.com\sheets.googleapis.com\workflows.googleapis.com
  4. Make note of theCompute Engine default service accountas you will associate it with the workflow in this tutorial for testingpurposes. New projects that have enabled the Compute Engine APIhave this service account created with the IAM basicEditor role, and with the following email format:

    PROJECT_NUMBER-compute@developer.gserviceaccount.com

    You can retrieve your project number:

    gcloudprojectsdescribePROJECT_ID

    For production environments, we strongly recommendcreating a new service account andgranting it one or more IAM roles that contain theminimum permissions requiredand follow the principle ofleast privilege.

    Note:

    Theiam.automaticIamGrantsForDefaultServiceAccounts organization policy constraint prevents the Editor role from being automatically granted to default service accounts. If you created your organization after May 3, 2024, this constraint is enforced by default.

    We strongly recommend that you enforce this constraint to disable the automatic role grant. If you disable the automatic role grant, you must decide which roles to grant to the default service accounts, and thengrant these roles yourself.

    If the default service account already has the Editor role, we recommend that you replace the Editor role with less permissive roles.To safely modify the service account's roles, usePolicy Simulator to see the impact of the change, and thengrant and revoke the appropriate roles.

Create a new folder in Google Drive

Create a new folder in Google Drive. This folder is used to store yourspreadsheet. By setting up a permission for the shared folder, your workflowis allowed to write to the spreadsheet.

  1. Go todrive.google.com.
  2. ClickNew> New folder.
  3. Enter a name for the folder.
  4. ClickCreate.
  5. Right-click your new folder and selectShare.
  6. Add the email address for the Compute Engine default serviceaccount.

    This gives the service account access to the folder. When you associatethe service account with your workflow, the workflow will have editaccess to any file in the folder.Learn more about sharing files, folders & drives.

  7. Select theEditor role.

  8. Clear theNotify people checkbox.

  9. ClickShare.

Create a spreadsheet using Google Sheets

When you create a spreadsheet through Google Sheets, it's saved inGoogle Drive. By default, the spreadsheet is saved to your root folder onDrive. There's no option to create a spreadsheet directlywithin a specified folder using the Google Sheets API. However, thereare alternatives, including moving the spreadsheet to a specific folder afteryou create it, as is done in this example. For more information, seeWork with Google Drive folders.

  1. Go tosheets.google.com.

  2. ClickNewPlus.

    This creates and opens your new spreadsheet. Every spreadsheet has a uniquespreadsheetId value,containing letters, numbers, hyphens, or underscores. You can find thespreadsheet ID in a Google Sheets URL:

    https://docs.google.com/spreadsheets/d/spreadsheetId/edit#gid=0

  3. Note this ID as it will be needed when you create your workflow.

  4. Add column headings to match the following example:

    Example of spreadsheet to record approvals

    Note that the value in columnG,Approved?, is used to initiatecallbacks in the workflow.

  5. Move the spreadsheet to the Google Drive folder that you createdpreviously:

    1. In the spreadsheet, selectFile> Move.
    2. Navigate to the folder you created.
    3. ClickMove.

You can also use theGoogle Sheets API connectorto create a spreadsheet. Note that when using the connector, thespreadsheetId can be retrieved from theresp result.For example:

- create_spreadsheet:    call: googleapis.sheets.v4.spreadsheets.create    args:      body:      connector_params:        scopes: ${driveScope}    result: resp- assign_sheet_id:    assign:      - sheetId: ${resp.spreadsheetId}

Extend Google Sheets using Apps Script

Apps Script lets you programmatically create, read, and editGoogle Sheets. Most scripts designed for Sheets manipulatearrays to interact with the cells, rows, and columns in a spreadsheet. For anintroduction to using Apps Script with Google Sheets, seetheCustom function quickstart.

Note: If you're logged into multiple Google Accounts at the same time, you mighthave trouble accessing Apps Script. Multi-login, or beinglogged into multiple Google Accounts at once, isn't supported forApps Script. For more information, seeFix issues with multiple Google Accounts.
  1. Create an Apps Script project from Google Sheets:

    1. Open your Sheets spreadsheet.
    2. SelectExtensions> Apps Script.
    3. In the script editor, clickUntitled project.
    4. Give your project a name and clickRename.

    Your script is nowboundto your spreadsheet, which gives the script special abilities to alter theuser interface or respond when the spreadsheet is opened.

    A script project represents a collection of Apps Scriptfiles and resources. Code files in a script project have a.gsextension.

  2. You can use Apps Script to write custom functions that youcan use in Google Sheets just like a built-in function. Custom functions arecreated using standard JavaScript. Create a function:

    1. Open your Apps Script project.
    2. ClickEditor.
    3. A script file appears as a project file namedCode.gs. To edit the file,select it.
    4. Replace any code in the script editor with the following code which readsthe data in your spreadsheet and passes it along as input to a workflowexecution:

      functionhandleEdit(e){varrange=e.range.getA1Notation();varsheet=e.source;if(range.length >1 &&range[0]==='G'){if(e.value=="TRUE"){Logger.log("Approved: TRUE");varrow=range.slice(1);varurl=sheet.getRange('E'+row).getCell(1,1).getValue();varapprover=sheet.getRange('F'+row).getCell(1,1).getValue();callback(url,approver);}else{Logger.log("Approved: FALSE");}}}functioncallback(url,approver){constheaders={"Authorization":"Bearer "+ScriptApp.getOAuthToken()};varpayload={'approver':approver};constparams={"method":'POST',"contentType":'application/json',"headers":headers,"payload":JSON.stringify(payload)};Logger.log("Workflow callback request to "+url);varresponse=UrlFetchApp.fetch(url,params);Logger.log(response);}
    5. Click Save.

  3. Apps Scriptinstallable triggerslet a script project execute a specified function when certain conditions aremet, such as when a spreadsheet is opened or edited. Create a trigger:

    1. Open your Apps Script project.
    2. ClickTriggers.
    3. ClickAdd Trigger.
    4. In theAdd Trigger for YOUR_PROJECT_NAME dialog, configure thetrigger:
      1. In theChoose which function to run list, selecthandleEdit.
      2. In theChoose which deployment should run list, selectHead.
      3. In theSelect event source list, selectFrom spreadsheet.
      4. In theSelect event type list, selectOn edit.
      5. In theFailure notification settings list, selectNotify me daily.
    5. ClickSave.
    6. If you receive a prompt to choose a Google Account, select the appropriateaccount, and then clickAllow.

      This allows your Apps Script project to see, edit,create, and delete your Google Sheets spreadsheets; and to connect toan external service.

  4. An Apps Script projectmanifest fileis a JSON file that specifies basic project information thatApps Script needs to run a script successfully. Note that theApps Script editor hides manifest files by default to protect your Apps Scriptproject settings. Edit the manifest file:

    1. Open your Apps Script project.
    2. ClickProject Settings.
    3. Select theShow "appsscript.json" manifest file in editor checkbox.
    4. ClickEditor.
    5. The manifest file appears as a project file namedappsscript.json. Toedit the file, select it.
    6. TheoauthScopes field specifies an array of strings. To set theauthorization scopesyour project uses, add an array with the scopes you want supported. For example:

      {"timeZone":"America/Toronto","dependencies":{},"exceptionLogging":"STACKDRIVER","runtimeVersion":"V8","oauthScopes":["https://www.googleapis.com/auth/script.external_request","https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/spreadsheets"]}

      This sets explicit scopes to:

      • Connect to an external service
      • See, edit, configure, and delete your Google Cloud data and seethe email address for your Google Account
      • See, edit, create, and delete all your Google Sheets spreadsheets
    7. Click Save.

    Note: To protect your project settings, hide the manifest when you are doneediting by clearing theShow "appsscript.json" manifest file in editorcheckbox.

Deploy a workflow that writes to a spreadsheet and uses callbacks

Deploy a workflow that executes, pauses, and then resumes when a callback isapproved through a spreadsheet. The workflow writes to a Sheetsspreadsheet using theGoogle Sheets API connector.

Console

  1. In the Google Cloud console, go to theWorkflowspage:

    Go to Workflows

  2. ClickCreate.

  3. Enter a name for the new workflow:workflows-awaits-callback-sheets.

  4. In theRegion list, selectus-central1 (Iowa).

  5. For theService account, select the Compute Engine defaultservice account(PROJECT_NUMBER-compute@developer.gserviceaccount.com).

  6. ClickNext.

  7. In the workflow editor, enter the following definition for your workflow:

    main:steps:-init:assign:# Replace with your sheetId and make sure the service account# for the workflow has write permissions to the sheet-sheetId:"10hieAH6b-oMeIVT_AerSLNxQck14IGhgi8ign-x2x8g"-before_sheets_callback:call:sys.logargs:severity:INFOdata:${"Execute steps here before waiting for callback from sheets"}-wait_for_sheets_callback:call:await_callback_sheetsargs:sheetId:${sheetId}result:await_callback_result-after_sheets_callback:call:sys.logargs:severity:INFOdata:${"Execute steps here after receiving callback from sheets"}-returnResult:return:${await_callback_result}await_callback_sheets:params:[sheetId]steps:-init:assign:-project_id:${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}-location:${sys.get_env("GOOGLE_CLOUD_LOCATION")}-workflow_id:${sys.get_env("GOOGLE_CLOUD_WORKFLOW_ID")}-execution_id:${sys.get_env("GOOGLE_CLOUD_WORKFLOW_EXECUTION_ID")}-create_callback:call:events.create_callback_endpointargs:http_callback_method:POSTresult:callback_details-save_callback_to_sheets:call:googleapis.sheets.v4.spreadsheets.values.appendargs:range:${"Sheet1!A1:G1"}spreadsheetId:${sheetId}valueInputOption:RAWbody:majorDimension:"ROWS"values:-["${project_id}","${location}","${workflow_id}","${execution_id}","${callback_details.url}","","FALSE"]-log_and_await_callback:try:steps:-log_await_start:call:sys.logargs:severity:INFOdata:${"Started waiting for callback from sheet " + sheetId}-await_callback:call:events.await_callbackargs:callback:${callback_details}timeout:3600result:callback_request-log_await_stop:call:sys.logargs:severity:INFOdata:${"Stopped waiting for callback from sheet " + sheetId}except:as:esteps:-log_error:call:sys.logargs:severity:"ERROR"text:${"Received error " + e.message}-check_null_await_result:switch:-condition:${callback_request == null}return:null-log_await_result:call:sys.logargs:severity:INFOdata:${"Approved by " + callback_request.http_request.body.approver}-return_await_result:return:${callback_request.http_request.body}
  8. Make sure to replace the placeholdersheetId value with yourspreadsheetId.

  9. ClickDeploy.

gcloud

  1. Create a source code file for your workflow:

    touchworkflows-awaits-callback-sheets.yaml
  2. In a text editor, copy the following workflow to your source code file:

    main:steps:-init:assign:# Replace with your sheetId and make sure the service account# for the workflow has write permissions to the sheet-sheetId:"10hieAH6b-oMeIVT_AerSLNxQck14IGhgi8ign-x2x8g"-before_sheets_callback:call:sys.logargs:severity:INFOdata:${"Execute steps here before waiting for callback from sheets"}-wait_for_sheets_callback:call:await_callback_sheetsargs:sheetId:${sheetId}result:await_callback_result-after_sheets_callback:call:sys.logargs:severity:INFOdata:${"Execute steps here after receiving callback from sheets"}-returnResult:return:${await_callback_result}await_callback_sheets:params:[sheetId]steps:-init:assign:-project_id:${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}-location:${sys.get_env("GOOGLE_CLOUD_LOCATION")}-workflow_id:${sys.get_env("GOOGLE_CLOUD_WORKFLOW_ID")}-execution_id:${sys.get_env("GOOGLE_CLOUD_WORKFLOW_EXECUTION_ID")}-create_callback:call:events.create_callback_endpointargs:http_callback_method:POSTresult:callback_details-save_callback_to_sheets:call:googleapis.sheets.v4.spreadsheets.values.appendargs:range:${"Sheet1!A1:G1"}spreadsheetId:${sheetId}valueInputOption:RAWbody:majorDimension:"ROWS"values:-["${project_id}","${location}","${workflow_id}","${execution_id}","${callback_details.url}","","FALSE"]-log_and_await_callback:try:steps:-log_await_start:call:sys.logargs:severity:INFOdata:${"Started waiting for callback from sheet " + sheetId}-await_callback:call:events.await_callbackargs:callback:${callback_details}timeout:3600result:callback_request-log_await_stop:call:sys.logargs:severity:INFOdata:${"Stopped waiting for callback from sheet " + sheetId}except:as:esteps:-log_error:call:sys.logargs:severity:"ERROR"text:${"Received error " + e.message}-check_null_await_result:switch:-condition:${callback_request == null}return:null-log_await_result:call:sys.logargs:severity:INFOdata:${"Approved by " + callback_request.http_request.body.approver}-return_await_result:return:${callback_request.http_request.body}
  3. Make sure to replace the placeholdersheetId value with yourspreadsheetId.

  4. Deploy the workflow by entering the following command:

    gcloudworkflowsdeployworkflows-awaits-callback-sheets\--source=workflows-awaits-callback-sheets.yaml\--location=us-central1\--service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com

    ReplacePROJECT_NUMBER with your Google Cloudproject number. You can retrieve your project number:

    gcloudprojectsdescribePROJECT_ID

Test the end-to-end flow

Execute the workflow to test the end-to-end flow. Executing a workflow runs thecurrent workflow definition associated with the workflow.

Console

  1. In the Google Cloud console, go to theWorkflowspage:

    Go to Workflows

  2. On theWorkflows page, select theworkflows-awaits-callback-sheets workflow to go to its details page.

  3. On theWorkflow details page, clickExecute.

  4. ClickExecute again.

    The workflow starts and its execution state should beRunning. Thelogs also indicate that the workflow is paused and waiting:

    Execute steps here before waiting for callback from sheets...Started waiting for callback from sheet 1JlNFFnqs760M_KDqeeeDc_qtrABZDxoalyCmRE39dpM
  5. Verify that the workflow has written the callback details to a row inyour spreadsheet.

    For example, you should see your workflow execution ID in theExecution ID column, a callback endpoint in theCallback URL column, andFALSE in theApproved? column.

  6. In the spreadsheet, change theFALSE toTRUE.

    After a minute or two, the execution should resume and then complete with an execution state ofSucceeded.

gcloud

  1. Open a terminal.

  2. Execute the workflow:

    gcloudworkflowsrunworkflows-awaits-callback-sheets

    The workflow starts and the output should indicate that the workflow is paused and waiting:

      Waiting for execution [a8361789-90e0-467f-8bd7-ea1c81977820] to complete...working.

  3. Verify that the workflow has written the callback details to a row inyour spreadsheet.

    For example, you should see your workflow execution ID in theExecution ID column, a callback endpoint in theCallback URL column, andFALSE in theApproved? column.

  4. In the spreadsheet, change theFALSE toTRUE.

    After a minute or two, the execution should resume and then complete with an execution state ofSUCCEEDED.

Clean up

If you created a new project for this tutorial,delete the project.If you used an existing project and wish to keep it without the changes addedin this tutorial,delete resources created for the tutorial.

Delete the project

The easiest way to eliminate billing is to delete the project that you created for the tutorial.

To delete the project:

    Caution: Deleting a project has the following effects:
    • Everything in the project is deleted. If you used an existing project for the tasks in this document, when you delete it, you also delete any other work you've done in the project.
    • Custom project IDs are lost. When you created this project, you might have created a custom project ID that you want to use in the future. To preserve the URLs that use the project ID, such as anappspot.com URL, delete selected resources inside the project instead of deleting the whole project.

    If you plan to explore multiple architectures, tutorials, or quickstarts, reusing projects can help you avoid exceeding project quota limits.

  1. In the Google Cloud console, go to theManage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then clickDelete.
  3. In the dialog, type the project ID, and then clickShut down to delete the project.

Delete resources created in this tutorial

  1. Delete files in Google Drive.
  2. Delete a workflow.

What's next

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2026-02-19 UTC.