Brevo
Send through the Brevo transactional email API with full field support and metadata mapped to template params.
Capabilities
| Repeated headers | Idempotency | Scheduling | Personalized |
|---|---|---|---|
| No | none | Yes | expanded |
These values come from the adapter's exported capabilities declaration. The field support matrix covers normalized message fields.
The Brevo adapter calls the Brevo transactional email API with plain fetch. It authenticates with Brevo's api-key header (not a Bearer token), supports every common field, and maps metadata to Brevo's params, the same values Brevo templates substitute.
Configure
Create an API key under SMTP & API in the Brevo dashboard and verify the sender or domain you use in from.
import { createEmailClient } from "@opencoredev/email-sdk";
import { brevo } from "@opencoredev/email-sdk/brevo";
export const email = createEmailClient({
adapters: [brevo({ apiKey: process.env.BREVO_API_KEY! })],
});Prop
Type
Send
Brevo maps cc, bcc, headers, attachments, tags (values only), and metadata (as params). replyTo accepts a single address; two or more throw an EmailValidationError before any request. sendAt maps to Brevo's scheduledAt (ISO 8601), so scheduling happens on Brevo's side. Brevo accepts at most 72 hours in the future.
const result = await email.send({
from: "Acme <hello@acme.com>",
to: [{ email: "user@example.com", name: "Ada" }],
replyTo: "support@acme.com",
subject: "You're invited to the Acme workspace",
html: "<p>Ada invited you to join the Acme workspace.</p>",
metadata: { workspaceId: "ws_123" },
tags: [{ name: "type", value: "invite" }],
});
console.log(result.id); // Brevo messageIdThe response id is Brevo's messageId (falling back to the provider's id field). Match it against events in Brevo's logs and webhooks.
Metadata becomes template params
metadata is sent as Brevo params, the values Brevo substitutes into templates. If you use
Brevo template syntax in your content, pick metadata keys that don't collide with template
placeholders.
Verify from the CLI
BREVO_API_KEY="xkeysib-..." npx --package @opencoredev/email-sdk email-sdk doctor --adapter brevoBREVO_API_KEY="xkeysib-..." npx --package @opencoredev/email-sdk email-sdk send \
--adapter brevo \
--from "Acme <hello@acme.com>" \
--to user@example.com \
--subject "Brevo smoke test" \
--text "It works" \
--dry-runDrop --dry-run for one real send to confirm the key, sender verification, and recipient policy end to end.
Compare Brevo with other providers
Side-by-side message-field support from the SDK capability matrix, with working code for both adapters:
Frequently asked questions
Does Email SDK support Brevo?
Yes. Email SDK ships a Brevo adapter imported from @opencoredev/email-sdk/brevo. You keep your Brevo account and credentials; the SDK adds message validation, typed errors, and no-network test adapters around the same send() call used for every other provider.
Which message fields does the Brevo adapter support?
Brevo supports every normalized message field: CC recipients, BCC recipients, Reply-To address, Custom headers, Attachments, Tags, Metadata, and Scheduled sending (sendAt).
Can Brevo schedule email for later with Email SDK?
Yes. Set sendAt on the message and the Brevo adapter passes the scheduled time to the provider.
Does the Brevo adapter support idempotent sends?
No. Brevo has no provider-side idempotency, so a retried send can be delivered twice. Deduplicate in your own queue before retrying.