Manage user preferences, store and retrieve information from an Airtable database

In this tutorial, we will use different blocks available in Voiceflow to get information about the user and save them in a database with Airtable, we will also use the new Reminder block to notify the user when he can launch the skill again to discover new content.

Here is the list of elements we will use for this tutorial

  • Permission block
  • User info
  • Reminder
  • API block
  • Code block
  • {user_id} variable

Let’s start by creating our database from the Airtable site. So let’s go to, log in and create a new base

And click on “Start from scratch


Name it as you wish and open it

First, let’s rename the table to “Users” by double clicking on the tab


For the first field we will use the user id provided by Alexa and Voiceflow, so let’s rename it “UserID”.

Double click on the “Name” field and enter “UserID” as the new name. Keep Single line text as field type. Click on the “Save” button


This first field is a primary field so it is a good idea to use it to store the unique identifiers of each user.


Double click on the “Notes” field and rename the field to “Name” and change its type to “Single line text”. Click on the “Save” button.


Now, double click on the “Attachments” field and rename it to “Email” and change its type to “Email”. Click on the “Save” button.


We will add a new field to save the user’s choice on accessing his name or email from our skill.
Click on the + to add a new field


Let’s name the “Permission” and change it to “Number” with an “integer (2)” format. Click on the “Save” button.


Again, let’s add a field.


Let’s rename the “Reminder”, type “Number” and format “Integer (2)”. Click on the “Save” button.


Finally, let’s add a new table to our database. We will name it “Messages”. Click on the “+” at the right of “Users” tab.


Click on “Create empty table


And renamed it to “Messages” and press “Enter” on your keyboard to confirm.


As before, we will rename the first field “Welcome” and the second field “Update”. These two fields will be of the type “Long text”.

We can delete the last “Attachments” field because we will not use it. Click on the small arrow to the right of the field and select “Delete field” from the menu that appears.


To clean up a little, we will check the three lines already present in the table, then, with a right click, we select “Delete all selected records”.


To be able to have a match in the documentation, we create a first example record in this table like this:


Let’s go back to the “Users” table and do the same.


We create a first example record like this:

If this is the first time you have used Airtable or you have never used the API, click on the user icon at the top right and on “Account” in the drop-down menu. From the window that opens, click on “Generate API key”.


Back to the main Airtable window, we will have to retrieve some information from the Airtable online help. Click on the “Help” menu at the top right, then, in the drop-down menu, click on “API documentation”.


In the window that appears, check the “show API key” option at the top right if it is not already done.


Then in the right menu, click on “AUTHENTICATION


Copy for later the url of the second example in the tab curl on the right.

Mine is looking like this:

Where app2LVT8O1tRuUoqT is the base id, Users is the table name and keyY6PccqvLBwFzSi is the API key.

You can also find more information and examples by clicking on “USERS TABLE” and “Create a record”. In the code on the right you can then access an example of a request and answer in JSON format.


