Brevo (formerly Sendinblue) is an all-in-one marketing platform for email, SMS, and WhatsApp campaigns. Hiro CRM uses Brevo to send targeted communications to customer segments.
What You Can Do
Send personalized email campaigns to customer segments
Send SMS notifications for reservations and promotions
Track email open rates and click-through rates
Use templates with dynamic content (customer name, loyalty points, etc.)
Schedule campaigns for optimal send times
Compliance-ready for GDPR and Spanish marketing laws
Why Brevo?
Hiro CRM migrated from Resend to Brevo for:
Multi-channel support - Email, SMS, and WhatsApp in one platform
Spanish market focus - Excellent deliverability in Spain
Competitive pricing - Pay only for what you send
No daily limits - Unlike some competitors
Advanced segmentation - Perfect for hospitality CRM
Prerequisites
Brevo Account
Sign up for a free or paid Brevo account at brevo.com
Verify Domain
Add and verify your sending domain (e.g., @yourrestaurant.com)
API Key
Generate an API key with transactional email and SMS permissions
Sender Identity
Configure your sender name and email address
Setup
1. Create a Brevo Account
Go to brevo.com and sign up
Choose a plan based on your email volume:
Free : 300 emails/day
Lite : 10,000 emails/month starting at €25/month
Premium : Unlimited contacts, advanced features
2. Verify Your Sending Domain
Add Domain
In Brevo dashboard, go to Senders & IP > Domains
Add DNS Records
Copy the SPF, DKIM, and DMARC records
Update DNS
Add records to your domain’s DNS settings (via your domain provider)
Verify
Click “Verify” in Brevo (may take 24-48 hours)
Domain verification is required for email delivery. Without it, your emails will be rejected or marked as spam.
3. Generate API Key
Go to Settings > API Keys
Click Create a new API key
Give it a name like “Hiro CRM Production”
Copy the key immediately (you won’t see it again)
Add your Brevo settings to frontend/.env.local:
# Brevo Email & SMS
BREVO_API_KEY = xkeysib-your-api-key-here
BREVO_SENDER_EMAIL = [email protected]
BREVO_SENDER_NAME = Your Restaurant Name
BREVO_SMS_SENDER = YourBrand
Configuration Notes:
BREVO_SENDER_EMAIL: Must be from your verified domain
BREVO_SENDER_NAME: Appears as “From” name (e.g., “La Tasca Alicante”)
BREVO_SMS_SENDER: 11 characters max, alphanumeric only (e.g., “LaTasca”)
API Reference
Send Email
import { sendEmail } from '@/lib/email/brevo' ;
const result = await sendEmail ({
to: '[email protected] ' ,
subject: 'Thank you for your visit!' ,
htmlContent: '<h1>We hope you enjoyed your meal</h1><p>Come back soon!</p>' ,
textContent: 'We hope you enjoyed your meal. Come back soon!' ,
tags: [ 'post-visit' , 'marketing' ],
params: {
customerName: 'María' ,
loyaltyPoints: 1250
}
});
if ( result . success ) {
console . log ( 'Email sent:' , result . messageId );
} else {
console . error ( 'Email failed:' , result . error );
}
Send Email to Multiple Recipients
const result = await sendEmail ({
to: [ '[email protected] ' , '[email protected] ' ],
subject: 'Exclusive offer for VIP members' ,
htmlContent: '<p>Get 20% off your next visit!</p>' ,
tags: [ 'vip-campaign' ]
});
Send SMS
import { sendSMS } from '@/lib/email/brevo' ;
const result = await sendSMS ({
to: '+34612345678' ,
content: 'Your table at La Tasca is confirmed for tonight at 8:30pm. See you soon!' ,
tag: 'reservation-confirmation'
});
SMS phone numbers must include country code (e.g., +34 for Spain). Brevo will validate the format.
Use Custom Sender
const result = await sendEmail ({
to: '[email protected] ' ,
subject: 'Invoice for your stay' ,
htmlContent: '<p>Thank you for staying with us!</p>' ,
from: {
email: '[email protected] ' ,
name: 'Hotel Reservations Team'
},
replyTo: {
email: '[email protected] ' ,
name: 'Customer Support'
}
});
Data Structures
EmailOptions
interface EmailOptions {
to : string | string []; // Recipient(s)
subject : string ; // Email subject line
htmlContent : string ; // HTML body
textContent ?: string ; // Plain text fallback
from ?: { // Optional custom sender
email : string ;
name ?: string ;
};
replyTo ?: { // Optional reply-to address
email : string ;
name ?: string ;
};
tags ?: string []; // For tracking/analytics
params ?: Record < string , any >; // Template variables
}
SMSOptions
interface SMSOptions {
to : string ; // Phone number with country code
content : string ; // Message (160 chars recommended)
sender ?: string ; // Override default sender
tag ?: string ; // For tracking
}
How It Works
Campaign Creation
Create a campaign in Hiro CRM with target segment and content
API Call
Hiro sends email/SMS data to Brevo’s transactional API
Brevo Processing
Brevo validates, queues, and delivers your messages
Delivery Tracking
Brevo tracks opens, clicks, bounces, and unsubscribes
Webhook (Optional)
Brevo can send webhooks back to Hiro for engagement events
Troubleshooting
API Key Invalid
Verify the key in your .env.local matches Brevo dashboard
Check for extra spaces or line breaks
Regenerate the key if it was revoked
Ensure the key has “Transactional Emails” and “SMS” permissions
Emails Not Delivered
Domain not verified : Complete DNS verification
Sender email doesn’t match verified domain : Use [email protected]
Recipient marked you as spam : Check Brevo’s blacklist
Hitting rate limits : Upgrade your Brevo plan
SMS Failed
Phone number must include country code (+34 for Spain)
SMS sender must be 11 characters or less
Ensure you have SMS credits in your Brevo account
Some countries require pre-registered sender IDs
Template Variables Not Working
If params aren’t rendering:
// ❌ Wrong: Brevo doesn't auto-replace {{variables}} in htmlContent
htmlContent : '<p>Hello {{customerName}}</p>'
// ✅ Correct: Replace variables before sending
htmlContent : `<p>Hello ${ params . customerName } </p>`
Example Use Cases
Post-Visit Thank You Email
import { sendEmail } from '@/lib/email/brevo' ;
const customer = await getCustomer ( customerId );
await sendEmail ({
to: customer . email ,
subject: `Thank you for dining with us, ${ customer . first_name } !` ,
htmlContent: `
<h2>We hope you enjoyed your experience</h2>
<p>Dear ${ customer . first_name } ,</p>
<p>Thank you for choosing ${ restaurantName } . We'd love to hear your feedback!</p>
<p><a href="https://yourrestaurant.com/review">Leave a Review</a></p>
` ,
tags: [ 'post-visit' , 'nps' ]
});
VIP Segment Campaign
// Get VIP customers (RFM score > 4)
const vipCustomers = await getCustomerSegment ({ rfmScore: { min: 4 } });
for ( const customer of vipCustomers ) {
await sendEmail ({
to: customer . email ,
subject: 'Exclusive invitation for our VIP guests' ,
htmlContent: `
<h1>You're Invited!</h1>
<p>Dear ${ customer . first_name } ,</p>
<p>Join us for an exclusive wine tasting event on March 15th.</p>
<p>Your loyalty tier: <strong> ${ customer . loyalty_tier } </strong></p>
` ,
tags: [ 'vip-event' , 'wine-tasting' ]
});
// Rate limit: wait 100ms between sends
await new Promise ( resolve => setTimeout ( resolve , 100 ));
}
Reservation Confirmation SMS
import { sendSMS } from '@/lib/email/brevo' ;
await sendSMS ({
to: reservation . client_phone ,
content: `Hi ${ reservation . client_name } ! Your table for ${ reservation . pax } at ${ restaurantName } is confirmed for ${ reservation . date } at ${ reservation . time } . See you soon!`
});
Best Practices
Use responsive HTML templates (mobile-friendly)
Include both htmlContent and textContent
Keep subject lines under 50 characters
Always include an unsubscribe link (required by GDPR)
Test emails before sending to large segments
Verify your domain with SPF, DKIM, and DMARC
Use a dedicated IP if sending 100k+ emails/month
Monitor bounce rates and remove invalid emails
Respect unsubscribe requests immediately
Avoid spam trigger words (“free”, “urgent”, “click now”)
Keep messages under 160 characters to avoid splitting
Only send SMS to customers who opted in
Include your business name in the message
Avoid sending late at night (respect quiet hours)
Provide an opt-out method (e.g., “Reply STOP”)
Free plan: 300 emails/day max
Add delays between bulk sends (100-200ms)
Use Brevo’s campaign API for large batches
Monitor your quota in Brevo dashboard
GDPR Compliance
When using Brevo for customers in the EU:
Obtain consent : Customers must opt-in to marketing emails
Easy unsubscribe : Every email must have an unsubscribe link
Data minimization : Only collect necessary customer data
Right to erasure : Allow customers to request data deletion
Privacy policy : Disclose that you use Brevo for communications
Brevo is GDPR-compliant and has data processing agreements available.
Next Steps
Marketing Campaigns Create targeted email and SMS campaigns
Customer Management Manage customer segments and data