App guides

The Brevo app keeps your store's customers in sync with Brevo contacts, and sends cart and order events you can use to trigger Brevo automations. Customers who accept email marketing are added to your email list, and customers who accept SMS marketing can have their phone number saved for SMS.

With order sync on, orders also go to Brevo eCommerce for revenue reporting and segmentation. An action in the dashboard imports the customers you already have.

WhenWhat the app does
A customer account is created, or its email, name, phone, addresses or opt-ins changeCreates or updates the Brevo contact, and adds it to your email list if the customer accepts email marketing.
A customer turns off email marketingRemoves the contact from your email list, if Remove from list on opt-out is on.
A cart is createdSends checkout_started, if the cart already has a customer.
Swell marks a cart abandonedSends cart_abandoned.
An order is placedSends order_submitted, and the order to Brevo eCommerce if order sync is on.
An order is fully fulfilledSends order_fulfilled, and updates the order in Brevo eCommerce if order sync is on.
An order is canceledSends order_canceled, and updates the order in Brevo eCommerce if order sync is on.
You run Import existing customersCreates or updates a contact for every customer account, in the background.

Events and orders are sent only for carts and orders linked to a customer account with an email. Each event can be turned off in the app settings, and nothing is sent while Enabled is off.

  • A Brevo account and a Brevo API key. You create the key in step 1.
  • Blocking of unknown IP addresses turned off in Brevo, under Security > Authorized IPs. Swell has no fixed IP addresses to add, and while blocking is on, Brevo refuses every call from the app. Brevo turns it on by default for accounts created since May 2024.
  • A Brevo list for customers who accept email marketing. Without a list, customers are synced as contacts but aren't added to one.
  • The names of the first and last name contact attributes in your Brevo account, if they aren't FIRSTNAME and LASTNAME.
  • For SMS marketing, Brevo's SMS contact attribute, where the app saves the customer's phone number.
  • For order sync, eCommerce activated in your Brevo account.
  • Opt-ins at checkout. Customers accept marketing with Email opt-in and SMS opt-in in Settings > Checkout in Swell. SMS opt-in is set to Disable and hide by default, so change it to collect SMS opt-ins.

Install Brevo from the Swell App Store, and set it up in your test environment before the live one.

1
Create an API key

In Brevo, go to Settings > SMTP & API > API Keys, create a key, and copy it. The key starts with xkeysib-.

Then go to Security > Authorized IPs and turn off blocking of unknown IP addresses. Swell has no fixed IP addresses to add to the list.

2
Find your list ID

In Brevo, go to Contacts > Lists and find the list for customers who accept email marketing. Its ID is the number after #, such as 7.

3
Add them to the app

In Swell, go to Apps > Brevo > Settings and paste the key in API key. Enabled is on by default. On the Contacts tab, enter the Email list ID, turn on Sync phone for SMS opt-ins if you send SMS, and change First name attribute and Last name attribute if your Brevo account uses other names. On the Events tab, turn off the events you don't use. To send orders, turn on Sync orders to Brevo eCommerce on the eCommerce tab. Click Save settings.

Then choose Actions > Test connection. The message names your Brevo account and your list. From then on, new and changed customers and their events are sent as they happen.

4
Import your existing customers

Choose Actions > Import existing customers, then Start import. The import runs in the background and creates or updates a contact for every customer account, with the settings you saved.

5
Create a test customer

Go to Customers and create a customer with an email you can check, with Customer accepts email marketing turned on. In Brevo, the contact appears under Contacts with the customer's name, in your list. The logs in Swell show Brevo: synced contact with the email and the list ID. Then place a test order as that customer, and the logs show Brevo: tracked order_submitted with the email.

6
Go live

Settings are saved separately for each environment. In the live environment, repeat steps 3 and 4 with the API key and list your store uses. Test customers and orders go to the Brevo account whose key you enter, so use a separate Brevo account or list for the test environment.

Each event reaches Brevo with its name below and the customer's email, so you can use it to trigger automations. For example, trigger cart recovery emails on cart_abandoned, order follow-ups on order_submitted and review requests on order_fulfilled.

Brevo eventSent whenSetting
checkout_startedA cart is created, if it already has a customer.Checkout started
cart_abandonedSwell marks a cart abandoned.Cart abandoned
order_submittedAn order is placed.Order placed
order_fulfilledAn order is fully fulfilled.Order delivered
order_canceledAn order is canceled.Order canceled

