Why route Brevo signups through your own form
Brevo (formerly Sendinblue) is a capable, EU-based email and marketing platform. Its hosted subscription forms work, but they're styled within Brevo's limits, load Brevo's script, and give you no independent spam filtering or submission record.
Own the HTML and route it through splitforms: you get a fully custom, fast form with an AI spam classifier, email notifications, and an auditable dashboard, while Brevo stays your email platform. A small proxy turns each signed webhook into a Brevo contact create/update with your list and attributes.
Step 1 — Get your Brevo API key and list ID
In Brevo, open Settings → SMTP & API → API Keys and create a key. Find the target list ID under Contacts → Lists (the numeric ID shown when you open the list). Store both as environment variables on your proxy host — never in the browser.
Step 2 — The splitforms → Brevo proxy
splitforms fires a signed webhook to your endpoint; the proxy holds the API key and creates/updates the contact. Cloudflare Worker version:
export default {
async fetch(req, env) {
if (req.method !== "POST") return new Response("Method Not Allowed", { status: 405 });
// 1. (Recommended) verify the splitforms HMAC signature header here.
const submission = await req.json();
const f = submission.data ?? submission;
if (!f.email) return new Response("no email", { status: 400 });
// 2. Create or update the contact in Brevo
const res = await fetch("https://api.brevo.com/v3/contacts", {
method: "POST",
headers: {
"api-key": env.BREVO_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
email: f.email,
attributes: {
FIRSTNAME: (f.name ?? "").split(" ")[0],
LASTNAME: (f.name ?? "").split(" ").slice(1).join(" "),
SMS: f.phone,
},
listIds: [Number(env.BREVO_LIST_ID)],
updateEnabled: true, // upsert if the contact already exists
}),
});
if (!res.ok && res.status !== 204) {
return new Response(await res.text(), { status: 502 });
}
return new Response("ok", { status: 200 });
},
};updateEnabled: true makes this an upsert, so a repeat submitter updates rather than errors. Deploy the Worker and paste its URL into your form's webhook settings in the splitforms dashboard. Verify the webhook signature — see send form data to a webhook.
Step 3 — The form
Your public form only talks to splitforms with the public access key. Swap YOUR_ACCESS_KEY for the one from your free account.
<form action="https://splitforms.com/api/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input name="name" placeholder="Name" />
<input name="email" type="email" required placeholder="Email" />
<input name="phone" type="tel" placeholder="Phone (optional)" />
<label><input type="checkbox" name="consent" required /> I agree to receive emails</label>
<!-- honeypot -->
<input type="checkbox" name="botcheck" style="display:none" tabindex="-1" autocomplete="off" />
<button type="submit">Subscribe</button>
</form>What to do next
- Other email tools: Kit (ConvertKit) · ActiveCampaign · Mailchimp
- Webhook fundamentals: send form data to a webhook
- Consent + privacy: GDPR-compliant submissions
- Ready to set it up: get a free access key
FAQ
Is Brevo the same as Sendinblue?
Yes. Sendinblue rebranded to Brevo in 2023. The API moved to api.brevo.com but works the same way — an api-key header and JSON endpoints for contacts, lists, and transactional email. Existing accounts and keys carried over.
Why not use Brevo's own subscription form?
Brevo's hosted forms are convenient but constrained in styling and behavior, load Brevo's script, and don't give you independent spam filtering or a submission dashboard. Owning your HTML and routing through splitforms gives you a fully custom, fast form with AI spam filtering and an auditable dashboard, while a small proxy adds the contact to Brevo via the API and applies your list and attributes.
Is it safe to call the Brevo API from the browser?
No. The Brevo API key is a secret and must stay server-side. In this setup the browser only sends the public splitforms access key; splitforms fires a signed webhook to your proxy, and the proxy holds the Brevo key and creates or updates the contact. The secret never touches client code.
How do I add the contact to a specific list?
Brevo organizes contacts into lists by numeric ID. Find the list ID under Contacts → Lists, and pass it as listIds in the create-contact call. The proxy example includes this. You can add a contact to multiple lists at once by passing several IDs.
What about consent and GDPR, given Brevo is EU-based?
Add a consent checkbox to your form and only call the proxy when it's checked, and rely on Brevo's double opt-in list settings if you use them. The splitforms dashboard keeps a timestamped record of every submission, which helps with consent evidence. Treat this as general guidance and confirm your obligations — see our GDPR guide for the basics.