# Supabase send email, SMS and WhatsApp: free, in one function

> Supabase's default email sends 2 messages an hour, to your team only. One Edge Function on insert sends email, WhatsApp and SMS for free. Code inside.

Source: https://unlimitedmessaging.app/articles/supabase-whatsapp-email-sms-notifications

Supabase guide

# A new row in Supabase,  
_an email and a WhatsApp go out._

A database webhook calls one Edge Function on insert, the function makes one API call, and the welcome or order message leaves from your own mailbox, WhatsApp number or Android phone. Free, with the code and a prompt for your AI editor.

[Get a free API key](https://app.unlimitedmessaging.app)[See the API](https://unlimitedmessaging.app/api)

The short answer

## How do you send email, SMS and WhatsApp from Supabase?

Create a database webhook on your table (profiles, orders) that calls a Supabase Edge Function on INSERT. The function reads the new row and makes one POST /message request to Unlimited Messaging, which sends the email from your mailbox, the WhatsApp from your number and the SMS from your Android phone. [Database webhooks](https://supabase.com/docs/guides/database/webhooks) run on pg\_net, so the insert never waits for the message.

Supabase has no API for the messages your app sends. Its built-in email service is there for Auth emails: it sends 2 messages an hour, only to addresses in your project's team, and Supabase states it is not meant for production. A welcome email, an order confirmation or a WhatsApp to a customer is yours to send.

An Edge Function is the right place for it: it runs on the server, reads secrets with Deno.env.get, and Supabase's Free plan includes 500,000 invocations. The usual setup is one provider per channel, an email API, Twilio for SMS, Meta's Cloud API for WhatsApp: three keys, three bills. Here one request covers the three channels, and the Free plan of Unlimited Messaging has no per-message fee.

This guide covers the messages your app sends. Auth emails (sign-up confirmation, magic link, password reset) and phone OTP stay in Supabase Auth's own settings, where you plug a custom SMTP server or an SMS provider.

Related: [email and WhatsApp in a single API request](https://unlimitedmessaging.app/articles/email-whatsapp-single-api-request), and [the free SMS API that sends from your own phone](https://unlimitedmessaging.app/articles/free-sms-api).

![Illustration: automation nodes linking a trigger to a message and an email, with the headline “A new row in Supabase, a message out”.](https://unlimitedmessaging.app/_next/image?url=%2Fassets%2Farticles%2Fcovers%2Fsupabase-whatsapp-email-sms-notifications-en.png&w=3840&q=75)

Definition
Supabase database webhook

A trigger that sends an HTTP request through the pg\_net extension after an INSERT, UPDATE or DELETE on a table. The JSON payload carries type, table, schema, record and old\_record.

Usually paired with an Edge Function to send an email or an SMS when a row is inserted.

[Source: Supabase Docs, Database Webhooks↗](https://supabase.com/docs/guides/database/webhooks)

Step by step

## How do you wire it up, step by step?

Five steps, about 15 minutes. You need a Supabase project, the Supabase CLI and a free Unlimited Messaging account.

1. 01  
### Connect your channels and create an API key  
In the Unlimited Messaging app, link your WhatsApp number by QR code, connect your mailbox over IMAP/SMTP (a Gmail app password works) and, for SMS, sign in to the free Android app on a phone with a SIM. Connect only the channels you need, then create an API key.  
supabase/functions/.env.env  
```  
# supabase/functions/.env (gitignored, local only)  
# Created at app.unlimitedmessaging.app > API keys  
UM_API_KEY=um_live_xxxx  
# Any long random string, shared with the database webhook  
WEBHOOK_SECRET=change-me-to-a-long-random-string  
```
2. 02  
### Create the function and store the secrets  
Create the function with the CLI and push both secrets to your project. They live only in the function's environment: never put the API key in a VITE\_ or NEXT\_PUBLIC\_ variable, or anywhere in frontend code.  
TerminalSupabase CLI  
```  
supabase functions new notify-signup  
# Push the secrets to your project (never to the frontend)  
supabase secrets set --env-file supabase/functions/.env  
supabase secrets list  
```
3. 03  
### Write the function  
The function checks the shared secret, reads the inserted row, and sends the email every time and the WhatsApp only when the row has a phone number. priority: transactional puts the message ahead of any bulk send waiting in your queue.  
notify-signup/index.tsDeno / TypeScript  
```  
// supabase/functions/notify-signup/index.ts  
type Profile = { id: string; email: string; phone: string | null; full_name: string | null };  
type WebhookPayload = {  
  type: 'INSERT' | 'UPDATE' | 'DELETE';  
  table: string;  
  schema: string;  
  record: Profile;  
  old_record: Profile | null;  
};  
Deno.serve(async (req) => {  
  // The database webhook sends this header; nobody else knows it  
  if (req.headers.get('x-webhook-secret') !== Deno.env.get('WEBHOOK_SECRET')) {  
    return new Response('Unauthorized', { status: 401 });  
  }  
  const { record } = (await req.json()) as WebhookPayload;  
  const name = record.full_name ?? 'there';  
  // Email always, WhatsApp when the row has a phone (E.164: +33612345678).  
  // Use { channel: 'SMS' } instead for people who are not on WhatsApp.  
  const channels: Array<{ channel: 'EMAIL' | 'WHATSAPP' | 'SMS' }> = [{ channel: 'EMAIL' }];  
  if (record.phone) channels.push({ channel: 'WHATSAPP' });  
  const res = await fetch('https://api.unlimitedmessaging.app/message', {  
    method: 'POST',  
    headers: {  
      Authorization: `Bearer ${Deno.env.get('UM_API_KEY')}`,  
      'Content-Type': 'application/json',  
    },  
    body: JSON.stringify({  
      to: { email: record.email, phone: record.phone ?? undefined },  
      channels,  
      subject: 'Welcome aboard',  
      text: `Hi ${name}, your account is ready. Reply to this message if you need anything.`,  
      priority: 'transactional',  
    }),  
  });  
  if (!res.ok) console.error('Unlimited Messaging', res.status, await res.text());  
  return new Response(null, { status: res.ok ? 200 : 502 });  
});  
```
4. 04  
### Deploy it, protected by your own secret  
A database webhook sends no user JWT, so turn the platform check off for this function only (--no-verify-jwt, or verify\_jwt = false in config.toml). The x-webhook-secret header the function checks keeps strangers out.  
TerminalSupabase CLI  
```  
# A database webhook sends no user JWT: turn the platform check off  
# for this function only, the x-webhook-secret header protects it  
supabase functions deploy notify-signup --no-verify-jwt  
# Or keep it in supabase/config.toml:  
# [functions.notify-signup]  
# verify_jwt = false  
```
5. 05  
### Create the database webhook  
In the dashboard, Database > Webhooks: choose the table (profiles here), the Insert event, the type Supabase Edge Functions and the notify-signup function, then add an x-webhook-secret header with the same value. Insert a test row: this is the body the function receives.  
POST bodyWebhook payload  
```  
{  
  "type": "INSERT",  
  "table": "profiles",  
  "schema": "public",  
  "record": {  
    "id": "8f1c2d3e-0000-4000-8000-000000000000",  
    "email": "lea@example.com",  
    "phone": "+33612345678",  
    "full_name": "Lea"  
  },  
  "old_record": null  
}  
```

Vibe coding

## Using Lovable, Cursor or Claude Code? Paste this prompt

The prompt gives your AI editor the exact pattern: an Edge Function, secrets stored in Supabase, one REST call. It asks you before anything is sent for real.

Prompt to copy

Add transactional notifications to this Supabase project with Unlimited Messaging (email, WhatsApp and SMS sent from my own accounts).

1. Create a Supabase Edge Function named notify-signup. Read UM_API_KEY and WEBHOOK_SECRET with Deno.env.get. Never put the key in frontend code or in a VITE_ / NEXT_PUBLIC_ variable.
2. The function receives a Supabase database webhook payload { type, table, schema, record, old_record }. Return 401 unless the x-webhook-secret header equals WEBHOOK_SECRET.
3. Send one POST https://api.unlimitedmessaging.app/message with the header Authorization: Bearer UM_API_KEY and the JSON { to: { email, phone }, channels: [{ channel: 'EMAIL' }, { channel: 'WHATSAPP' }], subject, text, priority: 'transactional' }. Only add WHATSAPP (or SMS) when the row has a phone number in E.164 format.
4. Give me the commands: supabase secrets set, supabase functions deploy notify-signup --no-verify-jwt, and how to create the database webhook on INSERT of my table with the x-webhook-secret header.
5. API reference: https://docs.unlimitedmessaging.app. I create the API key at https://app.unlimitedmessaging.app.

Ask me which table and which message text to use before writing the code.

The options

## Which way to send messages from Supabase?

Four ways to send a notification when a row lands in your database, from the built-in service to one API for every channel.

__Which way to send messages from Supabase?__
| [Supabase built-in email](https://supabase.com/docs/guides/auth/auth-smtp)Auth emails only | [Resend from a function](https://resend.com/pricing)Email API | [Twilio from a function](https://www.twilio.com/en-us/sms/pricing)SMS and WhatsApp API | Unlimited MessagingEmail, WhatsApp and SMS      |                                                 |
| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------- | ----------------------------------------------- |
| Channels                                                                                   | Auth emails only                                              | Email                                                                                  | SMS and WhatsApp, billed per message            | Email, WhatsApp and SMS in one request          |
| Free allowance                                                                             | 2 emails an hour, team addresses only                         | 3,000 emails a month, 100 a day                                                        | Trial: up to 5 verified numbers                 | Free plan with no per-message fee               |
| Sender                                                                                     | Supabase's address                                            | Your verified domain                                                                   | A Twilio number or a registered WhatsApp sender | Your own mailbox, WhatsApp number and phone     |
| WhatsApp messages                                                                          | No                                                            | No                                                                                     | Meta-approved templates to start a conversation | Free text from your linked number               |
| Setup                                                                                      | None                                                          | DNS records for your domain                                                            | Account, number, WhatsApp sender registration   | QR code, IMAP/SMTP login, Android app           |
| Best for                                                                                   | Testing Auth flows                                            | High-volume email                                                                      | High-volume SMS, official WhatsApp              | App messages one at a time, free while you grow |

Checked on 9 November 2026 on supabase.com, resend.com/pricing and Twilio's trial documentation (links in the sources). Free tiers change: follow the links before you build on one.

The catch

## What are the limits?

Free removes the per-message bill. It does not remove the rules of WhatsApp, of your phone or of your mailbox.

1. 01  
### WhatsApp is unofficial, and spam gets numbers banned  
Your number is linked as a device, outside Meta's Business Platform. Messages to customers who signed up and expect them are low risk; bulk messages to strangers can get the number banned. Keep WhatsApp for transactional messages.
2. 02  
### SMS needs an Android phone that stays on  
SMS leave from the phone's SIM, on your carrier plan. Android asks for confirmation beyond 30 SMS in 30 minutes, so the app paces sends to about 30 every 30 minutes: fine for sign-ups and orders, not for a launch-day blast.
3. 03  
### Email follows your mailbox's limits  
Emails leave from your own mailbox over SMTP, so its daily cap applies: 500 a day on a Gmail account. For newsletters to thousands of people, use a bulk email service.
4. 04  
### Free plan messages carry a footer  
On the Free plan, messages end with a short "Sent with UnlimitedMessaging.app" line, and media and webhooks are paid features. Medium and Max remove the line.
5. 05  
### The insert does not wait for the message  
pg\_net sends the request asynchronously, so a failing function never rolls back the insert. Log the API response in the function and watch the function logs.
6. 06  
### The key stays server-side  
Anyone who opens your frontend bundle can reuse a key placed there. The key belongs in Edge Function secrets, and the webhook secret stops strangers from calling your function.

When to choose something else

### Thousands of emails a day, or official WhatsApp?

For newsletters or high-volume email, a dedicated email API such as Resend or SendGrid fits better. For Meta's official WhatsApp Business Platform, use the Cloud API or a provider like Twilio. Unlimited Messaging fits the messages a SaaS sends one at a time, welcome, order, reminder, alert, from your own accounts, free while you test and grow.

FAQ

## Questions about sending messages from Supabase

Only Auth emails. The built-in service sends 2 emails an hour, only to members of your project's team, and is not meant for production. For your own app emails, call an email API from an Edge Function triggered by a database webhook.

From an Edge Function, with fetch. With Unlimited Messaging, POST /message with the channel SMS sends from your own Android phone's SIM, so there is no per-SMS fee from us; the phone has to stay on and online.

Create a database webhook on INSERT that calls an Edge Function, then send POST /message with the channel WHATSAPP and the phone number from the new row, in E.164 format (+33612345678).

Both: the database webhook is the trigger, the Edge Function holds the code and the secret. You can also call the function from your app right after a sign-up, or call the API from any other server code.

The Unlimited Messaging Free plan is permanent, needs no credit card and has no per-message fee on any channel; messages carry a short footer. Supabase's Free plan includes 500,000 Edge Function invocations. SMS count against your carrier plan.

Yes, when the project runs on Supabase. Paste the prompt above, and check that the editor stores the key as a Supabase secret, not in the frontend.

In Node.js code, yes: npm i @unlimited-messaging/sdk gives you a typed client. In a Deno Edge Function, plain fetch needs no dependency and is all this flow requires.

Sources

## Sources & references

To check the information in this article for yourself:

1. [01Database Webhooks↗Supabase Docs](https://supabase.com/docs/guides/database/webhooks)
2. [02Managing secrets (environment variables) for Edge Functions↗Supabase Docs](https://supabase.com/docs/guides/functions/secrets)
3. [03Function configuration (verify\_jwt)↗Supabase Docs](https://supabase.com/docs/guides/functions/function-configuration)
4. [04Send emails with custom SMTP (built-in limit: 2 messages an hour)↗Supabase Docs](https://supabase.com/docs/guides/auth/auth-smtp)
5. [05Pricing (500,000 Edge Function invocations on Free)↗Supabase](https://supabase.com/pricing)
6. [06Pricing (Free: 3,000 emails a month, 100 a day)↗Resend](https://resend.com/pricing)
7. [07How to use your free trial account (Messaging)↗Twilio Docs](https://www.twilio.com/docs/messaging/guides/how-to-use-your-free-trial-account)
8. [08Message templates↗Meta for Developers](https://developers.facebook.com/docs/whatsapp/business-management-api/message-templates)
9. [09Limits for sending and getting mail (500 emails a day)↗Gmail Help](https://support.google.com/mail/answer/22839)
10. [10SmsUsageMonitor (30 SMS in 30 minutes threshold)↗Android Open Source Project](https://android.googlesource.com/platform/frameworks/opt/telephony/+/refs/heads/main/src/java/com/android/internal/telephony/SmsUsageMonitor.java)
11. [11API reference: POST /message↗Unlimited Messaging Docs](https://docs.unlimitedmessaging.app)

![Ilian, senior software engineer](https://ilianazz.com/images/iliazz.png)

Written by

[Ilian](https://unlimitedmessaging.app/authors/ilian) · Senior Software Engineer

A senior software engineer, he founds and runs several tech companies. He builds products around messaging APIs, automation and AI integration, and shares here what he learns while building.

[View LinkedIn profile↗](https://www.linkedin.com/in/ilianAzz/)Updated November 9, 2026

![](https://unlimitedmessaging.app/assets/logos/whatsapp.svg)![](https://unlimitedmessaging.app/assets/logos/email.svg)![](https://unlimitedmessaging.app/assets/logos/sms.svg)

## Send your first Supabase notification today.

Create a free account, connect a mailbox or a WhatsApp number, paste the function. No credit card, no per-message fee.

[Start for free→](https://app.unlimitedmessaging.app)

Similar articles
* [![](https://unlimitedmessaging.app/_next/image?url=%2Fassets%2Farticles%2Fcovers%2Femail-whatsapp-single-api-request-en.png&w=3840&q=75)One API request, two channels: email and WhatsApp at onceSend the same message by WhatsApp and email in one call, from your own number and mailbox, free on every plan.](https://unlimitedmessaging.app/articles/email-whatsapp-single-api-request)
* [![](https://unlimitedmessaging.app/_next/image?url=%2Fassets%2Farticles%2Fcovers%2Ffree-sms-api-en.png&w=3840&q=75)Free SMS API: what is really free, and what is a trial?FreeTwilio's trial, Textbelt's free key, and Android gateways that send on your own plan: the honest comparison.](https://unlimitedmessaging.app/articles/free-sms-api)
* [![](https://unlimitedmessaging.app/_next/image?url=%2Fassets%2Farticles%2Fcovers%2Ftypescript-sdk-en.png&w=3840&q=75)Send WhatsApp from Node.js with a fully typed SDKFully typed npm package for Node.js, Next.js, and any JS environment.](https://unlimitedmessaging.app/articles/typescript-sdk)