Each event's properties are the cart's or order's id, number, status, currency, grand_total, sub_total, discount_total, tax_total, shipment_total, coupon_code and items, and for carts checkout_url, which brings the shopper back to their cart. Each item has id, product_id, variant_id, name, slug, sku, image_url, quantity, price, price_total and discount_total. Amounts are in the record's currency, not in cents. Properties without a value in Swell are left out.

Each event also sends the customer's first and last name as contact properties, under the attribute names in the settings.

A cart is usually created when the shopper adds the first item. At that point most carts don't have a customer yet, so checkout_started is sent only for carts that do, such as a cart started by a customer who's logged in.

Swell marks a cart abandoned 3 hours after its items, shipping or billing details last changed, or after the delay set for the abandoned cart email in Settings > Notifications. Swell marks carts abandoned whether that email is on or off. A cart that's abandoned again after the shopper comes back sends cart_abandoned again. If Brevo sends your cart recovery emails, turn off Abandoned cart in Settings > Notifications, so customers don't get both.

Each customer account with an email becomes a Brevo contact, identified by email, with the first and last name. Account changes that don't affect the contact, such as a new order count, aren't sent.

  • A customer who accepts email marketing is added to the Email list ID list.
  • A customer who turns off email marketing in Swell is removed from the list, if Remove from list on opt-out is on. The contact stays in Brevo.
  • Customers who didn't opt in are synced as contacts but not added to the list.
  • The app never blocklists or unsubscribes contacts in Brevo, and unsubscribes in Brevo don't reach Swell.

With Sync phone for SMS opt-ins on, a customer who accepts SMS marketing gets their phone number in the contact's SMS attribute. The app uses the account's phone number, or the phone number of its shipping or billing address. Numbers without a country code use the shipping country, or the billing country, and are sent in international format, such as +15035550142. Numbers that aren't valid are left out.

If Brevo refuses the number, for example because another contact already has it, the contact is saved without it. A customer who turns off SMS marketing in Swell keeps their number in Brevo.

To create contacts for the customers you already have, go to Apps > Brevo, choose Actions > Import existing customers, and click Start import. To import only customers who accept email marketing, check Only customers who opted in to email first.

  • The import runs in the background, and a message tells you when it has finished or failed. Runs are listed on the app's Workflows tab as Import customers, with their status. Click a run to see its steps or cancel it.
  • Customers are imported 100 at a time, oldest first. The settings are read again before each 100, so changes you save during an import apply to the next 100. Customers who accept email marketing are added to your list, and the others are created or updated as contacts without it.
  • Customers without an email are skipped. Contacts that Brevo refuses when they're created or updated without the list, such as ones with an invalid email, are logged and counted as failed, and the import continues. If Brevo refuses a group's import to your list, the error is logged and those customers are created or updated one by one instead, with the list, and counted as synced or failed.
  • Running the import again updates contacts without duplicating them, and doesn't clear values already in Brevo. It doesn't remove anyone from your list.
  • The import sends customers only. Past carts and orders aren't sent as events or eCommerce orders.
  • If Enabled is off or the API key is empty, the import doesn't start and fails with the reason. If you turn off Enabled or remove the API key during an import, it finishes the 100 customers it's sending, stops before the next 100, and fails with the totals sent until then.
  • When it finishes, the logs show the totals: added to list, synced, skipped and failed.

Import existing customers is in the Actions menu only while Sync customer accounts is on.

With Sync orders to Brevo eCommerce on, each order is sent to Brevo eCommerce when it's placed, and sent again when it's fully fulfilled or canceled. Each order has its order number, total, creation and update dates, the customer's email, the coupon, and each item's product ID, variant ID, price and quantity.

The order's status is its status in Swell, such as payment_pending, delivery_pending, complete or canceled. Brevo's copy is updated only at those three moments, so payments, refunds and edits in between aren't sent. Orders are sent whether or not their events are turned on.

