--- title: "Sidekick + App Platform Tutorial" slug: "sidekick-app-platform-tutorial" description: "Learn how to enhance Sidekick Threads with custom applications using the App Platform. Build integrations and retrieve external data to improve customer experience." updated: 2025-10-02T21:42:27Z published: 2025-10-02T21:42:27Z canonical: "help.gladly.com/sidekick-app-platform-tutorial" --- > ## Documentation Index > Fetch the complete documentation index at: https://help.gladly.com/llms.txt > Use this file to discover all available pages before exploring further. # Sidekick + App Platform Tutorial ## Introduction Developers can enhance Sidekick Threads by integrating external systems utilizing the App Platform. In particular, developers can build custom applications that: - Retrieve data from external systems to present external information to customers within Sidekick or trigger behavior in Sidekick based on data retrieved. Examples include, but are not limited to: - Retrieving an order and showing the order status to a customer. - Retrieving an order. If the order was created in the past 30 days, tell the user that it can still be canceled. Otherwise, tell the user it cannot be canceled. - Perform actions in an external system from within Sidekick. Examples include, but are not limited to: - Canceling an order. - Creating a Task in Gladly with the [Gladly Task API](https://developer.gladly.com/rest/#tag/Tasks). ## Tips and Tricks There are two important keys to designing a successful Sidekick app. ### Experience Design Understand what experience you want to build for your users and design a logical flow chart. For example, if you would like to build an enhancement to cancel an order, think of the following: - Should Sidekick be allowed to cancel all orders? If not- what criteria make an order non-cancelable? For example: - Orders should not be cancelable if some items are on final sale - Orders should not be cancelable if they were placed ≥ 100 days ago - Orders should not be cancelable if they have already been canceled - If an order is not cancelable, what should Sidekick do? For example: - If an order is non-cancelable, state the cancellation policy and close the Conversation - If an order is cancelable, what should Sidekick do? For example: - If an order contains multiple items, ask the customer if they want to fully cancel the order, or partial. If they want to cancel partial, then hand it off to an Agent - If an order only contains one item, then cancel the order - If a cancelation fails, what should Sidekick do? For example: - Upon failed cancelation, let the customer know the order could not be canceled and transfer the Conversation to an Agent - If a cancelation succeeds, what should Sidekick do? For example: - Upon successful cancelation, let the customer know the order has been canceled and ask if there is anything else they need help on. ### Understand your systems When building an integration, there are two key pieces of information you need to know: - If you need to **retrieve** external data and communicate it to an end customer / make decisions based on what it returns: - How will you retrieve this data (e.g., a REST API to Get Orders) - What information do you need to provide to the external system to retrieve this data (e.g., credentials, an order ID) - How will you supply the information to the external system to be able to retrieve the data (e.g., ask the customer for an order ID) - If you need to perform an Action in an external system: - How will you perform the action (e.g., a REST API to Cancel Orders). - What information must you provide to the external system to conduct the action (e.g., an order ID)? - How will you supply the information to the external system so that you can conduct the action (e.g., collect the order ID from the customer)? ## Goal The goal of this tutorial is to build a Thread in Sidekick that tells customers the status of their latest order via Chat. ## How To Gladly has created a Sample OMS system for this exercise. The apiToken you use to access this Sample OMS can be set to any value (e.g., 12345). ### Scoping **Experience Design** In this tutorial, we will design the following experience: - Customer initiates a Chat session via Chat. - Customer types in “what is the status of my order?” - This triggers Sidekick to do the following: - Retrieve customer’s latest order. - If order is found, send a message that tells them the status of their latest order and close the Conversation. - If order is not found, send a message that tells them the order cannot be found, and then transfer the Conversation. **Understand Your Systems** *Understand your APIs* Let’s say that you have an OMS, and that OMS has 2 APIs available: - GET customer: [https://gladly-sample-oms.vercel.app/api/customers?emailAddress=](https://gladly-sample-oms.vercel.app/api/customers?emailAddress=)` {{email_address}}` - Upon successful retrieval, retrieves an object that looks like this: ```json {  "id": "YW5kcmV3QGV4YW1wbGUub3Jn",  "fullName": "Lamont Russel",  "phones": [    "+644938853685"  ],  "emails": [    "andrew@example.org",    "Lamont.Russel@gmail.com",    "Lamont_Russel@hotmail.com",    "Lamont_Russel@gmail.com"  ],  "ltv": "$142.11" } ``` - GET customer orders: [https://gladly-sample-oms.vercel.app/api/orders?customerId=](https://gladly-sample-oms.vercel.app/api/orders?customerId=) `{{oms_customer_id}}` - Upon successful retrieval, retrieves an object that looks like this, where orders are sorted by `orderDate` descending: ```json {    "id": "1f85eb0a-caa8-42ee-ad10-1dcfd09d01e2",    "orderNumber": "sGMtsfUf",    "status": "pending",    "shippingAddress": "64389 Sienna Village Apt. 296",    "billingAddress": "",    "orderDate": "2021-08-19T06:42:30.609Z",    "customerId": "YW5kcmV3QGV4YW1wbGUuY29t",    "lineItems": [      {        "id": "f9930951-ff95-4e34-8ce4-e7320e01f538",        "quantity": 2,        "productId": "ab30f03a-be65-4b97-81f6-8f3157b13fbc",        "status": "return_initiated"      },      {        "id": "8e8a31b8-75e0-4edc-8a98-98fd29a6a18a",        "quantity": 3,        "productId": "5d2ba910-fd1b-4939-8f57-f71199964e95",        "status": "return_initiated"      },      {        "id": "e6f76583-40ca-4284-9baa-518a8a4e52e5",        "quantity": 4,        "productId": "38af722b-14be-40f1-a7fd-26b84bb46d15",        "status": "pending"      }    ],    "shippingSpeed": "expedited",    "totalPrice": "697.00",    "shippingAndHandling": "816.00" } ``` **Understand your authentication requirements** In addition, authentication-wise, your OMS just needs the following static header to be supplied across all requests: - `apiToken` **How do I retrieve the data I need?** For this experience, you need to retrieve a customer’s most recent order’s status. To retrieve this data, you will first need to: - Call the GET customer API to retrieve the customer’s ID - Call the GET customer orders API to retrieve the list of customer’s orders - where the most recent order placed is the first order in the response Array **What information do I need to supply to my external system to retrieve this data?** - For the GET customer API: - I must supply the customer’s email to the API - For the GET customer orders API: - I must supply the OMS customer ID **How will I supply this information to the external system using Chat and Sidekick?** - For the GET customer API: - I can collect the customer’s email via the Chat onboarding process - For the GET customer orders API: - I can collect the OMS customer ID upon successful retrieval of a customer profile using the GET customer API ### Pre-requisites To build the above experience, I must ensure: - I have an `apiToken` to access my OMS APIs - I have a Chat created that is connected to Sidekick - Chat has quick replies turned off - Chat has onboarding turned on ### Build App The goal of this section is to build your App. > [!NOTE] > What is an App? > > An App is folder containing files that define how your APIs behave. In this section, we will create an App that has the two APIs we defined above: - GET customer - GET customer orders **Install Tools** Install *appcfg* The tool, *appcfg,* allows you to create an application scaffold, validate, and build it. For this exercise, we are assuming you are using a Mac. For more in-depth documentation on utilizing this tool, please visit this README: [https://github.com/gladly/app-platform-appcfg-cli](https://github.com/gladly/app-platform-appcfg-cli). 1. Go to [https://github.com/gladly/app-platform-appcfg-cli/releases](https://github.com/gladly/app-platform-appcfg-cli/releases). 2. Scroll down to the `Assets` section and download the version that is most relevant to your machine. 3. Unzip the downloaded folder - you should see a file that is named `appcfg` . 4. Drag this file to your Desktop. 5. Open up Terminal on your Mac. - `cd ~/Desktop` - `chmod a+rx appcfg` - `./appcfg` - Click on the “OK” button. 6. Open up System Settings > Privacy and Security and click “Allow Anyway.” 7. Open up Terminal on your Mac. 1. `cd ~/Desktop` 2. `./appcfg` 3. Click OK 4. `./appcfg` 5. After running this, you should now see a help guide **Build App** For this exercise, we will be building a pre-built application. > [!NOTE] > For a more in-depth overview of all App Platform concepts > > Review the following: > > - This tutorial for an overview of concepts: [App Platform Tutorial](/docs/sidekick-app-platform-tutorial) > - This tutorial for how the Sample OMS App we are installing is built: [App Platform Tutorial](/docs/sidekick-app-platform-tutorial) 1. Download [https://github.com/gladly/app-platform-examples](https://github.com/gladly/app-platform-examples) and drag the `SampleOMS` folder to your Desktop 2. Open up the following files in your favorite code editor. Let’s cover some key concepts - these are all specified in the more in-depth App Platform [tutorial](/docs/sidekick-app-platform-tutorial), so think of the following as a cheat sheet for a robust application. 1. `app/authentication/headers/apiToken.gtpl` 1. Each file name in the `/headers/` folder represents the key of a header we send for every API request to the Sample OMS 2. In this particular case, we only need to send the header name `apiToken`, which is why we only have one file in this folder 3. The `.gtpl` extension represents the Go templating language, which you can find documented here: [https://masterminds.github.io/sprig/](https://masterminds.github.io/sprig/). 4. The file contains the following: `{{.integration.secrets.apiToken}}` - `integration.secrets` is a reserved object in App Platform that contains all the secrets associated with your application. This is a great place to put things like API tokens, secrets, and credentials that you don’t want to make public. In this case, we are accessing `apiToken`, a secret we store in the `integration.secrets` object. 5. The `integration.secrets` values get set during the App installation process we will go through in the next section 2. `app/data/pull/customer/request_url.gtpl` 1. Data pulls are stored in the `/data/` folder, whereas actions are stored in the `/actions/` folder 2. Each API you need access to should be stored in its own subfolder (e.g., customers) within `/data/`. In this tutorial, we only need access to two APIs: `customer` and `orders`, though the Sample OMS app you downloaded defines more. 3. `request_url.gtpl` is the file that is utilized to build the request URL for the API you need to call. 4. `.customer` is a reserved object that you can access in API calls - it represents the customer object that is undergoing the Sidekick experience. For more information on the values in the customer object, see the “Gladly Customer Profile data” section [here](https://help.gladly.com/developer-tutorials/docs/app-data-pulls-for-app-platform/). 3. `app/data/pull/customer/config.json` 1. In this file, we specify that the object name for the customer API response is called `sample_oms_customer` 2. We also specify that the request is a `GET` request 4. `app/data_schema.graphql` 1. You’ll see here that we define an object called `Customer` - which is based on the data pull for `customer` that we saw above 2. Importantly, you’ll see that an `orders` Array is present in the customer object: `orders: [Order] @parentId(template: "{{.id}}")`. This means that for each request to get a customer, we **also** trigger a request to get this customer’s orders. 5. `app/data/pull/orders/config.json` 1. You’ll see in this configuration file a value called `dependsOnDataTypes` - this field ensures that we get the customer data first **before** we execute this API request 6. `app/data/pull/orders/request-url.gtpl` 1. You’ll see here that the customerId query is built using this template `{{urlquery (index .externalData.sample_oms_customer 0).id}}` 2. In the above, `externalData` is a reserved object in the App Platform 3. Since this call is dependent on the `customers` call succeeding, and we know that the customer object is saved in the `sample_oms_customer` object based on this file - we can use `sample_oms_customer` to build the `customerId` parameter in this API request 3. Once you’re done inspecting the application, open up Terminal 1. `export GLADLY_APP_CFG_ROOT=~/Desktop/SampleOMS` 2. `./appcfg build` 3. The above will build a zip file **Install App** Send your zip file to the PS Engineer you are working with and ask them to install it. Make sure to specify the secrets that you want the PS Engineer to configure (e.g., set apiToken to 12345)