Migrate to Mailtrap from Brevo
A complete technical guide to switch from Brevo (formerly Sendinblue) to Mailtrap. Most teams complete the migration in under an hour.
Migration Checklist
- Authenticate your domain
Add and verify your domain before sending. Follow the Domain Setup article at docs.mailtrap.io.
Need some help?
Contact our support and our developers will help you with it.
- Get your API token
Mailtrap auto-generates a token when you add a domain. Find it under Settings → API Tokens. Read more on API tokens. - Update your integration
Swap your Brevo endpoints and credentials for Mailtrap’s (API or SMTP). See the migration sections below. - Migrate templates
Brevo and Mailtrap don’t use the same templating language, so you can’t migrate templates directly. See the templates sections below. - Migrate suppressions
Export Brevo suppressions and import them into Mailtrap via CSV or manually. Click here for more information. - Migrate users
Add users from the User Management tab and review permissions during migration. - Set up webhooks
Follow the Mailtrap Webhooks step-by-step guide. - Security and compliance
Visit the Trust Center page to review Mailtrap’s security practices and compliance standards.
Mailtrap tip
You can use ActionMailer Balancer Ruby gem to proportionally distribute the email sending load between two different sending services (e.g. 70% Brevo and 30% Mailtrap) to mitigate the sending risks.
Concepts
Before going over the technical details, it’s important to clear up some key concepts.
Sending domains
Brevo equivalent: Authenticate your domain (Brevo code + DKIM + DMARC)
Both platforms authenticate domains via DNS records. Brevo requires three records: a Brevo-specific verification code, DKIM, and DMARC. Mailtrap follows the same DNS standards – SPF, DKIM, DMARC.
If you already have DKIM and DMARC configured for Brevo, you’ll add Mailtrap-specific DNS records alongside them. The underlying standards are identical.RC record covers both. For SPF, however, you must merge Mailtrap’s include into your existing SPF record rather than adding a separate one.
See the Mailtrap domain setup guide for step-by-step instructions.
Separate sending streams
Brevo equivalent: N/A – single endpoint, single SMTP host
Brevo routes all transactional email through one API endpoint (/v3/smtp/email) and one SMTP host (smtp-relay.brevo.com). There’s no built-in separation between transactional and bulk transactional email.
Mailtrap separates these into distinct infrastructure:
- Transactional Stream: For sending user-triggered emails like welcome emails and password resets.
- Bulk Stream: For sending promotional, marketing, emails like newsletters and product updates.
By keeping the sending infrastructures separate, you are able to:
- Protect your transactional email reputation from the performance of your bulk campaigns
- Ensure each stream routes through the right IP pools
- Give mailbox providers the signals they need to categorize and deliver your emails correctly

Email categories
Brevo equivalent: Tags (array of strings)
Brevo uses tags, an array of strings in the API request, for categorizing emails and filtering webhook events. You can attach multiple tags per message.
Mailtrap uses Email Categories, set via the category field in the API or the X-MT-Category header in SMTP.

Key difference: Brevo supports multiple tags per message; Mailtrap assigns one category per message.
Organization & sub-accounts
Brevo equivalent: Users & User permissions (Owner, Admin, and custom roles on Enterprise)
Brevo manages access through a Users system under account settings, with role-based permissions available on higher-tier plans.
Mailtrap offers Organization and sub-account management which lets you manage complex setups involving multiple teams, clients, environments, or products under a single Organization. To start using the feature, you first need to enable it under the Organization tab.

