Executing Functions using the Apps Script API

The Apps Script API provides a
scripts.run method
that remotely executes a specfied Apps Script function. You can use this method
in a calling application to run a function in one of your script projects
remotely and receive a response.

Requirements

You must satisfy the following requirements before a calling application can use
the scripts.run
method. You must:

Deploy the script project as an API executable. You can
deploy, undeploy, and redeploy projects as needed. You can also deploy a
specific version of a project. This is helpful if you want to have stable
release while you continue to develop your application.

Provide a properly scoped OAuth token for the execution.
This OAuth token must cover all the scopes
used by the script, not just the ones used by the called function. See the
full list of authorization scopes
in the method reference.

Ensure that the script and the calling application share a common
Cloud Platform project. Any one of these projects work: the
default project
created with the Apps Script project, a new Cloud Platform
project, or an existing Cloud Platform project.

Note: API executables cease responding to script.run requests
if their script project changes ownership to either
Team Drive
or to an outside domain account. Fix this by redeploying the script in the
new domain or Team Drive, or by moving the script back to its original domain.Warning: Script projects that use sensitive scopes are subject to
review by Google. Users attempting to authorize apps that call such scripts
with the Apps Script API may see a warning screen saying the app is unverified
by Google. See the
OAuth client verification guide
for more details.

The scripts.run method

The scripts.run
method requires key identifying information in order to run:

You can optionally configure your script to execute with these behaviors:

Run in development mode. This mode executes with the most recently saved
version of the script project rather than the most recently deployed version.
Do this by setting the devMode boolean in the
request body
to true. Only the owner of the script can execute it in development mode.

Handling parameter data types

Using the Apps Script API
scripts.run method
usually involves sending data to Apps Script as function parameters and
getting data back as function return values. The API can only take and return
values with basic types: strings, arrays, objects, numbers, and booleans. These
are similar to the basic types in JavaScript. More complex
Apps Script objects like Document
or Sheet cannot be passed into
or from the script project by the API.

When your calling application is written in a strongly-type language such as
Java, it passes in parameters as a list or array of generic objects
corresponding to these basic types. In many cases, you can apply simple
type conversions automatically. For example, a function that takes a number
parameter can be given a Java Double or Integer or Long object as a
parameter without extra handling.

When the API returns the function response, you often need to cast the
returned value to the correct type before it can be used. Here are some
Java-based examples:

Numbers returned by the API to a Java application arrive as
java.math.BigDecimal objects, and may need to be converted to
Doubles or int types as needed.

If the Apps Script function returns an array of strings, a Java application
casts the response into a List<String> object:

List<String> mylist = (List<String>)(op.getResponse().get("result"));

If you are looking to return an array of Bytes, you may find it convenient
to encode the array as a base64 String within the Apps Script function and
return that String instead:

Step 1: Deploy the script as an API executable

In the Version drop-down menu, select a version of the script project
that you want the API to execute. You can
create a new vesion if
needed.

In the Who has access to the script drop-down menu, select the users who
are allowed to call the script's functions using the Apps Script API. Options
here include Only myself, members in your domain, or Anyone.

Click Deploy. The new dialog that opens shows your script's ID,
listed under Current API ID. Make note of this ID—you need to
include it in any Apps Script API scripts.run
requests your application makes. If you need to find it again later,
select Publish > Deploy as API executable.

Step 2: Set up the common Cloud Platform project

Both your script and the calling application need to share the same
Cloud Platform project. You can achieve this by doing one of the following:

Use the default Cloud Platform project that is attached to your script
project to set up the calling application's OAuth credentials. You can access
the script's Cloud Platform project by doing the following:

Open the script project in the Apps Script editor and select
File > Project properties > Scopes. Record all the scopes that the
script requires.

In the calling application code, generate a script OAuth access token
for the API call. This is not a token the API itself uses, but rather one the
script requires when executing. It should be built using the
Cloud Platform project client ID and the script scopes you recorded.

The Google client libraries can greatly
assist in building this token and handling OAuth for the application,
usually allowing you to instead build a higher-level "credentials" object
using the script scopes. See the
Apps Script API quickstarts for examples
of building a credentials object from a list of scopes.

Step 4: Make the script.run request

Once the calling application is configured, you can make
scripts.run calls. Each API
call consists of the following steps:

Build an API request
using the script ID, function name, and any required
parameters.

Make the scripts.run
call and include the script OAuth token you built in the
header (if using a basic POST request) or else use a crendentials object
you built with the script scopes.

Allow the script to finish executing. Scripts are allowed to take up to
six minutes of execution time, so your application should allow for this.

Upon finishing, the script function may return a value, which the API
delivers back to the application if the value is a supported type.

API request examples

The following examples show how to make an Apps Script API execution request in
various languages, calling an Apps Script function to print out a list of
folders in the user's root directory. The script ID of the Apps Script project
containing the executed function must be specified where indicated with
ENTER_YOUR_SCRIPT_ID_HERE. The examples rely on the
Google API Client libraries for their respective
languages.

Target Script

The function in this script requires the following Drive scope:

https://www.googleapis.com/auth/drive

The calling applications use the Google client libraries to build
credential objects for OAuth using this scope.

Python

def main():
"""Shows basic usage of the Apps Script API.
Creates a Apps Script API service object and uses it to call an
Apps Script function to print out a list of folders in the user's root
directory.
"""
SCRIPT_ID = 'ENTER_YOUR_SCRIPT_ID_HERE'
# Authorize and create a service object.
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('script', 'v1', http=http)
# Create an execution request object.
request = {"function": "getFoldersUnderRoot"}
try:
# Make the API request.
response = service.scripts().run(body=request,
scriptId=SCRIPT_ID).execute()
if 'error' in response:
# The API executed, but the script returned an error.
# Extract the first (and only) set of error details. The values of
# this object are the script's 'errorMessage' and 'errorType', and
# an list of stack trace elements.
error = response['error']['details'][0]
print("Script error message: {0}".format(error['errorMessage']))
if 'scriptStackTraceElements' in error:
# There may not be a stacktrace if the script didn't start
# executing.
print("Script error stacktrace:")
for trace in error['scriptStackTraceElements']:
print("\t{0}: {1}".format(trace['function'],
trace['lineNumber']))
else:
# The structure of the result depends upon what the Apps Script
# function returns. Here, the function returns an Apps Script Object
# with String keys and values, and so the result is treated as a
# Python dictionary (folderSet).
folderSet = response['response'].get('result', {})
if not folderSet:
print('No folders returned!')
else:
print('Folders under your root folder:')
for (folderId, folder) in folderSet.iteritems():
print("\t{0} ({1})".format(folder, folderId))
except errors.HttpError as e:
# The API encountered a problem before the script started executing.
print(e.content)
if __name__ == '__main__':
main()

Ruby

SCRIPT_ID = 'ENTER_YOUR_SCRIPT_ID_HERE'
# Create an execution request object.
request = Google::Apis::ScriptV1::ExecutionRequest.new(
function: 'getFoldersUnderRoot'
)
begin
# Make the API request.
resp = service.run_script(SCRIPT_ID, request)
if resp.error
# The API executed, but the script returned an error.
# Extract the first (and only) set of error details. The values of this
# object are the script's 'errorMessage' and 'errorType', and an array of
# stack trace elements.
error = resp.error.details[0]
puts "Script error message: #{error['errorMessage']}"
if error['scriptStackTraceElements']
# There may not be a stacktrace if the script didn't start executing.
puts "Script error stacktrace:"
error['scriptStackTraceElements'].each do |trace|
puts "\t#{trace['function']}: #{trace['lineNumber']}"
end
end
else
# The structure of the result will depend upon what the Apps Script function
# returns. Here, the function returns an Apps Script Object with String keys
# and values, and so the result is treated as a Ruby hash (folderSet).
folder_set = resp.response['result']
if folder_set.length == 0
puts "No folders returned!"
else
puts "Folders under your root folder:"
folder_set.each do |id, folder|
puts "\t#{folder} (#{id})"
end
end
end
rescue Google::Apis::ClientError
# The API encountered a problem before the script started executing.
puts "Error calling API!"
end

Limitations

The Apps Script API has several limitations:

A common Cloud Platform project. The script being called and the
calling application must share a Cloud Platform project. This can be the
default one created with the script, or another project (which requires
switching the script to use that project).
If using the default project of a script, be aware that when a script resides
in a Team Drive your access to its Cloud Platform project may be restricted.

Basic parameter and return types. The API cannot pass or return
Apps Script-specific objects (such as Documents,
Blobs,
Calendars,
Drive Files, etc.) to the
application. Only basic types such as strings, arrays, objects, numbers, and
booleans can be passed and returned.

OAuth scopes. The API can only execute scripts that have at least
one required scope. This means you cannot use the API to call a script
that does not require authorization of one or more services.