Guide
Send Email to a Notion Database (CLI)
Teams run intake in Notion — sales leads, bug reports, candidate pipelines — and the source is often email. The usual bridge is a paid automation that charges per record. The Nylas CLI gives you the email as JSON; the Notion API creates a database page per message with the properties mapped. This guide builds an email-to-Notion pipeline you control, mapping subject, sender, and date to Notion properties, and running it on a schedule for free.
Written by Nick Barraclough Product Manager
Command references used in this guide: nylas email search, nylas email list, and nylas email read.
How do you send email to a Notion database?
You send email to Notion by pulling the messages as JSON and creating one page per message in a Notion database. The CLI returns structured messages with nylas email search --json, and a single POST to the Notion API /v1/pages endpoint creates a page with your mapped properties. The page-creation contract is documented in the Notion API reference.
Two setup steps come first: create an internal integration to get a token, and share the target database with it so the integration can write. Notion's permission model is share-based, so a database the integration can't see returns a 404 — connecting it is a one-time click. After that, each message maps cleanly to a page.
# Pull the messages you want to file into Notion
nylas email search "subject:bug report newer_than:1d" --json --limit 50 > items.jsonHow do you map a message to Notion properties?
Map each message to a Notion properties object, where the database's title property holds the subject and your other columns hold the sender, date, or status. Notion types each property — title, rich_text, email, date — so the request must wrap values in the matching shape. The subject goes under the title property as a title array; the sender fits an email property directly.
Build the properties object with jq so the mapping is explicit and null-safe. A message with no subject would otherwise create a blank-titled page, so fall back to a placeholder. Keep the property names exactly matching your database schema, since Notion rejects unknown property keys rather than ignoring them.
DB_ID="your-database-id"
jq -c '.[]' items.json | while read -r msg; do
subject=$(echo "$msg" | jq -r '.subject // "(no subject)"')
sender=$(echo "$msg" | jq -r '.from[0].email // ""')
curl -s -X POST https://api.notion.com/v1/pages \
-H "Authorization: Bearer $NOTION_TOKEN" \
-H "Notion-Version: 2022-06-28" \
-H "Content-Type: application/json" \
-d "{\"parent\":{\"database_id\":\"$DB_ID\"},
\"properties\":{
\"Name\":{\"title\":[{\"text\":{\"content\":\"$subject\"}}]},
\"Sender\":{\"email\":\"$sender\"}}}"
doneHow do you keep the database in sync?
Keep it in sync by running the pipeline on a schedule and de-duplicating on a stable field. Store each message's ID in a Notion property and query before creating, or scope the search to newer_than:1d and run daily so you only ever process the last day's mail. A daily cron that files new bug reports keeps the database current without re-importing the whole inbox.
For near-real-time intake, drive the same create step from a webhook instead of a poll — when a new message arrives, file it immediately. The mapping code is identical; only the trigger changes. The Notion token is separate from the mailbox grant the CLI manages, so rotate them independently.
Next steps
- Email to Airtable — the same pattern into Airtable
- Log email to Google Sheets — a spreadsheet instead of a database
- Extract email data with jq — the JSON-shaping toolkit
- Parse inbound email webhooks — file messages in real time
- Full command reference — every flag and subcommand documented