WhereWhat it's for
Apps > Brevo > SettingsThe API key, Enabled, and the Contacts, Events and eCommerce tabs.
Apps > Brevo > ActionsTest connection, and Import existing customers. Save the settings first: the actions are unavailable while there are unsaved changes.
Apps > Brevo > WorkflowsThe runs of Import existing customers, with their status, who started them, when, and how long they took.
CustomersAccepts email marketing and Accepts SMS marketing on each customer.
Settings > CheckoutThe email and SMS opt-ins customers accept at checkout.
Settings > NotificationsThe abandoned cart delay, and Swell's own abandoned cart email.
Developer > Console > LogsEach contact, event and order the app sends, and each error.

Settings are in Apps > Brevo > Settings and are saved separately for each environment.

API key and Enabled are at the top. The other settings are on the Contacts, Events and eCommerce tabs.

SettingDescriptionDefault
API keyYour Brevo API key, from Brevo > Settings > SMTP & API > API Keys. Starts with xkeysib-. Required: without it, the app sends nothing.None
EnabledTurns all syncing on or off without uninstalling the app. While it's off, the import doesn't run.On
Contacts > Sync customer accountsCreates and updates a Brevo contact for each customer account. Import existing customers is available only while it's on.On
Contacts > Email list IDThe ID of the Brevo list for customers who accept email marketing, such as 7 or #7. When it's empty or not a number, contacts aren't added to a list.None
Contacts > Remove from list on opt-outRemoves the contact from the list when the customer turns off email marketing.On
Contacts > Sync phone for SMS opt-insSaves the phone number in the contact's SMS attribute for customers who accept SMS marketing and have a valid number.Off
Contacts > First name attributeThe Brevo contact attribute for the first name. Saved in uppercase.FIRSTNAME
Contacts > Last name attributeThe Brevo contact attribute for the last name. Saved in uppercase.LASTNAME
Events > Checkout startedSends checkout_started when a cart is created.On
Events > Cart abandonedSends cart_abandoned when a cart is abandoned.On
Events > Order placedSends order_submitted when an order is placed.On
Events > Order deliveredSends order_fulfilled when an order is fully fulfilled.On
Events > Order canceledSends order_canceled when an order is canceled.On
eCommerce > Sync orders to Brevo eCommerceSends orders to Brevo eCommerce. Activate eCommerce in Brevo first.Off
  • Data goes one way, from Swell to Brevo. Unsubscribes and edits made in Brevo don't reach Swell.
  • Contacts are identified by email. When a customer changes their email, a new contact is created for the new address, and the old one stays in Brevo.
  • Turning off email marketing removes the customer from your list only. Turning off SMS marketing doesn't remove the number from Brevo.
  • One list for email opt-ins. SMS opt-ins aren't added to a list.
  • Carts and orders without a customer email send nothing. Most new carts don't have one yet, so checkout_started is sent mainly for customers who are logged in.
  • The import sends customer accounts only. Past carts and orders aren't sent, and changes made while the app was off aren't sent later.
  • The app doesn't send your product catalog to Brevo. eCommerce orders refer to items by their Swell product and variant IDs.
  • Brevo accepts up to 50 KB of event properties, so an event for a cart or order with a very long item list can be refused.
  • Events have no ID, so the app sends each event at most once. It sends an event again only when Brevo rate-limits the app, because Brevo records nothing then. After a network error, timeout or server error, Brevo may already have recorded the event, so it isn't sent again and can be lost. If Swell runs the function again for another reason, for example after it times out, Brevo records the event again.
  • If Brevo can't be reached, rate-limits the app or has a server error while a contact or order is sent, Swell runs the function again, first after a minute and then at growing intervals. If it keeps failing for 4 days, Swell turns off the function and emails the store's admins. To turn it back on, update or reinstall the app. Other errors are logged and the change isn't sent again.
  • Event names and properties are fixed.

Test connection and Import existing customers show their messages in the dashboard. The app also logs each contact, event and order it sends, and each error. In the Swell dashboard, the logs are under Developer > Console > Logs.

Check that Enabled is on and the API key is filled in, and click Save settings. The logs show "Brevo: missing API key in app settings" when the key is empty. Then choose Actions > Test connection. Changes made while the app was off aren't sent later. To bring contacts up to date, run Import existing customers.

Test connection checks the saved settings. Enter the key and click Save settings before you test.

Copy the key again from Settings > SMTP & API > API Keys in Brevo, and check that it starts with xkeysib- and hasn't been deleted. Paste it, click Save settings, and test again.

