Overview
By default, the Nuxt Lettermint module automatically creates an API endpoint at /api/lettermint/send that handles email sending requests from the client side. This endpoint is used by the useLettermint() composable to send emails securely without exposing your API key to the client.
Default Behavior
When the module is installed with default settings, it automatically registers the endpoint:
// Automatically created by the module
if ( options . autoEndpoint !== false ) {
addServerHandler ({
route: '/api/lettermint/send' ,
handler: resolver . resolve ( './runtime/server/api/lettermint/send.post' ),
})
}
Endpoint Features
The auto-generated endpoint provides:
Validation Validates required fields (from, to, subject, and text/html)
Error Handling Comprehensive error handling for API and validation errors
Security Keeps your API key secure on the server side
Type Safety Full TypeScript support with proper types
Configuration
Enable Auto-Endpoint (Default)
export default defineNuxtConfig ({
modules: [ 'nuxt-lettermint' ] ,
lettermint: {
autoEndpoint: true // This is the default
}
})
With this configuration, you can use the client-side composable:
< script setup >
const { send , sending , error } = useLettermint ()
await send ({
from: '[email protected] ' ,
to: '[email protected] ' ,
subject: 'Hello!' ,
html: '<h1>Hello World</h1>'
})
</ script >
Disable Auto-Endpoint
If you want to create your own custom endpoint, disable the auto-generated one:
export default defineNuxtConfig ({
modules: [ 'nuxt-lettermint' ] ,
lettermint: {
autoEndpoint: false
}
})
When you disable the auto-generated endpoint, the useLettermint() composable will not work unless you create a custom endpoint at the same path (/api/lettermint/send).
When to Disable the Auto-Endpoint
Consider disabling the auto-generated endpoint if you need:
Add additional validation rules beyond the default required fields: server/api/lettermint/send.post.ts
import { sendEmail } from '#imports'
import { defineEventHandler , readBody , createError } from 'h3'
export default defineEventHandler ( async ( event ) => {
const body = await readBody ( event )
// Custom validation
if ( ! body . from . endsWith ( '@yourdomain.com' )) {
throw createError ({
statusCode: 400 ,
message: 'From address must be from your domain'
})
}
return await sendEmail ( body )
} )
Rate limiting or throttling
Implement rate limiting to prevent abuse: server/api/lettermint/send.post.ts
import { sendEmail } from '#imports'
import { defineEventHandler } from 'h3'
export default defineEventHandler ( async ( event ) => {
// Add rate limiting logic
await checkRateLimit ( event )
const body = await readBody ( event )
return await sendEmail ( body )
} )
Authentication/authorization
Require users to be authenticated before sending emails: server/api/lettermint/send.post.ts
import { sendEmail } from '#imports'
import { defineEventHandler } from 'h3'
export default defineEventHandler ( async ( event ) => {
// Verify user is authenticated
const user = await requireAuth ( event )
const body = await readBody ( event )
return await sendEmail ({
... body ,
from: user . email // Use authenticated user's email
})
} )
Track email sending activity: server/api/lettermint/send.post.ts
import { sendEmail } from '#imports'
import { defineEventHandler } from 'h3'
export default defineEventHandler ( async ( event ) => {
const body = await readBody ( event )
// Log email activity
await logEmailActivity ({
from: body . from ,
to: body . to ,
subject: body . subject ,
timestamp: new Date ()
})
return await sendEmail ( body )
} )
If you only send emails from server-side code and never from the client, you can disable the endpoint: server/api/some-action.post.ts
import { sendEmail } from '#imports'
export default defineEventHandler ( async ( event ) => {
// Your custom server logic
await sendEmail ({
from: '[email protected] ' ,
to: '[email protected] ' ,
subject: 'Welcome' ,
html: '<h1>Welcome!</h1>'
})
} )
Endpoint Implementation
The auto-generated endpoint is implemented as follows:
import { defineEventHandler , readBody , createError } from 'h3'
import { sendEmail , type SendEmailOptions } from '../../utils/lettermint'
export default defineEventHandler ( async ( event ) => {
try {
const body = await readBody < SendEmailOptions >( event )
// Validate required fields
if ( ! body . from ) {
throw createError ({
statusCode: 400 ,
statusMessage: 'Missing required field: from' ,
})
}
if ( ! body . to ) {
throw createError ({
statusCode: 400 ,
statusMessage: 'Missing required field: to' ,
})
}
if ( ! body . subject ) {
throw createError ({
statusCode: 400 ,
statusMessage: 'Missing required field: subject' ,
})
}
if ( ! body . text && ! body . html ) {
throw createError ({
statusCode: 400 ,
statusMessage: 'Either text or html content is required' ,
})
}
// Send the email
const result = await sendEmail ( body )
return {
success: true ,
messageId: result . message_id ,
status: result . status ,
}
}
catch ( error : unknown ) {
// Comprehensive error handling...
}
} )
Creating a Custom Endpoint
If you disable the auto-endpoint and still want to use the useLettermint() composable, create your own endpoint at the same path:
Disable auto-endpoint
export default defineNuxtConfig ({
modules: [ 'nuxt-lettermint' ] ,
lettermint: {
autoEndpoint: false
}
})
Create custom endpoint
Create a file at server/api/lettermint/send.post.ts: server/api/lettermint/send.post.ts
import { sendEmail } from '#imports'
import { defineEventHandler , readBody } from 'h3'
export default defineEventHandler ( async ( event ) => {
const body = await readBody ( event )
// Add your custom logic here
console . log ( 'Sending email:' , body . subject )
// Use the sendEmail utility
return await sendEmail ( body )
} )
Use the composable
The useLettermint() composable will now use your custom endpoint: < script setup >
const { send } = useLettermint ()
await send ({
from: '[email protected] ' ,
to: '[email protected] ' ,
subject: 'Hello' ,
html: '<p>Hello World</p>'
})
</ script >
You can create custom endpoints at different paths (e.g., /api/custom-send), but you’ll need to call them directly using $fetch instead of using the useLettermint() composable.
Impact on Client-Side Usage
With Auto-Endpoint Enabled (Default)
< script setup >
// ✅ Works out of the box
const { send , sending , error } = useLettermint ()
await send ({
from: '[email protected] ' ,
to: '[email protected] ' ,
subject: 'Hello' ,
html: '<h1>Hello</h1>'
})
</ script >
With Auto-Endpoint Disabled
< script setup >
// ❌ Won't work unless you create a custom endpoint at /api/lettermint/send
const { send } = useLettermint ()
// ✅ Alternative: Use $fetch with your custom endpoint
const result = await $fetch ( '/api/custom-send' , {
method: 'POST' ,
body: {
from: '[email protected] ' ,
to: '[email protected] ' ,
subject: 'Hello' ,
html: '<h1>Hello</h1>'
}
})
</ script >
Server-Side Usage
Server-side email sending with sendEmail() works regardless of the autoEndpoint setting. The auto-endpoint only affects client-side usage through the useLettermint() composable.
server/api/welcome.post.ts
import { sendEmail } from '#imports'
export default defineEventHandler ( async () => {
// ✅ Always works, regardless of autoEndpoint setting
return await sendEmail ({
from: '[email protected] ' ,
to: '[email protected] ' ,
subject: 'Welcome' ,
html: '<h1>Welcome!</h1>'
})
} )
Next Steps
Client-Side Usage Learn how to send emails from the client using useLettermint()
Server-Side Usage Send emails from server-side code and API routes