April 17, 2026

API specification overhaul: accuracy, completeness, and breaking corrections

This release reflects a major rework of the OpenAPI specification to bring it in line with actual API behavior. Some changes correct inaccuracies between the spec and the responses, some generated SDK types will change. See the breaking changes section before upgrading.

Breaking changes

These are corrections to the spec that reflect reality but will require updates to code relying on the previously incorrect types.

  • Process endpoints (GET /processes, GET /processes/{processId}) — Import info fields (invalid_emails, duplicate_contact_id, duplicate_ext_id, duplicate_email_id, duplicate_phone_id, duplicate_whatsapp_id, duplicate_landline_number_id) are now typed as string (URL to a CSV report) instead of integer. This corrects the type for all fields, not just duplicate_email_id which was previously patched.
  • Process endpoints — The following fields have been removed from the response schema as they are not returned by the API: error, created_at, completed_at, and info.export (with total_records and file_size).
  • Process endpointsGET /processes/{processId} 404 error code corrected from invalid_parameter to document_not_found.
  • Account endpoint (GET /account)dateTimePreferences object removed from the response schema (including timezone, timeFormat, dateFormat). startDate, endDate, and users removed from the required fields list in plan objects.
  • Webhooks — Event names corrected: listAdditionslistAddition, hardBounceshardBounce.
  • Feeds (GET /feeds, GET /feeds/{uuid})alias, isInternal, personalization, defaultAttr, and defaultContact fields removed from the response schema as they are not returned by the API.
  • Export webhook history (POST /webhooks/export)messageId field corrected from integer to string.
  • Domain creation (POST /senders/domains) — Domain name validation changed from a custom regex pattern to format: hostname.
  • Pagination minimumslimit minimum on GET /processes and maxRetries minimum on feed endpoints raised from 0 to 1.

Added

  • GET /account400 error response now documented.
  • Master account endpoints400 error responses now documented on GET /corporate/groups/{id}, GET /corporate/groups, GET /corporate/admin-users, GET /corporate/ips.
  • Webhook associations (PUT /crm/objects/{object_type}/records) — Associations now support an action field (link or unlink), enabling removal of associations in the same upsert request. Added three illustrative request body examples.
  • Marketing webhook eventscontactUpdated and contactDeleted added as supported event types for marketing webhooks.

Improved

  • Process endpointsinfo and export_url fields now clearly scoped: info is only returned for completed IMPORTUSER processes; export_url is only returned for SEARCH_EXPORT_USERS, SEARCH_EXPORT_USERS_API, CAMPAIGN_USER_DETAILS, and EXPORT_WEBHOOK process types.
  • Feeds — Auth fields (username, password, token) now documented as conditionally returned based on authType. cache default corrected to true.
  • Custom objects upsert — Significantly expanded description with upsert semantics, id vs ext_id behavior, attribute key vs label guidance, and async processing details.
  • Organization / User endpoints — Added descriptions to GET /organization/invited/users, PUT /organization/user/invitation/revoke/{email}, PUT /organization/user/invitation/{action}/{email}, GET /organization/user/{email}/permissions.
  • Sub-account deletionDELETE /corporate/subAccount/{id} now includes a description warning that deletion is permanent and unrecoverable.
  • Missing summaries — Added summary fields to several Senders, Domains, Webhooks, and Organization endpoints that previously had none.

SDK bug fixes: Node.js v5.0.5, PHP v4.0.14, Python v4.0.11

Fixed

  • Process endpointsduplicate_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 across all SDKs.
  • Event endpointscontact_properties and event_properties now accept boolean values in createEvent and createBatchEvents.
  • Contact endpointsattributes now accepts plain integers in createContact and updateContact. PHP users no longer need to cast integers to float.

March 25, 2026

SDK updates: Node.js v5.0.3, PHP v4.0.11, Python v4.0.9

New endpoints, new fields, and API improvements across all three SDKs.

Node.js — @getbrevo/brevo v5.0.3

Added

  • client.event.getEvents() — retrieve a paginated list of custom events, filterable by contact_id, event_name, object_type, startDate, and endDate. Currently only supports custom events.
  • client.event.createBatchEvents() — send multiple events in a single request. Returns a BatchAcceptedResponse with a confirmation message and queued event count.
  • client.companies.deleteAnAttribute() — delete a CRM attribute by ID.
  • PatchCrmAttributesIdRequest — update a CRM attribute’s display label and selectable option labels, scoped to companies or deals.
  • GetProductDetails response now includes brand and description.
  • CreateUpdateProductRequest and batch product upsert now accept optional brand and description fields.
  • Balance: getActiveBalancesApi(), getContactBalances(), and getSubscriptionBalances() now accept an optional includeInternal parameter.
  • Balance: getTransactionHistory() now supports filtering by status and transactionType.