For example here to create a new record we will have to send a POST request with the header “Content-Type: application/json” and the following raw body:

  "fields": {
    "UserID": "userid",
    "Name": "name",
    "Email": "",
    "Permission": 0,
    "Reminder": 0

Keep these web pages open in a corner for later and let’s create a new skill in Voiceflow

Select the “Blank” template and click on “Start”.


This is what this skill will look like.

You can start by studying the preview of this skill that I made available to you (I commented almost all the blocks and different actions).

And here are the variables we will use in this skill.

Let’s start at the beginning

The first block is an API block that will retrieve customized messages from our database.

Here is the API block in detail

With the information you obtained earlier in the Airtable documentation, we will create the url needed to query the Airtable database.

Mine looks like this:

Again, app2LVT8O1tRuUoqT is the database, Messages is the name of the second table we’ve created earlier and keyY6PccqvLBwFzSi is my API key.

Edit this informations with the informations in the Airtable doc from the page you left open earlier.

While you are on the Airtable page, edit the records in the “Messages” table as follows:

You can also copy these texts from my shared database here:

Once you have updated the “Welcome” and “Updates” fields in your database and you have retrieved all the information to edit the url address, go back to your API block to map the variables.

Here we will map:

response.records.0.fields.Welcome to the Welcome variable
response.records.0.fields.Updates to the Updates variable.

In the following speak block, we use the “Welcome” variable which contains our personalized welcome message


In the next step we check if the user is already registered or if it is the first launch thanks to the recordID variable.

If recordID = 0 we ask the user if he wants the skill to automatically retrieve his name and email.

Then, either the user accepts and we use the User Info block to retrieve his name and email (or the Permission block if the user has not yet authorized the skill), or he does not want to use this function and we ask him if he can still give us his name with an Interaction block.

I let you study the construction of the different paths from the skill preview.

You will see that here we are using the API block again to create and update records in our database.


For the creation of a new record (new user), we use this type of url:

It’s almost the same url as before but we use here the “Users” table and with a POST method.

In the “Headers” part we add a pair with as key Content-Type and as value application/json.

We map to our recordID variable.

Finally, in the Body Raw Input we will use the following code:

  "fields": {
    "UserID": "{user_id}",
    "Permission": {permission},
    "Reminder": {reminder}

So much for creating (POST) a recording in Airtable. Let’s now study the second API block to update a record (PATCH).

For the update so, the url looks like this:{recordID}/?api_key=keyY6PccqvLBwFzSi

We use the recordID variable in the url to tell Airtable which record we want to modify.

The “PATCH” method is used here instead of a GET or POST

And as before, we add the header Content-Type with the value application/json.

In the Body Raw Input we use this:

  "fields": {
    "Permission": 3

To update the user’s permission field.

The last API block we will see together here is the “CheckIfExist” block. Indeed, if the user has given us access to his information and in particular his email, we will be able to check if a registration with this email is not already present in our database thanks to the SEARCH formula of Airtable.
This is convenient because the UserID is replaced each time the user disables or reactivates the skill while his email remains the same.


We come back to the GET method with a url that looks like this:'{email}',%20%7BEmail%7D)&api_key=keyY6PccqvLBwFzSi

Here we’ve added maxRecords=1 to retrieve only one record and filterByFormula=SEARCH('{email}',%20%7BEmail%7D) to search for our variable {email} in the “Email” field of our database.

Finally, we map response to JSONresponse variable.

In the Code block next to it, we use the Javascript language to check if we have a match


//Check if we get a match
isResult = JSONresponse.records.length;

if(isResult == 1){
  checkID = JSONresponse.records[0].id;
  checkEMail = JSONresponse.records[0].fields.Email;

isResult = JSONresponse.records.length; allows you to know how many records we have (0 if no match or 1 if the email is already registered in the database).

If isResult = 1 we set the checkID and checkEmail variables with the JSON response.

if(isResult == 1){
  checkID = JSONresponse.records[0].id;
  checkEMail = JSONresponse.records[0].fields.Email;

The last part uses the Reminder block and our variable {Updates} to create a reminder with a custom message every 24 hours.


Congratulations, you have learned to use the API block to create, update and retrieve information from an Airtable database. You now know how to use dynamic content in your Speak block, ask the user for authorization and send reminders. You even wrote your first javascript code in a Code block. But most importantly, you can now restore your users’ information even after they have disabled and reactivated a skill.

Have fun, feel free to study the preview link of the skill and post questions and comments below.


You’re unbelievable!! Thanks for posting

1 Like

Thank you! Do not hesitate if this need some edits, it’still frenglish :slight_smile:

Thanks for this. I’m learning a lot.

ps: would be great to open a shared project and work in my own project on two tabs :slight_smile:


You’re unbelievable!! Thanks for posting

1 Like

Very good job and great description. I will rebuild that. I can learn something there. Thank you.:grinning:

1 Like

Another great tutorial, thank you! Is there a way we can use Google Sheets at this level (to post and pull specific cells) instead of Airtable? I was getting ready to go Pro with Airtable for $20 per month until I realized they charge $20 PER USER/mth (even if the user is only an editor of any doc in your base). Airtable is awesome, but I think their revenue model is an issue for anyone who is thinking about scaling their business.

1 Like

@audiorush With Google Sheet you can’t modify the data, it’s read-only with this url sharing function principle. To be able to make changes you have to go through Google APIs and that’s another story.
About Airtable, nothing prevents you from taking a pro account and sharing the table in “Editor” mode with anyone who has an Airtable account (even free).
More infos here:

1 Like

True, but let’s say I select the Pro Plan at $20/mth. If I share any base with anyone (even if they just have edit access) my cost goes to $40 per month. You can give people view only access for free, but if they have any type of editing role, you have to pay for them. Airtable%202019-02-02%2020-50-57

Thanks for clarifying this!

Hi. Could not find AMAZON.YesIntent on NoIntent…

Any ideas?

You can found them in the first tab (Choices) of you interaction block.

Hi there,
I am trying to open the preview link of the skill but is not working.
I Would like to make a skill that reading a list of times on an airflow table gives a reminder each set time (like everyday at 8 am and 10 am ).
I am trying to figure out how studying your tutorial. I still don’t know if is possible there are no tutorial out there on the subject. Do you think it might work?
Thanks a lot for your help.

preview link didn’t work for me, too…maybe it’s been a while since the created this tutorial.

Anyway, you can set reminder using Reminder Block.

This is reminder block tutorial.

Actually, you can create reminder skill without airtable. if you still want to integrate with airtable, your use-case might be different from what I think. so could you explain more in detail?

Hi there,
Thanks for your answer :slight_smile:
So my skill should work like this: I have a week list on my database which set times every day, my skill should check for a time set e reminder and then interact with the user to get information. It’s like a regulary check where everytime the user provide a new value and this value is memorized in my database. So I will have two tables one for the times and another for the values. I already tried to follow this tutorial but is not working for me. Even though I gave the autorization I don’t get any notification and the process fails.

I’m still not sure about your data design(sorry, English is not my language), but, your current problem is integration failure with airtable, right?

I recommend start simple and small, for example, just create a project with only 2 blocks, an integration block and a speak block. Set integration with a Messages table, speak Welcome and Updates. Make sure if it works, then go further.

Actually I tried above just a little bit and will show some screen shots for your reference. (Sorry, All written in Japanese)

This is Messages table on Aritable.

first, create 2 variables “varWelcome” and “varUpdates”.

This is my flow.

Settings of Integration block.

URL was cut off in the middle, so it’s like this. you should replace XXXXX with your Base ID and ****** with your API KEY.**********

Finally, settings of speak block.

Test. It works! Tada!

1 Like

Hi Kun,
You are great thanks for your help. Now it works for me as well. I gave up on my project for a while because I want to learn more first to get better and then trying with something a little bit harder. So…
I am trying to reproduce the project that was posted in this Tutorial but there are many missing pieces. I tried to rebuild everything on my own. But I don’t get to figure out what this part of the blocks is suppose to do:

I mean I did a check if the mail match in the database but then I don’t get to understand why we need the check backup email. I tried Like that :

But now I don’t know what I am suppose to do with the check backup mail and then swap record…
It would be great to have some help from the author as well. Like an explanation on the others blocks!

I’m not sure in detail, so just guess.

  • database holds each user’s user_id(which is uniquely provided when a user activates the skill), name, email, and preferances.
  • user_id will be changed if a user de-activate and re-install skill, that means the skill see this welcome-back user is a different new user, so in a standard way, will try to all the infornation again from the beginning.
  • If user-id is different and there are email address in the database, that means user come back again and all the information corrected previously can be re-usable.

does it make sense?

1 Like

It does a lot!!! Thank you for giving me the missing piece! A lot of good vibes mate !
Last thing : what do you think he means with “registration number” up this block:

So if i get everything well it should be like that for Already in base:

Check Backup email:

and then Swap Record:

do you think I miss something?.. :shushing_face: