getbrevo/brevo-php
Official PHP SDK for the Brevo API.
5.0.2
4.3M downloads/mo
#1568 most downloaded on Packagist
getbrevo/brevo-php
What this package is like to depend on
Last release 13 days ago
10 Aug 2026
Release timing varies
gaps range from 2 weeks to 4 months
Some releases are documented
notes for 9 of 31 stable releases
Nothing withdrawn
no release was ever pulled
3 years old
32 releases · first in 2023
18 releases in the last 12 months
see the full history below
Release timeline
32 releases · May 2023 to Aug 2026Releases
latest 32-
5.0.210 Aug 2026Release notes
Open source →Added
- Email Campaigns — UTM parameter customization —
EmailCampaigns::createEmailCampaign()andEmailCampaigns::updateEmailCampaign()now accept optionalutmCampaign,utmContent, andutmTermfields to customize UTM tracking parameters. - Transactional Email — per-contact pixel tracking consent —
TransactionalEmails::sendTransacEmail()now accepts optionalcontactPixelTrackingConsentboolean field on individual recipient objects to control whether opens are tracked identifiably or anonymized.
Backward-compatible patch release. No breaking changes.
- Email Campaigns — UTM parameter customization —
-
5.0.103 Jul 2026Release notes
Open source →PHP SDK v5.0.1
What's New
🔧 Bug Fix: Empty Object Serialization
- Fix:
JsonSerializableTypenow correctly serializes empty objects to{}instead of[] - Resolves backend validation errors when sending empty optional/nested objects
✨ New Features: Consent Groups Management
- List consent groups — GET /contacts/consent-groups
- Create a consent group — POST /contacts/consent-groups
- Get consent group details — GET /contacts/consent-groups/{id}
- Update consent group — PUT /contacts/consent-groups/{id} (name, description, signup mode)
- Delete consent group — DELETE /contacts/consent-groups/{id}
📲 Extended Operations
- Import contacts — POST /contacts/import now accepts optional
consentGroupIdsfield to add imported contacts to specified consent groups - Get contact details — GET /contacts/{identifier} now returns
consentGroupsarray showing subscription status (when feature enabled)
💳 New Wallet Feature
- Get pass installation URL — GET /wallet/passes/{passId}/installUrl/{contactId}
- Generates per-contact wallet installation URLs
- Enables sharing via email, SMS, or QR code for Apple Wallet/Google Wallet integration
Bug Fixes
- Fixed serialization of empty
JsonSerializableTypeinstances at the top level - Fixed serialization of empty nested objects within parent objects
- Resolves backend validation failures from strict type checkers
Compatibility
- ✅ Backward compatible — no breaking changes
- ✅ No method removals or signature changes
- ✅ Public API unchanged
Installation
composer require getbrevo/brevo-php:^5.0.1
- Fix:
-
v5.0.0-rc.115 May 2026 pre-releaseRelease notes
Open source →v5.0.0-rc.1
Release candidate for the v5 line. This pre-release is published so adopters can validate the new surface against their integrations before
v5.0.0is tagged stable. It is not picked up bycomposer updateautomatically — opt in explicitly (see Installing this RC below).If no blocking issues surface within the soak window, this build will be promoted to
v5.0.0unchanged.composer require getbrevo/brevo-php:^5.0.0@RC
Status
- Stability:
RC— API surface is frozen. Only critical regressions discovered during soak will be patched into an RC.2. - v4.x: remains supported and continues to receive wire-compatibility fixes.
- Feedback welcome: please open an issue against
getbrevo/brevo-phpif you hit anything unexpected during migration. Tag withv5-rc.
Why this release
Most of the breaking changes in v5 come from an internal effort at Brevo to make our API endpoints, parameters and models more self-descriptive. The goal is to make the public surface easier to read at a glance — both for developers and for AI agents working against the Brevo API — so that names, shapes and required fields convey intent without needing to cross-reference external docs. Concretely, this means consistent parameter naming, payload wrappers that reflect what the endpoint actually does (e.g.
CreateBatchEventsRequest), filter keys that match the wire format, model fields renamed or removed where the previous names were ambiguous, and tightened types (DateTimeinstead ofstringfor dates, typed unions instead of generic arrays) so static analysis catches mistakes earlier.We're aware that renaming costs callers a one-time migration, and we've kept v4.x supported so you can adopt v5 on your own timeline.
⚠️ Breaking changes
Companies —
GetCompaniesRequest::filtersrenamedfiltersis renamed tofiltersAttributesNameto match the wire format.- Existing code passing
'filters' => ...does not throw, but the filter is silently ignored server-side and the response is unfiltered. Audit every call site.
Events —
Event::createBatchEventspayload shape changed- First argument changed from
arrayto aCreateBatchEventsRequestwrapper.
Balance —
getActiveBalancesApiresponse shape changed- Return type changed from
?BalanceLimitto?GetLoyaltyBalanceProgramsPidActiveBalanceResponse(different shape).
Balance —
getContactBalancesrequiresbalanceDefinitionId$requestno longer defaults to empty;balanceDefinitionIdis required.
Balance —
BeginTransactionRequest::eventTimetype tightened- Type changed from
?stringto?DateTime. ISO strings now causeTypeError.
CRM —
Tasks::getAllTaskTypesreturns an array- Return type changed from
?GetCrmTasktypesResponse(wrapper) to?array<GetCrmTasktypesResponseItem>.
Email campaigns —
utmIdActiverenamedEmailCampaigns\GetEmailCampaignResponse::utmIdActiverenamed toutmId(wire keyutmIDActive→utmID, type?bool→?int).- Same change on
GetEmailCampaignsResponseCampaignsItem.
Model fields removed
GetAccountResponse::dateTimePreferencesWebhook::channelGetProcessResponseInfo::exportGetProcessResponse::error,::createdAt,::completedAt- Several
ExternalFeedsresponse fields
Model field types tightened
Process\GetProcessResponseInfoImportcount fields changed from?intto?string(now URLs to CSV reports) — affectsinvalidEmails,duplicateContactId,duplicateExtId, and others.Ecommerce\CreateUpdateProductResponse::idandCreateUpdateCategoryResponse::id:?int→?string.- Several
stringdate fields tightened to?DateTime(Program::*,Reward::*,BalanceLimit::createdAt/updatedAt).
Model fields renamed
ConversationsMessageAttachmentsItem::fileName→name,::inlineId→link.
Custom objects — associations union flattened
UpsertrecordsRequestRecordsItemAssociationsItemis now a single class with anaction: 'link' | 'unlink'discriminator. 7 old variant classes have been deleted.
Added
- New optional fields and filters across
contacts->createContact,contacts->updateContact,emailCampaigns->getEmailCampaigns,ecommerce->getProducts, and several other endpoints. - Tier groups support upgrade and downgrade schedule fields.
Installing this RC
Composer only installs RC builds when you ask for them explicitly. Either:
composer require getbrevo/brevo-php:^5.0.0@RC
Or set
minimum-stabilityin yourcomposer.json:{ "minimum-stability": "RC", "prefer-stable": true, "require": { "getbrevo/brevo-php": "^5.0" } }When
v5.0.0ships stable,composer updatewill swap this RC for the stable release automatically.Holding on v4.x
If you're not ready to migrate, pin to v4:
composer require getbrevo/brevo-php:^4.0
Migration
See the Upgrading from v4.x guide for full migration details.
Documentation
- Stability:
-
4.0.1615 Jun 2026Release notes
Open source →Fixed
CreateBatchOrderResponse::$batchIdnow deserializes correctly. ThecreateBatchOrderendpoint returns the batch id asbatch_id(snake_case), but the SDK looked forbatchId, leaving it unset and throwingCannot assign null to property ...::$batchId of type floaton every call. The wire mapping is corrected tobatch_idand the property is now nullable (?float). The$response->batchIdaccessor is unchanged.
Backward-compatible patch release. No breaking changes.
-
4.0.1513 Jun 2026Release notes
Open source →Fixed
GetCampaignStatscount fields are now nullable (?int):clickers,complaints,delivered,hardBounces,sent,softBounces,trackableViews,uniqueClicks,uniqueViews,unsubscriptions,viewed. This model is reused forstatsByDomainongetEmailCampaign(s), where per-domain rows are sparse and the API returnsnull/absent for some counts. The previous non-nullable typing threw aTypeErrorwhile deserializingstatsByDomain(globalStatswas unaffected). (#138)
Backward-compatible patch release. No breaking changes.
-
4.0.1412 Jun 2026Release notes
Open source →Fixed
- senderEmail is now nullable (?string) on GetTransacBlockedContactsResponseContactsItem; the API returns null for some blocked or unsubscribed contacts (#137)
- campaignId is now nullable (?int) on both UserUnsubscription item classes; form based unsubscriptions return null (#136)
- Guzzle timeout support now works: interface_exists replaces class_exists for GuzzleHttp\ClientInterface, so the timeout option is honored (#133)
Backward compatible patch release. No breaking changes.
-
4.0.1310 Apr 2026Release notes
Open source →v4.0.13
Bug fixes
getProcess / getProcesses — deserialization failure on completed processes (#121)
$duplicateEmailIdwas typed as?int, but the API returns a URL string pointing to a CSV file of duplicate IDs.- It is now typed as
?string.
getProcess / getProcesses — unknown status
in_process(#122)- The API still returns the legacy
in_processvalue (v3 name forprocessing). GetProcessResponseStatusandGetProcessesResponseProcessesItemStatusnow includeInProcess = "in_process", so deserialization no longer throws on active processes.
createEvent / createBatchEvents — boolean values rejected in
contactProperties(#123)contactPropertiesandeventPropertiesonly acceptedstring|int.- Boolean values (e.g.
'MY_FLAG' => true) now serialize correctly.
createContact / updateContact — integer values rejected in
attributes(#124)attributesvalues were typed asfloat|string|bool|array.- Passing a plain PHP
int(e.g.'OFFICE_ID' => 1234) now works without casting to(float).
-
4.0.1227 Mar 2026Release notes
Open source →Summary
Resolved a field naming mismatch in the /orders/status/batch API response to align the implementation with the public contract.
Issue
During investigation of an L3 issue, a discrepancy was identified between the Swagger contract and the actual API response:
• Contract (Swagger): batchId (camelCase)
• Implementation: batch_id (snake_case)This inconsistency caused misalignment with client expectations and SDK behavior.
Fix
• Updated the response format to use batchId (camelCase) as defined in the Swagger specification.
• Ensured consistency across API responses and documentation.Release notes
Open source →- fix: improve JSON serialization and test configuration
- Fix boolean type handling in JSON serialization and deserialization by adding explicit checks for bool values, since PHP's gettype() returns "boolean" instead of "bool". Also improve property default value detection using hasDefaultValue() check to avoid potential warnings. Update test configuration to support external WireMock orchestration via WIREMOCK_URL environment variable.
- Key changes:
- Add special case handling for bool types in JsonSerializer and JsonDeserializer
- Use hasDefaultValue() check before calling getDefaultValue() in JsonSerializableType
- Make test suite configurable with WIREMOCK_URL environment variable
- Support dynamic port discovery for WireMock container in bootstrap
- 🌿 Generated with Fern
-
4.0.1125 Mar 2026Release notes
Open source →What's Changed
New features
Events
- Added
getEvents()— retrieve a paginated list of custom events, filterable bycontactId,eventName,objectType,startDate, andendDate.
Supportslimit(default 100, max 10,000) andoffsetfor pagination.
Note: currently only supports custom events. - Added
createBatchEvents()— create multiple events in a single request using an array ofCreateBatchEventsRequestItem. Returns aBatchAcceptedResponse.
Ecommerce
CreateUpdateProductRequestand batch product upsert now accept two new optional fields:brandanddescription.
Balance
getActiveBalancesApi()now acceptsincludeInternalto include balances tied to internal definitions.getContactBalances()andgetSubscriptionBalances()now accept a request object with anincludeInternalparameter.getTransactionHistory()now supports filtering bystatus(draft,completed,rejected,cancelled,expired) andtransactionType(credit,debit).createBalanceDefinition()andupdateBalanceDefinition():- the
metafield is now a typed object (isInternal: bool) instead of a generic key-value array.
- the
CRM
- Added
PatchCrmAttributesIdRequestto update CRM attribute labels and selectable option labels.
Changes
Ecommerce
metaInfosize limit for products clarified: maximum 20,000 characters total (previously documented as 1,000 KB / max 20 items).
Account
usersfield on plan verticals is now nullable.
Bug fixes
createContact()no longer throws aBrevoException- Checks if the response body is empty and returns null instead of trying to deserialize it
- Only calls CreateContactResponse::fromJson($json) when there's actual content
Release notes
Open source →- SDK regeneration
- Unable to analyze changes with AI, incrementing PATCH version.
- Added
-
4.0.1012 Mar 2026Nothing published for this version
-
v4.0.927 Feb 2026Nothing published for this version
-
4.0.701 Mar 2026Nothing published for this version
-
4.0.627 Feb 2026Release notes
Open source →- chore: update Fern CLI version to 3.85.3
- Update the Fern CLI version from 3.82.0 to 3.85.3 to incorporate latest tooling improvements and bug fixes.
- Key changes:
- Update cliVersion in .fern/metadata.json from 3.82.0 to 3.85.3
- Maintain existing generator configuration settings
- 🌿 Generated with Fern
-
4.0.523 Feb 2026Nothing published for this version
-
v2.0.1406 Nov 2025Nothing published for this version
-
v2.0.1316 Sep 2025Nothing published for this version
-
v2.0.1214 Sep 2025Nothing published for this version
-
v2.0.1102 Sep 2025Nothing published for this version
-
v2.0.1001 Aug 2025Nothing published for this version
-
v2.0.920 Jul 2025Nothing published for this version
-
v2.0.824 Jun 2025Nothing published for this version
-
v2.0.713 Jun 2025Nothing published for this version
-
v2.0.622 May 2025Nothing published for this version
-
v2.0.512 May 2025Nothing published for this version
-
v2.0.416 Jan 2025Nothing published for this version
-
v2.0.303 Oct 2024Nothing published for this version
-
v2.0.212 Aug 2024Nothing published for this version
-
v2.0.112 Aug 2024Nothing published for this version
-
v2.0.012 Mar 2024Nothing published for this version
-
v1.0.214 Jul 2023Nothing published for this version
-
v1.0.128 May 2023Nothing published for this version
-
v1.0.025 May 2023Nothing published for this version