sendinblue/sendinblue-api-bundle
A Symfony bundle that integrates the Sendinblue (now Brevo) API into Symfony applications, offering service configuration for transactional email, SMS, and marketing features. Low adoption; verify compatibility with current Brevo SDKs before use.
First, the honest framing: this is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config/sendinblue.php. It ships a Symfony Bundle class, a DI extension, and a config tree. Installing it in a Laravel app is not supported — Composer will pull it, but nothing will wire it up, and its Symfony ^2.x || ^3.x constraints will likely conflict with any modern Laravel (symfony/*: ^6/^7) dependency tree anyway. Treat this package as a reference for the SendinBlue V2 SDK wiring, not as something you composer require in a Laravel project.
Minimal steps if you were in a Symfony 2/3 app (the only place it works):
composer require sendinblue/sendinblue-api-bundlenew SendinBlue\SendinBlueApiBundle\SendinBlueApiBundle() in app/AppKernel.php (no Flex/auto-discovery era).app/config/config.yml under the bundle's config key with your API v2 key, sourced from parameters.yml — never hard-coded.bin/console debug:container sendinblue to find the actual service ID the bundle registers (the exact ID and config key shape are not documented well outside the README; verify against the container rather than trusting blog posts).messageId.What a Laravel developer should actually do instead:
composer require sendinblue/api-v3-sdk (or sendinblue/api-v2-sdk only if you are pinned to V2 for legacy reasons — don't be).SendinblueServiceProvider using config('services.sendinblue.key').sendinblue to config/services.php and the key to .env.SendinblueMailer service, or a custom Laravel Notification channel.Where to look first in the repo: the DependencyInjection/ folder (config keys and service definitions), then the README. That is the whole surface area — everything else is SDK passthrough.
Since the bundle itself is a thin DI wrapper, the "patterns" that matter day-to-day are about how you expose a Mailin/SendinBlue client to application code. In a Laravel context, port the intent of the bundle rather than the bundle.
Singleton client + thin wrapper (the core pattern).
// app/Services/Sendinblue/Client.php
namespace App\Services\Sendinblue;
use SendinBlue\Client\Api\TransactionalEmailsApi;
use SendinBlue\Client\Configuration;
class Client
{
public function __construct(private Configuration $config) {}
public function transactional(): TransactionalEmailsApi
{
return new TransactionalEmailsApi(null, $this->config);
}
}
Bind Configuration and the client as singletons in a service provider. This mirrors exactly what the Symfony bundle does with its DI extension — one configured client, injected wherever needed.
Mail transport integration. Register a custom Laravel mail transport so Mail::to(...)->send(...) routes through SendinBlue. This is the highest-leverage pattern: your existing Mailable classes and Blade views keep working, and only the transport swaps. The Symfony bundle does not give you this — it hands you an API client — so expect to write ~50 lines of adapter.
Notification channel. For SMS (sendTransacSms) and transactional email, implement toSendinblue() on notifiables and a SendinblueChannel. This keeps business logic out of controllers and gets queueing, retries, and failed() hooks for free.
Contact/list sync on domain events. Listen for Registered / OrderPlaced and dispatch() a job that calls ContactsApi::createContact with an updateEnabled = true upsert. Always queue it — the API is a network call and registration latency is user-visible.
Webhook ingestion. Add a dedicated route + controller for SendinBlue delivery/bounce events. The API v2/v3 SDKs do not validate signatures for you; implement your own shared-secret check and make the endpoint idempotent (store event IDs) before touching users.email_status or subscriptions.
Testing pattern. Type-hint your wrapper interface (SendinblueClient) everywhere, never the SDK class directly. In tests, $this->mock(SendinblueClient::class) — the SDK's generated API classes are painful to fake because their constructors want a Guzzle client and a Configuration.
SwiftMailer/Mailer transport and it does not give you templating. It exposes the raw SDK. If you expected sendinblue: { transport: ... } magic, that misconception will cost you an afternoon.api_key isn't picked up, check the Configuration.php in DependencyInjection/ for the exact key name before assuming the key is wrong.SendinBlue\Client\ApiException with a response body string; parse it (json_decode($e->getResponseBody())) rather than string-matching the message. Catch at the job level and let Laravel's queue retry policy handle 5xx and 429; do not retry 400s.->chunk(100) and put a small sleep() or RateLimited job middleware between batches. The bundle gives you no throttling.api-key header into laravel.log — set Guzzle debug false in production and scrub the header if you add logging middleware.Configuration object accepts a custom Guzzle HandlerStack. Use it to add retry middleware and a correlation-ID header rather than wrapping every call in try/catch/retry yourself.202 with a messageId even when the recipient is suppressed or the sender is unverified, so a green HTTP status proves very little.How can I help you explore Laravel packages today?