Actions

Actions

Actions

Actions allow admins to create predefined Web requests which take user-provided inputs.

Once you’ve defined an Action, you and your team can execute the predefined Web request by providing values to the inputs and submitting them to be run via button click.

Overview

💡
Basedash started out as a Web app that can talk to SQL databases. Now, with Actions, Basedash can talk to Web servers too.
  • Actions can be created by admins, and can be run by:
    • Admins, or
    • Users with "Can edit" permissions
  • An Action an admin-defined Web request, which can target:
    • Your own Web server, or
    • A 3rd party Web server
  • An Action can take, and be run with, admin-defined inputs
    • These inputs can be set to come pre-filled, for the user who goes to run the Action
    • Upon running the action, our back-end constructs a Web request based on the Action's definition and the submitted values of the inputs
    • Inputs can be wired up to pass their submitted values to the URL, headers, and/or body of the Web request to be executed
  • An action can be associated with a table from one of your SQL database connections
    • In this case, the Action becomes available to be run with values from a selected record when working in a view based on that table
    • Additionally, the action's pre-fill values can incorporate values from the selected record
⚠️
Caution Actions execute Web requests with user-provided input targeting your own server, or a 3rd party server. It is important to ensure only trusted parties maintain and use the Actions you create.

Step 1: Add an API connection to Basedash

➡️
You must be an admin to setup API connections

If you haven't yet added an API connection to Basedash you'll need to do that first.

As an admin, you can add an API connection either:

  • From your Workspace via “Add connection”
  • From within an App, when adding an Action, you'll be prompted to select an existing API connection, or if you have none, to proceed to creating one. (See below screenshot)
  • image
  • Once created, API connections appear in the sidebar from your Workspace. (See below screenshot)
  • image

An API connection provides the foundation for one or more Actions

  • An API connection defines:
    • A base URL, e.g. https://www.example.com/api
    • Zero or more request headers, e.g. Authorization Bearer 12345678-9876-pretend-example-token
The request headers you define for an API connection end up being sent with all Actions using that API. Think of these headers as being "common" across all endpoints of that API.

So, the idea is that, for a given API, you can setup multiple Actions that each define a path to a specific endpoint on that API.

Here’s a screenshot of the UI for creating/updating an API connection

image

For example, if the API's base URL is https://www.example.com/api, and if the Action's URL path is /widgets/go then you end up with them being joined together into a full URL like so: https://www.example.com/api/widgets/go

To further illustrate, imagine that following endpoints all share the same base URL and all share the same common headers (provided by the API connection). You could end up with a collection of endpoints like so:

  • https://www.example.com/api
    • /widgets/go
    • /collections/archive
    • /users/{{ userID }}/settings
    • /widgets?id={{ widgetID }}
    • ...

The building blocks of an HTTP request

Keep in mind that an Action isn't really enough by itself, it needs to pair with one of your API connections. Taken together they provide:

  • The API connection provides:
    • The Base URL
    • Common request headers
  • The Action provides:
    • The HTTP method
    • A URL path
    • Endpoint-specific request headers
    • A request body
📒
What you are defining with an API connection plus an Action is ultimately just the recipe for an HTTP request consisting of:
  • An HTTP method (specified in the Action)
  • A URL (built from the chosen API's base URL joined with the Action's URL path)
  • Request headers (some of which you can define as part of the API, some of which you can define as part of the Action)
  • A body (optional text to be sent as the request payload)

Step 2: Create an Action

➡️
You must be an admin to create or update Actions

Here’s a screenshot of the Action builder interface:

image
Screenshot legend:
1) Action name
2) HTTP method
3) Base URL (from the chosen API connection)
4) URL path
5) Interpolation helper
    (a popover available in multiple places in the Action builder)
6) User inputs
7) Request headers
    (including those that come from the chosen API connection)
8) Request body
    (can be empty)
9) Preview area
    (As you define the Action you'll see it reflected here)
10) cURL area
    (Values from the preview inputs will be reflected here)
History pane (not pictured)

