---
title: "Recipe: Email Verification Flow"
description: "Sign up, verify the email address and log in with teenybase's built-in auth extension and an email provider."
url: https://teenybase.com/docs/recipes/email-verification
last_updated: 2026-10-26
---

> Documentation index: https://teenybase.com/llms.txt lists every teenybase docs page with a link to its Markdown version. All docs in one file: https://teenybase.com/llms-full.txt

# Email Verification Flow

Full sign-up, verify email, and login flow using the built-in auth extension with an email provider.

### Config

```typescript
export default {
    appUrl: 'https://myapp.com',
    jwtSecret: '$JWT_SECRET',
    email: {
        from: 'My App <noreply@myapp.com>',
        variables: {
            company_name: 'My App',
            company_url: 'https://myapp.com',
            company_address: '123 Main St',
            company_copyright: '© 2025 My App',
            support_email: 'support@myapp.com',
        },
        resend: {
            RESEND_API_KEY: '$RESEND_API_KEY',
        },
    },
    tables: [{
        name: 'users',
        autoSetUid: true,
        fields: [...baseFields, ...authFields],
        triggers: [createdTrigger, updatedTrigger],
        extensions: [{
            name: 'rules',
            listRule: 'auth.uid == id',
            viewRule: 'auth.uid == id',
            createRule: 'true',
            updateRule: 'auth.uid == id',
            deleteRule: null,
        } as TableRulesExtensionData, {
            name: 'auth',
            jwtSecret: '$JWT_SECRET',
            jwtTokenDuration: 3600,
            maxTokenRefresh: 4,
        } as TableAuthExtensionData],
    }],
} satisfies DatabaseSettings
```

### The flow

```bash
# 1. Sign up
curl -X POST http://localhost:8787/api/v1/table/users/auth/sign-up \
  -H 'Content-Type: application/json' \
  -d '{
    "username": "alice",
    "email": "alice@example.com",
    "password": "strongpassword",
    "passwordConfirm": "strongpassword",
    "name": "Alice"
  }'
# → Returns token + refreshToken. email_verified is false.

# 2. Request verification email
curl -X POST http://localhost:8787/api/v1/table/users/auth/request-verification \
  -H 'Content-Type: application/json' \
  -d '{"email": "alice@example.com"}'
# → Sends email with verification link containing a token

# 3. Confirm verification (token from email link)
curl -X POST http://localhost:8787/api/v1/table/users/auth/confirm-verification \
  -H 'Content-Type: application/json' \
  -d '{"token": "VERIFICATION_TOKEN_FROM_EMAIL"}'
# → email_verified is now true

# 4. Login
curl -X POST http://localhost:8787/api/v1/table/users/auth/login-password \
  -H 'Content-Type: application/json' \
  -d '{"identity": "alice@example.com", "password": "strongpassword"}'
```

### Email providers

Teenybase supports **Resend** and **Mailgun**. Set the API key in your `.prod.vars` file and reference it with `$`:

```env
# .prod.vars
RESEND_API_KEY=re_xxxxxxxxxxxxx
```

For local development, add `mock: true` to the email config to log emails to the console instead of sending them.
