Add every WhatsApp opt-in to your Brevo contact list automatically, look up whether a customer is already subscribed before sending a campaign, and keep both channels in sync without any manual CSV work.
Before following this guide, read the External API Request step foundation guide. It covers every field in the step interface so this guide can stay focused on Brevo-specific values.
Unlike most APIs in this series that use Authorization: Bearer or Authorization: Basic, Brevo uses a custom header: api-key: YOUR_API_KEY. The header name is literally api-key. Using Authorization will return a 401 error.
Brevo API v3 reference: developers.brevo.com
Brevo organises contacts into lists. List IDs are integers. Fetch them once and store the ID of the list you want WhatsApp opt-ins to join.
{{
"lists": [
{{
"id": 2,
"name": "WhatsApp Opt-Ins",
"totalSubscribers": 1204,
"folderId": 1
}}
],
"count": 1
}}
Copy: lists[0].id = 2 (integer, not a string)
Use this integer in the listIds array when adding contacts.When a customer opts in on WhatsApp, push their details to Brevo
in the same automation flow. Setting updateEnabled: true
makes this an upsert: creates if new, updates if they already exist.
Body:
{{
"email": "{{customer_email}}",
"attributes": {{
"FIRSTNAME": "{{customer_name}}",
"PHONE": "{{customer_phone}}"
}},
"listIds": [2],
"updateEnabled": true
}}
Response (new contact created):
{{"id": 42}}
Response (existing contact updated):
HTTP 204 No Content (empty body, success)
Key points:
- attributes keys are UPPERCASE (FIRSTNAME, LASTNAME, PHONE)
- listIds is an array of integers [2], not strings
- updateEnabled: true prevents 400 on duplicate email
- 204 No Content on update is normal and means successBrevo predefined contact attributes use all-caps names: FIRSTNAME, LASTNAME, PHONE, COMPANY. Custom attributes use whatever case you defined in the Brevo dashboard. Always match the case exactly or the field will be silently ignored.
To check whether a WhatsApp contact is already in your Brevo list before deciding what to send them, fetch their contact record by email address.
{{
"id": 42,
"email": "priya@example.com",
"attributes": {{
"FIRSTNAME": "Priya",
"PHONE": "+919820000001"
}},
"listIds": [2, 5],
"emailBlacklisted": false,
"smsBlacklisted": false,
"createdAt": "2026-06-01T10:00:00Z"
}}
Map: id, email, attributes.FIRSTNAME, listIds, emailBlacklisted
If contact not found: Brevo returns HTTP 404.Map these response paths to WhatsApp variables:
| Variable name | Response path | Example value |
|---|---|---|
| contact_id | id | 42 |
| contact_name | attributes.FIRSTNAME | Priya |
| contact_lists | listIds | [2, 5] |
| is_blacklisted | emailBlacklisted | false |
If emailBlacklisted is true, Brevo will not send campaigns to this address. Check this before using their email for outreach.
Trigger: Customer messages 'JOIN' on WhatsApp.
Bot asks: 'Share your email to receive our newsletter.'
Customer: priya@example.com
Stored as {{customer_email}}, {{customer_name}} already captured.
Step 1 — Check existing (GET /contacts/email):
GET https://api.brevo.com/v3/contacts/priya@example.com
api-key: YOUR_API_KEY
Response: HTTP 200 -> contact exists; HTTP 404 -> new contact
Conditions:
HTTP 200 -> 'You are already on our list. Thank you!'
HTTP 404 -> run Step 2
Step 2 — Add contact (POST /contacts):
POST https://api.brevo.com/v3/contacts
api-key: YOUR_API_KEY
Body: {{email: 'priya@example.com', attributes: {{FIRSTNAME: 'Priya'}},
listIds: [2], updateEnabled: true}}
Response: {{id: 42}} or HTTP 204
Bot replies:
'You are now subscribed, Priya! You will receive our latest updates
at priya@example.com.'| Symptom | Likely cause | Fix |
|---|---|---|
| 401 Unauthorized | Wrong header name or invalid key | Use api-key as the header name, not Authorization. Confirm the key value is correct and was not truncated. |
| 400 on POST: duplicate contact | updateEnabled not set | Add updateEnabled: true to the POST body. This makes the call an upsert instead of a create-only. |
| Attribute value not saved | Wrong attribute name case | Brevo attribute names are case-sensitive. Use FIRSTNAME, LASTNAME, PHONE exactly. Custom attributes must match the name you defined in the dashboard. |
| listIds not working | Passing string instead of integer | List IDs must be integers in the array: [2], not ['2']. Copy the integer id from GET /contacts/lists. |
| 404 on contact lookup | Contact not in Brevo | Contact does not exist yet. Use the POST step to add them. A 404 here is expected for new contacts. |
| 204 No Content on update | Normal success response | A 204 on POST /contacts with updateEnabled: true means the existing contact was updated successfully. It is not an error. |
Mailchimp API: data centre prefix, anystring Basic Auth, subscriber sync.
Read guide →Klaviyo API: Bearer token, profile lookup, list subscription.
Read guide →Free trial, no credit card. If you get stuck, we answer live on WhatsApp.