> ## Documentation Index
> Fetch the complete documentation index at: https://docs.brew.new/llms.txt
> Use this file to discover all available pages before exploring further.

# Supabase

> Trigger Brew automations from Supabase auth events, signups, email confirmation, password changes, bans, and more.

Connect [Supabase](https://supabase.com) so events on the `auth.users` table fire Brew automations. Send a real welcome email after the email is verified, alert the user the moment their password changes, drip pending-invite reminders, or surface account-suspension notices.

## What you can do

* **Trigger automations from Supabase auth events.** Real signups, email + phone confirmations, password changes, bans, invites
* **Auto-sync contacts into your audience.** Every Supabase event upserts the user into Brew with `supabase_*` custom fields (`supabase_user_id`, `supabase_account_status`, `supabase_email_verified_at`, `supabase_phone_verified_at`, `supabase_last_sign_in_at`, etc.) you can filter and segment on
* **Get more than INSERT/UPDATE/DELETE.** Brew classifies column-level transitions into 12 marketing-relevant events (e.g. `auth.user.email_confirmed` fires the moment `email_confirmed_at` flips from null to set)
* **Stay safe at scale.** Brew signs every webhook with a shared secret you control; pgcrypto + Vault handle the HMAC inside Postgres

## How it works

1. Brew mints a unique webhook URL for your brand and generates the setup SQL you paste into your Supabase project.
2. The SQL installs the `pgcrypto` extension, stores your shared secret in Supabase Vault, and creates a trigger on `auth.users` that HMAC-signs every change before pg\_net POSTs it to Brew.
3. On receipt Brew verifies the signature against your shared secret. Any UPDATE is classified — if a specific column transition matches one of the 9 synthetic events (e.g. `email_confirmed_at` going from null to set), Brew fires that more-specific event instead of the generic `auth.user.updated`.
4. For each verified event Brew (a) starts every **Published** automation whose trigger matches and (b) upserts the Supabase user into your [audience](/audience/add-contacts) with `supabase_*` custom fields.

See [How event triggers work](/integrations/integrations#how-event-triggers-work) for the conceptual flow shared by every event-source integration.

## Setup

<Steps>
  <Step title="Generate your Brew webhook URL">
    In Brew, open **Integrations**, click the **Supabase** card, and click **Generate URL**. The SQL block in step 3 will pre-fill the URL for you.
  </Step>

  <Step title="Generate a 32-character shared secret">
    Run `openssl rand -hex 32` in your terminal. You'll paste this same value into the SQL block (step 3) and the Brew connect form (step 4).
  </Step>

  <Step title="Run the setup SQL in Supabase">
    In your Supabase project, open **SQL Editor → New query**. Paste the SQL block that Brew shows in the connect dialog, replace `<PASTE_YOUR_SECRET_HERE>` with the secret from step 2, then click **Run**.

    The block installs the pgcrypto extension, stores your shared secret in Supabase Vault, and creates a trigger on `auth.users` that signs every change with HMAC-SHA-256 before pg\_net POSTs it to Brew.
  </Step>

  <Step title="Paste the same secret into Brew">
    Paste the secret from step 2 into the Brew connect form and click **Connect**. Brew uses it to verify every webhook the new trigger sends.
  </Step>

  <Step title="Verify it's working">
    Sign up a test user in your Supabase Auth UI (or run an `INSERT` into `auth.users` via the SQL Editor). Within a few seconds it should appear in the **Manage → Recent events** panel of the Supabase integration page in Brew. If it doesn't, recheck the Vault entry and that the trigger SQL ran cleanly.
  </Step>
</Steps>

<Note>
  Re-running the SQL block after rotating the secret is safe. The block drops and re-creates the trigger idempotently.
</Note>

## Triggering automations

Once connected, every Supabase event below is provisioned automatically and available as a trigger in the [automation builder](/create-emails/automations). The **Manage** tab is a read-only catalogue plus a live **Recent events** stream — no per-event enable step. Whether an event fires is controlled by whether the bound automation is **Published**.

### Supported events

Brew supports 12 Supabase auth events — 3 raw envelope types and 9 synthetic UPDATE classifications:

**Raw envelope events**

* `auth.user.created` — INSERT into `auth.users`
* `auth.user.updated` — UPDATE that didn't match a synthetic classification
* `auth.user.deleted` — DELETE from `auth.users`

**Synthetic UPDATE events**

* `auth.user.email_confirmed` — `email_confirmed_at` transitions from null to set
* `auth.user.phone_confirmed` — `phone_confirmed_at` transitions from null to set
* `auth.user.email_changed` — `email` column changes between rows
* `auth.user.password_changed` — `encrypted_password` changes between rows
* `auth.user.signed_in` — `last_sign_in_at` changes
* `auth.user.banned` — `banned_until` transitions from null to set
* `auth.user.unbanned` — `banned_until` transitions from set to null
* `auth.user.invited` — `invited_at` transitions from null to set
* `auth.user.upgraded_from_anonymous` — `is_anonymous` flips from true to false

<Note>
  A single UPDATE only fires one synthetic event — the highest-priority classification wins. Email confirmation beats phone confirmation, which beats anonymous-to-real upgrade, and so on.
</Note>

<Tip>
  In chat, say *"Send the real welcome email after the user confirms their email"* and Brew will scaffold the automation with `auth.user.email_confirmed` pre-selected.
</Tip>

## Common patterns

| Goal                                        | Supabase event                      |
| ------------------------------------------- | ----------------------------------- |
| Initial signup notification                 | `auth.user.created`                 |
| Real welcome email (after verification)     | `auth.user.email_confirmed`         |
| Security alert on a password change         | `auth.user.password_changed`        |
| Security alert sent to the **old** email    | `auth.user.email_changed`           |
| Pending-invite reminder drip                | `auth.user.invited`                 |
| Welcome anonymous users after they convert  | `auth.user.upgraded_from_anonymous` |
| Account-suspension notice                   | `auth.user.banned`                  |
| Welcome-back after a successful appeal      | `auth.user.unbanned`                |
| Re-engagement detection for returning users | `auth.user.signed_in`               |

<Warning>
  `auth.user.signed_in` also fires on Supabase token refreshes. Add a per-user filter or a `wait` node if you want a true "they came back after a long time" signal.
</Warning>

## Personalization

| Variable                                                     | Example                                |
| ------------------------------------------------------------ | -------------------------------------- |
| `{{@trigger:output.payload.email}}`                          | `alex@example.com`                     |
| `{{@trigger:output.payload.userId}}`                         | `2c5b2c1c-fa18-4d79-9e6f-d83eda2f9d68` |
| `{{@trigger:output.payload.phone}}`                          | `+15555550100`                         |
| `{{@trigger:output.payload.previousValue}}` (e.g. old email) | `old@example.com`                      |
| `{{@trigger:output.payload.newValue}}` (e.g. new email)      | `alex@example.com`                     |

## Troubleshooting

<AccordionGroup>
  <Accordion title="An event arrived but no automation fired" icon="circle-question">
    Open the canvas and confirm at least one automation bound to this event is set to **Published** (not Draft). The Brew integration's **Manage → Recent events** panel confirms the webhook is arriving — if it isn't there, the issue is upstream (pgcrypto trigger not installed, secret mismatch). If the event is there but no email sent, the only remaining gate is `automation.published`.
  </Accordion>

  <Accordion title="Webhooks aren't arriving at all" icon="triangle-exclamation">
    Re-run the setup SQL block from the integration page. The block is idempotent — it'll re-create the trigger and re-write the Vault entry. Confirm that `pgcrypto` is installed (`SELECT * FROM pg_extension WHERE extname = 'pgcrypto';`) and that the secret in Vault matches the one pasted into Brew.
  </Accordion>

  <Accordion title="auth.user.signed_in fires constantly" icon="rotate">
    Supabase token refreshes also bump `last_sign_in_at`, which fires `auth.user.signed_in` alongside true sign-ins. Add a per-user `wait` or `filter` node in your automation to ignore repeats within a short window, or rely on `auth.user.email_confirmed` / `auth.user.upgraded_from_anonymous` for higher-signal events.
  </Accordion>

  <Accordion title="I want to test before going live" icon="flask">
    Insert a test row into `auth.users` (or sign up via your normal flow) and watch the **Manage → Recent events** panel. Pre-publish your automation as a Draft, run a test send from the email editor, then flip to Published once you're happy.
  </Accordion>
</AccordionGroup>

## Requirements

* A Supabase project where you can run SQL against the `auth` schema
* Permission to install extensions (`pgcrypto`) and write to Supabase Vault

## Need Help?

Our team is ready to support you at every step of your journey with Brew. Choose the option that works best for you:

<Tabs>
  <Tab title="Self-Service Tools">
    <CardGroup cols="2">
      <Card title="Search Documentation" icon="magnifying-glass" color="#c44925">
        Type in the "Ask any question" search bar at the top left to instantly find relevant documentation pages.
      </Card>

      <Card title="ChatGPT/Claude Integration" icon="robot" color="#c44925">
        Click "Open in ChatGPT" at the top right of any page to analyze documentation with ChatGPT or Claude for deeper insights.
      </Card>
    </CardGroup>
  </Tab>

  <Tab title="Talk to Our Team">
    <CardGroup cols="2">
      <Card title="Schedule a Call" icon="calendar" color="#c44925" href="https://calendar.google.com/calendar/u/0/appointments/schedules/AcZssZ1iYoRUG1J792XQpbuQLjSRRDupr7MwraFK-HQRCtTYdBmrQi8nZu2qXfzKQigb8gbKJK3KN3-R">
        Book time with our founders for personalized guidance on strategy, best practices, or complex implementation questions.
      </Card>

      <Card title="Call Us Directly" icon="phone" color="#c44925">
        Need immediate assistance? Reach us at **+1-(332)-203-2145** for urgent issues or time-sensitive questions.
      </Card>

      <Card title="Slack Channel" icon="slack" color="#c44925">
        Our preferred support channel. You'll receive an invite after signup for direct founder support and fast responses.
      </Card>

      <Card title="Email Support" icon="envelope" color="#c44925" href="mailto:support@brew.new">
        Contact us at **[support@brew.new](mailto:support@brew.new)** for detailed inquiries or if you prefer not to use Slack.
      </Card>
    </CardGroup>
  </Tab>
</Tabs>
