Overview
The GCN Labs Email Service provides a simple, reliable API for sending transactional emails via the Brevo (SendInBlue) platform. The service offers two primary endpoints for different use cases:
- /send-raw - Send custom HTML emails with full control over content
- /send-template - Load templates from Supabase with variable merging
🤖 Machine-Readable API Spec
For AI agents and automated tools, we provide a complete OpenAPI 3.0 specification that can be easily ingested and processed.
View OpenAPI Specification →Authentication
Currently, the API is open and does not require authentication. For production use, consider implementing API key authentication or IP whitelisting through your deployment platform.
Base URL
All API requests should be made to:
https://your-deployment-url.netlify.app
Endpoints
1. Send Raw Email
Send a custom HTML email with full control over the content and styling. Ideal for one-off emails or when you want complete customization.
Request Headers
| Header | Value | Required |
|---|---|---|
Content-Type |
application/json |
Required |
Request Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
to |
string | string[] | Required | Recipient email address(es). Can be a single email or array of emails. |
subject |
string | Required | Email subject line. |
html |
string | Required | HTML content of the email. Must be valid HTML. |
text |
string | Optional | Plain text version of the email for clients that don't support HTML. |
fromEmail |
string | Optional | Sender email address. Defaults to DEFAULT_FROM_EMAIL environment variable. |
fromName |
string | Optional | Sender name. Defaults to DEFAULT_FROM_NAME environment variable. |
cc |
string | string[] | Optional | Carbon copy recipient(s). |
bcc |
string | string[] | Optional | Blind carbon copy recipient(s). |
replyTo |
string | Optional | Reply-to email address. |
attachments |
array | Optional | Array of attachment objects (see below). |
Attachment Object Structure
| Property | Type | Description |
|---|---|---|
name |
string | Filename (e.g., "document.pdf") |
content |
string | Base64-encoded file content |
contentType |
string | MIME type (e.g., "application/pdf", "image/png") |
Example Request
curl -X POST https://your-api.netlify.app/send-raw \
-H "Content-Type: application/json" \
-d '{
"to": "recipient@example.com",
"subject": "Welcome to Our Service",
"html": "<h1>Welcome!</h1><p>Thank you for joining us.</p>",
"text": "Welcome! Thank you for joining us.",
"fromEmail": "noreply@yourdomain.com",
"fromName": "Your Company",
"replyTo": "support@yourdomain.com"
}'
Example with Multiple Recipients and Attachments
curl -X POST https://your-api.netlify.app/send-raw \
-H "Content-Type: application/json" \
-d '{
"to": ["user1@example.com", "user2@example.com"],
"subject": "Document Attached",
"html": "<h1>Please find the document attached</h1>",
"cc": "manager@example.com",
"bcc": "archive@example.com",
"attachments": [
{
"name": "report.pdf",
"content": "JVBERi0xLjQKJeLjz9MK...",
"contentType": "application/pdf"
}
]
}'
Success Response (200 OK)
{
"success": true,
"message": "Email sent successfully",
"id": "abc123-brevo-message-id"
}
Error Response (4xx/5xx)
{
"success": false,
"error": "Validation failed",
"details": [
"to: Invalid email",
"html: Required"
]
}
2. Send Template Email
Load a pre-built email template from Supabase, merge variables using Mustache syntax, and send. Perfect for consistent, reusable email designs.
Request Headers
| Header | Value | Required |
|---|---|---|
Content-Type |
application/json |
Required |
Request Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
to |
string | string[] | Required | Recipient email address(es). |
template_id |
string | Required | Template identifier from Supabase email_templates table. |
variables |
object | Optional | Key-value pairs to merge into template. Keys match Mustache variables in template (e.g., {{firstName}}). |
subject |
string | Optional | Override the template's default subject line. |
fromEmail |
string | Optional | Sender email address. |
fromName |
string | Optional | Sender name. |
cc |
string | string[] | Optional | Carbon copy recipient(s). |
bcc |
string | string[] | Optional | Blind carbon copy recipient(s). |
replyTo |
string | Optional | Reply-to email address. |
Template Variables
Templates use Mustache syntax for variable substitution. Define variables in your HTML template like this:
<h1>Hello, {{firstName}}!</h1>
<p>Your order #{{orderId}} has been confirmed.</p>
<a href="{{ctaUrl}}">View Order</a>
Then pass the corresponding values in the variables object:
{
"variables": {
"firstName": "John",
"orderId": "12345",
"ctaUrl": "https://example.com/orders/12345"
}
}
Example Request
curl -X POST https://your-api.netlify.app/send-template \
-H "Content-Type: application/json" \
-d '{
"to": "newuser@example.com",
"template_id": "welcome-email",
"variables": {
"firstName": "Jane",
"companyName": "Acme Corp",
"ctaUrl": "https://app.example.com/onboarding"
}
}'
Example with Subject Override
curl -X POST https://your-api.netlify.app/send-template \
-H "Content-Type: application/json" \
-d '{
"to": "customer@example.com",
"template_id": "order-confirmation",
"subject": "Your Order #12345 is Confirmed!",
"variables": {
"orderNumber": "12345",
"total": "$99.99",
"trackingUrl": "https://track.example.com/12345"
},
"replyTo": "support@example.com"
}'
Success Response (200 OK)
{
"success": true,
"message": "Email sent successfully",
"id": "xyz789-brevo-message-id",
"template": "Welcome Email"
}
Error Response - Template Not Found (404)
{
"success": false,
"error": "Template with id 'invalid-template' not found"
}
HTTP Status Codes
| Code | Status | Description |
|---|---|---|
200 |
OK | Email sent successfully |
204 |
No Content | CORS preflight request successful |
400 |
Bad Request | Invalid request body or validation error |
404 |
Not Found | Template not found (send-template only) |
405 |
Method Not Allowed | HTTP method not supported (use POST) |
500 |
Internal Server Error | Server error or email provider failure |
503 |
Service Unavailable | Supabase connection issue |
CORS Support
Both endpoints support Cross-Origin Resource Sharing (CORS) with the following configuration:
- Access-Control-Allow-Origin: * (all origins)
- Access-Control-Allow-Methods: POST, OPTIONS
- Access-Control-Allow-Headers: Content-Type
Email Features
Template Processing (send-template only)
- Variable substitution using Mustache syntax
- CSS inlining for better email client compatibility
- HTML sanitization to remove dangerous scripts
Logging
All email events are logged to logs.gcnlabs.com with the following information:
- Full HTML content as sent
- Template variables (for template emails)
- Message metadata (subject, recipient, provider)
- Success/failure status with error messages
- Timestamps for all events
Rate Limits
Rate limiting is managed by your Brevo account and Netlify deployment plan. Check your provider's documentation for specific limits.
Best Practices
- Always provide both HTML and plain text versions when using
/send-raw - Test your templates thoroughly before using in production
- Use descriptive template IDs that reflect their purpose
- Keep email HTML simple and compatible with major email clients
- Always include an unsubscribe link in marketing emails
- Validate email addresses on the client side before calling the API
- Use meaningful subject lines that pass spam filters
- Consider implementing retry logic for network failures
Security Considerations
- API key authentication via headers
- IP whitelisting through your deployment platform
- OAuth 2.0 or JWT-based authentication
- Rate limiting per API consumer
- Input validation and sanitization (already implemented)
Need Help?
For additional support or questions:
- Review the OpenAPI Specification for complete technical details
- Test the API using the interactive testing page
- Check the health endpoint for service status
- Contact your development team or system administrator