Build a Low Code Brex Client to Automate Operations

Build a Low Code Brex Client to Automate Operations

Build a Low Code Brex Client to Automate Operations
Stephen Tillman
 minutes ↗

Some things are fantastic together. 🍔🥤

In particular, REST APIs and Low code dovetail nicely.

Although APIs simplify development, they also demand a level of programming skill and technical ability. Low code frameworks like Appsmith can provide a visual layer on top of the API that empowers non-technical audiences and citizen developers to build client applications.

There is much value in simplifying the development process where we can. Low code works best for development projects where the problem domain is well understood and there are very few use cases. REST API clients are well suited to that extent - the API contract itself serves as a kind of blueprint for the client application. Take, for instance, the Brex APIs.

Brex offers several APIs that range from Onboarding and Payments to Teams and Transactions. Brex admins can plug into these APIs to build powerful workflows and custom automations. To demonstrate, we'll build an Appsmith dashboard that will connect to your Brex account.

Key Takeaways

  • Appsmith has a REST interface that allows us to create and modify query objects. A query object is a portable, reusable construct that defines parameters needed for a single API call. We'll use several query objects to engage the Brex APIs.
  • Building a multi-page interface with Appsmith is incredibly simple and well-documented. The platform provides a visual way to build pages using widgets and drag/drop functionality. However, unlike the global Appsmith store, page resources are page-scoped and cannot be referenced across different pages. Despite that, it is still possible to move or copy resources from one page to another.
  • We'll use JavaScript Promises to simplify asynchronous workflows. This will enable us to launch multiple API calls concurrently and then handle the responses elegantly. Normally, this is a challenge because API calls rely on the network and conclude at inexact points in time. To overcome this, we used to apply callback functions, but JavaScript Promises are an improvement over callbacks.

What are we building?

In this tutorial, we'll create an Appsmith tool that leverages the Brex APIs to perform bulk operations on your Brex account. By uploading a CSV file, you'll be able to create credit cards, users, and vendors. These changes will be reflected in your Brex dashboard immediately. Our tool will also support terminating cards and deleting vendors.

As it is not intended for production use, this application doesn't attempt to be either complete or systematic. It is more like a demo project. Rather than serve as a proper software solution, the final application is meant to demonstrate what is possible using Appsmith and the Brex APIs.

For context, this tutorial depicts the reader as a fictional Brex customer in order to provide a frame of reference and bring meaning to the sample CSV files. Pretend that you are an outer space company that issues Brex credit cards to your colleagues. The cardholders have personal cards as well as other cards designated for expenses such as Equipment Repairs, Launch Services, and Telecom. You will also define fictional Vendors: General Atomics, Orbital Transport Services, Space Food Systems. Let's suppose you are building this application to automate a few back office operations. You have chosen to build it using Appsmith.

What do I need?

First, you'll want to sign into Appsmith and create a new application. Next, sign in to your Brex account and generate a user token with Read/Write permissions for Cards, Referrals, Users, and Vendors. Appsmith will use this token to authorize API calls.

To confirm that your token is working, you can perform a quick sanity check with curl:

COPYcurl --request GET '' \
--header 'Authorization: Bearer <your-token>'

The response will resemble the following:

   "id": "cuuser...",
   "first_name": "Michael",
   "last_name": "Collins",
   "email": "",
   "status": "ACTIVE"


Alternatively, you can use Postman to test API calls. In fact, the Brex Developer workspace allows you to experiment with every endpoint documented in the Brex Developer Portal.

Appsmith Echo API

Consider using the Appsmith Echo API to spare production API calls.


While testing your Appsmith tool, sometimes you will need to invoke non-idempotent API endpoints such as Create card and Invite user. Instead of exercising the live endpoints, you can create an API datasource that relies on the Appsmith Echo API:

COPYfor(let i = 0; i < 5; i++) {, onError, params);

To mock HTTP status codes and errors, you might try

Disposable Inbox

For testing user invites, I recommend a disposable email system like Mailinator or Temp Mail.

Git Repo

There's a companion repo that contains sample CSV files and supporting JavaScript code for this tutorial. You can also use Appsmith's Import-Export feature to migrate the demo application to your own account.

Brex APIs

The base URL for all Brex APIs is

  1. Use this URL to create an authenticated API datasource called brex-prod.
  2. Select Bearer Token for the Authentication Type.
  3. Supply your Brex user token.
  4. Click Save.

You should now have a datasource that we can use to create Queries.

New query objects will show in the left side panel, under QUERIES/JS. For example, here I've created a query for the Get current user endpoint:


Now, you can create new query objects from the brex-prod datasource. The following search box will appear when you click the + icon next to the QUERIES/JS menu option:


Going forward, we'll create several queries to support our application.

Onboarding API

The Onboarding API allows you to refer your customers and personal contacts to Brex. You might use the Create referral endpoint as part of the Brex Referral Program.

Unlike the Get current user endpoint, Create referral is a POST endpoint that requires a JSON body.


Later on, we'll discuss this.params. For now, understand that it is possible to run the create_referral query object and pass parameters into it, like so:

COPYconst params = { referral_code, email, first_name, last_name };
return; // always return the promise

Team API

The Team API lets you manage users, departments, locations, and cards. For this example, we'll manage users and cards, starting with the Invite user endpoint, which allows you to invite a new team member as an employee. Through the dashboard, Brex admins can assign various role types to the employee, but team members created through this endpoint will bear the Employee role type by default.

Your invite_user query object will POST to /v2/users. The request body should match the following:

   "first_name": {{this.params.first_name}},
   "last_name": {{this.params.last_name}},
   "email": {{}}


Under the Headers tab, be sure to generate a random string value for the Idempotency-Key:


Idempotency is well beyond the scope of this tutorial. But, in short, the idempotency key ensures that the API server will only process a non-idempotent request once.

For a moment, consider network interruptions that may cause downstream services (or even the application itself) to perform a retry. Without an idempotency, the server would attempt to process the same request again. The idempotency key helps the API server keep track of whether the operation was already performed or not.

Notice that the code to generate the Idempotency-Key includes a reference to Lodash: _.random(1000). Lodash, among other libraries, is built into the Appsmith platform, which is super handy.

Create Card

