Orders — stable sort when paging
Get orders (GET /orders) accepts a new optional query parameter, secondarySortByModifiedAt (boolean, default false).
When true, orders with the same createdAt are then ordered by their updatedAt, in the same direction as sort. Use it to get a stable order when paging through the results with limit and offset.
api_key_name in contact webhooks
- Marketing Webhooks — The Contact updated and Contact added to list events now include
api_key_name: the name of the API key that made the change, or an empty string when the change wasn’t made through the API. Use it to recognise and ignore webhooks triggered by your own integration’s writes.
Orders — shipping address and product SKU
Orders now accept two optional fields:
shipping: the shipping recipient and ship-to address (name,address,city,region,postCode,country,countryCode,phone), separate frombilling. Use it when the recipient or ship-to address differs from billing, or when your platform sends both.products[].sku: the Stock Keeping Unit identifier of each line item, next toproductId. It’s stored as sent and isn’t matched against the product catalog.productIdstays required.
Transactional Email — send without the open pixel (Enterprise)
You can now send a recipient an email with no open pixel. Pass removeTrackingPixel: true on a recipient in to, cc or bcc, including inside messageVersions. No open is recorded for that recipient, not even in aggregate statistics.
- Only available to Enterprise plans. For other accounts the field is accepted but ignored, and the open pixel is added as usual.
- Considered only if the recipient isn’t tracked:
contactPixelTrackingConsentisfalse, or not passed and your account doesn’t track unknown-consent contacts. - Click tracking is unchanged.
- A value other than
true/falseis rejected.
Loyalty webhooks documentation corrected
The Loyalty webhooks page now matches what Brevo sends:
- The event reference table lists all 24 Loyalty events. It was missing
membership_anniversary_reminder,subscription_member_added,subscription_member_removed,tier_association_month_anniversary,tier_association_year_anniversary,voucher_created,voucher_revoked,voucher_redeem_unauthorizedandvoucher_attribution_failed. - A new section documents the fields included in every Loyalty webhook payload:
contact_id,contact_properties,event_date,event_id,event_name,identifiersandsource. - The
voucher_createdexample now shows a complete payload.
Apps — public apps
With Brevo CLI 2.5.0, you can create public apps: OAuth apps that any Brevo account can authorize once Brevo has reviewed and approved them. Use a public app when you offer a Brevo integration to your own customers, for example with an install link in your SaaS product or a listing on a third-party marketplace. Brevo doesn’t list public apps on a Brevo marketplace. Private apps are unchanged and remain limited to your own organization.
Wallet — redeem a pass
New endpoint POST /wallet/passes/{installationId}/redeem records that a contact’s wallet pass was scanned or redeemed, for example a store visit, event check-in or loyalty check-in. The scan is recorded as an event that can trigger automations and update contact segments.
The request body is optional. You can include location, amountSpent, eventTag and customData to describe the scan. If Wallet isn’t enabled for the account, the endpoint returns 422 with the code WALLET_NOT_ENABLED.
Contacts — export with no matching contacts
POST /contacts/export now documents what happens when no contact matches the filter: no export process is created, and the endpoint returns 200 with an empty object instead of 202 with a processId. Treat that response as “nothing to export” rather than a failure, and don’t assume processId is always present.
Endpoint reference: Export contacts
Contacts — date filtering on contact export
POST /contacts/export now supports date filtering through customContactFilter, so you can export only the contacts that changed within a time window instead of pulling the full set and filtering client-side.
New filter fields (used with actionForContacts):
modifiedSince— export only the contacts modified after this date-time.createdSince— export only the contacts created after this date-time.
M2M token endpoint moves to the API host
Improved
- Machine-to-machine (M2M) authentication — The
client_credentialstoken endpoint is nowhttps://api.brevo.com/realms/partner/oauth/token, on the same host as the API. The previous URL,https://oauth.brevo.com/realms/partner/oauth/token, keeps working. The guide’s token example now requests an explicitscopeand explains that requesting a scope the app wasn’t granted returns400 invalid_scope. - API reference — The OAuth 2.0 token URL in the API reference points to the new endpoint.
Brevo Developer Terms and site footer
- Added the Brevo Developer Terms page, linked from the site footer. The terms govern your use of the Developer Tools and the Distributable Apps you build with them.
- Added a site-wide footer with links to the Brevo Anti-Spam policy, Privacy policy, User agreement, Legal Notice and Developer Terms.
Integration guides for app builders and automation tools
Added
- Integrations — Six new guides under Messaging API > Integrations show how to send email through Brevo from popular app builders and automation tools: Base44, Bolt.new, Lovable, n8n, v0, and Supabase Auth emails over SMTP. The Supabase guide is also linked from SMTP relay integration.
Improved
OAuth 2.0 machine-to-machine (M2M) authentication
Added
- Machine-to-machine (M2M) authentication — New guide for authenticating server-to-server calls with the OAuth 2.0
client_credentialsgrant. Create an M2M app with the Brevo CLI, exchange itsclient_idandclient_secretathttps://oauth.brevo.com/realms/partner/oauth/tokenfor a short-lived access token (about 1 hour, no refresh token), then call the API withAuthorization: Bearer <token>instead of theapi-keyheader. API keys are unaffected and keep working. - API reference authentication — The API reference now lists OAuth 2.0 alongside API key as an authentication option. See Authentication schemes.
- CLI reference — Documented the M2M commands:
brevo app create --m2m --scopes,brevo app list --type m2m,brevo app token,brevo app secret rotate, andbrevo app scopes update. These commands require a Brevo CLI release that includes Machine-to-machine support.
Loyalty transaction status renamed, new balance field
Breaking changes
- Begin transaction / Cancel transaction / Complete transaction — The transaction
statusenum valuespendingandcompletewere renamed todraftandcompleted(rejected,cancelled, andexpiredare unchanged). Code that checks for the old string values must be updated.
Added
Loyalty subscription details and image gallery naming guidance
Added
- Get subscription info (
GET /loyalty/config/programs/{pid}/account-info) — Response now includesloyaltyProgramName, amembershipobject (loyaltySubscriptionId,createdAt,updatedAt) resolved from the providedcontactIdorloyaltySubscriptionId, and new reward fields:publicDescription,unit(currency code orPERCENT), andvalue(the reward’s value snapshot at attribution time). Also addsbalanceDefinitionName,rewardName,groupName, andtierNamealongside their respective IDs. See Get subscription info.
Get the records associated with an object record
New endpoint GET /v3/objects/{object_type}/associated-records returns the records associated with a single source record. Associations of every type come back together in one paginated list, most recently created association first.
- Identify the source record with exactly one of
id,ext_id,emailorsms.emailandsmsare only accepted whenobject_typeiscontact. - Filter the response with
type, up to 5 associated object types per call, for example?type=contact&type=garage. - Results are returned 20 per page. Increase
offsetby 20 untilhas_moreisfalse. - Contacts in the response carry all of their attributes, with attribute keys in lowercase.
brevo app upload replaces brevo app update
Push app-config.json to Brevo with brevo app upload. It fetches your app’s current state, shows a local-vs-server diff, and asks you to confirm before pushing anything. No differences means no network call.
- Edit the field you want to change in
app-config.json— name, redirect URLs, scopes, logo — then runbrevo app upload. The old--name,--redirect-uri,--scope,--logo-uri, and--app-idflags are gone. app-config.jsonalso has a cleaner shape:auth.redirectUrlsis nowauth.redirectUris,distributionis nowdistribution_type, and there’s a new read-onlyversion. Existing files keep working and migrate automatically the next time a command writes them.brevo app updatestill runs, but only to point you tobrevo app upload— it no longer changes anything.
Product import guide now documents alternativePrice
The Import your products guide now documents the alternativePrice (float) field: a secondary price displayed alongside the main price, typically a discounted or sale price, a member price, or a compare-at price.
Added alternativePrice to the request examples and parameter tables for Create or update a product and Create products in a batch.