Docs

Messaging: push and email to your users

One API for push and email to your app users: templates with variables, audiences written in SQL, a preview before every send, marketing opt-outs with one-click unsubscribe, and a delivery log.

Updated Oct 17, 2026Open in console

Messaging sends a template to an audience over push (your FCM / APNs credentials, see Push notifications) and/or email (Sovaria's sender or your own SMTP). Every recipient gets their own copy with their own variables, and every send leaves a per-recipient log.

Audience (SQL)user_id,first_name, …TemplateHi {{ first_name}}Sendpreview firstPusheach deviceEmailunsubscribe linkDelivery logper user andchannel

Templates

A template has push content (title, body, image, data), email content (subject, html, text) or both, with {{ variables }} anywhere. Transactional templates (receipts, security alerts) always go out; marketing templates skip users who opted out and add an unsubscribe link and the one-click List-Unsubscribe header (RFC 8058) to every email.

await sov.api.messaging.putTemplate({
  name: 'weekly-digest',
  category: 'marketing',
  push: { title: 'Hi {{ first_name }}', body: 'Your week on the {{ plan }} plan' },
  email: { subject: 'Your week, {{ first_name }}', html: '<p>Hello {{ first_name }} …</p>', text: 'Hello {{ first_name }} …' },
})

Audiences in SQL

An audience is a query on your project database that returns user_id (your app users' ids). Every other column becomes a variable for that user, so the data that picks the audience also personalises the message. Queries run read-only, as one statement, with a 10-second timeout; ids that aren't app users of the project are left out.

select p.user_id, p.first_name, p.plan, count(o.id) as orders
  from profiles p left join orders o on o.user_id = p.user_id
 where p.plan = 'pro' and p.last_seen_at > now() - interval '30 days'
 group by 1, 2, 3

Preview, then send

const preview = await sov.api.messaging.send({
  template: 'weekly-digest',
  to: { audience: 'active-pro' },          // or user_ids, sql, topic, all_users
  variables: { promo: '20% off' },         // the same for everyone
  dry_run: true,
})
// preview.counts → { push: { eligible: 980, no_device: 250, opted_out: 10 }, email: { eligible: 1190, … } }
// preview.preview → the first recipient's rendered push and email

const send = await sov.api.messaging.send({ template: 'weekly-digest', to: { audience: 'active-pro' }, variables: { promo: '20% off' } })
const done = await sov.api.messaging.getSend({ send_id: send.id })   // status: sending → done
  • A send answers at once and continues in the background, 500 recipients at a time; History in the console (or getSend) shows the progress.
  • Each recipient and channel is logged as sent, failed (with an error code such as UNREGISTERED, SEND_ERROR, PLAN_LIMIT), no_device, no_email or opted_out — never the content.
  • Push goes to every device the user registered; a user counts as reached when any device accepts it.
  • Email through Sovaria's sender is paced at your plan's emails per second instead of failing; your own SMTP (Authentication › Email) isn't counted against email.sends_month.
  • Sends from functions use the service role key; app users and the anon key can never send.

Opt-outs and unsubscribe

// The signed-in user's own marketing choices
await sov.api.messaging.setPreferences({ marketing: { email: false } })
const { marketing } = await sov.api.messaging.getPreferences()   // { push: true, email: false }

Marketing emails carry a signed unsubscribe link that works without signing in (a button on a small page, so mail scanners opening the link don't unsubscribe anyone) and the one-click header mail apps show as "Unsubscribe". Your own settings screen can record choices with setUserOptout.

Limits

FreeProUltraTeamEnterprise
Message templates per project101003001,0005,000
Message audiences per project3502005002,000
Recipients per message send1,00050,000200,0001,000,0005,000,000
Message delivery log history7 days30 days90 days180 days365 days
Monthly push notifications10,0001,000,0005,000,00020,000,000100,000,000
Monthly emails from Sovaria's sender (own SMTP is unlimited)2002,0006,00030,000150,000
Something unclear or missing on this page?Tell us