The create_card query object also requires an Idempotency-Key, and will POST to /v2/cards. The request body is:

   "owner": {
       "type": "USER",
       "user_id": {{this.params.user_id}}
   "card_name": {{this.params.card_name}},
   "card_type": "VIRTUAL",
   "limit_type": "USER"

The Create card endpoint also accepts other parameters, card types, and limit types, so check out the developer docs. There's also a spend_controls parameter that allows you to define a spend limit for the card. This limit can be set to refresh each month, quarter, year, or never (for one-time use).

Terminate Card

We can also reference {{this.params...}} in the query object URL. For example, the terminate_card query object will POST to the Terminate card endpoint, which has a URI parameter, {{this.params.card_id}}:


The request body for terminate_card:

 "description": "demo",
 "reason": "OTHER"

There are also other reason codes such as CARD_LOST, CARD_NOT_RECEIVED and FRAUD, but for this example, we'll stick with OTHER.

Note that the Idempotency-Key is not required, because card termination is idempotent by definition. In other words, terminating a card multiple times has the same effect as terminating a card once.

Payments API

The Payments API allows you to initiate and manage payments and vendors from your Brex Cash account. We'll use the Create vendor endpoint as an example. In a production application, you would also include vendor payment information to enable ACH, wire, or cheque payments from your Brex Cash account. But, for this example, we'll omit the vendor's payment type. You can also add vendor payment information from the dashboard - How do I manage my vendors on Brex Cash?

Create Vendor

The create_vendor query object will POST to /v1/vendors. This endpoint requires an Idempotency-Key and the request body is:

  "company_name": {{this.params.company_name}}

Delete Vendor

The delete_vendor query object will send DELETE requests to /v1/vendors/{{this.params.vendor_id}}. There is no request body.

Initial Data Loading

The following query objects will enable us to populate tables on page load. To ensure that Appsmith pulls the initial dataset each time, you can configure each query object to run on page load:

QueryEndpointget_cardsList cardsget_usersList usersget_vendorsList vendors

This option is located under the Settings tab inside the query object:


Appsmith Pages

The goal of our app is to provide a user-friendly way to create Brex credit cards, vendors, invites, and referrals. In this section, we'll envision the page layout and breifly touch on a few key points. You'll use a drag/drop interface to build the UI. But, before we get started:

  1. Rename Page1 to Cards.
  2. Add a page for Users and another page for Vendors.
  3. Move get_users, create_referral and invite_user from the Cards page to the Users page.
  4. Move get_vendors, create_vendor and delete_vendor to the Vendors page.

Now that our work is cut out, we'll begin creating each page.


Use the Appsmith widgets to create the following page to your ability. Note that the green Upload widget is a file picker, not a button.


Make sure the Data Format property is set to Text for each file picker:



The Users page has a Tabs widget with two tabs, one for invites and one for referrals. You can drag each Table widget into the appropriate tab.


The Referrals tab:



The Vendors page is almost identical to the Cards page. In fact, you can select every widget on the Cards page and copy/paste them onto the Vendors page. Of course, you'll also need to adjust the widget properties and table data.


Application Logic

Our application is starting to take shape. We now have an end-to-end skeleton system. Next, we'll incrementally add functionality to each page, incorporating the query objects we created earlier. We'll also learn about JS Objects, which allow us to define handler functions that we can bind to the page widgets.

Page Load

Earlier, we created a few query objects to run on page load. Now, we'll use them to populate our table widgets. As stated in Running APIs on Page Load, "If we connect an API response to a widget, Appsmith automatically runs that API on page load..."

In effect, this means that binding {{}} to the Table Data property for tbl_cards will populate the table. However, for this tutorial, we only need the card id and card_name fields from each card. So, we'll write some additional code to remove the unwanted fields:

COPY// bind this to tbl_cards - Table Data property
 .filter(card => card.status == "ACTIVE") // only get ACTIVE cards
 .map(card => ({ id:, card_name: card.card_name }))

Likewise, we initialize tbl_invites and tbl_vendors:

COPY// bind this to tbl_invites - Table Data property
 .filter(item => item.status == "INVITED") // only get INVITED users
 .map(item => ({ email:, name: `${item.first_name} ${item.last_name}` }))

// bind this to tbl_vendors - Table Data property => ({ id:, company_name: vendor.company_name }))

JS Objects

In earlier versions of Appsmith, there was only support for writing small code snippets to data bind page widgets. But, Appsmith now supports JS Objects, which enable multi-line JavaScript code and reusable functions.

To create a new JS Object, click the + icon next to the QUERIES/JS menu option, and find the New JS Object option.


Create an object for each page: cards_object, users_object, and vendors_object.


Replace the contents of cards_object with the following code:

COPYexport default {
   upload: () => {
       showAlert('Cards created!', 'success');

We'll revisit this code shortly. At the moment, let's go back to the page editor and bind {{cards_object.upload()}} to the file picker's onFilesSelected event:


If you are curious, deploy the application and upload a file to the Cards page. You should receive a Cards created! notification.

The cards_object.upload method will leverage the create_card query to issue virtual cards. To follow along here, you'll need your Brex cuuser ID, which you can obtain by running the get_current_user query. Place your ID into a CSV file, formatted like this:

Michael Collins,cuuser...

Later on, we'll upload this file to the Cards page.

Reading CSV Files

The following code will read lines from a CSV file, assuming that your file picker is called fp_cards:

COPY// get the first uploaded file
const csv_file = fp_cards.files[0];

// collect each line from the csv file
const csv_lines ="\n");

// omit csv header and blank lines
const rows = csv_lines.slice(1).filter(row => row.length > 0);


COPYconst rows = fp_cards.files[0].data.split("\n")
                    .slice(1).filter(row => row.length > 0);

Iterating API Calls

To smoothen the discussion around asynchronous code and JavaScript promises, we'll be using a helper function called loop to iterate API calls. For reference, the full loop implementation is here, but we'll strictly focus on understanding its usage:

COPY// visit each row
return cards_object.loop({
 collection: rows, // assign rows as the collection
 onReadLine: () => {
   // do this on every row
 onEnd: () => {
   // do this after the loop ends

The loop helper calls onReadLine once per row. On each loop iteration, we can pass card_name and user_id into

COPYonReadLine: (card_name, user_id) => {
 // be sure to always return the promise,
 // otherwise this will not behave as expected
 return{ card_name, user_id });

When the loop ends, we report the number of cards created successfully, and then call so that the new items appear in tbl_cards:

COPYonEnd: () => {
 const count =;
 if (count > 0) {
   showAlert(`${count} cards created!`, "success");

Once you re-deploy the application and upload a valid CSV file, your card will show in the Brex dashboard, under Card > Manage cards:


Last, but not least, we have cards_object.terminate. Bind this method to btn_terminate_cards - onClick event:

COPYterminate: () => {
   // clear variables

   // get comma-separated values from the textbox
   const rows = txt_card_ids.text.split(",").map((id) => id.trim());

   // visit each row, terminate card
   return cards_object.loop({
     collection: rows,
     onReadLine: (card_id) => {
       return{ card_id });
     onEnd: () => {
       const count =;
       if (count > 0) {
         showAlert(`${count} cards terminated!`, "success");


The Users page involves many of the same techniques and concepts discussed earlier. However, there are two tables involved here. We'll need to refresh one of the tables, depending on whether the CSV file is intended for referrals or invites.

I should mention that an invite asks someone to join your Brex account as a team member, whereas a referral prompts someone to sign up for their own Brex account.

Invites vs Referrals

Creating an invite sends an email to the recipient:


On the other hand, creating a referral generates a personalized invite link to an onboarding flow. You can find your referral code at When the prospect visits their personalized link, they will see a pre-filled form containing data values sent through the Create referral API call:


When the CSV file is uploaded, we can inspect the header row to determine if the file contains referrals or not - referrals have a referral_code column while invites do not:

COPY// invites csv header: "first_name,last_name,email"
// referrals csv header: "referral_code,first_name,last_name,email"
let is_referral = rows[0].indexOf("referral_code,") == 0;

// ...

return is_referral
       ? users_object.createReferrals(rows)
       : users_object.createInvites(rows)

For brevity, the full implementation code is shown here.

Referral Data Store

Something to note about the Create referral endpoint is that it returns the referral id and the referral_signup_url, but it does not return the applicant details (first name, last name, and email). Instead, the API consumer is expected to store and handle their own Brex referrals securely, as they contain sensitive information about the applicant.

Why do we need a data store?

At first glance, this might seem trivial. Perhaps, we don't need a referral data store. Maybe we could just create the referrals and then use the List referrals endpoint to load the recent items. However, the List referrals endpoint does not return any applicant information either.

So, by design, we need the data store to establish a link between the applicant details (passed into create_referral) and the referral id (returned from create_referral).

Without a data store, it's also not possible to seed tbl_referrals on page load. The List referrals endpoint doesn't return any applicant information, so we need to query the data store instead and then use that response data to populate tbl_referrals.

Implementing the data store

I'm using a serverless database (Fauna) to host the data store for this tutorial, but the type of database you use is unimportant. It is only important that the data store is accessible via a REST API, so that we can easily connect to the data source and create query objects:

Fauna exposes a GraphQL API. Please see the the wiki for more details about this as it relates to add_referral and get_referrals.

Storing the referral data

Now that the data store is in place, we can persist the referral id and referral_signup_url along with the applicant information:

COPY// get response data and csv row
onSuccess: ({ id, referral_signup_url }, row) => {
 // get applicant info from the row
 const [referral_code, first_name, last_name, email] = row;
 // store the referral data{
   name: `${first_name} ${last_name}`,

Get referrals on page load

Also, remember to configure get_referrals to run on page load:

COPY// bind this to tbl_referrals - Table Data property && &&


Implementation of the Vendors page is left as an exercise for the reader. Here are some things to keep in mind:

  1. The fp_vendors file picker needs an event handler for onFilesSelected.
  2. The create_vendor query object has a company_name parameter.
  3. The delete_vendor query object has a vendor_id parameter.
  4. Bind {{}} to tbl_vendors.
  5. Uploading vendors.csv should create three new vendors in your Brex dashboard.

The full vendors_object implementation is here. You can also create multiple vendors by using the bulk upload tool in your Brex dashboard.

Error Handling

Thus far, we've only explored the happy path. If we return to the Cards page and upload cards.invalid-user-id.csv the create_card query will fail. Thankfully, Appsmith will handle this exception and display an error message.


But, imagine if you were to upload the following CSV file:

Space Mountain,invalid-user-id
Cargo Dragon,cuuser...
Planet Express,invalid-user-id

In this case, the API call would fail on Space Mountain and Planet Express, but the default error handling would not be able to detect which rows failed. To correct this, we'll need to implement the error handling ourselves.

During cards_object.loop(), whenever onReadLine fails, the onError function will trigger. We can implement onError to display a message:

COPYonError: ({ row }) => {
 const [card_name] = row;
 const message = `failed to create card "${card_name}"`;
 showAlert(message, "error");
 return message; // return message to the loop helper

The loop helper also keeps track of errors. There's a has_errors flag, which is a boolean that indicates when any errors have occurred. There is also an errors_arr collection where we store each error message for later display in tbl_errors.

The has_errors flag will determine if the red Icon Button is visible. Set its Visible property to {{}}. Also bind its onClick handler to {{showModal("error_modal")}}. This button will launch a Modal that contains a table bound to {{}}:



The beauty of Appsmith is that you can migrate this application to your own workspace and repurpose it for your own needs. Here, we've touched on a few Brex API endpoints. We've also learned how to create an Appsmith dashboard that allows Brex admins to create and terminate Brex cards and refer and invite Brex users.

I encourage Brex admins to build and share custom Appsmith workflows that tap into the Brex APIs. There is much value in simplifying the development process where we can. Low code tools like Appsmith can provide practical advantages to Brex admins who need them, but they can also change the perspectives and attitudes of those who do not.

The views expressed in this post are my own and have not been reviewed or approved by my employer (Brex, Inc.).

Build a Tool to Generate PDF Files with APITemplate and n8n

Build a Tool to Generate PDF Files with APITemplate and n8n

Build a Tool to Generate PDF Files with APITemplate and n8n
Vihar Kurama
 minutes ↗

Information is the lifeline of any business, and to keep it alive and well, businesses have to transfer information to their various stakeholders like investors, bankers, suppliers, customers, government, etc. One of the simplest and the most effective ways of transferring information is using PDF files. These PDF files can be generated in different ways, but it involves lots of coding and configuration on your frontend and backend applications. To make this process easier on Appsmith (low-code framework to build internal tools), we created a workflow on n8n that uses APITemplate and simple webhooks.

This tutorial is a step-by-step guide on generating and exporting PDF files from data on your Appsmith application. Let's dive in!

Getting Started: Setting up Appsmith and the Data to Export

The first step is to create an account on Appsmith. In this tutorial, I'll be using the cloud version of Appsmith, but you can always choose to use Appsmith locally or self-host it on your server.

  • Navigate to and sign-up for a new account if you're a new user or login to the existing one.
  • Next, create a new application under your preferred organization. You'll see an editor with everything you need to build your internal application.

Now, let's create a table from the mock database already provided on Appsmith.

  • For this, click on the + icon next to the Datasources on the left sidebar under Page1.
  • Now choose the users database (Postgres) under-sample databases section.
CleanShot 2022-03-17 at 00.35.15@2x.png
  • With this, you should see users' databases under your data sources section on the left sidebar. Now create a new query by clicking on Create New button from the user's datasource.
  • This will create an empty query named Query1, rename this as getUsers and paste the following SQL query:


  • Hit the Run button on the top right to execute this query; it will return details of the first ten users from the user's table on the database.

Now let's bind this on a Table widget and then create a workflow to export it into a PDF file.

  • To bind the query on a table widget, click on the + icon next to the widget and search for the table under the Widgets tab.
  • Drag and drop the table widget onto the canvas and open its property pane by selecting the table on the canvas. You should see all the table configurations on the side right bar.
  • Next, update the Table Data property to the following:
{{  }}

  • Here, we use the moustache bindings to bind the data from the query onto the widget. You can write JavaScript anywhere across appsmith inside these bindings.

Following is what the application looks like now:

CleanShot 2022-03-17 at 00.54.43@2x.png

Excellent, our data is now ready. Now let’s create a workflow on n8n to generate PDF using APIs from

Setting up

If you are new to these tools, the following is a quick intro to help you get started: APITemplate helps auto-generate images and PDFs with Zapier, Integromat, N8n ow with a simple REST API.

Now let’s create a free account on APITemplate; you will be redirected to your dashboard after signing up. Navigate to the Manage Templates tab and create a new PDF template.

The template here is how you want your PDF to be organized this tutorial; I’ll be using the basic table template provided under the PDF template section.

Since our goal is to export the data on the Appsmith table, I’ve navigated to the HTML editor and removed all the unnecessary HTML content.

CleanShot 2022-03-17 at 01.06.53@2x.png
The idea is straightforward we send dynamic data from Appsmith onto the HTML template using a webhook, and APITemplate will generate a PDF file from the HTML.

Here’s how the HTML is added:

CleanShot 2022-03-17 at 01.08.52@2x.png

The item variable here holds all the data that will be updated from the webhook request on Appsmith.

We don't see any data here, as we did not have any workflow. So let's create on n8n!

Creating a Workflow on n8n

n8n: n8n helps you to interconnect every app with an API in the world with each other to share and manipulate its data without a single line of code. It is an easy-to-use, user-friendly, and highly customizable service, which uses an intuitive user interface for you to design your unique workflows very fast.

I'll be using the cloud version of n8n for this tutorial. Note that you can also self-host n8n on your server.

Now, let's create the workflow:

  • Drag and drop a webhook node and add the following configuration:
  • Set the authentication type to None.
  • The HTTP method to POST.
  • Set the Response method to Using 'Respond to Webhook' node

Now copy the TEST URL, and create a new API on the Appsmith app by clicking on the + icon next to Queries and pasting the TEST URL in the request URL. Rename the query to generatePDF for a better naming convention.

Now navigate to the Body tab in the API request and paste the following JSON:


Here, we send the items data from the Table to the webhook using the moustache bindings.

Now, we can test this webhook by starting the workflow; here’s how it works:

Next, drag and drop a new node and connect it to the webhook and use the following configuration:

  • First, copy the API key to the Credentials for property.
  • Set resource to PDF and Operation to Creation
  • The template ID property can be found under the manage templates tab; this refers to the template created in the last section.
  • Toggle the JSON parameters and Download to ON
  • Copy the following in the Properties:
    "items": {{(JSON.stringify($node["Webhook"].json["body"]["items"]))}}

This is where n8n sends data from Appsmith to APITemplate using a webhook.

Now, connect a new Respond to webhook node and set its respond with property to First incoming item property. This is how the complete workflow looks like:

CleanShot 2022-03-17 at 02.02.07@2x.png

Now click on execute the workflow and RUN the API on Appsmith; we should see a response with a downloadable PDF URL:

CleanShot 2022-03-17 at 02.13.55@2x.png

To improve the look and feel, we could create a new button and set its onClick property to run generatePDF query and bind the response to a text widget.

Here’s the complete workflow:

Alternatively, for PDF generation on Appsmith, we could also rely on other services like Zapier / Adobe.

If you’re interested in using a database not listed on our website as an integration, please let us know about it by raising a PR on Github, and we will do our best to include it at the earliest.

Join our growing community on Discord, and follow us on Youtube and Twitter to stay up to date.

Upload and Manage Files on Cloudinary with the Filepicker Widget

Upload and Manage Files on Cloudinary with the Filepicker Widget

Upload and Manage Files on Cloudinary with the Filepicker Widget
Olubisi Idris Ayinde
 minutes ↗

Many internal tools, especially administrative applications, often require file uploading and file management features. File pickers, and file selectors, therefore, are some of the most used components in internal tool development. Developers experience numerous challenges when it comes to implementing these features resulting in delayed operations. This can easily be mitigated by using Appsmith to build and deploy applications quickly. Appsmith has a dedicated filepicker widget that can be used to upload files to any of the developers' preferred cloud storage services, such as Cloudinary, S3, among others. 

In this short blog, we’re going to focus on one such widget, the filepicker. With this, you can upload files from your local machines to any cloud storage via API. You can upload files by implementing a POST API and reference the base64 or binary version in the post body.

Features of the Filepicker Widget

1. The Allowed File Types properties allow us to restrict the types of files that a user (of our application) can upload.

2. The Maximum File Size attribute allows us to specify the total file size that a user can upload.

3. When the user selects files to be uploaded, we can immediately use an API or utilize the S3 plugin to upload the file's base64 to our cloud storage.

4. The visibility property controls the widget's visibility on the page. When the widget is switched off, the widget will not be displayed when the app is published. 

5. There is a parameter that allows us to specify the maximum number of files that a user is allowed to upload.

How Does the Filepicker Widget Work?

In this section, we'll look at how the filepicker works. First, let’s set up a new application to get started!

  • Create a new account on Appsmith (it’s free!), if you are an existing user, log in to your Appsmith account.
  • Create a new application by clicking on the Create New button under the Appsmith dashboard.
  • We’ll now see a new Appsmith app with an empty canvas and a sidebar with two directories: Datasources and Widgets. This is where we can connect to data sources and find all the widgets.

Now, we’re all set to explore how the filepicker widget works in Appsmith.

Drag and drop the filepicker widget (as shown in the image below). 

Now that we have our filepicker widget on the canvas, we can customize the properties as desired. 

After selecting our file(s), we get the following result:

How to manage files on Cloudinary using Appsmith

Filepicker configuration

We'll go over each of the configurations accessible in the Appsmith filepicker one by one.

Label: This is used to set the label of the Filepicker from the default “Select Files” to any label of our choice.

Maximum No. of files: This allows us to specify the maximum number of files that a user is authorized to upload. 

Maximum File Size: This property allows us to specify the maximum file size that a user can upload.

Data Type: This determines the data format of the files uploaded. 

Allowed File Types: Allows us to restrict the types of files that a user can upload. 

Accepts an array of wildcardsimage/*, exact mime types image/jpeg, or file extensions .jpg:['image/*', '.jpg', '.jpeg', '.png', '.gif']

Required: When turned on, it marks user input as a required field and disables form submission until the input is made.

Visible: Controls widget's visibility on the page. When turned off, the widget will not be visible when the app is published.

See the documentation to learn more.

Uploading single and multiple images to cloud storage via Filepicker using a Cloudinary API

Let's now explore how to upload single or multiple files using filepicker to cloud storage using the Cloudinary API.

Setting up a data source

We'll need to connect to our data source by clicking on the Plus icon next to the data sources link in the sidebar, then selecting "Create New" from the menu, as shown below:

After this, we should now choose the "Create New API" option. This will take us to the screen shown below:

We renamed the datasource from the default "Api1" to "Cloudinary API" in the image above to have a clear description. 

We will be making use of the Cloudinary API: `{cloud_name}/image/upload` where {cloud_name} is our cloudinary username.

The API requires our Cloudinary cloud_name and upload_preset.

To get our cloud_name and upload_preset, we follow the steps listed in the following sections. 

The cloud name is obtained from our Cloudinary dashboard, as shown below.

An upload preset can be found in the “Upload” tab of our Cloudinary settings page, which we access by clicking on the gear icon in the top right corner of the dashboard page.

We then click on the Upload tab on the settings page:

We scroll down to the bottom of the page to the upload presets section, where we see our upload preset or the option to create one if we don't have any.

Adding the Cloudinary API URL and setting the header should look similar to what we have below:

Let's go to the "Body" tab and configure it, as shown below.

We specified the file(s) to be uploaded as well as our upload preset in the image above, and we configured our request body in a multipart structure.

Now that we've finished configuring the API, let's put it to the test before using it in our filepicker.

We will click on the FIlePicker Widget as shown below and select a file to be uploaded from our system.

Now let’s head over to the API section; the following is the test result:

Yay! That works! We’ve successfully tested our API and got a valid response.

Upload images using Filepicker

Let's upload a single image directly from our filepicker to cloud storage by connecting to the API Datasource we just created. We will head over to the filepicker configuration and update the "onFilesSelected" property.

As seen below, we can add a success alert to show when the image is successfully uploaded and when there is an issue after selecting our query to be conducted.

The response below shows a success alert after uploading our image to cloud storage utilizing the Cloudinary API directly from our filepicker widget.

We hope that you found this short guide helpful. If you want to know how to upload or download files from S3, you can look at this document and follow this discussion. To learn more about how to upload a file to a local server, take a look at this discussion on our community forum. 

Appsmith has more than 35 UI widgets, and these can cut your development time in half! To know more, head to our docs

Did you get stuck somewhere? We’re happy to help! Join us on Discord today! 

Olubisi Idris Ayinde is a software engineer, technical writer, and community builder. This article was written as part of the Appsmith Writers Program. If you’d like to write for Appsmith, send an email to expressing your interest.

Using the Notion API to Build a Content Management System

Using the Notion API to Build a Content Management System

Using the Notion API to Build a Content Management System
Vihar Kurama
 minutes ↗

At Appsmith, we use Notion to manage our content calendar. We also work with a few external agencies and freelancers for some of our content. It is impossible to create granular access control and develop a workflow on Notion to run the process smoothly and thus, as soon as Notion released their API, we decided to build an application that helps us manage our entire content management in one place while giving our collaborators the necessary access only.

Our application uses our Notion (mock) Table as a data source and lets you plant, submit and edit articles on the application, while at the same time has a provision for integrating with an email service of your choice (we use SendGrid here) to send reminder emails or updates to people in the project.

In this tutorial, we’ll build an essential Content Management System, which will let you:

  • Submit new content idea submissions from authors
  • Set deadlines for submissions
  • Follow up with authors directly with their Emails
  • Organise all data on a Notion page

Check out the live demo here. Here's a screenshot of how the app looks like:

Notion App Screenshot.png
Appsmith is an open-source framework that lets developers build dashboards, workflows, and CRUD apps with only the necessary code. You can connect to any API or databases like MongoDB, PostgreSQL, or MYSQL and get access to multiple widgets, including charts, tables and forms, for building a UI fast.

Let’s dive right in!

Configuring the Notion API

Notion API lets us connect to Notion Pages and Databases. Now, let's look at how we can set up the API, gather all the required keys and connect to Appsmith.

  • Firstly, choose the workspace you want to work with on your Notion. If you want to test it, feel free to create a new workspace.
  • Now, open the workspace setting by clicking on the Settings and Members option on the left navigation bar. We should see a new modal with all the settings.
  • Find the select the Integrations option under Workspace options in the settings modal. This will redirect to the integrations tab.
  • Next, choose the Develop your integration option. Now we'll be redirected to our integration page.
Image One.png
  • On the integrations page, select the New integration option and add a name and associated workspace you want to work with and hit submit. This will create us a new secret key!
Image Two.png
Image Three.png
  • Now head back to our workspace, choose a specific page and click on the share option (we can find this on the top-right corner)
  • Next, hit the invite button, a new modal opens, here we can find our created integration. Select the integration and confirm the invite.
  • With this, we should be able to add an integration to a Notion page; also, make sure to save your integration key; we’ll have to use it for using the Notion API
In Notion, integration has a secret key; when added to a workspace, we could perform all the actions (create, read, update). We'll use the secret key of the integration to connect with third-party applications.

Setting up a Notion Page

To work with the Notion API, firstly, let’s create a database for our content calendar.

  • On your page, add a new table with the following fields that are required for our content manager:
Title: Text Field
Description: Text Field
Author: Text Field
Category: Text Field
Status: Dropdown Field
Notes: Text Field
Deadline: Date Field
Author Email: EMail Field

You can also use this Notion page of ours, which can be used as a mock database. You can click on this link duplicate to one of your workspaces. Also, make sure to add the integration to this page to use the Notion API.

Now that we have our page and integration-ready, we’ll start building an App on Appsmith.

Querying Data from Notion API

In this section, we’ll be querying data from Notion API. Follow the below steps:

  • Firstly, we should have an Appsmith account; if not, sign-up here (it's free)! Next, create a new application under an organisation by clicking on the Create New button.
  • We’ll now find Widgets, APIs, and DB Queries on the left navigation; we can use these features to build our application. We’ll start by creating a Notion API.
  • Click on the + icon next to the APIs and click on Create new and name the API as query_data_from_database
  • Now, add the following in the URL for the API:
  • Here, db-id is the database id for a notion page. To find this, we’ll have to open our Notion Table as a page and pick the database id from the URL.
  • Following is an example URL showing the id of a Notion page.
                                  |--------- Database ID --------|
  • Next, add the following keys under the Headers tab.
	Notion-Version: 2021-05-13
	Content-type: application/json

Below is a screenshot of how the configuration looks like:

Image Four.png
  • Lastly, hit the RUN button, and we can find all the data from our page in the Response Body pane.

Awesome, we now have the response from the Notion API; let’s bind this onto a List Widget.

Binding Notion APIs onto Appsmith

Now that we have an API containing data from the Notion Table let’s bind this onto a list widget to display all the details. Follow the below steps:

  • Select Page1 on the left navigation and click on the + icon next to the widgets section. Now we should see different UI widgets that we can use to build UI.
  • *Based on your preference, you can either choose a table widget or a list widget to bind the data from Notion API. In this example, we’ll be using a List widget.
  • Now drag and drop the list widget onto the canvas; we should see list items filled with Pokemon information. To inspect these, we can click on the cog icon on the top of the list widget and check out the data in the Items property. You can find more information from the docs here.
  • Now, we’ll be using the moustache syntax to write JS in Appsmith, replace the Items property on the list widget with the following code snippet:
In Appsmith, you can access the API’s anywhere inside the moustache syntax using the API name.
    	(item) => {
        	return (

Here, we’re using the query_data_from_database and mapping it to return item properties. This how the response looks like:

Image Five.png

Awesome, now let’s add some widgets onto the list widget and show the details from the Notion API. Drag and drop six text widgets and set its Text property to the following:

- Title
- Description
- Status
- Author
- Email
- Deadline

Add six more text widgets next to them, where we’ll be binding their corresponding values from the Notion API.

Now in the text widget next to the Title text widget, set the Text property to the following:

{{ currentItem.Title.title[0].text.content }}

Here the currentItem corresponds to a unique item in the list widget, and next, we access the Title property from the Items on our list and parse the JSON. Below is the screenshot of how the response looks like:

Image Six.png

Great, we can now see our Titles from the Notion API on items of our list widget; similarly, let’s set the Text property of other text widgets to show the contents from the API:

  • Description text widget set the Text property to:
  • Status text widget, set the Text property to:
  • Author text widget, set the Text property to:
  • EMail text widget set, the Text property to:
{{currentItem["Author Email"].email || "Not Added"}}
  • Deadline text widget set, the Text property to:
  • Category text widget set the Text property to:
{{ => {return row.plain_text})[0]}}
The code for parsing through items changes based on the API response from the Notion API.

We’ve added some additional styles and added a button widget at the end so that admins can send Emails to the authors directly from Appsmith. Below is how the App looks like after we parse all the data from the Notion Table onto the Appsmith List widget:

Notion App Screenshot.png

We can also add a refresh button to the query_data_from_database query. For this, drag and drop the Button widget onto the canvas, set the Label property to Refresh. Next, open the onClick property, click the Call an API option, and select the query_data_from_database API. Now, whenever we click the refresh button, we should see all the new data updated on the Notion page.

Adding an Item into Notion Database

For our content calendar, we can list all the details from the Notion Table. Now let’s add a feature to add new items on the table from Appsmith. Follow the below steps.

  • First, let’s create a new page named “Author Submission” now drag and drop a form widget onto the canvas.
  • Inside the Form widget, let’s add some text widgets and input widgets from which the authors should submit their new content ideas.
  • This is how our form should look like:
Image Eight.png

Following are the fields we’ve created for reference:

Now, let’s name these widgets (so that we can use them to refer in the POST API method) to the following:

Title - titleInput
Description - descriptionInput
Author Name - authorInput
Email - emailInput
Category - categoryInput
Submission Date - dateInput

Let’s create a new API that’ll add a new value to the Notion page when making submissions from the Appsmith form. Follow the below steps:

  • First, create a new API under the Author Submission page and name it as add_an_item_to_database
  • Next, add the following keys under the Headers tab.
Notion-Version: 2021-05-13
Content-type: application/json
  • Now in the body tab, paste the following code:
	"parent": { "database_id": "" },
 "properties": {
           "Author": {
          "type": "rich_text",
          "rich_text": [
              "type": "text",
              "text": {
                "content": "{{authorInput.text}}",
                "link": null
        "Author Email": {
          "type": "email",
          "email": "{{emailInput.text}}"
        "Category": {
          "type": "rich_text",
          "rich_text": [
              "type": "text",
              "text": {
                "content": "{{categoryInput.text}}",
                "link": null
        "Status": {
          "type": "select",
          "select": {
            "name": "Not Started",
    "color": "blue"
        "Description": {
          "type": "rich_text",
          "rich_text": [
              "type": "text",
              "text": {
                "content": "{{descriptionInput.text}}",
                "link": null
        "Deadline": {
          "type": "date",
          "date": {
            "start": "{{dateInput.selectedDate}}",
            "end": null
        "Title": {
          "type": "title",
          "title": [
              "type": "text",
              "text": {
                "content": "{{titleInput.text}}",
                "link": null

This is how Notion API allows us to add new items to a database. Here we'll also have to add the database id in the place of <db-id>. If we observe the body inside each property's content field, we added a moustache operation from which we'll take the input from the Appsmith input forms.

Now open the Submit button’s property pane, update the onClick property to Call an API, and choose add_an_item_to_database API. With this, we should add new data to the Notion table using the Appsmith form!

Send Grid Email Integration

Our content manager now shows all the data and also has a feature to add new content ideas. Now let’s add an email integration to communicate with Authors via Appsmith. We’ll be using Sendgrid to achieve this.

Creating a Modal for sending emails:

  • First, create a new modal when the Send Mail button is clicked on the list item. We can do this by setting the onClick property to Open Modal and selecting Create New.
  • Set the modal type to Form modal by toggle the option in the property pane.
  • Inside the Modal widget, let’s add some text widgets and input widgets from which we should send Emails.
  • Following are the fields we’ve created for reference:
Sending To: Input Widget
Email subject: Input Widget
Email content: Rich Text Editor Widget
  • Now, let’s name these widgets (so that we can use them to refer in the POST API method) to the following:
Sending To: emailInput
Email subject: subjectInput
Email content: contentInput

Below is a screenshot of how the Modal should look like:

Image Nine.png

Configuring the SendGrid API:

  • Firstly, we should have a SendGrid account, and if you don’t have one, you can create a free account here.
  • Next, navigate to the Integration Guide by clicking on the Email API on the left navigation pane.
  • Choose the Web API and choose the cURL language. Now you’ll be redirected to the verification tab.
  • On the verification, tab click on the Create API by giving it a name. With this, we should have our SendGrid API key.
  • Next, open Appsmith and create a new API under Page1, name it as send_email. Set the request type to POST and add the following under the URL form:

Authorization : Bearer 
Content-Type : application/json
  • Lastly, set the body to the following:
{"personalizations": [{"to": [{"email": "{{emailInput.text}}"}]}],"from": {"email": ""},"subject": "{{subjectInput.text}}","content": [{"type": "text/plain", "value": "{{contentInput.text}}"}]}

This is the default configuration from SendGrid that lets us send Emails, but here we are dynamically passing the to-email, from-email, subject and content field from the widget’s we’ve created on the Modal. Now, set the onClick property of the form to Call an API and choose the send_email query. With this, we should be able to send Emails from Appsmith successfully!


Deploy your application on the cloud and share it with others, and that's it. We're done!

We've seen how easy it is to build an application on Appsmith, specifically a CMS with Notion as a backend. This guide covered how to create a CRM and connect it to a Notion API and how to create and read data. You learned how to build interactive pages, work with widgets, and customize them for your purposes.

We have made a slightly more robust application public here; try it out and let us know what you think. You can also check the live demo of our app here.

The Complete Table Widget: Building Complex Tables with Appsmith

The Complete Table Widget: Building Complex Tables with Appsmith

The Complete Table Widget: Building Complex Tables with Appsmith
Vihar Kurama
 minutes ↗

By: Veronica Stork

What Are Web Tables?

Tables are an important component of HTML that allows us to display data in rows and columns. There are several different ways to create tables.

If you don’t have many values to display, you can create your table using pure HTML. This is fairly straightforward but quite cumbersome if you have many values or if your data may change.

Alternatively, a table can be used to display information from a database programmatically or an API. Just fetch your data, then use JavaScript to append table rows for each datapoint retrieved.

If you need more interactivity, you can write JavaScript functions that implement more advanced features such as search and filter. This adds more functionality to your app but also more code and complexity.

When you build your table using these methods, you will also need to style and structure it in a readable way for the user. This is not difficult, but it can be tedious. Ultimately, the minutiae of correctly structuring and displaying your data will eat up time that could be better spent on the underlying logic of your app.

Appsmith to the Rescue

Appsmith is an open-source framework that lets developers build dashboards, workflows, and CRUD apps with only the necessary code. You can connect to any API or databases like MongoDB, PostgreSQL, or MYSQL and get access to multiple widgets, including charts, tables and forms, for building a UI fast.

Using Appsmith allows you to focus on the logic behind your tables instead of fiddling around creating the UI, connecting to the API, and reinventing the wheel in the form of filter and search functions. You can also see your table working in real-time as you build, a feature that is super handy when you’re trying to develop something quickly.

Creating a Table in the Appsmith

  • Firstly, you should have an Appsmith account; if not, sign-up here (it's free)!
  • Next, create a new application under an organisation by clicking on the Create New button.
  • Now, to create a table, first, click the + icon next to the widgets directory in the sidebar.
  • Then, drag the table widget to the canvas. Once it is on the canvas, the table will be pre-populated with dummy data, and the property pane will be open to the right side of the widget.
New table in Appsmith with property pane open on the right side
  • You can rename the table to something descriptive by clicking on the default name in the property pane (Table1 in the above example), then entering your data.

Your data should be an array of objects, with each object representing a row in the table. The object keys represent column names. You can populate your table with data in a few different ways: by typing the data directly into the property pane manually, by importing it from a data source using queries, or by connecting to an API.

Connecting to an API

To connect to an API, hover over the table data field of the property pane, and click on the lightning bolt icon. You will be presented with several options. Choose Use data from an API, then create new API. This will bring up a screen where you can paste the API URL in if you want to know more about creating a new API check out the docs.

Below is a screenshot showing the Table Data property and how we can connect to APIs:

Appsmith table property pane with data options displayed


Appsmith tables include features relevant to some of the most common use cases, including pagination, filters, downloading, searching, actions, and drilling into individual rows of data. You can use JavaScript to customise these features based on different use-cases.


Pagination is often required to display large amounts of data. If you have more data than rows in your table, you will need some way of splitting the data into separate pages. This can be accomplished using either offset-based or key-based pagination.

Offset pagination is based on the table’s page number and page size. For example, if you have a table with ten rows, your app will use ten and the current page number to determine which data to retrieve next. Let’s walk through how to set up offset pagination.

Enable server-side pagination in the property pane of your table. Make a query or API call that utilizes the pageSize and pageNo variables.

Query of users database that uses server-side pagination

Run that query or API call from the table onPageChange.

Appsmith table property pane with the query being run onPageChange

Key-based pagination uses a value returned by the API to make the next page’s API call. If the API’s response includes URLs for the next and previous pages, you can enter those on the API settings.

API settings with key-based pagination enabled and previous and next pages set


Client-side filtering is included in Appsmith out of the box, but implementing server-side filtering requires a few steps. First, create a dropdown widget and fill it with filter values. Then call that API or Query onOptionChange from the dropdown.

Property pane for dropdown widget populated with filter values
Query that returns filtered results

In the above example, we are filtering based on the user status.


As with filtering, client-side searching is included in Appsmith out of the box. To implement server-side searching, you must call the API or query onSearchTextChange from the table and pass in the search box contents, represented by the searchText property.

Query for server-side searching that uses searchText property


Downloading also works with no additional setup: users can click the included download button on a table to download all of its data. You can also bind the download function to an action of your choice and set it to download whatever portion of the data you want.

Property panel with onRowSelected set to download the current row’s data

In the above example, you choose the option to download the currently selected row’s data, but you can specify which portion of the data you want and give the file whatever name you want.


Actions in Appsmith represent ways in which your users can interact with the app and describe what you want to happen when they do. You can set the app to download data (as you saw above), call an API, open a modal, and more. All of the available options are listed when you modify action in the property pane.

Actions include the following:

  • onRowSelected describes what happens when a user selects a row.
  • onPageChange describes what happens when a user navigates to the next page of data.
  • onSearchTextChange describes what happens when a user types in the search bar.

A table is set to display Modal1 when onRowSelected is triggered in the example below.

Property pane with onRowSelected option set to show a modal

Drilling into a single row of data

Drilling into a single row of data is as simple as referencing the currently selected row using the selectedRow property. For example, {{Table1.selectedRow}} targets the currently selected row of our table. You can add a column name to narrow down the targeted data further. In the following example, {{}} targets the name of the user represented by the currently selected row.

Text area using the `selectedRow` property to display the value of the name column from the currently selected row
Modal displaying name obtained from`selectedRow property


Making tables can be time-consuming and finicky, but with Appsmith’s rich table creation tool, you can focus on bigger structural and logical issues while letting it take care of all the nuts and bolts. Writing less code might seem strange at first, but you’ll quickly realize the benefits of working smarter, not harder.

I hope you enjoyed this introduction to Appsmith’s table features, which is just a taste of the whole suite of tools and features Appsmith can provide.

You can check some of the example app's that use the Table widget here. If you found this tutorial helpful, please consider giving us a star on Github.

Connecting Mixpanel, and Active Campaign using Appsmith to engage with your users

Connecting Mixpanel, and Active Campaign using Appsmith to engage with your users

Connecting Mixpanel, and Active Campaign using Appsmith to engage with your users
Vihar Kurama
 minutes ↗

Like most companies, we use analytics and marketing automation software to run our daily operations and engage with different segments of users. We use Mixpanel, ActiveCampaign and for analytics, managing lists and automation, and email engagement.

To determine which users we need to reach out to, we have a report we run on Mixpanel. Sometimes we need to send them a simple email, and sometimes we need to send them an engaging sequence of emails. This decision is again based on the report from Mixpanel. ActiveCampaign helps us with the one-off emails, but we use for engaging and personalised sequences.

This is what the process looks like:

  • Mixpanel reports generating cohorts
  • Feed relevant cohort data to ActiveCampaign for single one-off emails
  • Feed relevant cohort data along with user specifics to for engagement

We’re still young, and we look at most users we want to engage with personally, and doing this manually every day would take a lot of time and workforce. So we ended up building a dashboard on which, with a single click of a button, we can customise and send out emails to our users.

This is what our process looks like now:

  • Look at user details in the Appsmith dashboard
  • Personalise engagement based on an app built, usage and organisation
  • Click on the button to engage the user

It saves us a LOT of time and helps us keep our core focus on our users.

In this tutorial, we’ll be walking through different steps to build such workflows with various APIs and extend them based on our use cases using Appsmith.

Appsmith is an open-source framework that lets developers build dashboards, workflows, and CRUD apps with only the necessary code. You can connect to any API or databases like MongoDB, PostgreSQL, or MYSQL and get access to multiple widgets, including charts, tables and forms, for building a UI fast.

Setting up Mixpanel API on Appsmith

Mixpanel is a product analytics tool that’ll give reports based on defined queries. It also provides API, which we’ll consume on Appsmith to pull out all the reports of users who have invited others. Now, let’s follow the below steps to set Mixpanel API as a data source on Appsmith:

  • Create a new account on Appsmith (it’s free!), if you are already an existing user, log in to your Appsmith account.
  • Next, create a new application by clicking on the “Create New” button under the Appsmith dashboard.
  • We’ll now see a new Appsmith app with an empty canvas and a sidebar with Widgets, APIs and DB Queries.
  • Now, click on the + icon next to the APIs section and choose Create new.
  • Now add the following Mix Panel API endpoint URL in the request input.
  • Click on the SAVE AS DATASOURCE button next to the URL, rename this data source as MixPanel API, and hit Save.
  • Now choose the data source and create a new API; let’s rename it asget_users, add the following route at the end of the URL: /engage?project_id=2032485. This is how our API should look like:
  • Sometimes, Mixpanel APIs might be slow to process; hence we’ll have to increase the API timeout options; we can simply do this by going to the settings tab and increasing the time out to 100000.
  • Lastly, set the request type to POST and hit RUN; we should see the list of users that are inside the Mixpanel report with id 2032485
The API's and ids used in these tutorials are examples created for demo purposes. These do not depict the original data. Feel free to work with your APIs or follow along with these tutorials with the given examples.

Fantastic, we should now see the response from API having a set of users for whom we want to build customised email engagements.

In the next section, let’s show the users on a List widget and customise it based on our UI preferences.

Binding Users onto the List Widget

Let’s use the List widget to show all the invited users from the get_users API endpoint. Follow the below steps:

  • Click+ icon next to the Widgets from the left navigation and drop the List widget on canvas.
  • Now open the list property pane by clicking on the cog icon on the top-right of the list widget. Inside the property pane, we can bind the data and create necessary actions using the pre-defined properties.
  • Now paste the following code snippet into the Items property in the property pane:
{ => ({
    email: r.$properties.$email,
    last_name: r.$properties.$last_name,
    first_name: r.$properties.$first_name,
    lat: r.$properties.clearbit_company_geo_lat,
    city: r.$properties.$city,
    lng: r.$properties.clearbit_company_geo_lng,
    company: r.$properties.clearbit_company_domain,
    country: r.$properties.clearbit_company_geo_country,
  })).filter(r =>;

Above, we have used the moustache syntax and consumed the get_users API, which was defined previously. In Appsmith, we can use the moustache syntax anywhere, anytime and write JS to manipulations. In this case, we are returning the important variables like email, last name, location of user, company to the list.

Following is a screenshot of how the evaluated value looks like after we add in the JS:

CleanShot 2021-06-09 at 01.58.51.jpeg

Now let’s drag and drop a few text widget’s on the first list item and bind the values from the list Items property.

  • Find the text widget from the Widgets section drag and drop four of these; the first two text widgets will act as the Label’s, and the last two will act as the Values from the API.

For the first two widgets, set the values like Name and Email. Next, set the following text Values to {{}} and {{currentItem.first_name + ' ' + currentItem.last_name}} for the other two widgets. Now add one more text widget and customise it with a background colour such that it looks like a button; this is because whenever we click this, we can use the list’s selected item property and show the details of the selected user from the list.

Below is a screenshot of how our list widget looks now:

CleanShot 2021-06-09 at 02.07.57.jpeg

Now, let’s add a Map widget and bind the latitude and longitude to locate the user visually. Let’s follow the below steps:

  • First, find the map widget’s from the widget’s section and drag and drop a new Map Widget next to our user’s table.
  • Now, open the Map’s property and add the following JS in the Initial location property by toggling the JS button next to it:
    "lat": {{users_list?.selectedItem?.lat || 0}},
    "long": {{users_list?.selectedItem?.lng || 0}},
    "title": "{{}}"

Here, we’re setting the initial tag to the latitude, longitude and title from the list widget based on the selected item using the selectedItem property.

  • We’ll also need to set the Default markers to the following:
"lat": {{users_list?.selectedItem?.lat || 0}},
"long": {{users_list?.selectedItem?.lng || 0}},
"title": "{{}}"

This is usually an array that takes details of markers we mark on the map. We need only one marker hence adding only a single object from the selected list item. With this, we should see our map, and when an item is selected, we can see the users' location. Simple right!

Below is a screenshot of the Map widget:

CleanShot 2021-06-09 at 02.22.04.jpeg

Fetch Smartlook Recordings from Mix Panel API

In this section, we’ll add one more workflow where when clicked on a button, we should be redirected to the list-item selected user’s smart look recordings. These smart look recordings are added in a different mix panel API which is protected. Hence we’ll be using an authorization mode to access this API. Follow the below steps to follow:

  • Use the Mixpanel API data source we’ve created before and click Create new.
  • Now, add the following route to the end of the data source: /jql?project_id=2032485, this is how the API should look overall.
  • Now let’s add Authorisation in the headers, copy-paste the below into the key-value pairs:

Authorization : Basic YmZkNDhhYjk1NzcxNTg4NjI0M2VhZDYyNzNhNDhlMTk6

content-type: application/x-www-form-urlencoded

  • Now, navigate to the Body tag and set the type to X-WWW-FORM-URLENCODED and add the following as a key-value pair.
Key: script
function main() {
  return Events({
    from_date: '2021-01-01',
    to_date: '{{moment().format('YYYY-MM-DD')}}',
    event_selectors: [
        event: 'WIDGET_DROP',
        selector: '"{{}}" in properties["$email"]',
        label: 'Invite Graph',

Awesome, this is a custom configuration for our Mixpanel Report to fetch the Smartlook recordings, you can customise this based on your report or use this as an example. Now let’s add a button below the Map widget.

Now, whenever this button is clicked, we should be redirected to the Smartlook URL of that particular users. Hence, we have to use JS to solve this. Now drag and drop a button widget beneath the map widget and set the onClick property to the following:


Here, when the button is clicked, we navigate to a new page, and the target link is the link that’s returned from the get_recording. We’ve done some additional parsing to fetch the smartlookPlayUrl property.

If the API’s are slow, we can always increase the Timeout.

Sending Customised Emails to the Users

In this section, we'll be using the APIs of to send emails to the users shown on the list.

First, let’s make a simple UI, we’ll have a button labelled, send Email when clicked these email campaign should start.

For this, we'll be needing to create two APIs; follow the steps below:

1. Fetch the Emails from Appsmith API

In this step, we'll have to fetch the profiles from the Appsmith account. Hence, we need to consume one of our Appsmit APIs and pass in the Email that's selected on the list widget.

  • First, let's create a new API called get_user and set the URL as follows:{{}}
  • Here, user_list is the name of the list widget, and we're binding the selected email using the moustache API.
  • This API is secure, hence, we'll need to add an API key in header, in our case, it's Api-Token and the value is a60fdd2cb979167412b0a4daa60de8837db13f08538e7221e0d63126a7163c795eb04f7a

2. Send Email

Now, let's create one more API with to send customised Emails by clicking a button widget.

  • Create a new API and name it as send_email and set the URL as follows:
  • In the header, we'll need to add the API keys that can found in the dashboard.
  • Now in the body, we take the inputs from the form widget and then run the API's to send the emails. Below is the JS.
    campaignid: 558301,
    lastName : {{users_list.selectedItem.last_name}},
    firstName: {{users_list.selectedItem.first_name}},
    email: {{}}

Now set the button onClick property to the following JS:

{{ =>
      () => showAlert("Reached out to user", "success"),
      () => showAlert(, "warning")

Here, we’re fetching the users and sending them the Emails using a campaign that's already created!

Wrapping Up

Deploy your application on the cloud and share it with others, and that's it. We're done!

You've seen how easy it is to build a customised workflow on Appsmith. Similarly, we can integrate the number of APIs and data sources and build customised dashboards.

If you like this tutorial, drop us a star on our GitHub repository here

Test and Deploy your APIs Using These Open Source Tools

Test and Deploy your APIs Using These Open Source Tools

Test and Deploy your APIs Using These Open Source Tools
Vyom Srivastava
 minutes ↗

Testing an API is one of the most important phases of the API development lifecycle. It ensures that the API you’re deploying on the server is bug-free and highly optimized. But the testing phase can be very complex as it involves different types of testing, such as load testing, regression testing, security testing, etc. There are a lot of challenges developers and testing teams face during the testing of API. Let's discuss them first:

Why is API Testing a Difficult Task?

We all know that APIs involve a lot of modules that have a lot of functionalities. Let’s take a simple example of an e-commerce application. You’re going to have many endpoints such as /login, /logout, /cart, /wishlist, /profile, and so on. You need to ensure that each endpoint is delivering what it is supposed to. For example, /cart should only show products associated with a particular profile and shouldn’t mix with other products.

An application like the one mentioned above can have about 300-400 endpoints or sometimes even more! On top of that, you need to make sure that the validations are working fine, response time is low or at least optimized, there’s no bug in the API, and good performance even when 1000s of requests are being made simultaneously. You also need to ensure that the API returns an appropriate status code such as 20x, 40x, 50x, etc. All this makes API testing not only tricky but also a time-consuming task.

To reduce the complexity of the whole testing and deployment process of the API, there are a lot of open-source tools available on the internet (if you prefer non-open-source tools, you can check out Postman or Firecamp ). These tools not only save a lot of time but also give you insights like the response time of the API, among others.

Once you’re done with testing, you can deploy the API on a server. Deployment is the process where you’re ready to go live with the API and need to move it to the live server. Every time you make a change to the API, you need to redeploy the API on the server (after testing, obviously! 😬)

Here's our list of open source tools that you can use to test and deploy your API:


Screen Shot 2021-07-27 at 10.54.02 PM.png

SoapUI is another API tool that allows you to test and deploy your APIs. This is one of the most matured and trusted API testing tools. One of the unique features of this tool is, it supports SOAP APIs too. The tool is mainly used for QA and API testing. It also allows you to connect external data sheets to retrieve data for executions.

Soap UI also allows you to send multiple API requests; triggering a single test case and supports a wide variety of testing such as load testing, functional testing, security testing, etc.


  • Easy to define variables and pass them in parameters.
  • Support for SOAP API


  • Slower to perform tests on complex APIs
  • Not completely free
  • UI takes a little bit of getting used to

Apache Jmeter

Screen Shot 2021-07-27 at 10.58.03 PM.png

Apache Jmeter is an open-source testing tool that not only tests APIs but scripts too. You can create your own test cases, and it’ll perform different types of testing like module testing, regression testing, etc.

The UI is quite simple and easy to use. You can test the APIs in two ways: either use direct API requests or write a code to make the requests to an API endpoint. The tool is entirely written in Java and supports multiple languages such as Python, C, Java, etc.

It also comes with a marketplace where you can just download the plugins to expand the platform’s functionalities. It supports multiple protocols such as FTP, HTTP, LDAP, SOAP, etc. JMeter also supports graphs and charts, so the results can be visualized easily. To perform UI testing, you can run Selenium test cases as well.


  • Free to use and completely open source
  • Can be connected to third party platforms like Jenkins
  • Can be scaled easily
  • Marketplace is a unique feature


  • Very slow
  • UI is dated


Screen Shot 2021-07-27 at 10.59.48 PM.png

Hoppscotch, previously known as Postwoman, is another popular open-source API development and testing platform. It has a dark UI and a minimalistic design scheme. It is one of the fastest API testing tools allowing you to send requests and copy responses in real-time.

It comes with a variety of themes and you can even install it as a PWA (Progressive Web App) on your mobile device. The tool also lets you make a full-duplex communication channel over a single TCP, in other words you can make Websocket connections. Another big feature of this tool is that you can also test GraphQL queries.


  • Support for Websocket
  • PWA
  • Easily create documentation


  • Comes in web variant only
  • It doesn’t support testing like regression, load, etc


Screen Shot 2021-07-27 at 11.07.24 PM.png

This platform has been developed by Intuit and is used for multiple purposes like API testing, deployment, creating mock test servers, web browser automation, etc. It is written in Java but doesn’t require the end-users to write anything in Java. It’s so easy to use that even non-programmers can write the test cases. It supports YAML as andV, so you can easily use them to write data drives tests. You can also perform cross-browser-based Web UI testing.


  • Support for multiple testing
  • Includes a lot of functionalities


  • It doesn’t have a great UI so you might have to write a lot of code


Screen Shot 2021-07-27 at 11.08.14 PM.png

Insomnia is another open-source tool that lets you track the development and deployment of API endpoints very easily. It uses a Swagger-inspired editor, so if you’re familiar with it you’ll be able to easily use this tool.

It allows you to import API specs from OpenSpec API as well as Postman. It also comes with a CLI tool called Inso, which lets you go in-depth with the API testing. You can also connect version control software like GitHub, Bitbucket, SVN, etc.


  • Support for .env files
  • Support for Gitsync


  • Process to test the API is a bit lengthy

What’s Next?

Now that you’re equipped with your APIs, you can use Appsmith to create full-fledged applications by connecting your data to our extensive repository of pre-built UI widgets like forms, buttons, lists, maps and so much more. And since Appsmith is a GUI based platform, you can drag and drop these widgets to create your applications. You can also invite your colleagues to collaborate with them and then deploy it to be shared with internal or external users.

Psst! You can connect your data on Appsmith either through APIs or through our native integrations with popular databases like Postgres, MongoDB, and Snowflake, among others, as well as apps like Google Sheets!


Also, by running CURL commands directly on the platform, you can test and deploy your apps easily and quickly.

Are you interested in building something with Appsmith? Take it for a spin. Join our vibrant community on Discord. To get regular updates on what we’re up to, follow us on Twitter!

Building a Shopify Admin Panel: A Step by Step Guide

Building a Shopify Admin Panel: A Step by Step Guide

Building a Shopify Admin Panel: A Step by Step Guide
Joseph Petty
 minutes ↗

Hey everyone! Joseph here from GreenFlux, LLC. I'm a Shopify Partner Developer and a HUGE fan of Appsmith! 😻

In fact, I've written several blog posts on Appsmith integrations already, but today will be my first post officially written for Appsmith! I'm super excited to be working with the Appsmith team and sharing my API integration experience with the community.

I've done a lot of work with the Shopify API over the last few years, but only recently discovered Appsmith. So I wanted to put together this guide with some specific use-cases that help solve some common business problems.

but before I get to those specific use-cases...

This guide is written for the Shopify API, but the build process can easily be applied to any API.

The Authentication steps may be different, but most of this guide will work with any API to:

  • Perform CRUD (Create/Read/Update/Delete) operations with the API directly
  • Download/sync API-GET request to Google Sheets
  • Find/Modify/Delete a row in Google Sheets based on API data
  • Send data from Google Sheets to Shopify (Create, or Update existing)

Now for the specific use-cases

Most shops only take orders for products that they have in inventory, then ship them out as the orders come in. But some businesses wait to begin 'creating' the product until an order has been placed. Think T-shirt printing, custom-built bikes/skateboards, and even wholesale produce and flowers that are only harvested after an order is placed.

That creation/ harvest process can have several steps and require multiple employees, and even have an approval process with different access levels. Lots of industries are creating products to-order, and need a way to track this process without sharing the Shopify admin login to all users.

☝️ So let's say you have a Shopify store that sells high-tech vehicle upgrades! 🛸

And you have a team of workers in three departments:

[Assembly, Quality Control, Shipping]

Use CaseDescription
Case 1
Track production with Google Sheets data linked to each order
Case 2
Safely enable workers to edit orders (mark shipped) without sharing Shopify login

Let's get to building! 🛠

Start by creating a Google Sheet for Workers and another for Assignments. Or you can copy this public sample sheet .

2021-08-31 08.33.42.gif

Next, you'll want to enable the Shopify API.

  1. Login to Shopify and click Apps on the left sidebar
  2. Scroll down and click manage private apps
  3. Create a new private app
  4. Click Show inactive Admin API permissions to expand
  5. Select: Orders = Read and write
  6. Save and note the new API Key and Password

Ok, on to Appsmith

Add Shopify Datasource

  1. Create a new App (from Drag & Drop)
  2. Under Datasources, create a new Authenticated API
  3. Set the URL to

      4. Set Authentication Type to Basic

  1. Enter the API Key (as the username) and the password, and SAVE.

Screen Shot 2021-08-29 at 9.49.36 AM.png

Add Query

Next let's create our first query to GET orders.

  1. Under the Shopify datasource, add a new Query named get_orders
  2. Append the URL with orders.json
  3. Click RUN.
Screen Shot 2021-08-29 at 9.52.00 AM.png

Awesome! Our new app is now making authenticated API calls to Shopify and returning data.

  1. Note the response format; All orders are nested inside the "orders" property.

Copy the API and rename get_products, then change orders to products in the endpoint URL.

Screen Shot 2021-08-30 at 5.11.45 PM.png

Next, let's add a few widgets to display the data

Add Table Widget

  1. Click the Widgets + on the left sidebar, and drag in a new table widget
  2. In the table's settings panel, click the / (Slash) command
  3. Select the get_orders API.
  4. Add .orders to bind the Table Widget to the order array from response body.

Alright, now to connect the Google Sheet data.

Add Google Sheets APIs

If this is your first time connecting Google Sheets to Appsmith, start out by adding a new datasource:
Datasources + > Create New > Google Sheets
Appsmith Docs
Then follow the prompts and authorize Appsmith to connect to your Google account.
  1. Add new Query under Google Sheets datasource, named get_workers
  2. Enter URL for your spreadsheet
  3. Enter worker for the sheet name
  4. Set Row offset to 0 and Row Limit to 50.
  5. RUN.
Screen Shot 2021-08-30 at 4.55.38 PM.png

Next, copy the get_workers API, rename get_assignments and change the sheet name.

Screen Shot 2021-08-31 at 6.09.29 AM.png

Ok, so far we have GET requests working to Shopify and Google Sheets.

Go ahead and add a few more Table Widgets for Workers and Assignments using the same method above.

Now we need a way to feed the get_orders request to the orders sheet.

Add a POST (Create) API for Google Sheets

Appsmith has a full list of methods available for performing CRUD operations with Google Sheets. We could use Insert sheet row to add orders one at a time, but the get_orders API returns an array of orders.

Now, the Bulk Insert Rows method expects an array of objects, with keys that match the the sheet's column names:

  ...{more objects},

And the map() method returns an array.

So we can map()! over the get_orders data and build our rows.

Detailed explanation here:
  1. Copy the get_assignments API and rename create_assignments
  2. Change the method to Bulk insert rows
  3. In the Row Object, enter:
o => {
return {'id', 'email', 'products' =>};

4. RUN 🚀

Screen Shot 2021-08-31 at 7.22.49 AM.png


All open orders are saved to Google Sheets with a single click!

giphy (3).gif

But what happens when we run it again?

Uhhh... now I have two copies of every order.

giphy (2).gif

Hmm... we need a way to tell Shopify what orders we already have, and only download new ones!

Passing values from an API response to a new request

Here's where things get interesting. First we have to get_assignments, then find the max order number that's already in our sheet, and finally, send a new request to Shopify to get new orders after that order number.

Shopify API docs

We can use the since_id parameter to filter the orders that are returned and then save only new orders back to the sheet.

First we need to know the last order number from our sheet. I like to store these values into a separate widget, so I can reference just the name, instead of trying to insert a whole function in place of the ID in the URL.

  1. Add a Text Widget named maxId
  2. Set the Text value to:
 o =>{ return}

3. Update the get_orders API endpoint

This will produce an array of all order ids, and then sort them in case any of the rows are stored out of order in the sheet. The default sort order is low to high, so reversing and taking the first (zero index [0]) item returns the max value.
Screen Shot 2021-08-31 at 8.10.53 AM.png

Now we're getting somewhere. We can continuously download orders to the order sheet, but what about updating individual rows?

First let's add a few Widgets to view/edit the selected assignment. I've added a Container Widget to the right of the table_assignments, Text Widgets to display the Order# and Products, and Input Widgets for the Worker and Instructions.

Now we can reference the table_assignments.selectedRow properties to populate the default values for our Widgets. This will update the Widgets automatically when the selected row is changed.

Screen Shot 2021-09-02 at 5.44.49 AM.png

Next, let's add a few Widgets to set values in the assignment sheet.

First we want to add a Select Widget (dropdown menu) with all the workers. The Options should contain an array of objects with label and value properties. (literal array, or expression that returns an array).

So you could hard-code the Select Widget's Options:

    'label': 'Worker1',
    'value': W00001'

...but wouldn't it be cool if our dropdown could automatically show all the current workers from our workers sheet?!

    w =>  {return {,}
Screen Shot 2021-08-31 at 4.38.57 PM.png
giphy (4).gif


Time to test out these new input fields!

{dividerUpdate a row in Google Sheets

  1. Copy the get_assignments API and rename update_assignment
  2. Change the method to Update a sheet row
  3. Copy a single object from the get_assignments response to the update_assignment Row Object
  4. Add commas between properties
  5. Add references to the new Widgets' text values
Screen Shot 2021-09-02 at 6.18.56 AM.png
NOTE: I removed the id and products because these should not be edited once downloaded. Our template is only for updating the worker_id and associated timestamps/ instructions.

Fulfill an Order in Shopify

Ok, we're almost there! The last piece we need is a way to fulfill an order in Shopify.

NOTE: Orders can have multiple fulfillments per line item and different status for each fulfillment. To keep this example simple, our app is going to create a single fulfillment per order and ignore partial fulfillments.

This step will be using the /fulfillments.json endpoint, and we need the location id. You can get this through the API, but the easiest way is to view the location and get the id from the URL.

  1. In Shopify, click Settings on left sidebar
  2. Click Locations
  3. Click the location you want to use for fulfillments
  4. Copy the id from the URL

We want the employees to be able to select a row in the app and click 'Fulfill Order' without giving them full access to the Shopify admin account.

In other words, we want to use data from the selectedRow of the table_assignments to send a POST request to Shopify.

  1. Under the Shopify datasource, add a new Query named create_fulfillment
  2. Set the URL to orders/{{Number(}}/fulfillments.json
Screen Shot 2021-09-02 at 6.23.11 AM.png

3.Set the body to:

"fulfillment": {
 "location_id": YOUR_LOCATION_ID,
 "notify_customer": true

4. Add a button to run the create_fulfillment API

  1. MAKE IT SO! 🛸
Screen Shot 2021-09-02 at 6.01.21 AM.png

WHEW! What an adventure!

Thanks for taking this journey with me on my first official Appsmith post!

This is just a small sample of the awesome power of Appsmith. There's so much more we could do from here, like connecting another API and sending Slack messages or emails to each worker when an order is assigned, emailing customers pictures of the products during production, or calculating average processing times per worker or product.