Now that you’ve had a chance to look over the UI, here’s a walkthrough of each step to create an Action:

  1. Select the HTTP request method from the dropdown (e.g. POST)
  2. Select the Base URL (defined in your chosen API connection, see ”Adding an API connection” above)
  3. Optionally provide a URL path to be joined with the Base URL
🪄
In the field for the Action’s URL path you can interpolate values from the Action’s User inputs using the double curly bracket syntax, e.g. {{ userId }} (More details in the below section, “Variable interpolation”)
  1. Provide a short, descriptive Name for your action
  2. Optionally, choose an Associated table from one of your SQL database connections
🪄
If you choose an Associated table for your Action, then the Action can be run from the right sidebar when you select a record from within one of your views. Furthermore, the User inputs for the Action can then be prefilled with values from the selected record. The Prefill value of a user input can take data from the selected record via interpolation using the double curly bracket syntax, e.g. {{ User.fullName }}. (More details in the below section, “Variable interpolation”)
  1. Optionally provide Button text to be seen on the button your users use to ultimately run the action
  2. Provide a detailed Description to be presented to users of the Action
    1. The Description text ends up presented above the User inputs when going to run the Action
    2. You can include links in the description (e.g. to your own documentation, or to documentation about the endpoint) and they will be rendered as links for users of the Action
  3. Define one or more User inputs
    1. Click the “+” button to the right of the User inputs section heading
    2. Provide a Label for the input
    3. The Identifier will be automatically generated based on the Label
    4. 🏷️
      The Identifier is used as a handle for interpolating input values into the following parts of the Action: - URL Path - Header values - Body (More details in the below section, “Variable interpolation”)
    5. Choose a Type for the input (text or textarea)
    6. Optionally provide some Prefill text, which will be used to prefill the input for the user going to run the Action
    7. 🪄
      If the Action is associated with a table from one of your SQL connections, in the Prefill text you can interpolate column values using the double curly bracket syntax, e.g. {{ User.fullName }} (More details in the below section, “Variable interpolation”)
    8. Optionally provide some Helper text which will be displayed adjacent to the given input for the user going to run the Action
  4. Define one or more Headers
    1. 📒
      The Headers defined in an Action are specific to the Action being created. They get included with the Web request along with any “common” headers which come from the chosen API connection (See above section on “API connections”)
    2. Provide a Name for the header
    3. Provide a Value for the header
    4. 🪄
      In a header’s Value you can interpolate values from the Action’s User inputs using the double curly bracket syntax, e.g. {{ userId }} (More details in the below section, “Variable interpolation”)
  5. Optionally define a Body for the Action
    1. The Body is the plain-text payload for the Web request to be executed
    2. It might be a JSON string, or delimited key value pairs, or something else, depending on the type of payload expected by your endpoint
    3. 🪄
      In the Action’s Body you can interpolate values from the Action’s User inputs using the double curly bracket syntax, e.g. {{ userId }} (More details in the below section, “Variable interpolation”)

Working with the Preview area

As you’ve been authoring this Action, you will have seen your changes reflected in the Preview area on the right.

  • You’ll see a preview for User input fields appearing on the right in the Preview area.
    • You can try running the Action from there in the Preview area (but if you have unsaved changes you’ll need to save first).
  • You’ll also see a snippet of shell script with a curl command.
    • You can use this to get an idea of the ultimate Web request that will be executed.
    • You can copy and paste it into a terminal and try running it with test data to see how the endpoint responds. This can be a useful tool for development, debugging, and testing.
    • The curl command can help to diagnose issues, to see whether the issue is with the Web request itself, or possibly with Basedash’s execution of the Web request (in either case, please don’t hesitate to reach out to us for support anytime).
    • You can type values into the User inputs of the preview area and see them reflected in the curl command via interpolation

