DEV Community

Cover image for Write to a Notion Database via SMS with Twilio Serverless, the Notion API, and JavaScript
Lizzie Siegle for Twilio

Posted on • Edited on

Write to a Notion Database via SMS with Twilio Serverless, the Notion API, and JavaScript

This blog post was written for Twilio and originally published on the Twilio blog.

Notion is an app that bills itself as "an all-in-one workspace where you can write, plan, collaborate and get organized", letting you take notes, add tasks, manage projects, and more. They recently released their API. Read on to see how to write to a Notion database using Twilio Programmable Messaging, the Twilio Serverless Toolkit, and Twilio Functions.
gif showing sending SMS text saves to Notion database

Prerequisites

  1. A Twilio account - sign up for a free one here and receive an extra $10 if you upgrade through this link.
  2. A Twilio phone number with SMS capabilities - configure one here.
  3. Node.js installed - download it here.
  4. Notion account - download the Mac or iOS app here and make an account (or you can just make an account at that link and use Notion in the browser).
  5. A personal phone number to test the project.

Get Started with the Notion API

Go to the Notion API website and make sure you are logged into a Notion workspace as an Admin user. If you're not an Admin in your current workspace, make a new personal workspace for free here. From the Notion API site, click on My integrations in the top right corner.
my integrations in the top right corner
Select New integration and on the following page, give your integration a name like general-db. For the purposes of this post, the integration type can be internal.

After clicking Submit, you will be taken to a page with your integration's Internal Integration Token. Copy it and keep it hidden for later.
page showing internal integration token for your integration
Make a new Notion page in your workspace either in your Notion app or at notion.so by clicking the plus sign next to Workspace. Your Notion workspace might have an Add a Page button beneath all the workspaces which you would click instead, like this.
Add a page button
For this blog post, I made a workspace called Trip to-do's and then added a table as shown in the gif below: type "/" and select Table-Full page.
gif showing add full table
This inserts a new database into our workspace. You can read more on the types of databases in Notion here.

The workspace organization should look similar to the "Trip to-do's" directory with the database named "SoCal to-do" nested in the project workspace as seen in this example:
workspace organization with nesting
Integrations don't have access to any pages or databases in the workspace at first: a Notion user needs to share certain pages with an integration so that the pages can be accessed using the API and keep the information in Notion secure.

To let the Notion API access our database, click Share in the top right of your database (in the workspace) followed by the blue Invite button. Under Integrations, click Trip to-do's workspace.
share to web button
You can see more information on sharing a database with your integration here on the Notion API website.

Give your database a title and some column names. This blog post's database is named "SoCal to-do". The column names reflect the data we want to keep track of such as Name, What, and Where. Set these in the Notion app like below:
column table names
Take note of the ID of the database you just created. Open Notion in a browser and view the database as a full page. The database ID is in between the URL after notion.so and ends before the question mark. The ID is 32 characters long with numbers and letters--copy the ID and save it somewhere you can easily find soon.

The database in this article begins with dcfc and ends with e9e as seen below:
database URL
Make sure that your database link does not contain your Notion username. If you see this, you may have to make a new database under a different project workspace so that it looks like the image above.

So far, we can add items to the database in Notion, but what if a user does not have Notion? Now we can add Twilio to the project so that non-Notion users can fill the database via SMS!

Get your App Up and Running Quickly with the Twilio Serverless Toolkit

The Serverless Toolkit is CLI tooling that helps you develop locally and deploy to Twilio Runtime. The best way to work with the Serverless Toolkit is through the Twilio CLI. If you don't have the Twilio CLI installed yet, run the following commands in the terminal to install it and the Serverless Toolkit:

npm install twilio-cli -g
twilio login
twilio plugins:install @twilio-labs/plugin-serverless
Enter fullscreen mode Exit fullscreen mode

Run the following commands to create your new project and install the lone requirement superagent - an HTTP client library to make HTTP requests in Node.js:

twilio serverless:init notion-api-twilio-sms --template=blank
cd notion-api-twilio-sms
npm install superagent
Enter fullscreen mode Exit fullscreen mode

Edit the .env file and add an environment variable called NOTION_API_KEY for your Notion API key.

Make a Twilio Function with JavaScript

cd into the /functions directory and make a new file called write_to_db.js containing the following code:

