The `send_email` hook payload's `email_data.site_url` is populated from `API_EXTERNAL_URL` (e.g. `https://<ref>.supabase.co/auth/v1`) instead of `GOTRUE_SITE_URL` (e.g. `https://myapp.com`). The [SMTP template path](https://github.com/supabase/auth/blob/master/internal/mailer/templatemailer/templatemailer.go) gets this right — `{{ .SiteURL }}` resolves from `GOTRUE_SITE_URL`. The [hook path](https://github.com/supabase/auth/blob/master/internal/api/mail.go#L780) doesn't, it pulls from `API_EXTERNAL_URL` instead. So if you're using the hook to build confirmation links from `site_url`, they point to the auth server instead of your app. The field is called `site_url` but it's not the site URL. `email_data.site_url` in the hook payload should use `GOTRUE_SITE_URL`, same as `{{ .SiteURL }}` in the templates.