A Saloon-based SDK for interacting with the Brevo (formerly Sendinblue) API v3. Brevo provides email marketing, transactional emails, SMS, and marketing automation services.
Installation
The SDK is included as part of the Inly Core package. No additional installation is required.
Configuration
Add your Brevo API key to your .env file:
BREVO_API_KEY=your-api-key-here
BREVO_BASE_URL=https://api.brevo.com/v3 # Optional, defaults to https://api.brevo.com/v3
BREVO_TIMEOUT=60 # Optional, defaults to 60 seconds
The SDK automatically loads configuration from config/brevo.php.
Getting Your API Key
Log in to your Brevo account
Navigate to Settings → API Keys
Create a new API key or copy an existing one
Add it to your .env file
Keep your API key secure and never commit it to version control. Always use environment variables.
Laravel Integration
Service Container Registration
For seamless Laravel integration, register Brevo as a singleton in your AppServiceProvider. The Inly Core package provides a stub file with the recommended setup:
// app/Providers/AppServiceProvider.php
use Inly\Core\Connectors\Brevo\ Brevo ;
class AppServiceProvider extends ServiceProvider
{
public function register () : void
{
// Brevo SDK
$this -> app -> singleton ( Brevo :: class , function ( $app ) {
return new Brevo (
apiKey : config ( 'brevo.api_key' )
);
});
}
}
The stub file at vendor/inly/core/stubs/laravel/app/Providers/AppServiceProvider.php contains commented examples for all available SDKs. Copy the Brevo section and uncomment it in your application’s AppServiceProvider.
Dependency Injection
Once registered, you can inject Brevo into your classes:
use Inly\Core\Connectors\Brevo\ Brevo ;
class NewsletterController extends Controller
{
public function __construct (
protected Brevo $brevo
) {}
public function subscribe ( Request $request )
{
$this -> brevo -> contacts () -> create (
email : $request -> email ,
listIds : [ config ( 'brevo.newsletter_list_id' )]
);
return back () -> withSuccess ( __ ( 'Subscribed successfully!' ));
}
}
Basic Usage
Initialization
use Inly\Core\Connectors\Brevo\ Brevo ;
// Create instance - automatically loads from config
$brevo = new Brevo ();
// Or create with explicit API key
$brevo = new Brevo ( 'your-api-key' );
// Or set it later
$brevo -> setApiKey ( 'your-api-key' );
// Check if configured
if ( $brevo -> isConfigured ()) {
// Ready to use
}
// Using dependency injection (recommended)
public function __construct ( protected Brevo $brevo ) {}
Get details about your Brevo account:
// Get account info
$account = $brevo -> account () -> get ();
echo $account [ 'email' ];
echo $account [ 'companyName' ];
echo $account [ 'plan' ][ 'type' ];
echo $account [ 'relay' ][ 'data' ][ 'userName' ];
{
"email" : "user@example.com" ,
"companyName" : "My Company" ,
"plan" : {
"type" : "enterprise" ,
"credits" : 50000
}
}
Manage your contact lists and individual contacts.
// Get all contacts as a Collection
$contacts = $brevo -> contacts () -> list ();
foreach ( $contacts as $contact ) {
echo $contact [ 'email' ];
echo $contact [ 'attributes' ][ 'FIRSTNAME' ];
}
// With parameters
$contacts = $brevo -> contacts () -> list (
limit : 50 ,
offset : 0 ,
modifiedSince : '2024-01-01'
);
// By email or ID
$contact = $brevo -> contacts () -> get ( 'user@example.com' );
echo $contact [ 'email' ];
echo $contact [ 'attributes' ][ 'FIRSTNAME' ];
echo $contact [ 'attributes' ][ 'LASTNAME' ];
print_r ( $contact [ 'listIds' ]);
// Create a new contact
$result = $brevo -> contacts () -> create (
email : 'new@example.com' ,
attributes : [
'FIRSTNAME' => 'John' ,
'LASTNAME' => 'Doe' ,
'SMS' => '+1234567890'
],
listIds : [ 1 , 2 ],
emailBlacklisted : false ,
smsBlacklisted : false
);
echo $result [ 'id' ]; // New contact ID
Contact attributes must be pre-defined in your Brevo account. Go to Contacts → Settings → Contact Attributes to manage them.
// Update existing contact
$brevo -> contacts () -> update (
identifier : 'user@example.com' ,
attributes : [
'FIRSTNAME' => 'Jane' ,
'COMPANY' => 'Acme Corp'
],
listIds : [ 3 , 4 ], // Replace list memberships
unlinkListIds : [ 1 , 2 ] // Remove from these lists
);
// Delete a contact permanently
$brevo -> contacts () -> delete ( 'user@example.com' );
Deleting a contact is permanent and cannot be undone. Consider unsubscribing them from lists instead.
// For large datasets, use manual pagination
$paginator = $brevo -> contacts () -> paginate ();
foreach ( $paginator as $response ) {
$contacts = $response -> json ( 'contacts' , []);
foreach ( $contacts as $contact ) {
// Process each contact
echo $contact [ 'email' ];
}
}
Lists
Manage contact lists (segments) in your Brevo account.
List All Lists
// Get all contact lists
$lists = $brevo -> lists () -> list ();
foreach ( $lists as $list ) {
echo $list [ 'name' ];
echo $list [ 'totalSubscribers' ];
}
Get Single List
// Get specific list details
$list = $brevo -> lists () -> get ( 123 );
echo $list [ 'name' ];
echo $list [ 'totalSubscribers' ];
echo $list [ 'folderId' ];
{
"id" : 123 ,
"name" : "Newsletter Subscribers" ,
"totalSubscribers" : 1500 ,
"totalBlacklisted" : 10 ,
"folderId" : 1 ,
"createdAt" : "2024-01-01T00:00:00.000Z" ,
"dynamicList" : false
}
Create List
// Create a new contact list
$result = $brevo -> lists () -> create (
name : 'My New List' ,
folderId : 1
);
echo $result [ 'id' ]; // New list ID
Update List
// Update list details
$brevo -> lists () -> update (
listId : 123 ,
name : 'Updated List Name' ,
folderId : 2
);
Delete List
// Delete a list and all its contacts
$brevo -> lists () -> delete ( 123 );
Deleting a list will remove all contacts from that list. The contacts themselves will remain in your account unless they’re not in any other lists.
// Paginate through lists
$paginator = $brevo -> lists () -> paginate ();
foreach ( $paginator as $response ) {
$lists = $response -> json ( 'lists' , []);
// Process lists...
}
Transactional Emails
Send transactional emails and track their delivery.
Send Email
// Send a transactional email with HTML content
$result = $brevo -> transactionalEmails () -> send (
to : [
[ 'email' => 'recipient@example.com' , 'name' => 'John Doe' ]
],
subject : 'Welcome to Our Service' ,
htmlContent : '<h1>Hello!</h1><p>Welcome to our service.</p>' ,
sender : [
'email' => 'sender@example.com' ,
'name' => 'My Company'
],
replyTo : [
'email' => 'reply@example.com' ,
'name' => 'Support Team'
]
);
echo $result [ 'messageId' ]; // Track the email
The sender email must be verified in your Brevo account before sending emails.
Send with Template
// Send using a pre-defined template
$result = $brevo -> transactionalEmails () -> sendWithTemplate (
templateId : 1 ,
to : [
[ 'email' => 'recipient@example.com' , 'name' => 'John Doe' ]
],
params : [
'FIRSTNAME' => 'John' ,
'ORDER_ID' => '12345' ,
'TOTAL_AMOUNT' => '$99.99'
]
);
echo $result [ 'messageId' ];
{
"messageId" : "<202401011200.1234567890@smtp-relay.brevo.com>"
}
Advanced Send Options
// Send with attachments, CC, BCC, and more
$result = $brevo -> transactionalEmails () -> send (
to : [[ 'email' => 'recipient@example.com' , 'name' => 'John Doe' ]],
subject : 'Invoice #12345' ,
htmlContent : '<h1>Your Invoice</h1>' ,
sender : [ 'email' => 'billing@example.com' , 'name' => 'Billing' ],
cc : [[ 'email' => 'manager@example.com' ]],
bcc : [[ 'email' => 'archive@example.com' ]],
attachment : [
[
'name' => 'invoice.pdf' ,
'content' => base64_encode ( $pdfContent )
]
],
headers : [
'X-Custom-Header' => 'custom-value'
],
tags : [ 'invoice' , 'billing' ]
);
Track Email Events
// Get email events/activity
$events = $brevo -> transactionalEmails () -> events (
email : 'user@example.com' ,
event : 'delivered' , // 'delivered', 'opened', 'clicked', 'bounced', 'spam', 'blocked'
startDate : '2024-01-01' ,
endDate : '2024-12-31' ,
limit : 100
);
foreach ( $events as $event ) {
echo $event [ 'event' ]; // 'delivered', 'opened', etc.
echo $event [ 'date' ];
echo $event [ 'subject' ];
}
{
"events" : [
{
"email" : "user@example.com" ,
"event" : "delivered" ,
"subject" : "Welcome Email" ,
"messageId" : "<202401011200.1234567890@smtp-relay.brevo.com>" ,
"date" : "2024-01-01T12:00:00.000Z" ,
"tags" : [ "welcome" ]
}
]
}
// For large event datasets
$paginator = $brevo -> transactionalEmails () -> paginateEvents (
email : 'user@example.com' ,
event : 'opened'
);
foreach ( $paginator as $response ) {
$events = $response -> json ( 'events' , []);
// Process events...
}
Senders
Manage verified sender email addresses and domains.
List Senders
// Get all verified senders
$senders = $brevo -> senders () -> list ();
foreach ( $senders as $sender ) {
echo $sender [ 'email' ];
echo $sender [ 'name' ];
echo $sender [ 'active' ] ? 'Active' : 'Inactive' ;
}
{
"senders" : [
{
"id" : 1 ,
"name" : "My Company" ,
"email" : "noreply@mycompany.com" ,
"active" : true ,
"ips" : [
{
"ip" : "123.45.67.89" ,
"domain" : "mycompany.com"
}
]
}
]
}
Create Sender
// Create a new sender
$result = $brevo -> senders () -> create (
name : 'My Company' ,
email : 'noreply@mycompany.com'
);
echo $result [ 'id' ]; // New sender ID
After creating a sender, you must verify the email address or domain before you can send emails from it. Check your email for a verification link.
Error Handling
The SDK automatically throws exceptions for API errors. Always wrap your calls in try-catch blocks:
use Saloon\Exceptions\Request\ RequestException ;
use Exception ;
try {
$contact = $brevo -> contacts () -> get ( 'nonexistent@example.com' );
} catch ( RequestException $e ) {
// Handle API errors (4xx, 5xx)
$statusCode = $e -> getResponse () -> status ();
$errorMessage = $e -> getResponse () -> json ( 'message' );
if ( $statusCode === 404 ) {
// Contact not found
echo "Contact does not exist" ;
} else {
echo "API Error: { $errorMessage }" ;
}
} catch ( Exception $e ) {
// Handle other errors
echo "Error: { $e -> getMessage ()}" ;
}
Rate Limiting
Brevo enforces rate limits based on your plan:
Plan Requests per Second Free 10 requests/sec Starter 10 requests/sec Business 100 requests/sec Enterprise Custom
The SDK automatically handles rate limit errors. If you exceed limits, you’ll receive a 429 Too Many Requests exception.
Testing
Test your SDK configuration with the included command:
This will:
✅ Verify your API key is configured
✅ Test connectivity to Brevo API
✅ Display account information
✅ Show sample contact data
Available Resources
Resource Methods Description account()get()Get account information contacts()list(), get(), create(), update(), delete(), paginate()Manage contacts lists()list(), get(), create(), update(), delete(), paginate()Manage contact lists transactionalEmails()send(), sendWithTemplate(), events(), paginateEvents()Send and track emails senders()list(), create()Manage sender addresses
Common Use Cases
Newsletter Signup Flow
use Inly\Core\Connectors\Brevo\ Brevo ;
use Illuminate\Http\ Request ;
class NewsletterController extends Controller
{
public function __construct (
protected Brevo $brevo
) {}
public function subscribe ( Request $request )
{
$request -> validate ([
'email' => 'required|email' ,
'first_name' => 'required|string' ,
'last_name' => 'required|string' ,
]);
// 1. Create a contact
$this -> brevo -> contacts () -> create (
email : $request -> email ,
attributes : [
'FIRSTNAME' => $request -> first_name ,
'LASTNAME' => $request -> last_name
],
listIds : [ config ( 'brevo.newsletter_list_id' )]
);
// 2. Send welcome email
$this -> brevo -> transactionalEmails () -> sendWithTemplate (
templateId : config ( 'brevo.welcome_template_id' ),
to : [[ 'email' => $request -> email , 'name' => $request -> first_name ]],
params : [ 'FIRSTNAME' => $request -> first_name ]
);
return back () -> withSuccess ( __ ( 'Subscribed successfully!' ));
}
}
Order Confirmation Email
use Inly\Core\Connectors\Brevo\ Brevo ;
class OrderService
{
public function __construct (
protected Brevo $brevo
) {}
public function sendConfirmation ( Order $order ) : void
{
// Send order confirmation with invoice
$this -> brevo -> transactionalEmails () -> send (
to : [[ 'email' => $order -> customer -> email , 'name' => $order -> customer -> name ]],
subject : "Order Confirmation #{ $order -> id }" ,
htmlContent : view ( 'emails.order-confirmation' , compact ( 'order' )) -> render (),
sender : [ 'email' => 'orders@myshop.com' , 'name' => 'My Shop' ],
attachment : [
[
'name' => "invoice-{ $order -> id }.pdf" ,
'content' => base64_encode ( $order -> generateInvoicePdf ())
]
],
tags : [ 'order-confirmation' , "order-{ $order -> id }" ]
);
}
}
Sync Users to Marketing List
use Inly\Core\Connectors\Brevo\ Brevo ;
use Illuminate\Support\Facades\ Log ;
use Saloon\Exceptions\Request\ RequestException ;
class SyncUsersToBrevoJob
{
public function __construct (
protected Brevo $brevo
) {}
public function handle () : void
{
// Sync active users to a marketing list
$users = User :: whereActive ( true ) -> get ();
foreach ( $users -> chunk ( 100 ) as $chunk ) {
foreach ( $chunk as $user ) {
try {
$this -> brevo -> contacts () -> create (
email : $user -> email ,
attributes : [
'FIRSTNAME' => $user -> first_name ,
'LASTNAME' => $user -> last_name ,
'SIGNUP_DATE' => $user -> created_at -> format ( 'Y-m-d' )
],
listIds : [ config ( 'brevo.active_users_list_id' )],
updateEnabled : true // Update if exists
);
} catch ( RequestException $e ) {
Log :: warning ( "Failed to sync user { $user -> id }: { $e -> getMessage ()}" );
}
}
// Rate limiting: wait between chunks
sleep ( 1 );
}
}
}
Additional Resources
Support
For issues or questions:
Check the Brevo API Status
Contact Brevo Support through your dashboard
Report SDK bugs to the Inly Core team