Skip to main content
This guide only covers auth emails. To sync Supabase users into your Loops audience and trigger workflows, see our Supabase contact sync guide.
Supabase Auth’s Send Email Hook lets you send emails via an HTTP endpoint you control rather than using Supabase’s own sender. This guide shows how to point that hook at Loops, with a Supabase Edge Function that verifies the request and sends the matching Loops transactional email.
This is the recommended way to send Supabase authentication emails with Loops. Looking for something simpler to set up? See our Supabase SMTP guide.

How it works

1

A user triggers an auth email

For example, they sign up, request a magic link, or ask to reset their password.
2

Supabase calls your Edge Function

Instead of sending the email itself, Supabase POSTs a signed payload containing the user and an email_action_type (like signup or recovery) to your Send Email Hook endpoint.
3

Your function sends the matching Loops email

The function verifies the request signature, maps the email_action_type to a Loops transactional email, and sends it through the Loops API with the token and links Supabase provided.

1. Create transactional emails in Loops

Create a transactional email in Loops for each Supabase auth email type you want to send. You don’t need to create all of them — only create templates for the action types you use, and any action type without a matching template will fall back to Supabase’s default sender (see step 3).
Supabase occasionally adds new email_action_type values. Check the Send Email Hook docs for the current list before going live.
For token, add a {token} data variable to show a 6-digit OTP code. For a clickable link instead, build a URL data variable using {siteUrl}, {tokenHash} and {redirectTo}, for example:
After publishing each email, copy its Transactional ID from the Review page — you’ll need it in the next step.

2. Add environment variables

You’ll need a Loops API key and the transactional IDs from the previous step. Create an API key from API Settings.
.env
Only add variables for the templates you created in step 1. You’ll generate SEND_EMAIL_HOOK_SECRET from the Supabase dashboard in step 4.

3. Write the Edge Function

Create a new Supabase Edge Function:
Supabase signs each request using the Standard Webhooks spec, so verify it with the standardwebhooks library before sending anything. This function maps email_action_type to a Loops transactional ID and sends the email with the Loops SDK.
supabase/functions/send-email/index.ts
Only include data variables in the request that exist on that specific template. If a template doesn’t have tokenNew or tokenHashNew added as data variables (all types other than email_change), it’s fine to send them anyway — Loops ignores values that don’t match a variable on the template.
Deploy the function and push your secrets:

4. Enable the hook in Supabase

In your Supabase project, go to Authentication -> Hooks and add a new Send Email hook. Select HTTPS as the hook type and paste in your deployed Edge Function URL (find it in Edge Functions after deploying). Supabase will generate a signing secret in the form v1,whsec_... — copy it into SEND_EMAIL_HOOK_SECRET and re-run supabase secrets set so the deployed function has the matching value.

Testing the hook

Create a test user from Authentication -> Users -> Add user, then trigger an email (for example, click Send magic link on that user). Check the Loops Transactional page for the send, and Supabase’s Logs -> Auth logs (search for “magiclink” or “signup”) if nothing arrives. A 401 in the auth logs usually means SEND_EMAIL_HOOK_SECRET doesn’t match the secret shown on the Hooks page.

Keep templates in sync from code

Because auth templates are just transactional emails, you can update them programmatically with the Update an email message API instead of editing them by hand. Pass expectedRevisionId on every update so a stale edit doesn’t silently overwrite someone else’s change — the API returns 409 Conflict if the revision has moved on since you last fetched it.
This is useful for keeping subject lines, preview text, or LMX content in version control and rolling changes out with a script or CI job instead of the editor. See more email message API examples.

Send Email Hook vs Loops SMTP

Both approaches use the same transactional emails you create in Loops, so you can start with SMTP and move to the Send Email Hook later without rebuilding your templates.

Bring in the rest of the lifecycle

The Send Email Hook only covers auth emails. Combine it with our Supabase contact sync guide to sync users to your Loops audience and trigger onboarding, activation, or plan-change workflows from the same auth.users events:
  1. Use this guide’s Send Email Hook for confirm signup, magic link, invite, reset password, and security notification emails.
  2. Use the Supabase contact sync database webhook to create or update Loops contacts on INSERT and UPDATE of auth.users.
  3. Build a workflow triggered by the INSERT event to send a welcome or onboarding sequence once a user signs up.
Setting this up with a coding agent? Give it this prompt:

Troubleshooting

If your emails are not sending:
  • Confirm each transactional email in Loops is Published.
  • Confirm SEND_EMAIL_HOOK_SECRET matches the secret shown on the Hooks page in Supabase, including the v1,whsec_ prefix before it’s stripped in code.
  • Check that email_action_type in the incoming payload matches a key in TRANSACTIONAL_IDS — unmapped types are silently skipped rather than erroring.
  • Check Supabase’s Logs -> Auth for the response your function returned.
  • Check that your Loops sending domain is verified.

Read more

Send transactional email

Loops API endpoint used to send transactional emails.

Update email message

Sync template content programmatically with revision-safe updates.

Supabase contact sync

Sync contacts and trigger workflows from Supabase events.

Supabase SMTP

A simpler setup for sending Supabase auth emails through Loops.
Last modified on July 13, 2026