top of page
Search

How to Integrate Salesforce Leads with a Notion Database

  • Writer: Architect
    Architect
  • Jun 24
  • 5 min read

Keeping lead data consistent and accessible across platforms is crucial for efficient sales and marketing workflows. While Salesforce remains the system of record for customer relationship management, Notion is rapidly gaining popularity as a flexible, collaborative workspace for teams.

This guide shows how to integrate Salesforce with Notion by enabling your Salesforce Leads to sync directly into a Notion database. Whether you're building a prototype, testing an internal workflow, or preparing for a production rollout, this tutorial will walk you through:

  • Creating a Notion database structured like Salesforce's Lead object

  • Authenticating and testing the Notion API

  • Sending lead data from Salesforce to Notion via Apex

  • Planning future improvements like duplicate prevention and bidirectional sync

By the end, you’ll have a working setup where lead records from Salesforce can be stored, viewed, and enriched inside a Notion database — combining the CRM power of Salesforce with Notion’s flexibility and UX.


Read More about the Notion Database: https://www.notion.com/help/category/databases





Step 1: Creating a Notion database

Steps:

  1. Go to Notion and create a new page.

  2. Select Empty Database.

  3. A new page will open with the default database view.


Go to Notion and create a new page:


Select Empty Database:


A new page will be opened with the default database view:

Rename the table to “Leads” and update the columns to match the Salesforce Lead object. Include the following fields:

  • First Name

  • Last Name

  • Company

  • Email

  • Phone


Your database should now look like this:


Step 2: Getting the Notion Access Token

Steps:

  1. Open the Notion integrations page: Notion Integrations

  2. Click "New Integration"

  3. Enter the integration details (e.g., name, associated workspace)

  4. Click "Configure Integration Settings"

  5. Go to the Access tab

  6. Click "Select Pages" and choose the Leads database

  7. Click "Update Access"

  8. Go back to the Configuration tab → Click "Show" next to Internal Integration Secret and copy the token


Open the Notion integration page: https://www.notion.so/profile/integrations


Click on the New integration:


Enter the integration details:

Click on the Configure integration settings:

Go to the access tab on the new page:

And click Select pages:

Select the Leads one and the Update access:

Then go back to the Configuration tab -> Click Show on the Internal Integration Secret and then copy the secret:


Test Connection in Postman:


You can test your integration using Postman by supplying the integration secret.


Authorization: Beare Token + the secret value

