User Creation Webhook
This endpoint is a webhook that processes user creation events from Supabase. It is automatically triggered when a new user is created in the database.
Security
Authentication
This endpoint uses Supabase’s webhook signature verification for security. Each request must include a valid signature in the headers.
// Webhook signature verification
import { createHmac } from 'crypto'
const WEBHOOK_SECRET = process . env . SUPABASE_WEBHOOK_SECRET
export function verifyWebhookSignature (
payload : string ,
signature : string
) : boolean {
const hmac = createHmac ( 'sha256' , WEBHOOK_SECRET )
const computedSignature = hmac . update ( payload ). digest ( 'hex' )
return computedSignature === signature
}
x-supabase-signature: SHA256 hash of the payload
content-type: application/json
Request Body
Operation type. Must be “INSERT” for user creation.
Table name. Must be “users”.
Database schema. Must be “auth”.
New user data Creation date in ISO format
Previous data (null for an insert)
Implementation
Webhook Handler
import { NextApiRequest , NextApiResponse } from 'next'
import { createClient } from '@supabase/supabase-js'
import { verifyWebhookSignature } from '../../../lib/webhooks'
const supabase = createClient (
process . env . NEXT_PUBLIC_SUPABASE_URL ! ,
process . env . SUPABASE_SERVICE_ROLE_KEY !
)
export default async function handler (
req : NextApiRequest ,
res : NextApiResponse
) {
// Verify request method
if ( req . method !== 'POST' ) {
return res . status ( 405 ). json ({ message: 'Method not allowed' })
}
// Verify signature
const signature = req . headers [ 'x-supabase-signature' ]
if ( ! signature || ! verifyWebhookSignature ( JSON . stringify ( req . body ), signature as string )) {
return res . status ( 401 ). json ({ message: 'Invalid signature' })
}
try {
const { type , record } = req . body
// Verify event type
if ( type !== 'INSERT' ) {
return res . status ( 400 ). json ({
success: false ,
message: 'Invalid data: unsupported operation type'
})
}
// Process the new user
await processNewUser ( record )
return res . status ( 200 ). json ({
success: true ,
message: 'New user processed successfully'
})
} catch ( error ) {
console . error ( 'Webhook error:' , error )
return res . status ( 500 ). json ({
success: false ,
message: 'Internal server error'
})
}
}
async function processNewUser ( userData : any ) {
// 1. Create user profile
await supabase
. from ( 'profiles' )
. insert ({
id: userData . id ,
email: userData . email ,
full_name: userData . raw_user_meta_data ?. full_name
})
// 2. Send welcome email
await sendWelcomeEmail ( userData . email )
// 3. Initialize settings
await initializeUserSettings ( userData . id )
// 4. Record analytics event
await recordAnalyticsEvent ( 'user_created' , {
user_id: userData . id ,
timestamp: new Date (). toISOString ()
})
}
## Triggered Actions
When a new user is created , this webhook automatically performs the following actions :
1. ** User Profile Creation **
- Creates an associated profile in the `profiles` table
- Initializes default user preferences
2. ** Welcome Email **
- Sends a personalized welcome email via Resend
- Includes getting started guide and next steps
3. ** Marketing Platform Sync **
- Adds user to Resend audience for marketing communications
- Tags user based on signup source and preferences
4. ** Account Setup **
- Initializes default account settings
- Creates necessary database records for the user
5. ** Analytics **
- Records the signup event in our analytics system
- Tracks user attribution data if available
## Error Handling
The webhook implements comprehensive error handling :
```typescript
try {
// Process webhook
} catch (error) {
// Log error details
console.error('Webhook error:', {
error,
timestamp: new Date().toISOString(),
payload: req.body
})
// Determine error type and return appropriate response
if (error.code === 'P2002') {
return res.status(409).json({
success: false,
message: 'User already exists'
})
}
// Default error response
return res.status(500).json({
success: false,
message: 'Internal server error'
})
}
Testing
Local Testing
# Start local development server
npm run dev
# Test webhook with curl
curl -X POST http://localhost:3000/api/webhooks/user-created \
-H "Content-Type: application/json" \
-H "x-supabase-signature: YOUR_TEST_SIGNATURE" \
-d '{
"type": "INSERT",
"table": "users",
"schema": "auth",
"record": {
"id": "test-user-id",
"email": "test@example.com",
"created_at": "2024-04-02T12:00:00Z"
}
}'
Production URLs
Development: http://localhost:3000/api/webhooks/user-created
Production: https://onlyautomator.com/api/webhooks/user-created
Notes
This webhook is designed to be called automatically by Supabase
Manual calls should only be made for testing purposes
All webhook calls are logged for monitoring and debugging
Failed webhook calls are automatically retried by Supabase
Operation type. Must be "INSERT" for user creation.
Table name. Must be "users".
Database schema. Must be "auth".
Previous data (null for an insert)
Example: "New user processed successfully"