Brevo's Authorized IPs check is on, so Brevo refuses calls from the app even with a valid key. Swell has no fixed IP addresses to add. In Brevo, go to Security > Authorized IPs, turn off blocking of unknown IP addresses, and run Test connection again. While it's on, every sync and event fails with a 401 in the logs, and the import counts every customer as failed.

Check the Email list ID against Contacts > Lists in Brevo. The message shows only when Brevo answers that the list doesn't exist.

Brevo answered the list check with an error, and its reason follows the message. When the message says try again, Brevo couldn't be reached, rate-limited the app or had a server error: test again in a minute.

Brevo answered with another error or couldn't be reached. The reason follows the message. Try again in a minute.

Check that the customer accepted email marketing: the Swell customer page shows Accepts email marketing. Then check that Sync customer accounts is on and the Email list ID is right. Customers who existed before you set up the app are added when you run Import existing customers.

Check that Sync phone for SMS opt-ins is on, that the customer page shows Accepts SMS marketing, and that the customer has a valid phone number with a country code, or a shipping or billing country. The logs show "Brevo: SMS rejected for …, retrying without it" when Brevo refuses the number, for example because another contact has it.

Check that First name attribute and Last name attribute match the names of the contact attributes in your Brevo account.

The logs show "Brevo: checkout_started skipped", or the name of another event, followed by "has no customer email" when the cart or order isn't linked to a customer with an email. Also check that the event is turned on in the Events tab. cart_abandoned arrives only after Swell marks the cart abandoned.

An event that failed with a network error, timeout or Brevo server error is logged with "(not retried, Brevo may have recorded it)" and isn't sent again.

Check that Sync orders to Brevo eCommerce is on and that eCommerce is activated in Brevo. Orders are sent when they're placed, fully fulfilled or canceled after you turn it on. The logs show the reason when Brevo refuses an order, after "order sync for order" and the order ID.

When Brevo refuses the import to your list for a group of customers, the logs show "Brevo: import job for … contacts rejected, syncing them one by one:" with Brevo's reason, and those customers are created or updated one by one instead. If that fails too, for example because the list was deleted, they're counted as failed. Check the Email list ID and the Authorized IPs setting with Actions > Test connection, then run the import again.

Brevo adds the customers who accept email marketing to your list in a background job of its own, so the logs don't show contacts that Brevo refuses there, and the totals count them as added to list.

The import fails without sending anyone, with "Import not started: the Brevo app is disabled in its settings." when Enabled is off, or "Import not started: add your Brevo API key in the app settings." when the API key is empty. Fix the setting, click Save settings, and run the import again.

Enabled was turned off or the API key was removed while the import was running. The import finished the 100 customers it was sending and stopped before the next 100. The message gives the reason and the totals sent until then, such as "Import stopped: the app was disabled in settings. Before stopping: added to list 100, synced 0, skipped 0, failed 0." Fix the setting, click Save settings, and run the import again. Customers already sent are updated, not duplicated.

Open the run on the Workflows tab to see its error and the step that failed. On temporary errors, such as when Brevo can't be reached, rate-limits the app or has a server error, each group of 100 customers is tried up to 5 more times before the import fails. Running the import again is safe.

Turn on Sync customer accounts and click Save settings.

Uninstalling the app stops syncing contacts and sending events and orders to Brevo, so automations triggered by the app's events don't start for new activity. It removes the app's functions and settings, including the API key, and the Test connection and Import existing customers actions. Uninstalling applies to the environment you are in, so remove the app from the test and live environments separately.

Contacts, list members, events and orders already in Brevo stay there. The app isn't notified when it's uninstalled, so if you no longer need the API key, delete it in Brevo under Settings > SMTP & API > API Keys. To pause syncing without uninstalling, turn off Enabled.

FunctionRuns onWhat it does
contact-syncaccount.created and account.updatedReads the account and creates or updates the contact. Skips updates that change none of email, first_name, last_name, phone, email_optin, sms_optin, shipping and billing. Unlinks the list when email_optin changed to false.
cart-eventscart.created and cart.abandonedReads the cart with its account and items, and sends checkout_started or cart_abandoned.
order-eventsorder.submitted, order.delivered and order.canceledReads the order with its account and items, sends the order to Brevo eCommerce if order sync is on, then sends order_submitted, order_fulfilled or order_canceled.
test-connectionThe Test connection actionReads the Brevo account and the email list.
import-customersThe Import existing customers actionA workflow. Reads accounts 100 at a time in id order, one step per page, each step retried up to 5 times with exponential backoff from 30 seconds.

