Airplane quickstart guide
Build a multi-step workflow in under 15 minutes
This guide will walk you through using Airplane to set up an example task and runbook to give you a
rough sense of the Airplane platform. We'll end up with a runbook that deletes a user and sends out
a link to a temporary archive of their data. Along the way, we'll explore a couple of key Airplane
features including adding parameters, deploying code, and referencing output.
Our use case
We're going to create a workflow in Airplane that lets non-engineers perform a "delete user"
operation. This is a common use case for Airplane. Companies need to delete users due to GDPR or
CCPA reasons, and being able to deploy a script to Airplane that performs this operation lets
non-engineers perform the task safely.
First, we're going to create a task in Airplane that performs a user deletion. Then, we'll build
a runbook that uses that task and also sends out a Slack notification afterwards.
Create a task
We're going to create a GDPR deletion task that deletes a user's data by looking up their email.
Tasks can either be created through the web UI or through the
Airplane CLI. In this guide, we'll use the web UI for convenience.
Start from the Library page on Airplane. From here, click
Create a task
to reach the new task page and select Node from the options.
In this tutorial, we're going to select Node. For this user deletion task, we want to write a custom
JS script that hits a deletion endpoint that we've already defined.

Define your task
Fill in the task definition form with the following values:
- Name: Delete user by email
- Description: Permanently deletes a user who has a matching email
- Folder: Ignore this for now
Since we're using the user's email to determine which user to delete from the system, whoever runs
this task will need to input the user's email. Let's add a
parameter that represents the user's email. Click
Add parameter
and enter the following information:- Name: User email
- Description: The email address of the user to be deleted
- Type: Short text

Once you click the
Add
button, it will take you back to the task definition screen where you can
now see the parameter you just input listed there along with the task name and description.
Once the fields under the task definition screen have been completed, click
Continue
.Build your task
Since this is a Node script, we can add in
environment variables or select the
version of Node that we want to use to run this script. For this tutorial, the default Node version
will be sufficient, and we don't need any env vars.

Task advanced settings
The next screen displays "Advanced settings". You can set explicit permissions here and assign users
and groups to specific roles, such as admin or requestor. Let's leave these as team access for this
task and click
Create task
.
You've created the task but there's no code backing the task yet! Now we'll write and deploy some
JavaScript to implement our code.
Using the CLI to deploy your task
After you click
Create task
, you'll see a short list of instructions on how to deploy the code.
If you haven't yet, first install the Airplane CLI (
airplane
) by following the
installation instructions.Once you've installed and logged in to the CLI, create an empty folder and navigate inside it.
bashCopied1mkdir airplane_test2cd airplane_test
From within this directory, you can run the
init
command shown on the task page:bashCopied1airplane init --from delete_user_by_email
Enter a name for the script and the definition file. The script contains the task code
(
delete_user_by_email.js
) while the definition file contains task metadata
(delete_user_by_email.task.yaml
). Press ENTER
to stick with the default filenames.To use TypeScript, use a
.ts
extension instead of .js
for the script.Once the initialization is complete, you'll have two new files that represent your new Airplane
task.
Definition file
The definition file (
delete_user_by_email.task.yaml
) contains the task metadata that we set up in
the web UI. It will look something like this:yamlCopied1name: Delete user by email2slug: delete_user_by_email3description: Permanently deletes a user who has a matching email4parameters:5- name: User email6slug: user_email7type: shorttext8description: The email address of the user to be deleted9node:10entrypoint: delete_user_by_email.js11nodeVersion: "18"12timeout: 3600
Script
The file
delete_user_by_email.js
contains the actual Node.js script. It looks something like this:javascriptCopied1// Put the main logic of the task in this function.2export default async function (params) {3console.log("parameters:", params);45// You can return data to show output to users.6// Output documentation: https://docs.airplane.dev/tasks/output7return [8{ element: "hydrogen", weight: 1.008 },9{ element: "helium", weight: 4.0026 },10];11}
For Node.js scripts, Airplane looks for the default export function and calls it. The first
argument will contain the parameters for the run.
When we configured our task, we created a single parameter, "user email". This means that
params
will be an object:javascriptCopied1{2user_email: "email@example.com";3}
Deploy
We'll modify this code in a bit, but just to test it out, you can deploy the task:
bashCopied1airplane deploy delete_user_by_email.task.yaml
This will bundle up the source code, build it, and deploy it to Airplane. Deploying can take a
couple of minutes. Once the deployment is finished, find the task in the
Airplane UI.

