Interactive Email Powered by Live Salesforce Data

Salesforce authenticates server-to-server integrations with a signed JWT, not a password or a refresh token that quietly expires. MailInApp's API data source speaks that flow natively: sign in with a Connected App's certificate and private key, run a SOQL query, and bind the returned rows directly to a KPI scorecard or chart block — a pipeline digest with real, current numbers every time it sends, not a screenshot pasted into an email.

Subject

Your pipeline this week

Salesforce authenticates server-to-server integrations with a signed JWT, not a password — and MailInApp's API data source speaks that flow natively. Connect once, and a KPI scorecard or chart block can bind straight to live Opportunity, Account, or Contact rows, no refresh token to babysit and no CSV to re-export before every send.

Most "weekly pipeline" emails are a screenshot of a report, stale the moment someone pastes it in. Binding a chart block directly to a Salesforce-backed data source means the block's own number comes from a real SOQL query — and a recurring send re-runs that query fresh on every send, so Monday's digest actually reflects Monday's pipeline.

How the connection works

MailInApp

Signs a JWT with your Connected App's private key

Salesforce token endpoint

Verifies the signature, returns an access token

Salesforce REST API

Runs your SOQL query, Bearer-token authenticated

Your email

KPI scorecard & chart blocks bound live to the rows

Every step happens server-side on each send. No password is ever sent, and there's no refresh token — a stale token is replaced by signing a fresh assertion.

This is the same JWT Bearer flow Salesforce documents for its own server-to-server integrations, wired into MailInApp's existing OAuth2 auth modes for API data sources rather than a bespoke Salesforce-only integration.

Set up a Connected App once

In Salesforce Setup, create a Connected App, enable OAuth settings, and upload a self-signed certificate under Use digital signatures — the certificate goes to Salesforce, the paired RSA private key goes to MailInApp. Set Permitted Users to Admin approved users are pre-authorized, which is what makes the exchange non-interactive: there's no consent screen for a script to click through. Note the Connected App's Consumer Key and your org's My Domain URL — both go into the connection in MailInApp.

Point it at a SOQL query

The data source's Endpoint is a REST query URL, and the query string is the actual data you get back:

SELECT Name, Amount, StageName, CloseDate FROM Opportunity WHERE IsClosed = false

Set Data path to records — Salesforce wraps its query results in a records array. Relationship fields like Owner.Email come back nested and get dropped by MailInApp's row parser, so keep the query flat; select OwnerId instead if you need an owner identifier to filter or merge on later.

Bind blocks straight to it, not merge tags

Add the connection to a project from the studio's Data panel with a collection role — the same binding a repeat block uses. From there, KPI scorecard, bar, line, and pie chart blocks can bind directly to it in their own Inspector:

  • A KPI scorecard set to Amount with a Sum aggregate becomes a live "total open pipeline" figure.
  • A bar chart grouped by StageName, with Amount as its series (Sum aggregate again), becomes a pipeline-by-stage breakdown.

Neither block needs a single merge tag typed by hand — the binding does the work, and both stay correct as deals move stage or close.

Send it on a schedule

A recurring weekly send re-runs the SOQL query and re-renders both blocks against Salesforce's current rows every time it fires — the same digest structure, fresh numbers each Monday, with nobody rebuilding it by hand. A Button block pointed at each Opportunity's Salesforce URL gives anyone reading the digest a one-click way to open the record behind a number that catches their attention.

Getting started

Create a Salesforce Connected App with a certificate for the JWT Bearer flow, connect it in MailInApp's Data Sources tab with your Consumer Key, integration username, and private key, point the endpoint at a SOQL query with records as the data path, then bind a KPI scorecard and bar chart to it from the studio's Data panel. See the Salesforce integration guide for the full field-by-field setup.

A typical build-and-send sequence

  1. 1

    Create a Salesforce Connected App for server-to-server access

    Enable OAuth settings, upload a self-signed digital certificate, turn on the JWT Bearer Flow, and set Permitted Users to "Admin approved users are pre-authorized" so no human has to click through a consent screen.

  2. 2

    Connect Salesforce as an API data source

    Pick OAuth2 JWT Bearer in MailInApp's Data Sources tab, then paste the token URL, the Connected App's Consumer Key as Issuer, the integration user's username as Subject, the login host as Audience, and the matching private key.

  3. 3

    Point the endpoint at a SOQL query

    The Endpoint is your org's REST query URL and the Data path is "records" — a query like SELECT Name, Amount, StageName, CloseDate FROM Opportunity WHERE IsClosed = false returns live pipeline rows on every fetch.

  4. 4

    Bind KPI and chart blocks straight to it

    Add a collection-role binding to the source from the studio's Data panel, then bind a KPI scorecard's Value field (Sum of Amount) and a bar chart's Group by (StageName) to it — no merge tags to type by hand.

  5. 5

    Send it on a recurring schedule

    A weekly recurring send re-runs the query and re-renders both blocks against Salesforce's current rows every time, so Monday's digest always reflects Monday's pipeline.

Frequently asked questions

Does the access token ever need to be renewed by hand?

No — MailInApp signs a fresh JWT assertion and exchanges it for a new access token automatically whenever the cached one is close to expiring, and again if a call ever comes back unauthorized. There's no refresh token to babysit in this flow; a stale token is simply replaced by minting a new one.

Does my Salesforce password ever reach MailInApp?

No — the JWT Bearer flow authenticates with a signed assertion verified against a certificate, never a username/password exchange. The only secret MailInApp stores is the private key half of that certificate pair, masked in every response after you save it.

Can each sales rep see only their own opportunities?

Only if the SOQL query returns a flat field to filter on — a relationship field like Owner.Email comes back as a nested object and gets dropped, since MailInApp's row parser doesn't flatten nested values. Select a flat identifier such as OwnerId instead, and filter a bound chart block against a matching field on your audience's own contact row (a chart's Bind to data filter can reference recipient merge tags) to slice the same shared query per recipient.

What Salesforce edition do I need?

Any edition with REST API access enabled — Enterprise, Unlimited, Performance, and Developer Edition include it; Professional and Essentials need the API add-on. The integration user's own profile also needs API Enabled turned on.

Does this work against a sandbox instead of production?

Yes — use https://test.salesforce.com as both the token URL host and the Audience value, and point the Endpoint at the sandbox's own My Domain URL instead of production's.

Build this in the studio

Start on the free plan — every interactive block and the full fallback engine are included on every tier.