Saving and testing your action

  • As you build up your Action, note that changes are not saved until you hit the “Save” or “Done editing” button in the header.
  • If you click “Save”, your Action will be saved, but you’ll remain in Action builder. You can try inputting values and running your Action there from the Preview area. You’ll also see warnings for common issues with defining an Action.
  • If you click “Done editing”, you’ll be taken to the Action page for the action you’ve created
    • Try running your Action there and seeing the response
    • Click the “Edit” button to return to the Action builder and modify, and then save again, and repeat.
👋
Please don’t hesitate to contact us for support if you encounter any issues or would like assistance with your API, your Action, or the Web request you’re trying to construct.

Explainer: Variable Interpolation

➡️
This section is for admins. (It explains a key concept in building Actions, and you must be an admin to build and modify actions)

An Action can be thought of as a function which takes User inputs in order to do its work. The work, in this case, is formulating and executing a Web request. Your job is to define how the inputs will get passed through to the Web request to be executed.

Think of each User input as a variable. The mechanism of resolving the value of the variable and passing that value through is with string interpolation.

  • Say you have a variable userName, and you want to put the value of that variable into a message.
  • You can write the message like so: "Hello, {{ userName }}. How's it going?".
  • And then, when you execute the interpolation (say with a value for userName of “Louis”), then what you get is the message: “Hello, Louis. How’s it going?”
🪄
For interpolation, Basedash uses a double-curly bracket syntax.
  • Say you have a variable userName, and you want to put the value of that variable into a message.
  • You can write the message like so: "Hello, {{ userName }}. How's it going?".
  • And then, when you execute the interpolation (say with a value for userName of “Louis”), then what you get is the message: “Hello, Louis. How’s it going?”

Case 1: Interpolating User inputs into the Web request

Recall, when you define a User input for your action, you give it a Display name and then, an identifier is generated for you. Say the Display name is “User ID”, then the identifier would be userID. So, you can now use that identifier as a variable, and you can include it in one of the following three parts of the Web request.

  1. The URL path
    • e.g. /users/{{ userID }}/settings
  2. The Value of a request Header
    • e.g. Say you add a custom Header whose Name is User-ID, then you could set its Value to be {{ userID }}
  3. The request Body, e.g.
  4. {
      "renew": true,
      "userID": {{ userID }}
    }

Then, say that a user going to run the Action would provide a value of 42 to the “User ID” input:

  • The request URL would end up like: https://www.example.com/users/42/settings
  • The request header would end up like: User-ID 42
  • The request Body would end up like:
  • {
      "renew": true,
      "userID": 42
    }

Case 2: Interpolating column values to be “prefilled” into a User input

➡️
This case is only possible if you have chosen an Associated table for your action. (See the following section about “Associating a table with your Action”)

Recall that when defining User inputs for your action, you can stipulate text to be prefilled into them, when a user goes to run the Action. Supposing you have chosen an Associated table for your action, then you have the ability to interpolate use columns from that table as variables for interpolation.

For example, say you’ve chosen a table called Subscriber from one of your SQL database connections (imagine it has columns such as fullName, email, renewsOn, etc.). And say you’ve defined a few User inputs for your Action like so:

  • A User input called “Message”:
    • You could define the Prefill text to be Hello, {{ Subscriber.fullName }}, thank you for signing up.
  • A User input called “Email”:
    • You could define the Prefill text to be {{ Subscriber.email }}
  • A User input called “Plan renewal date”
    • You could define the Prefill text to be {{ Subscriber.renewsOn }}

Then, when a user goes to a view (one based on the Subscriber table) and then selects a given record (imagine they’ve selected a subscriber named “Amelia”), and then opens up the Action there, then all these inputs, “Message”, “Email”, and “Plan renewal date”, will be prefilled with the text you’ve defined and with the variable values interpolated, like so:

  • “Message” would be prefilled with e.g. “Hello, Amelia, thank you for signing up.”
  • “Email” would be prefilled with e.g. “amelia@example.com”
  • “Plan renewal date” would be prefilled with e.g. “Jul 26, 2022”

The user going to run this Action still has the ability to change the values for these inputs before clicking the Run action button, but the fact that they come prefilled, could help out with efficiency and accuracy for Actions where specific values from a selected record are to be used as inputs.

