jeffersongoncalves/laravel-beehiiv
Laravel Beehiiv provides a clean integration with the beehiiv API for managing publications, posts, subscriptions, and newsletter data from your Laravel apps.
Install via Composer: composer require jeffersongoncalves/laravel-beehiiv. Laravel's package discovery registers the service provider and the Beehiiv facade automatically.
Publish the config: php artisan vendor:publish --tag=beehiiv-config. This drops config/beehiiv.php into your application.
Add the two required credentials to .env:
BEEHIIV_API_KEY — issued from your Beehiiv dashboard under Settings › API.BEEHIIV_PUBLICATION_ID — found in the Beehiiv URL (/publications/pub_xxxxxxx/...).First use case: subscribing a user to your newsletter. A minimal smoke test in Tinker:
use JeffersonGoncalves\Beehiiv\Facades\Beehiiv;
Beehiiv::subscriptions()->create(email: '[email protected]');
A successful response returns a subscription object with an id you can persist locally for later lookups.
Look first at the published config (for the base URI and timeout/retry knobs) and the facade class under src/Facades/Beehiiv.php — it exposes the resource accessors (publications(), subscriptions(), posts(), segments(), webhooks()), which map one-to-one onto the Beehiiv API surface.
Registered event listener that calls Beehiiv::subscriptions()->create(...) keeps newsletter sign-ups decoupled from auth and makes the behavior easy to disable per project.id on your users table (beehiiv_subscription_id). This gives you a cheap join for later update/unsubscribe flows without hitting the API to search by email.php artisan beehiiv:sync-users command that chunks your users table and calls the subscription endpoint per user (respecting rate limits) is the standard onboarding pattern for adding an existing user base to a publication.https://your-app/webhooks/beehiiv by calling Beehiiv::webhooks()->create(...) once in a migration or bootstrap command, then handle inbound events (subscription.created, subscription.deleted, etc.) in a controller. Store inbound payloads verbatim alongside your normalized fields — Beehiiv payloads evolve and a raw column saves you from schema churn.Beehiiv::posts()->create(...) with a segment_id pulled from Beehiiv::segments()->all(). Cache the segment list for a few minutes — it rarely changes and saves a round trip per editorial request.NewsletterService with methods like subscribe(), unsubscribe(), isSubscribed(). This keeps the package's fluent API out of your controllers and gives you a seam to fake in tests ($this->mock(NewsletterService::class)).ShouldQueue) so a slow Beehiiv response never blocks a checkout or registration request.publication_id is required for most endpoints but lives only in config. If you support multi-brand newsletters in a single app, the single global config is a limit — you'll need to instantiate client objects manually or override config per request.data envelopes. List endpoints return ['data' => [...], 'page' => ..., 'limit' => ...], not a flat array. Don't assume count() of the top-level response reflects result count.ConnectionException) separately from your own domain errors, or you'll mask real bugs.Http::globalRequestMiddleware(...)) or set the config timeout to a low value while verifying credentials — the default timeout can make 401/403 misconfiguration look like a hang.429s that surface as generic exceptions.$request->getContent() (raw), not $request->all(), or verification will fail.php artisan config:cache the published beehiiv.php is frozen; env changes require a recache. A frequent "my API key doesn't work" cause in production.$this->app->extend(...) in a service provider without forking the package.Release note caveat: 1.0.0 ships with only a changelog link — no migration notes, breaking-change list, or feature summary. Treat the API surface as the baseline and pin the version in composer.json until subsequent release notes document behavioral changes.
How can I help you explore Laravel packages today?