Improved

  • meta field on balance definition requests is now a typed object ({ isInternal?: boolean }) instead of a generic Record<string, unknown>.
  • metaInfo size limit for products clarified: maximum 20,000 characters total.
  • users field on plan verticals is now nullable (Item.Users | null).

PHP — getbrevo/brevo-php v4.0.11

Added

  • $client->event->getEvents() — retrieve a paginated list of custom events with filters for contact, event name, object type, and date range. Currently only supports custom events.
  • $client->event->createBatchEvents() — track multiple contact interactions in a single request.
  • PatchCrmAttributesIdRequest — update a CRM attribute’s display label and option labels.
  • CreateUpdateProductRequest and batch product upsert now accept optional brand and description fields.
  • Balance: getActiveBalancesApi(), getContactBalances(), and getSubscriptionBalances() now accept includeInternal.
  • Balance: getTransactionHistory() now supports filtering by status and transactionType.

Improved

  • meta field on balance definition requests is now a typed class instead of a generic array.
  • metaInfo size limit for products clarified: maximum 20,000 characters total.
  • users field on GetAccountResponsePlanVerticalsItem is now nullable.

Fixed

  • createContact() no longer throws BrevoException: Failed to deserialize response: Syntax error on empty success responses.

Python — brevo-python 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. Currently only supports custom events.
  • 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 21, 2026

Ecommerce, Events, and Loyalty API updates

Ecommerce — New product fields

Two new fields are now supported on the POST /products and POST /products/batch endpoints, as well as the GET /products/{id} response:

  • brand — Brand name of the product. String, max 128 characters. Example: "Adidas".
  • description — Description of the product. String, max 3000 characters. Example: "Shoes for sports".

metaInfo limit updated: The size limit for the metaInfo field has changed from 1000 KB to 20,000 characters (total across all keys and values). The maximum number of keys remains 20.

Events API — New GET endpoint

A new GET /events endpoint is available to retrieve events filtered by contact, name, object type, or date range.

Query parameters:

ParameterDescription
contact_idFilter by contact ID (repeatable)
event_nameFilter by event name (repeatable)
object_typeFilter by object type (repeatable)
startDate / endDateDate range filter (YYYY-MM-DD or RFC3339). Defaults to the past 6 months.
limitMax events to return. Default 100, max 10000.
offsetEvents to skip for pagination. Default 0.

The response includes a count field for pagination and an events array sorted by event_date descending.

See Event endpoints for the full reference.

Events API — Batch events breaking changes

These are breaking changes to the POST /events/batch endpoint.

Response code changed: 204202

Successful batch requests now return 202 Accepted instead of 204 No Content. The response body is no longer empty — it returns a JSON object:

1{
2 "message": "Batch accepted. Valid events have been added to the processing queue.",
3 "count": 7
4}

Update any client code that checks for 204 on batch event responses.

Partial success status renamed: partialSuccesspartiallyQueued

The status field in the 207 partial success response body has been renamed from partialSuccess to partiallyQueued. Update any client code parsing this field.

Loyalty — Internal balance definitions and tier groups

Balance definitions and tier groups now support a meta object with an isInternal flag:

1"meta": {
2 "isInternal": true
3}

Internal balance definitions are excluded from member-facing balance reads by default. Pass includeInternal=true as a query parameter to include them.

The includeInternal query parameter is available on the following endpoints:

  • GET /loyalty/config/programs/{pid}/balance-definitions
  • GET /loyalty/balance/programs/{pid}/subscriptions/{cid}/balances
  • GET /loyalty/balance/programs/{pid}/balances
  • GET /loyalty/config/programs/{pid}/members

Loyalty — Transaction list filters

The transaction history endpoint (GET /loyalty/balance/programs/{pid}/subscriptions/{cid}/transactions) now supports additional query parameters:

ParameterDescription
statusFilter by status: draft, completed, rejected, cancelled, expired
transactionTypeFilter by type: credit or debit

The offset parameter now represents a page number (not a record skip count).


March 12, 2026

SDK updates: Node.js v5.0.1, PHP v4.0.10, Python v4.0.7

Bug fixes, type corrections, and a deprecation across all three SDKs.

Node.js — @getbrevo/brevo v5.0.1

