Migration illustration Migration guide

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

  1. 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.

Need some help?
  1. 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.
  2. Update your integration
    Swap your Brevo endpoints and credentials for Mailtrap’s (API or SMTP). See the migration sections below.
  3. Migrate templates
    Brevo and Mailtrap don’t use the same templating language, so you can’t migrate templates directly. See the templates sections below.
  4. Migrate suppressions
    Export Brevo suppressions and import them into Mailtrap via CSV or manually. Click here for more information.
  5. Migrate users
    Add users from the User Management tab and review permissions during migration.
  6. Set up webhooks
    Follow the Mailtrap Webhooks step-by-step guide.
  7. 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.

 

Mailtrap tip

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

API migration

Authentication

Both platforms use a token in a request header, but with different header names:

BrevoMailtrap
MethodAPI keyBearer token
Headerapi-key: YOUR_API_KEYAuthorization: Bearer YOUR_API_KEY
Account-levelSeparate SMTP keys and API keysSame 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 typeBrevoMailtrapNotes
Transactional emailPOST https://api.brevo.com/v3/smtp/emailPOST https://send.api.mailtrap.io/api/sendSimilar flat JSON; different field names
Bulk emailSame /v3/smtp/email with messageVersions arrayPOST https://bulk.api.mailtrap.io/api/sendBrevo uses message versions (up to 1,000/call); Mailtrap uses a dedicated bulk endpoint (500/batch)
Template sendingSame /v3/smtp/email with templateIdSame send endpoint with template_uuidBoth use the same send endpoint for templates
SuppressionsGET/DELETE /v3/smtp/blockedContacts, POST/GET/DELETE /v3/smtp/blockedDomainsGEThttps://mailtrap.io/api/accounts/{account_id}/suppressionsBrevo separates contacts and domains
StatsGET /v3/smtp/statistics/aggregatedReport, /reports, /eventsGET/api/accounts/{account_id}/stats, /stats/domains, /stats/categories, /stats/email_service_providers, and  /stats/dateBrevo offers aggregated, daily, and per-event endpoints
Email logsGET /v3/smtp/statistics/events (unaggregated)GET https://mailtrap.io/api/accounts/{account_id}/email_logsN/A

Outbound Sending API JSON Field Mapping

FieldBrevoMailtrap
From emailsender.emailfrom.email
From namesender.name (max 70 chars)from.name
To emailto[].emailto[].email
To nameto[].name (max 70 chars)to[].name
Cccc[].emailcc[].email
Bccbcc[].emailbcc[].email
Subjectsubjectsubject
HTML bodyhtmlContenthtml
Text bodytextContenttext
Category/Tagtags (array of strings)category (single string)
Custom variables/Metadataparams (JSON object, max 100 KB)custom_variables
Reply-ToreplyTo.email + replyTo.namereply_to object
Custom headersheaders (JSON object)headers
Template identifiertemplateId (integer)template_uuid
Template variablesparams (JSON object)template_variables
Open trackingVia account settingsVia account settings or headers
Click trackingVia account settingsVia account settings or headers
Attachmentsattachment[].{url or content, name}attachments:[{content, filename, type, disposition}]
Inline imagesNot documented as separate from attachmentsattachments:[{content, filename, type, disposition:”inline”,content_id}]
Scheduled sendscheduledAt (ISO 8601 UTC)
Batch IDbatchId (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 streamN/A – single endpointDetermined by endpoint: send.api (transactional) vs bulk.api (bulk)

Code snippets

  • Mailtrap cURL SDK code snippet cURL
Brevo Brevo
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"]
  }'
Mailtrap Mailtrap

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 auth header
  • Brevo uses sender (Mailtrap uses from
  • Brevo uses htmlContent/textContent (Mailtrap uses html/text
  • Brevo uses tags array (Mailtrap uses single category)

SMTP migration

SettingBrevoMailtrap (Transactional)Mailtrap (Bulk)
Hostsmtp-relay.brevo.comlive.smtp.mailtrap.iobulk.smtp.mailtrap.io
Port587 (recommended), 465 (SSL/TLS), 2525587 (recommended), 25, 2525587 (recommended), 25, 2525
TLSPort 465: SSL/TLS; 587/2525: STARTTLS auto-negotiatedRequired (STARTTLS)Required (STARTTLS)
Auth methodLOGINPLAIN, LOGINPLAIN, LOGIN
UsernameSMTP login email (provided by Brevo)api (literal string)api (literal string)
PasswordSMTP key (separate from API key)API tokenAPI 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

LimitBrevoMailtrap
API rate limit1,000 RPS (general); up to 6,000 RPS (enterprise)150 requests per 10 seconds per API token
Batch size1,000 message versions per call; 100 batch calls/minute500 emails per batch call
Message size20 MB (including attachments); 4 MB per attachment10 MB default (extendable to 30 MB on request)
Max recipients per send2,000 total per request; 99 per message versionNot publicly specified
Daily limit (free plan)300 emails/day1,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

PatternBrevo (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 formattingFilter-based: {{ params.date | date:”Y-m-d” }}Not supported – format before passing
Pass variables via APIparams (JSON object)template_variables (JSON object)
Template identifiertemplateId (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.

Question icon

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}}, remove params. 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 scheduledAt for 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.