const superagent = require('superagent');
exports.handler = async function(context, event, callback) {
  const twiml = new Twilio.twiml.MessagingResponse();
  let inbMsg = event.Body.trim();
  let propObj, firstCell, secondCell, thirdCell;
  let count = (inbMsg.match(/,/g) || []).length; //# of commas means # columns sent
  //check count of commas in inbound message: this will affect the Notion database columns we write to
  switch(count) {
    case 0: 
      firstCell = inbMsg;
      propObj = {
        "Name": [
          {
            "text": {
              "content": `${firstCell}`
            }
          }
        ]
      }
      break;
    case 1: //1 comma = 2 columns
      firstCell = inbMsg.split(',')[0];
      secondCell = inbMsg.split(',')[1];
      propObj = {
        "Name": [
          {
            "text": {
              "content": `${firstCell}`
            }
          }
        ],
        "What": [
          {
            "text": {
              "content": `${secondCell}`
            }
          }
        ],
      }
      break;
    case 2: //2 commas, 3 columns
      firstCell = inbMsg.split(',')[0];
      secondCell = inbMsg.split(',')[1];
      thirdCell = inbMsg.split(',')[2];
      propObj = {
        "Name": [
          {
            "text": {
              "content": `${firstCell}`
            }
          }
        ],
        "What": [
          {
            "text": {
              "content": `${secondCell}`
            }
          }
        ],
        "Where": [
          {
            "text": {
              "content": `${thirdCell}`
            }
          }
        ]
      }
      break;
  }
  superagent.post(`https://api.notion.com/v1/pages`, 
  { "parent": { 
    "database_id": `REPLACE-WITH-YOUR-DATABASE-ID`
  }, "properties": propObj
})
  .set('Authorization', `Bearer ${context.NOTION_API_KEY}`)
  .set('Content-Type', 'application/json')
  .set('Notion-Version', '2021-05-13')
  .then((res) => {
    twiml.message(`Wrote ${inbMsg} to the Notion page!`);
    callback(null, twiml);
  })
  .catch(err => {
  twiml.message(`Error: ${err.message}`);
    callback(null, twiml);
  });
};
Enter fullscreen mode Exit fullscreen mode

This code imports superagent so that we can handle HTTP requests in Node.js. It also makes a Twilio Messaging Response object which retrieves the inbound text message and checks the number of commas to decide which Notion database columns to post to.

The inbound message is parsed to separate the input based on commas and an object is passed to the Notion API's properties parameter which uses property names or IDs as keys. For more information on the Database object, check out this section of the Notion API documentation.

With superagent, we hit the Notion API's pages endpoint with the database ID to write content to the database. We set our Notion API key, the content-type, the Notion version, and then send a text message confirmation response back so the user knows what they texted was written to the shared database.

You can view the complete app on GitHub here.

Configure the Function with a Twilio Phone Number

To open up our app to the web with a public-facing URL, go back to the notion-api-twilio-sms root directory and run twilio serverless:deploy to deploy the app. This will return some information including a few URLs as shown below:
generated Function URLs when deployed
Grab the Function URL ending in '/write_to_db' and run these commands:

twilio phone-numbers:update {YOUR-TWILIO-NUMBER} --sms-url {https://YOUR-URL-HERE.twil.io/write_to_db}
Enter fullscreen mode Exit fullscreen mode

This connects the Twilio phone number to the deployed Function URL. If you view the phone number in your Phone Numbers Console, it will still show up there as a "Function" and not a "Webhook URL". You can now text your Twilio number things to do with its name, what, and , where separated by commas and have it written to your Notion database.
text body saved to Notion database

What's Next for Twilio Serverless and the Notion API?

There is a Notion integration that uses SendGrid to send an email whenever the Status property of a page in a database is updated, showing how Notion can cause an external action, and you can use the Notion API for so much more!

Let me know online what you're building with Twilio Serverless or how you use Notion.

Top comments (2)

Collapse
 
ivavay profile image
Ivy Chen • Edited

Hey Lizzie! I'm trying to follow along with this tutorial and the last step isn't working for me for some reason. When I tried to connect the Twilio phone number to the deployed function url, it gives me an error like this:

twilio-cli encountered an unexpected error.
Enter fullscreen mode Exit fullscreen mode

Would love your help! I'm using this to make a mental health tracker :)

I also got this notice a few steps before, not sure if it's that.


│ WARNING Different Node.js Version Found
│ 
│ You are currently running Node.js 18.9.0 on this local machine. The 
│ production environment for Twilio Serverless currently supports versions 
│ 14.x.
│ 
│ When you deploy to Twilio Serverless, you may encounter differences between
│  local development and production.
│ 
│ For a more accurate local development experience, please switch your 
│ Node.js version.
│ A tool like nvm (https://github.com/creationix/nvm) can help.
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ivavay profile image
Ivy Chen

Oh wait nmv it worked connecting wised! However, I'm getting this when trying to send a text using the format to my Twilio number:

Sent from your Twilio trial account - Error: Bad Request