Fixed

  • GetCampaignStats: appleMppOpens and opensRate are now typed as number | null. The API returns null when no data is available for the campaign period.
  • Order.products: the full set of product fields is now exposed — price, productId, variantId, quantity, and quantityFloat. Previously only quantity was available.
  • GetAccountResponsePlanVerticalsItem.users: now typed as optional/nullable, matching API behavior on certain plan types.
  • createContact(): no longer throws a JSON parse error on 204 No Content responses (returned when a contact already exists).

Deprecated

  • transactionalSms.sendTransacSms() — use transactionalSms.sendTransacSmsAsync() instead. The synchronous variant adds latency by waiting for carrier acknowledgment.

PHP — getbrevo/brevo-php v4.0.10

Added

  • Batch events endpoint: $client->event->createBatchEvents() to track multiple contact interactions in a single request.
  • getEmailCampaign() accepts a new optional excludeHtmlContent flag to omit the HTML body from the response.

Fixed

  • UpdateContactRequest and CreateContactRequest: boolean values in union-typed attribute maps now serialize correctly. Previously threw JsonException: Cannot serialize value of type boolean.
  • Order::products: OrderProductsItem now exposes all product fields — price, productId, variantId, quantity, quantityFloat.
  • GetCampaignStats: appleMppOpens and opensRate are now correctly typed as nullable (?int, ?float).

Deprecated

  • sendTransacSms() — use sendAsyncTransactionalSms() instead.

Python — brevo-python 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.

Loyalty API guides

Added a new Loyalty section to the Guides tab with six pages covering the full Loyalty API integration workflow.

The existing Loyalty webhooks page has been enriched with a complete event reference table and recommended automations for each event.


Batch event creation

Added POST /events/batch to the Events API. This endpoint allows sending multiple events in a single request, each with its own contact identifiers, event properties, and optional object associations.

The response supports partial success — if some events fail validation, the API returns a 207 status with a breakdown of successful and failed events, including per-event error messages.

Read more in the reference section


Brevo MCP server — security and configuration update

The Brevo MCP server has been updated with improved security, simplified maintenance, and rate limiting.

What changed:

  • Authentication method: MCP tokens are no longer passed in the URL. They are now transmitted securely via the HTTP Authorization: Bearer <token> header. All previous URL patterns containing /{token} are no longer valid.
  • Auto-generated tools: The 193 MCP tools are now automatically generated from the Brevo OpenAPI specification, eliminating discrepancies between the API and MCP server.
  • Rate limiting: Request limits have been added to protect services from abuse.
  • New tool support: Integration guides now cover Windsurf, VS Code (GitHub Copilot), and Claude Code CLI in addition to Claude Desktop, Cursor, and Cline.

Action required: Update your MCP configuration to use the new header-based authentication. See the integration guide for updated configuration examples for all supported tools.


February 27, 2026

Loyalty API: new endpoint and rate limits

New endpoint: DELETE /loyalty/config/programs/{pid}/contact/{cid}

Removes a contact from a loyalty program subscription. See the Loyalty API reference for details.

Rate limits: Loyalty endpoints now have documented rate limits across all account tiers.

EndpointsStarterBusinessEnterprise
GET /v3/loyalty/config
All endpoints under /v3/loyalty/{…}
600 RPH1,200 RPH3,600 RPH

See the rate limits documentation for the full breakdown.

PHP SDK v4 release

We’ve released the PHP SDK v4 (getbrevo/brevo-php) with a type-safe client for the Brevo API: unified Brevo client, strongly typed request and response objects with PHPDoc annotations, PSR-18 HTTP client compatibility (Guzzle, Symfony HttpClient), automatic retries with exponential backoff, and structured error handling via BrevoApiException.

You can learn more on the dedicated guide here: https://developers.brevo.com/docs/api-clients/php

Install it using:

$composer require getbrevo/brevo-php

Guzzle is recommended as the HTTP client:

$composer require getbrevo/brevo-php guzzlehttp/guzzle

Key highlights:

  • Unified client via Brevo(apiKey: "...") — single entry point with namespaced service clients
  • Strongly typed request and response objects with full PHPDoc annotations
  • PSR-18 HTTP client support — use Guzzle, Symfony HttpClient, or any compatible client
  • Automatic retries with exponential backoff (configurable per client or per request)
  • Structured errors via BrevoApiException with getCode(), getBody(), and getMessage()
  • 33 service namespaces covering the entire Brevo API

Resources:


Python SDK v4 beta release

We’ve released a beta version of the Python SDK (v4.0) with significant improvements including native async support via AsyncBrevo, Pydantic-based typed models, automatic retries with exponential backoff, and a custom httpx client support.

You can learn more on the dedicated guide here: https://developers.brevo.com/docs/api-clients/python

Install it using:

$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

Resources: