Triggering a Scheduled Plan Externally

  • 24 February 2017
  • 0 replies

Userlevel 3

Note: This feature requires technical understanding of using the API.

The scheduler provides a useful way to run tasks on periodic basis. Most commonly it is used to render looks or dashboards and email the results to a recipient, or it can be used to place the results as a file in an S3 or sftp destination.

The scheduling is fairly flexible, but is based on times and dates. This sample code uses the API to execute the same kind of scheduled job based on some external trigger. For example, an ETL job might load data into a database. When the load is done, the orchestration software might use a script like this to kick off jobs based on the newly loaded data.

This sample code is produced using standard Unix/Linux shell scripting methods and utilities. The only tool that is not extremely common to experienced Unix programmers and operators is the jq utility. jq stands for JSON Query and allows one to parse JSON documents and extract particular values from the command line. It is available from standard repositories on many platforms include Debian/Ubuntu Linux, Fedora, OpenSuse, etc. For information go to

The Looker API can be accessed not only though the simple shell scripting utilities as shown here, but from more advanced languages. Looker provides an Ruby based SDK. Swagger provides a method to generate an SDK for other languages such as Java, Python, C#, etc. The Ruby SDK and Swagger instructions can be found here:


DASHBOARD_FILTER='[ "Date=90 days", "State / Region=-Not State", "Brand=Calvin Klein" ]'

jq_location=`which jq`

if [ $status -gt 0 ]
echo "This utility requires the jq command line utility to parse JSON data. Find more information here:"
echo "On a mac with the brew utility installed, you should be able to install jq with the command \"brew install jq\"."
exit 255

echo "Logging in"
response=`curl --request POST --fail --silent --show-error \
-d "client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}" \

if [ $status -gt 0 ]
echo "Failed logging in"
exit 1

ACCESS_TOKEN=`echo $response | jq --raw-output '.access_token'`
echo "Got access token \"${ACCESS_TOKEN}\""

echo "Encode the filter string"
encoded_filter=`echo "${DASHBOARD_FILTER}" | jq --raw-output 'join("&")' -`
echo $encoded_filter

if [ $status -gt 0 ]
echo "Failed encoding Filter String"
exit 2

echo "Execute the plan"
response=`curl --request POST --fail --silent --show-error \
--header "Authorization: token ${ACCESS_TOKEN}" \
--data "
\"name\": \"Business Pulse\",
\"enabled\": false,
\"dashboard_id\": 73,
\"require_results\": null,
\"require_no_results\": null,
\"require_change\": null,
\"timezone\": \"America/Los_Angeles\",
\"run_as_recipient\": false,
\"dashboard_filters\": \"?${encoded_filter}\",
\"send_all_results\": false,
\"format\": \"wysiwyg_pdf\",
\"apply_formatting\": true,
\"address\": \"${DESTINATION_ADDRESS}\",
\"type\": \"email\"
}" \

if [ $status -gt 0 ]
echo "Failed executing the plan"
exit 3

echo "Loggin out"
curl --request DELETE --header "Authorization: token ${ACCESS_TOKEN}" "${END_POINT}/logout"

The easiest way to figure out the parameters for the request bady is to create a scheduled plan for a Look or Dashboard through the UI with the appropriate settings, then retrieve it though the API. The get_all_scheduled_plans API call ( will retrieve an array JSON objects that represent the scheduled plans for the current user. The result looks like this:

"id": 683,
"created_at": "2017-02-24T00:05:31.259+00:00",
"title": "Business Pulse",
"last_run_at": "2017-02-24T00:05:31.328+00:00",
"user_id": 813,
"user": {
"id": 999,
"first_name": "John",
"last_name": "Smith",
"avatar_url": "",
"display_name": "John Smith",
"url": "https://localhost:19999/api/3.0/users/999",
"can": {
"show": true,
"index": true,
"show_details": true,
"index_details": true,
"sudo": false
"scheduled_plan_destination": [
"id": 665,
"scheduled_plan_id": 683,
"format": "wysiwyg_pdf",
"apply_formatting": true,
"address": "",
"type": "email",
"parameters": null,
"looker_recipient": true,
"can": {
"index": true,
"show": true,
"update": true,
"destroy": true,
"create": true,
"run": true
"name": "Business Pulse",
"enabled": false,
"look_id": null,
"dashboard_id": 73,
"lookml_dashboard_id": null,
"require_results": null,
"require_no_results": null,
"require_change": null,
"crontab": null,
"timezone": "America/Los_Angeles",
"run_as_recipient": false,
"dashboard_filters": "?Date=90 days&State / Region=-Not State&Brand=Calvin Klein",
"send_all_results": false,
"next_run_at": null,
"can": {
"index": true,
"email_to_others": true,
"create": true,
"run": true,
"update": true,
"show": true,
"destroy": true

Most of these fields are not needed. To figure out if a field is not needed, go to the API documentation and look at the Parameters “Model”. It will look like this:

Any field marked read-only should not be included in the request. Some fields in the “Model” might be marked write-only and these can only be used when building the request. The secret_parameters entry, for example, is write-only and is used to provide the password or private key used to authenticate for SFTP or S3 delivery. With this information (and sometimes a bit of trial and error) the proper request body can be defined.

0 replies

Be the first to reply!