diff --git a/Meraki API Registration Form Screenshot.png b/Meraki API Registration Form Screenshot.png
new file mode 100644
index 0000000..5f5660b
Binary files /dev/null and b/Meraki API Registration Form Screenshot.png differ
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a424b11
--- /dev/null
+++ b/README.md
@@ -0,0 +1,98 @@
+# Meraki Dashboard with Google Scripts & Forms
+
+## Overview
+
+This learning lab demonstrates the power of Meraki APIs with Google Scripts and Forms.
+
+By building a simple Google Form and attaching a script written in JavaScript, a Meraki Dashboard administrator can easily be created. This is incredibly helpful when running workshops that require several administrators to have access to a lab network.
+
+# Instructions
+## Create a Google Form
+https://forms.google.com
+
+### The first two questions should be as follows:
+- Email
+- Name
+
+[SAMPLE]
+
+
+
+## Link the form to a Google Script
+
+
+
+## Paste the contents of this repository's `code.gs` file into the Google Scripts IDE.
+
+- [code.gs](code.gs)
+- update the **API_KEY**, **ORG_ID** and **SHARD** to match your settings.
+- save your changes
+
+
+
+## Add a Trigger to launch the script when the Form is submitted.
+
+
+
+### Configure the trigger
+- Run: **onFormSubmit**
+- Events: **From form**
+- --> On form submit
+
+
+
+## Test the API calls
+Several additional functions are included in this code to allow you to test with sample data and collect information.
+- Run --> *Select a **test** function*
+
+
+
+Feel free to modify the sample JSON data defined in the `testAddMerakiAdmin` function.
+
+```
+function testAddMerakiAdmin(){
+ var data = {
+ "name":"Google Scripts Demo",
+ "email":"GoogleScriptsDemo@meraki.com", // change this to an email you have access to!
+ "orgAccess":"full"
+ };
+ addMerakiAdmin(API_KEY,ORG_ID,SHARD,data);
+}
+```
+
+
+## View the results
+- View --> Logs
+
+
+
+
+
+
+## Google Form
+Now that the API calls are working, test the Google Form by hitting the preview button.
+
+
+
+Complete the form with a valid email address.
+
+
+
+If everything worked, you should get an email from Meraki asking to complete the admin account verification.
+
+
+
+
+## Verify Meraki account is created
+- Meraki Dashboard --> Organization --> Administrators
+
+
+
+## SUCCESS!
+
+You have now used the Meraki APIs to dynamically create Meraki administrator accounts. With Google Apps, you do not even need to host a server to run the application. Cool!
+
+
+
+### Meraki API Resources
+http://developers.meraki.com/
diff --git a/example-registerMerakiAdmin-form.gs b/example-registerMerakiAdmin-form.gs
new file mode 100644
index 0000000..889808c
--- /dev/null
+++ b/example-registerMerakiAdmin-form.gs
@@ -0,0 +1,153 @@
+/* #####################################################
+Cisco Meraki API Workshop Registration Google Script
+
+- This script collects a single response from a Google Form
+ * Email
+ * Name
+- Creates an admin account with Meraki API
+
+There are additional test functions which are useful to run API calls and view the output in the log without using the form.
+
+Please update your environment variables below for proper operation.
+
+Written by:
+Cory Guynn
+2017
+Cisco Meraki
+
+
+InternetOfLEGO.com
+/ ##################################################### */
+
+
+
+/* #####################################################
+ Enter Your Environment Variables
+/ ##################################################### */
+
+// Update your API Key. This is in your Meraki Dashboard profile. Your Org must have APIs enabled.
+var API_KEY = 'YourAPIKey';
+
+// Update your Org ID (use testGetMerakiOrgs(); to learn the org IDs)
+var ORG_ID = 'YourOrgID';
+
+// Update Shard Number (you can see this when looking at the URL when you login to Meraki Dashboard or by pulling the SNMP settings via API call)
+// https://nXXX.meraki.com/api/v0/organizations/{{organizationId}}/admins
+var SHARD = 'nXXX'; // if you are confused, you can try 'dashboard', but sometimes redirects are problematic.
+
+// Update the orgAccess. By default, the new account has FULL ADMIN ACCESS to the Organization!!!
+// Nice for hackathons, bad for production. The API call can also include network paramters and tags.
+var PERMISSIONS = 'full';
+
+
+// *************
+// API CALLS TO MERAKI
+// *************
+
+
+// Add Meraki Admin
+function addMerakiAdmin(apiKey, orgId, shard, payload){
+ var headers = {
+ "x-cisco-meraki-api-key": apiKey
+ };
+ var options =
+ {
+ "method" : "post",
+ "payload": payload,
+ "headers": headers,
+ "content-type": "application/json",
+ "contentLength": payload.length,
+ "followRedirects": true,
+ "muteHttpExceptions":true
+ };
+ response = UrlFetchApp.fetch('https://'+shard+'.meraki.com/api/v0/organizations/'+orgId+'/admins', options);
+ var result = JSON.parse(response.getContentText());
+ Logger.log(result);
+ Logger.log(response.getResponseCode());
+}
+
+// Test function (use this to test the API call without using the form)
+function testAddMerakiAdmin(){
+ var data = {
+ "name":"Google Scripts Demo",
+ "email":"GoogleScriptsDemo@meraki.com", // change this to an email you have access to!
+ "orgAccess":"full"
+ };
+ addMerakiAdmin(API_KEY,ORG_ID,SHARD,data);
+}
+
+
+// Get Meraki Admins -- Not used in the form, but really helpful to see if admins are getting created
+function getMerakiAdmins(apiKey,orgId){
+ var payload;
+ var headers = {
+ "x-cisco-meraki-api-key": apiKey
+ };
+ var url = 'https://dashboard.meraki.com/api/v0/organizations/'+orgId+'/admins';
+ var options = {
+ 'method': 'get',
+ 'headers': headers,
+ 'payload': payload
+ };
+ var response = UrlFetchApp.fetch(url, options);
+ var json = response.getContentText();
+ var data = JSON.parse(json);
+
+ Logger.log("URL JSON: "+ JSON.stringify(data));
+}
+
+// Test function (Use this to test the API call since it includes the environment variables)
+function testGetMerakiAdmins(){
+ getMerakiAdmins(API_KEY,ORG_ID);
+}
+
+// Get the Meraki Organizations and IDs this API key hass access to.
+function getMerakiOrgs(apiKey){
+ var headers = {
+ "x-cisco-meraki-api-key": apiKey
+ };
+ var url = 'https://dashboard.meraki.com/api/v0/organizations';
+ var options = {
+ 'method': 'get',
+ 'headers': headers
+ };
+ var response = UrlFetchApp.fetch(url, options);
+ var json = response.getContentText();
+ var data = JSON.parse(json);
+
+ Logger.log("Meraki Orgs: "+ JSON.stringify(data));
+}
+
+// Test function
+function testGetMerakiOrgs(){
+ getMerakiOrgs(API_KEY);
+}
+
+
+// *************
+// Form Handler
+// *************
+
+// Collects input from form submition
+// (must run this via form or an error will occur)
+
+function onFormSubmit(e) {
+ var form = FormApp.getActiveForm();
+ var formResponse = e.response;
+ var itemResponses = formResponse.getItemResponses();
+
+ var admin = {};
+ admin.name = itemResponses[0].getResponse();
+ admin.email = formResponse.getRespondentEmail();
+
+ Logger.log("onFormSubmit - name: "+admin.name);
+ Logger.log("onFormSubmit - email: "+admin.email);
+
+ // Create admin account
+ var payload = {
+ "name":admin.name,
+ "email":admin.email,
+ "orgAccess":PERMISSIONS
+ };
+ addMerakiAdmin(API_KEY, ORG_ID, SHARD, payload);
+}
diff --git a/images/Google Form Preview button.png b/images/Google Form Preview button.png
new file mode 100644
index 0000000..b903853
Binary files /dev/null and b/images/Google Form Preview button.png differ
diff --git a/images/GoogleScriptsForm.png b/images/GoogleScriptsForm.png
new file mode 100644
index 0000000..327d3b7
Binary files /dev/null and b/images/GoogleScriptsForm.png differ
diff --git a/images/GoogleScriptsIDE.png b/images/GoogleScriptsIDE.png
new file mode 100644
index 0000000..6fd2f02
Binary files /dev/null and b/images/GoogleScriptsIDE.png differ
diff --git a/images/GoogleScriptsLogs.png b/images/GoogleScriptsLogs.png
new file mode 100644
index 0000000..8db16cc
Binary files /dev/null and b/images/GoogleScriptsLogs.png differ
diff --git a/images/GoogleScriptsLogsMenu.png b/images/GoogleScriptsLogsMenu.png
new file mode 100644
index 0000000..a1b98e1
Binary files /dev/null and b/images/GoogleScriptsLogsMenu.png differ
diff --git a/images/GoogleScriptsMenu.png b/images/GoogleScriptsMenu.png
new file mode 100644
index 0000000..193ff72
Binary files /dev/null and b/images/GoogleScriptsMenu.png differ
diff --git a/images/GoogleScriptsRunMenu.png b/images/GoogleScriptsRunMenu.png
new file mode 100644
index 0000000..0bfec47
Binary files /dev/null and b/images/GoogleScriptsRunMenu.png differ
diff --git a/images/GoogleScriptsTriggers.png b/images/GoogleScriptsTriggers.png
new file mode 100644
index 0000000..67968ee
Binary files /dev/null and b/images/GoogleScriptsTriggers.png differ
diff --git a/images/GoogleScriptsTriggersMenu.png b/images/GoogleScriptsTriggersMenu.png
new file mode 100644
index 0000000..dd1817c
Binary files /dev/null and b/images/GoogleScriptsTriggersMenu.png differ
diff --git a/images/Meraki API Registration Form Screenshot.png b/images/Meraki API Registration Form Screenshot.png
new file mode 100644
index 0000000..5f5660b
Binary files /dev/null and b/images/Meraki API Registration Form Screenshot.png differ
diff --git a/images/Meraki Account Verification Email.png b/images/Meraki Account Verification Email.png
new file mode 100644
index 0000000..b768da3
Binary files /dev/null and b/images/Meraki Account Verification Email.png differ
diff --git a/images/Meraki Admin User screenshot - demo.png b/images/Meraki Admin User screenshot - demo.png
new file mode 100644
index 0000000..33e2fe4
Binary files /dev/null and b/images/Meraki Admin User screenshot - demo.png differ