The app adds no fields to Swell records. It reads its settings from brevo in the app settings, applies the defaults to values not saved yet, upper-cases the attribute names, and accepts the list ID as 7 or #7. Every function except test-connection stops when enabled is false or api_key is empty.

All calls go to https://api.brevo.com/v3 with the api-key header:

  • POST /contacts with updateEnabled: true, the name attributes, SMS when allowed, and listIds for an account with email_optin: true when a list is set. On a 400 response with SMS in the body, it's sent once more without SMS.
  • PUT /contacts/{email}?identifierType=email_id with unlinkListIds on opt-out. A 400 or 404 response is logged as nothing to remove.
  • POST /events for cart and order events.
  • POST /orders/status for eCommerce orders.
  • POST /contacts/import for the import's opted-in accounts when a list is set, one job per page, with updateExistingContacts: true, emptyContactsAttributes: false and disableNotification: true. The app logs the job's processId and doesn't wait for its result. A 4xx response other than 429 is logged, the page's opted-in accounts count as failed, and the import continues. Other accounts are sent with POST /contacts, 5 at a time.
  • GET /account and GET /contacts/lists/{id} for Test connection.

An event payload looks like this. No event_date is sent, and contact_properties is left out when the account has no name:

{
  "event_name": "order_submitted",
  "identifiers": { "email_id": "maya.chen@example.com" },
  "contact_properties": { "FIRSTNAME": "Maya", "LASTNAME": "Chen" },
  "event_properties": {
    "id": "6acc9e5f3b1d2a0012f4c771", "number": "1042", "status": "delivery_pending", "currency": "USD",
    "grand_total": 128, "sub_total": 118, "discount_total": 0, "tax_total": 10, "shipment_total": 0,
    "items": [{
      "id": "6acc9e5f3b1d2a0012f4c772", "product_id": "66e1a7c09b3f2a0012c5d8e5",
      "name": "Oak Desk Lamp", "slug": "oak-desk-lamp", "sku": "LAMP-OAK",
      "image_url": "https://cdn.schema.io/alder/lamp.jpg",
      "quantity": 1, "price": 118, "price_total": 118, "discount_total": 0
    }]
  }
}

The eCommerce order has id (the order number, or the order ID without one), status (the Swell order status, not mapped), amount (grand_total), createdAt and updatedAt (from date_created and date_updated, in YYYY-MM-DDTHH:mm:ssZ), identifiers.email_id, products with productId, variantId, price and quantity, and coupons with the coupon code.

SMS numbers are parsed with libphonenumber-js's parsePhoneNumberWithError, using the account's phone, then shipping.phone, then billing.phone, with shipping.country or billing.country as the default country. Numbers that fail to parse or isValid() are dropped, and the rest are sent as E.164.

For contacts and eCommerce orders, network errors, 429 and 5xx responses are rethrown, so Swell retries the function. Events are rethrown only on a 429 (handleEventError): after a network error or 5xx Brevo may have recorded the event, so it's logged with (not retried, Brevo may have recorded it). Other errors are logged with console.error and the function succeeds. In order-events, the order sync runs first, then the event. A retryable order sync failure is rethrown before the event is sent, and a retry repeats the order sync, which updates the same order. A 401 whose message mentions an IP address or authorised_ips is Brevo's Authorized IPs check (BrevoError.ipBlocked), which Test connection reports apart from a rejected key.

The step load settings returns only enabled and has_api_key, so the API key isn't stored in the run's step output. Each page step reads the settings again and uses them for that page. The workflow returns imported, upserted, skipped and failed. When enabled is false or api_key is empty, it throws instead, so the run ends as failed: with Import not started: … before the first page, or with Import stopped: … and the totals so far when a page step finds the app disabled or the key removed. The modal's only_optin value arrives in req.data.

Swell builds and maintains the Brevo app. For help with the app, email support@swell.is. For questions about your Brevo account, automations or lists, contact Brevo.