🪄
Not only can columns from the Associated table be used as variables for the prefill text for User inputs, but columns from joined tables may be used too (Assuming the view is built with the tables in question joined together)

Use with caution!

🚨
Passing through user-provided inputs to a predefined Web request provides a lot of power and flexibility, but opens up certain risks. It is important to ensure only trusted parties manage and use the Actions you create.

Imagine the following scenario:

  • You have an endpoint which deals with a resource called “collection”
    • The route for this endpoint is https://api.yourcompany.com/collections/:collectionId
  • You create an Action which would take the “Collection ID” via User input (with variable identifier collectionID) and pass it through to the URL
    • You’ve setup your chosen API connection to have the following Base URL: https://api.yourcompany.com
    • You define the URL path for your Action to be /collections/{{ collectionID }}
  • Then, someone goes to run the action, and they are asked to provide a value for the “Collection ID”
    • Normally, they would pass an ID like 42
    • But, what if they passed the following: /72/widgets/128?!?

In this scenario the resulting Web request from the Action gets executed with the following URL:

  • https://api.yourcompany.com/collections/72/widgets/128
  • If a “Widget” is in fact a nested resource within a “Collection”, then you’ve got a problem. The Action is ultimately targeting a certain widget, even though the author of the Action intended it to target a certain collection.

Step 3: Run the Action

➡️
Actions can be run by admins, or teammates with “Can edit” permissions

From within one of your Apps, you will see your actions listed in the left sidebar.

  1. Select an Action to go to its corresponding Action page (see screenshot)
  2. image
    Not pictured: You can view the history of runs of the action in the sidebar on this page.
  3. Provide values to the User inputs
    1. Depending on how the Action has been authored, they may be prefilled
    2. You can modify any of the values of any of the inputs as you like. If you want to discard what you’ve put in the inputs and return to the initial prefilled values you can refresh the page
  4. Review the values of your inputs, and then click the Run action button below the inputs (button text may be customized by the Action’s author)
  5. Wait for response from the Web request to appear in a toast message in the bottom-right corner of the window

Alternatively, in the case where your action has an Associated table, you can call up the view from within one of your corresponding views (where the view is based on the SQL table in question) like so:

  1. From your chosen view, select a record
  2. You should see the Record details appear in the sidebar. If the sidebar isn’t expanded, click the left-arrow button to expand it
  3. You should see the Available actions for the view. (See below screenshot)
  4. image
  5. Choose one of the Actions, and you will then open up the Action runner, and any Prefill values for the User inputs which were written to take data from the selected record, should have that data incorporated. (See below screenshot)
  6. image

Coming soon

Basedash Actions are just getting started. Here’s some of we’re working on:

  • Ability to see history of Actions run in your workspace via our Activity feed
  • Ability to customize which Actions appear on a given view
    • Currently, for an Action which is associated with a particular SQL database table, that Action would appear in the "Record details" sidebar on all views based on that table.
  • More robust handling of whitespace and quotes
    • Currently, there is little flexibility for formatting of the body of the Web request and how inputs are passed
  • Ability to specify different body types, such as:
    • raw
    • form-data
    • GraphQL
    • JSON
  • More detailed error messages when an action fails to run
  • Richer UI for handling the response from the Web request
    • e.g. prettified JSON
  • Better interpolation flow (e.g. autocompletion)
  • Warnings for issues in the Action builder interface
  • Ability to define User inputs which are, locked, and/or hidden
  • Ability select a record from the Associated table from the Action page
    • Currently the only way to run an Action with values from a selected record is via a view)
  • Ability for admins to manage "secrets" in a more discreet way
    • Currently, if you define an API or an Action that requires credentials, e.g in a request Header, you have to put your credential there in the Basedash UI, and it is from then on visible to admins.
  • Pull in data for a view from an API call (e.g. via an endpoint which returns a payload of JSON items)
  • Better support for HTTP Basic authentication for an API connection
💠
https://www.basedash.com

© BaseDash Inc.