(on the screenshot I converted the secret into a variable


Headers:

Notion-Version : 2022-06-28

Content-Type: application/json

Body:

{
  "filter": {
    "property": "object",
    "value": "database"
  },
  "page_size": 100
}


Test the integration by sending the request. If everything is fine, you will see a JSON response with the ID value:



Now, cpy the id value from the object "datbase" to use it for the future integration


Step 3: Send a New Lead from Salesforce to Notion


You can send leads to Notion using one of the following methods, depending on your team's preferred tools and level of automation:

Option 1: Apex Batch Job

Use an Apex class to send a selected batch of Lead records to Notion on a scheduled or manual basis.

Option 2: Lightning Web Component (LWC)

Build a custom LWC that allows users to manually push a single Lead record to Notion from the record page (e.g., via a “Sync to Notion” button).

Option 3: Salesforce Flow (No Code)

If you prefer a declarative, no-code approach, use Flow Builder to automate the sync process. Here's a high-level setup:

Prerequisites:

  • Create an Apex Action that wraps the HTTP POST request logic to Notion’s API

  • Mark the Apex method as @InvocableMethod to use it in Flow

Example Use Cases:

  • After Save Record-Triggered Flow: Automatically push a Lead to Notion after it’s created or updated

  • Screen Flow: Allow users to select fields and confirm sync before sending

Flow Configuration Steps:

  1. In Setup → Flows, create a new Record-Triggered Flow on the Lead object

  2. Add an Assignment step to format the input data if needed

  3. Add an Action element and select your custom Apex action

  4. Map the Flow inputs to the Apex method’s parameters (e.g., first name, email, database ID)

  5. Test the Flow by creating or updating a Lead in Salesforce

This approach is ideal for admins who want automation without code, and it integrates smoothly with Salesforce’s native tools.



When using Apex or Flow, the JSON payload you send to Notion should follow this structure. Replace database_id with the actual ID of your Notion database:


{
    "parent": {
        "database_id": "21a***************f"
    },
    "properties": {
        "Email": {
            "email": "alice@example.com"
        },
        "Phone": {
            "phone_number": "+14155552671"
        },
        "Company": {
            "rich_text": [
                {
                    "type": "text",
                    "text": {
                        "content": "Acme Corp",
                        "link": null
                    }
                }
            ]
        },
        "Last Name": {
            "rich_text": [
                {
                    "type": "text",
                    "text": {
                        "content": "Doe",
                        "link": null
                    }
                }
            ]
        },
        "First Name": {
            "title": [
                {
                    "type": "text",
                    "text": {
                        "content": "Alice",
                        "link": null
                    }
                }
            ]
        }
    }
}

Here's a complete and clean Apex class with an @InvocableMethod that:

  • Accepts a recordId and databaseId as inputs from Flow

  • Queries the specified Lead

  • Builds a Notion-compatible JSON payload

  • Sends it to the Notion API via a Named Credential for security


 Prerequisites:

  • Set up a Named Credential in Salesforce named Notion with:

    • URL: https://api.notion.com

    • Header: Authorization: Bearer <your_secret_token>

    • Notion-Version: 2022-06-28 added via a custom header or in the Apex call

    • Select “Per User” or “Named Principal” based on your needs



Apex Class:

public class NotionLeadSync {
    public class NotionFlowInput {
        @InvocableVariable(required=true)
        public Id recordId;
        @InvocableVariable(required=true)
        public String databaseId;
    }
    @InvocableMethod(label='Send Lead to Notion')
    public static void sendLeadsToNotion(List<NotionFlowInput> inputs) {
        for (NotionFlowInput input : inputs) {
            if (input.recordId == null || input.databaseId == null) continue;
            Lead leadRecord = [SELECT FirstName, LastName, Company, Email, Phone FROM Lead WHERE Id = :input.recordId LIMIT 1];
            Map<String, Object> payload = new Map<String, Object>{
                'parent' => new Map<String, Object>{ 'database_id' => input.databaseId },
                'properties' => new Map<String, Object>{
                    'First Name' => new Map<String, Object>{
                        'title' => new List<Object>{
                            new Map<String, Object>{
                                'text' => new Map<String, Object>{ 'content' => leadRecord.FirstName }
                            }
                        }
                    },
                    'Last Name' => new Map<String, Object>{
                        'rich_text' => new List<Object>{
                            new Map<String, Object>{
                                'text' => new Map<String, Object>{ 'content' => leadRecord.LastName }
                            }
                        }
                    },
                    'Company' => new Map<String, Object>{
                        'rich_text' => new List<Object>{
                            new Map<String, Object>{
                                'text' => new Map<String, Object>{ 'content' => leadRecord.Company }
                            }
                        }
                    },
                    'Email' => new Map<String, Object>{ 'email' => leadRecord.Email },
                    'Phone' => new Map<String, Object>{ 'phone_number' => leadRecord.Phone }
                }
            };
            sendToNotion(JSON.serialize(payload));
        }
    }
    private static void sendToNotion(String body) {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('callout:Notion/v1/pages');
        request.setMethod('POST');
        request.setHeader('Content-Type', 'application/json');
        request.setHeader('Notion-Version', '2022-06-28');
        request.setBody(body);
        HttpResponse response = http.send(request);
        if (response.getStatusCode() >= 300) {
            System.debug('Failed to sync with Notion: ' + response.getBody());
            throw new CalloutException('Notion API call failed: ' + response.getStatus());
        }
    }
}


Future Enhancements

  • Add a Salesforce Lead ID to Notion to prevent duplicates

  • Store the Notion Page ID back in Salesforce for updates

  • Add error logging and sync status tracking

  • Expand to sync other Salesforce objects (e.g., Contacts, Accounts)

  • Integrate transcription or voice memo storage via Notion AI


 
 
 

Comments


bottom of page