Note: The feature is available from the Business plan onward.
Terminology comparison
- Authenticated Domains (Brevo code + DKIM + DMARC)
- Transactional Logs / Email Event Report
- Users & User Permissions
- Email Templates (Brevo Template Language)
- Tags (array of strings)
- Headers (JSON object)
- params (key-value object)
- Blocklist (blockedContacts / blockedDomains)
- N/A (single endpoint)
- No direct equivalent
API migration
Authentication
Both platforms use a token in a request header, but with different header names:
| Brevo | Mailtrap | |
| Method | API key | Bearer token |
| Header | api-key: YOUR_API_KEY | Authorization: Bearer YOUR_API_KEY |
| Account-level | Separate SMTP keys and API keys | Same token for both |
Simple header rename. But there’s one thing to watch: Brevo uses different credentials for SMTP and API. Mailtrap uses the same API token for both.
API mapping
| API type | Brevo | Mailtrap | Notes |
| Transactional email | POST https://api.brevo.com/v3/smtp/email | POST https://send.api.mailtrap.io/api/send | Similar flat JSON; different field names |
| Bulk email | Same /v3/smtp/email with messageVersions array | POST https://bulk.api.mailtrap.io/api/send | Brevo uses message versions (up to 1,000/call); Mailtrap uses a dedicated bulk endpoint (500/batch) |
| Template sending | Same /v3/smtp/email with templateId | Same send endpoint with template_uuid | Both use the same send endpoint for templates |
| Suppressions | GET/DELETE /v3/smtp/blockedContacts, POST/GET/DELETE /v3/smtp/blockedDomains | GEThttps://mailtrap.io/api/accounts/{account_id}/suppressions | Brevo separates contacts and domains |
| Stats | GET /v3/smtp/statistics/aggregatedReport, /reports, /events | GET/api/accounts/{account_id}/stats, /stats/domains, /stats/categories, /stats/email_service_providers, and /stats/date | Brevo offers aggregated, daily, and per-event endpoints |
| Email logs | GET /v3/smtp/statistics/events (unaggregated) | GET https://mailtrap.io/api/accounts/{account_id}/email_logs | N/A |
Outbound Sending API JSON Field Mapping
| Field | Brevo | Mailtrap |
| From email | sender.email | from.email |
| From name | sender.name (max 70 chars) | from.name |
| To email | to[].email | to[].email |
| To name | to[].name (max 70 chars) | to[].name |
| Cc | cc[].email | cc[].email |
| Bcc | bcc[].email | bcc[].email |
| Subject | subject | subject |
| HTML body | htmlContent | html |
| Text body | textContent | text |
| Category/Tag | tags (array of strings) | category (single string) |
| Custom variables/Metadata | params (JSON object, max 100 KB) | custom_variables |
| Reply-To | replyTo.email + replyTo.name | reply_to object |
| Custom headers | headers (JSON object) | headers |
| Template identifier | templateId (integer) | template_uuid |
| Template variables | params (JSON object) | template_variables |
| Open tracking | Via account settings | Via account settings or headers |
| Click tracking | Via account settings | Via account settings or headers |
| Attachments | attachment[].{url or content, name} | attachments:[{content, filename, type, disposition}] |
| Inline images | Not documented as separate from attachments | attachments:[{content, filename, type, disposition:”inline”,content_id}] |
| Scheduled send | scheduledAt (ISO 8601 UTC) | |
| Batch ID | batchId (UUIDv4, auto-generated if omitted) | |
| Message versions (batch) | messageVersions[] (up to 1,000 per call) | N/A – use dedicated bulk endpoint |
| Sender ID (IP pool) | sender.id (integer) | N/A – managed by Mailtrap |
| Sending stream | N/A – single endpoint | Determined by endpoint: send.api (transactional) vs bulk.api (bulk) |
Code snippets
-
cURL
curl -X POST https://api.brevo.com/v3/smtp/email \
-H "api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"sender": {
"email": "sender@yourdomain.com",
"name": "Sender Name"
},
"to": [
{
"email": "recipient@example.com",
"name": "Recipient Name"
}
],
"subject": "Welcome aboard",
"htmlContent": "<h1>Hello</h1><p>Welcome to the platform.</p>",
"textContent": "Hello. Welcome to the platform.",
"tags": ["welcome"]
}'
Copy
curl -X POST https://send.api.mailtrap.io/api/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": {
"email": "sender@yourdomain.com",
"name": "Sender Name"
},
"to": [
{
"email": "recipient@example.com",
"name": "Recipient Name"
}
],
"subject": "Welcome aboard",
"html": "<h1>Hello</h1><p>Welcome to the platform.</p>",
"text": "Hello. Welcome to the platform.",
"category": "welcome"
}'
Note: The payloads are similar in shape, both use flat JSON with sender/recipient objects. The main differences are:
- A different
authheader - Brevo uses
sender(Mailtrap usesfrom) - Brevo uses
htmlContent/textContent(Mailtrap useshtml/text) - Brevo uses
tagsarray (Mailtrap uses singlecategory)
SMTP migration
| Setting | Brevo | Mailtrap (Transactional) | Mailtrap (Bulk) |
| Host | smtp-relay.brevo.com | live.smtp.mailtrap.io | bulk.smtp.mailtrap.io |
| Port | 587 (recommended), 465 (SSL/TLS), 2525 | 587 (recommended), 25, 2525 | 587 (recommended), 25, 2525 |
| TLS | Port 465: SSL/TLS; 587/2525: STARTTLS auto-negotiated | Required (STARTTLS) | Required (STARTTLS) |
| Auth method | LOGIN | PLAIN, LOGIN | PLAIN, LOGIN |
| Username | SMTP login email (provided by Brevo) | api (literal string) | api (literal string) |
| Password | SMTP key (separate from API key) | API token | API token |
Migration notes:
- Host: Replace smtp-relay.brevo.com with the appropriate Mailtrap host. If you send both transactional and bulk email, you now need two separate SMTP configurations instead of one.
- Username: Brevo provides a unique email address as the SMTP login. Mailtrap uses the literal string api.
- Password: Brevo uses a dedicated SMTP key (different from the API key). Mailtrap uses the same API token for both SMTP and API – one credential to manage.
- Port 465: Brevo supports implicit SSL/TLS on port 465. Mailtrap does not – use port 587 with STARTTLS instead.

