Brevo Bridge

Drop-in replacement for the Brevo transactional email API — use your wemail API key in the same api-key header, keep your existing request structure.

The Brevo bridge lets you migrate from Brevo (formerly Sendinblue) to wemail without changing your integration code. Point your base URL to https://api.wemail.io/bridge/brevo, swap your Brevo API key for a wemail API key in the same api-key header, and keep the same request bodies and response shapes. The bridge translates every call into the wemail pipeline — delivery, tracking, webhooks, and suppressions all work the same way.

Authentication

Exactly like Brevo, the bridge authenticates with an api-key header. Use your wemail API key (afn_live_… or afn_test_…) where your Brevo key (xkeysib-…) used to be. Test-environment keys route through the sandbox: messages are accepted, simulated, and never delivered.

bashAuthentication header
api-key: afn_live_YOUR_WEMAIL_KEY

Supported Endpoints

POST /bridge/brevo/v3/smtp/email

Send a transactional email — mirrors Brevo's Send a transactional email endpoint.

GET /bridge/brevo/v3/smtp/statistics/events

List email events — mirrors Brevo's transactional event statistics.

GET /bridge/brevo/v3/smtp/blockedContacts

List blocked contacts (bounces and spam complaints) — mirrors Brevo's blocked-contacts list.

Field-Level Compatibility

POST /v3/smtp/email — Request Fields

Send request fields
ParameterTypeRequiredDescription
senderobjectRequired{ email, name? } — must use a domain verified in your wemail workspace.
toarrayRequiredRecipient list [{ email, name? }].
cc / bccarrayOptionalCarbon-copy recipients, same shape as to.
subjectstringOptionalRequired unless templateId is provided.
htmlContentstringOptionalHTML body. At least one of htmlContent, textContent, templateId is required.
textContentstringOptionalPlain-text body.
templateIdstringOptionalA wemail template id (tpl_…). Numeric Brevo template ids are not resolvable — re-point to the migrated template's wemail id.
paramsobjectOptionalTemplate variables, substituted like Brevo params.
tagsarrayOptionalUp to 10 tags, echoed on events and webhooks.
headersobjectOptionalCustom SMTP headers.
scheduledAtstringOptionalISO-8601 timestamp for scheduled delivery.

Response

A successful send returns 201 with { "messageId": "<msg_…>" }, matching Brevo's response shape. Validation failures return 400 with { code, message } in Brevo's error format.

GET /v3/smtp/statistics/events

Query parameters
ParameterTypeRequiredDescription
limitintegerOptionalPage size, default 50, max 100.
offsetintegerOptionalPagination offset, default 0.
eventstringOptionalFilter by Brevo event name: requests, delivered, hardBounces, softBounces, opens, clicks, spam, blocked, deferred, unsubscribed.
startDate / endDatestringOptionalDate range filters (ISO-8601).

Returns { events: [{ email, date, subject, messageId, event, tag, from, ip, link, reason, templateId }] } with wemail events mapped back to Brevo event names.

GET /v3/smtp/blockedContacts

Returns { count, contacts: [{ email, reason: { code, message }, blockedAt }] }. count is the total number of blocked contacts. Reason codes follow Brevo's vocabulary: hard bounces report hardBounce, spam complaints report contactFlaggedAsSpam.

Webhooks

When the Brevo bridge is active, webhook deliveries are formatted exactly like Brevo transactional webhooks: a single flat JSON object with event, email, message-id, subject, tags, ts/ts_event (seconds), ts_epoch (milliseconds) and date. Event names use Brevo's vocabulary (request, delivered, hard_bounce, spam, opened, click, unsubscribed, blocked, deferred). Like Brevo, payloads are not signed — restrict your webhook endpoint by URL secrecy or network rules.

Known Deviations from Brevo API

Deviations
ParameterTypeRequiredDescription
templateIdbehaviorOptionalBrevo numeric template ids are not resolvable; use the wemail tpl_… id of the migrated template.
batchId / messageVersionsunsupportedOptionalBrevo batch sending fields are not yet supported — send one request per message.
attachmentunsupportedOptionalAttachments are not yet supported through the bridge; use the native wemail /v3/send for attachments.
events feedbehaviorOptionalEvents reflect the wemail pipeline; provider-internal Brevo states (e.g. proxy_open) never occur.

Migrating for good? Follow the Brevo migration guide — templates and suppressions auto-import, and Brevo stays warm for 30 days.

Code examples

cURL
curl -X POST https://api.wemail.io/bridge/brevo/v3/smtp/email \
  -H "api-key: afn_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sender": { "email": "sender@yourdomain.com", "name": "Your App" },
    "to": [{ "email": "user@example.com" }],
    "subject": "Hello from the Brevo bridge",
    "htmlContent": "<p>It works — zero code changes.</p>"
  }'
Node.js
// Brevo SDK — point the client at the wemail bridge
const brevo = require('@getbrevo/brevo');

const api = new brevo.TransactionalEmailsApi();
api.setApiKey(brevo.TransactionalEmailsApiApiKeys.apiKey, 'afn_live_YOUR_KEY');
api.basePath = 'https://api.wemail.io/bridge/brevo/v3';

await api.sendTransacEmail({
  sender: { email: 'sender@yourdomain.com', name: 'Your App' },
  to: [{ email: 'user@example.com' }],
  subject: 'Hello from the Brevo bridge',
  htmlContent: '<p>It works — zero code changes.</p>',
});
Python
import requests

resp = requests.post(
    "https://api.wemail.io/bridge/brevo/v3/smtp/email",
    headers={"api-key": "afn_live_YOUR_KEY"},
    json={
        "sender": {"email": "sender@yourdomain.com", "name": "Your App"},
        "to": [{"email": "user@example.com"}],
        "subject": "Hello from the Brevo bridge",
        "htmlContent": "<p>It works — zero code changes.</p>",
    },
)
print(resp.status_code, resp.json())  # 201 {'messageId': '<msg_…>'}