Enter any email and hit
Execute task
. The task should succeed. At the bottom of the results page
you will see the output that your task returned:
Create a non-trivial task
Now, let's modify our task to do something a bit more interesting. This is a "Delete user by email"
task, so we want our script to actually delete the user. In order to do this, we'll make an HTTP
request to a sample API endpoint that we've setup for you.
In the directory with our script, let's create an NPM package. If you're using PowerShell on
Windows, you'll need to install Node.js.
bashCopied1# This creates a package.json file. Make sure you're not in a directory2# that already has one!3npm init -y
Next, let's install the
airplane
SDK as well as node-fetch
:bashCopied1npm install airplane node-fetch
This should have updated your
package.json
with airplane
and node-fetch
. The Airplane CLI
looks for package.json
when deploying and will use it to install dependencies. Both NPM and Yarn
lock files are supported.Update your
delete_user_by_email.js
script with the following code:javascriptCopied1import airplane from "airplane";2import fetch from "node-fetch";34export default async function (params) {5// Send an API request to lookup this user's ID.6const getResp = await fetch(`https://demos.airplane.sh/users/get?email=${params.user_email}`);7if (getResp.status !== 200) {8airplane.setOutput(`Failed to get user: ${getResp.status}`, "error");9process.exit(1);10}11const { user } = await getResp.json();1213// Send another API request to perform the deletion, using the ID from the previous request.14const delResp = await fetch(`https://demos.airplane.sh/users/delete?id=${user.id}`, {15method: "delete",16});17if (delResp.status !== 200) {18airplane.setOutput(`Failed to delete user: ${delResp.status}`, "error");19process.exit(1);20}21const { archive_link, status } = await delResp.json();2223// Output results as a structured table24airplane.setOutput({25email: params.user_email,26archive: archive_link,27status,28});29}
After updating your code and saving, redeploy your code:
bashCopied1airplane deploy delete_user_by_email.task.yaml
Now, navigate back to the Airplane UI in your web browser, and try executing the task again with any
sample email. Click
Run again
to take you back to the option to Execute task
. This time, the run
results page will look a bit different:
You'll notice that now the output section is no longer blank. We see a structured table that
contains the data returned from the HTTP request we made to our sample API endpoint. It shows the
following information:
email
: the email of the user we chose to deletearchive
: A temporary link to the user's historical data so we can email that to them as part of our deletion processstatus
: a status showing whether the deletion succeeded or failed
If you click on
Logs
you can still see the raw stdout logs, and if you click on JSON you can see
this output table as a raw JSON object.Runbooks: Add more steps to your task
Now that you've created a task to delete a user by email, let's add on the second step of the
workflow. After the deletion process is complete, we also want to automatically be notified with a
link to their historical data.
We're going to use a runbook to do this. Runbooks are multi-step operations that can be used to look
up information, execute operations, send notifications, and perform other functions all together.
The second step we're adding is sending a Slack notification containing the link to the temporary
historical data archive.
Let's start by creating a new runbook from the library.
Define your runbook
Similar to the way we defined our task earlier, we're going to define and add parameters for our
runbook.
Let's call this runbook "Delete user and send historical data on Slack" where the runbook
"permanently deletes a user based on their email and sends a Slack notification with a link to their
historical data." Use the following information:
- Name: Delete user and send link to historical data
- Description: Permanently deletes a user based on their email and sends notification with historical data link
- Folder: Ignore this for now
Since we're using the user's email to determine which user to delete from the system, the input will
be the user's email. Let's add a runbook parameter
that represents the user's email.
Click add parameter and enter the following information:
- Name: User email
- Description: The email address of the user to be deleted
- Type: Short text
Once you click
Add
it will take you back to the runbook definition screen where you now see the
name, description, and parameter you just input listed there.
Once you've defined your runbook, click
Continue
, which takes you to the "Build Your Runbook"
screen.Build your runbook
Runbooks are comprised of a series of single-operations called
blocks. Blocks can be tasks or they can be other
functions that take in inputs, perform an operation, and produce an output. All tasks can be used as
blocks but you don't necessarily need to save every block you use in your runbook as its own task.

For the first block, let's select our
Delete user by email
task that we just created. Select the
task from the list on the left.
This will complete the same function as the task we created before returning an output table with
email, status, message, and archive.
What we want to do now is use a Slack block to automatically send a Slack message with a link to the
user's historical data. You'll recall that this was part of the output table when we ran this task
previously. But before we add this second step to the runbook, let's pass in our email parameter and
test to see that the task is working as expected.
Test blocks
Under
Parameters
at the top, enter any email. You can pass in the email that you're using by
inputing {{params.user_email}}
instead of typing "madhura@example.com" in manually. This will make
it such that the block Delete user by email
will automatically use what you enter in the parameter
when it runs.
When you click
Test
, you'll see a preview of the test block appear. The email that you've entered
under the top-level params should be the email that you see in the display box. Click Test
again
to run the task.
The run should have succeeded with the same output we saw from the previous section.

Add a Slack block
In our output, the column
archive
has a link to the user's historical data. Now, we want to
automatically send a Slack message with this link. To do this, let's add a second block to the
runbook: a Slack block. You can do this by clicking the + sign just below the Delete user by email
block.
Select
Slack
from the block types.
You'll need to connect your team's Slack account to use this. It'll take just a couple of minutes to
configure Slack by following the prompts below.

You can find more details on our Slack integration in
our docs.

Once configured, your runbook builder should look like the below:

There are two fields here: Channel name and message.
For channel name, type the name of the Slack channel you would like to send the message to.
Reference parameters and output
We want our Slack message to print out the
archive
field from our first block, as well as show the
email of the user that was deleted. Input the following into the Message
box:Copied1User tied to email {{params.user_email}} has successfully been deleted.2The user's historical data can be found here:3{{delete_user_by_email.output.archive}}
{{params.user_email}}
refers to the "user_email" top-level runbook parameter. "Params" is a global object that contains all the parameters of a runbook.{{delete_user_by_email.output.archive}}
will reference the output of yourDelete user by email
block and print what's underarchive
in the structured table.

Click the
Test
button on this block and you'll see a preview of the Slack message appear. The
email that you've entered as your param should be the email that you see in the display box and you
should also see the link displayed where you're pulling the archive
column of the structured table
from your previous task's output. Click Test
to run the task and send a Slack message.
You should see that your Slack block succeeded:

Since testing the block executes it, you should also receive a Slack notification with the message
that we configured using inputs and outputs from your runbook. You can see that we've successfully
referenced the user's email and automatically printed the link to the user's historical data.

Runbook advanced settings
Next, click
Continue
in the runbook builder to take you to the "Advanced Settings" screen. You'll
see a similar screen to when you created your Delete user by email
task. You can set explicit
permissions here and assign users and groups to
specific roles. Let's leave these as team access for now and click Create runbook
.
Execute your runbook
Your completed runbook should look something like the below. You can see all tasks and runbooks
you've created in the
Library
section of the Airplane sidebar. When you select the runbook you
just created "Delete user and send link to historical data," you'll see a web form with the
parameters you configured.
Fill out the user email with any email and click
Execute runbook
to run it. When the runbook
begins running, you'll see each block highlighted in blue if it's currently in progress, green if
it's finished, and grey if it hasn't started yet.
That's it! Congrats on creating your first runbook.
More features
This was a quick onboarding guide to walk you through the basic process of creating a task and then
a runbook for a real business use case. Airplane has a lot of use cases and features that we didn't
cover in this guide. Here are a few other resources that are worth diving into to learn more:
- Use Airplane schedules as a substitute for cron
- Set blocks in a runbook to run automatically or manually based on if you'd like to prompt your team for an input before your runbook continues to execute
- Configure group-based permissions and approval flows
- Leverage audit logs for monitoring and debugging
You can see a full list of tutorials and guides in our
tutorials library.
Thanks for using Airplane and don't hesitate to reach out at hello@airplane.dev or drop us a message
on Intercom (the
Help and Support
button in the lower-left corner of the app).