For more information on migrating your SMTP configuration, click this link. ⬅️
Rate limits & quotas
| Limit | Brevo | Mailtrap |
| API rate limit | 1,000 RPS (general); up to 6,000 RPS (enterprise) | 150 requests per 10 seconds per API token |
| Batch size | 1,000 message versions per call; 100 batch calls/minute | 500 emails per batch call |
| Message size | 20 MB (including attachments); 4 MB per attachment | 10 MB default (extendable to 30 MB on request) |
| Max recipients per send | 2,000 total per request; 99 per message version | Not publicly specified |
| Daily limit (free plan) | 300 emails/day | 1,000 emails/month |
Key difference: Brevo’s rate limits are significantly higher on paper (1,000+ RPS), but this is the ceiling; the actual throughput depends on your plan. Brevo’s free plan is also heavily capped at 300 emails/day with no rollover.
Email templates
This is where the migration gets interesting. Brevo uses the Brevo Template Language (based on Pongo2/Django template syntax). Mailtrap uses Handlebars. The {{ }} delimiters look similar, but the syntax is not compatible – you’ll need to convert templates.
Syntax comparison
| Pattern | Brevo (Pongo2/Django) | Mailtrap (Handlebars) |
| Variable insertion | {{ params.variableName }} | {{variable_name}} |
| Nested access | {{ params.order.item.name }} | {{order.item.name}} |
| Conditionals | {% if params.var %}…{% else %}…{% endif %} | {{#if var}}…{{else}}…{{/if}} |
| Iteration | {% for item in params.items %}{{ item.name }}{% endfor %} | {{#each items}}{{this.name}}{{/each}} |
| Default/fallback | {{ contact.FIRSTNAME|default:’there’ }} | {{#if name}}{{name}}{{else}}there{{/if}} |
| Raw HTML (unescaped) | {{ variable }} (Brevo doesn’t escape by default) | {{{variable}}} |
| Date formatting | Filter-based: {{ params.date | date:”Y-m-d” }} | Not supported – format before passing |
| Pass variables via API | params (JSON object) | template_variables (JSON object) |
| Template identifier | templateId (integer) | template_uuid |
Template conversion guide
Converting Brevo templates to Mailtrap Handlebars requires these changes:
1. Remove params. prefix: Brevo references variables as {{ params.name }}; Mailtrap uses {{name}} directly.
2. Convert conditionals: Brevo’s {% if %}...{% endif %} becomes {{#if}}...{{/if}}.
# Brevo
{% if params.hasOrder %}Order confirmed{% endif %}
# Mailtrap
{{#if hasOrder}}Order confirmed{{/if}}
3. Convert loops: Brevo’s {% for %}...{% endfor %} becomes {{#each}}...{{/each}}.
# Brevo
{% for item in params.items %}{{ item.name }}{% endfor %}
# Mailtrap
{{#each items}}{{this.name}}{{/each}}
4. Convert default values: Brevo’s | default:"value" filter becomes a Handlebars {{#if}}...{{else}} block.
# Brevo
{{ params.name | default:"there" }}
# Mailtrap
{{#if name}}{{name}}{{else}}there{{/if}}
5. Rename API field: Change params to template_variables in your send call, and change templateId to template_uuid.
Frequently Asked Questions
-
Do I need to re-verify my domain if I’ve already set it up in Brevo?
Yes, you’ll need to re-verify your domain. See the Mailtrap Knowledge Base for up-to-date guidance.
-
Why does Mailtrap have two separate SMTP hosts?
Mailtrap separates transactional and bulk streams to protect your sender reputation and ensure proper delivery routing for each email type. Brevo routes everything through a single host.
-
Does Mailtrap offer migration assistance?
Yes, Mailtrap offers migration assistance from Business plan onwards.
-
How do I migrate templates from Brevo?
Brevo uses Pongo2/Django template syntax; Mailtrap uses Handlebars. The templates are not directly compatible – you’ll need to convert
{% if %}to{{#if}},{% for %}to{{#each}}, removeparams.prefixes from variables, and replace| default:"value"filters with{{#if}}...{{else}}blocks. See the conversion guide above for examples. -
What about Brevo’s scheduled sending?
Brevo supports
scheduledAtfor deferred sends. And, currently, Mailtrap doesn’t support deferred sends via API. -
Do I need separate SMTP credentials?
No, you don’t. Brevo uses different credentials for SMTP and API (separate SMTP key), but Mailtrap simplifies this with the same API token works for both SMTP and API.
-
Can I migrate gradually?
Yes. If you’re on Rails, Mailtrap’s ActionMailer Balancer lets you split traffic proportionally (e.g., 80% Brevo / 20% Mailtrap) and shift over time. For other frameworks, route by email type – move transactional first, then bulk.