> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.brevo.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.brevo.com/_mcp/server.

# Python SDK Changelog

## August 10, 2026 — v5.0.2

### Added

* **Email Campaigns — UTM parameter customization** — `email_campaigns.create_email_campaign()` and `email_campaigns.update_email_campaign()` now accept optional `utm_campaign`, `utm_content`, and `utm_term` keyword arguments to customize UTM tracking parameters. Campaign retrieval methods return these values along with `utm_id`, `utm_medium`, and `utm_source` when UTM tracking is enabled.
* **Transactional Email — per-contact pixel tracking consent** — `transactional_emails.send_transac_email()` now accepts optional `contact_pixel_tracking_consent` boolean field on individual recipient dictionaries (in `to`, `cc`, `bcc`, and `message_versions` arrays) to control whether opens are tracked identifiably (`True`) or anonymized (`False`). When the per-contact pixel tracking consent feature is enabled for your account, this field determines tracking behavior per recipient.

Backward-compatible patch release. No breaking changes.

## July 3, 2026 — v5.0.1

### Added

* **Consent Groups Management** — new endpoints for managing contact consent groups:
  * `GET /contacts/consent-groups` — list all consent groups
  * `POST /contacts/consent-groups` — create a consent group
  * `GET /contacts/consent-groups/{id}` — retrieve consent group details
  * `PUT /contacts/consent-groups/{id}` — update consent group (name, description, signup mode)
  * `DELETE /contacts/consent-groups/{id}` — delete a consent group
* **Consent group support in contact operations** — `POST /contacts/import` now accepts optional `consent_group_ids` to add imported contacts to specified groups
* **Contact details enhancement** — `GET /contacts/{identifier}` now returns `consent_groups` array showing each group and subscription status (when feature enabled)
* **Wallet pass installation URLs** — `GET /wallet/passes/{passId}/installUrl/{contactId}` generates per-contact installation URLs for Apple Wallet and Google Wallet integration

### Fixed

* **Empty JSON object serialization** — objects with no properties now serialize correctly to `{}` instead of `[]`. Previously, empty optional/nullable objects would serialize as empty arrays, causing backend validation errors on strict type checkers. This affected both top-level objects and nested objects within parent types. The fix ensures proper JSON structure for all empty serializable objects.

Backward-compatible patch release. No breaking changes.

## May 14, 2026 — v5.0.0

### Breaking changes

* ⚠️ **`companies.get_companies(filters=...)`** — the `filters` keyword is renamed to `filters_attributes_name`. The old keyword is silently dropped, the request still succeeds, and the server returns an unfiltered list.
* **`event.create_batch_events`** — keyword renamed `request=` → `events=`; item types renamed in lockstep (`CreateBatchEventsRequestItem` → `CreateBatchEventsRequestEventsItem` and 5 sub-types).
* **`balance.get_contact_balances`** — new required `balance_definition_id` parameter.
* **`balance.get_active_balances_api`** — response type replaced with `GetLoyaltyBalanceProgramsPidActiveBalanceResponse` (different shape).
* **`balance.begin_transaction.event_time`** — `str` → `datetime`. Runtime-tolerant under `skip_validation`, but type-checkers will fail.
* **`tasks.get_all_task_types`** — return type changed from `GetCrmTasktypesResponse` to `List[GetCrmTasktypesResponseItem]`. Old `.id` / `.title` access on the response fails (it's a list now).
* **`webhooks.create_webhook`** — `events` argument moved from required to optional. Positional callers break; switch to keyword arguments.
* **`webhooks.*.message_id`** — type changed from `int` to `str` on history-fetch endpoints.
* Response fields removed: `GetAccountResponse.date_time_preferences`, `GetWebhook.channel`, `GetProcessResponseInfo.export`.
* Shape collapses: `SendTransacSmsTag` is now `Union[str, List[str]]` (was a pydantic model); `GetExtendedCampaignStats.links_stats` is now `Dict[str, int]` (was a pydantic class); `ConversationsMessageAttachmentsItem`: `file_name` → `name`, `inline_id` → `link`.
* 21 names removed from top-level `from brevo import ...` — most notably `CreateBatchEventsRequestItem*` (6 names), `GetWebhookChannel`, `GetAccountResponseDateTimePreferences`, `GetExtendedCampaignStatsLinksStats`, `SendTransacSmsTagField`, and `UpsertrecordsRequestRecordsItemAssociationsItemZero/One*` (8 names).

### Added

* New optional fields and filters across `contacts.create_contact`, `contacts.update_contact`, `email_campaigns.get_email_campaigns`, `ecommerce.get_products`, and several other endpoints.
* Both `Brevo` (sync) and `AsyncBrevo` are affected symmetrically by every change above.

See the [Upgrading from v4.x guide](https://github.com/getbrevo/brevo-python#upgrading-from-v4x) for migration details and a one-line rollback pin.

## April 10, 2026 — v4.0.11

### Fixed

* **Process endpoints** — `duplicate_email_id` is now typed as a string (URL to a CSV file) instead of an integer. The legacy `in_process` status value is now handled correctly.
* **Event endpoints** — `contact_properties` and `event_properties` now accept boolean values in `create_event` and `create_batch_events`.
* **Contact endpoints** — `attributes` now accepts plain integers in `create_contact` and `update_contact`.

## March 25, 2026 — v4.0.9

### Added

* `client.event.get_events()` — retrieve a paginated list of custom events with filters for contact, event name, object type, and date range.
* `client.event.create_batch_events()` — track multiple contact interactions in a single request.
* `CreateUpdateProductRequest` and batch product upsert now accept optional `brand` and `description` fields.
* `GetProductDetails` response now includes `brand` and `description`.
* Balance: `get_active_balances_api()`, `get_contact_balances()`, and `get_subscription_balances()` now accept `include_internal`.
* Balance: `get_transaction_history()` now supports filtering by `status` and `transaction_type`.

### Improved

* `meta` field on balance definition requests is now a typed model with an `is_internal` flag.
* `metaInfo` size limit for products clarified: maximum **20,000 characters** total.
* `users` field on plan verticals is now nullable.

## March 12, 2026 — v4.0.7

### Fixed

* `GetCampaignStats`: `apple_mpp_opens` and `opens_rate` are now correctly typed as nullable.
* `Order.products`: all product fields are now accessible — `price`, `product_id`, `variant_id`, `quantity`, `quantity_float`.
* `create_contact()`: correctly handles `204 No Content` responses without raising a deserialization error.

### Deprecated

* `transactional_sms.send_transac_sms()` — use `transactional_sms.send_transac_sms_async()` instead.

## February 23, 2026 — v4.0 beta release

Released a beta version of the Python SDK (v4.0) with native async support via `AsyncBrevo`, Pydantic-based typed models, automatic retries with exponential backoff, and custom `httpx` client support.

```bash
pip install brevo-python
```

### Key highlights

* Unified client via `Brevo(api_key="...")` — no more manual configuration objects
* Native async support with `AsyncBrevo`
* Full type annotations for all request and response models
* Raw response access via `with_raw_response`
* 33 service namespaces covering the entire Brevo API