jeffersongoncalves / laravel-beehiiv
PHP/Laravel client for the Beehiiv REST API v2: publications, subscriptions, posts, segments, automations and referral programs.
Package info
github.com/jeffersongoncalves/laravel-beehiiv
pkg:composer/jeffersongoncalves/laravel-beehiiv
Fund package maintenance!
Requires
- php: ^8.2
- illuminate/http: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.21
- orchestra/testbench: ^10.0|^11.0
- pestphp/pest: ^3.0|^4.0
- pestphp/pest-plugin-laravel: ^3.0|^4.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Laravel Beehiiv
A PHP/Laravel client for the Beehiiv REST API v2. Covers publications, subscriptions, posts, segments, automations and referral programs through a simple, typed API built on Laravel's Http client.
Features
- Publications: list, get
- Subscriptions: list, get, create, update, delete
- Posts: list, get, create, delete
- Segments: list, get
- Automations: list, get
- Referral Program: get
- Optional default publication scope (via config) so you don't have to pass a publication ID to every call
- Throws
BeehiivException(with the original API error body) on any non-2xx response - Throws
InvalidArgumentExceptionbefore hitting the API when a required field/argument is missing
Installation
You can install the package via composer:
composer require jeffersongoncalves/laravel-beehiiv
Publish the config file:
php artisan vendor:publish --tag=beehiiv-config
Set your Beehiiv credentials in .env:
BEEHIIV_API_KEY=your-api-key BEEHIIV_PUBLICATION_ID=pub_00000000-0000-0000-0000-000000000000
Both values are found under Settings > Integrations > API in your Beehiiv account. BEEHIIV_PUBLICATION_ID is optional — set it if most of your calls target a single publication, otherwise pass a publication ID explicitly to each method.
Configuration
// config/beehiiv.php return [ 'api_key' => env('BEEHIIV_API_KEY', ''), 'publication_id' => env('BEEHIIV_PUBLICATION_ID'), 'default_limit' => env('BEEHIIV_DEFAULT_LIMIT', 10), ];
Usage
The package is resolved via the Beehiiv facade or by injecting JeffersonGoncalves\Beehiiv\Beehiiv. Each resource is exposed as a method returning a dedicated resource class.
Publications
Publications are not scoped to a publication ID — this resource lists your publications and looks one up:
use JeffersonGoncalves\Beehiiv\Facades\Beehiiv; $publications = Beehiiv::publications()->list(); $publication = Beehiiv::publications()->get('pub_00000000-0000-0000-0000-000000000000');
Subscriptions
Every other resource is scoped to a publication. Pass $publicationId explicitly, or omit it to use beehiiv.publication_id from config:
// List (supports email, status, tier, cursor, expand filters) $subscriptions = Beehiiv::subscriptions()->list(filters: ['email' => 'jane@example.com']); $subscription = Beehiiv::subscriptions()->get('sub_00000000-0000-0000-0000-000000000000'); $subscription = Beehiiv::subscriptions()->create([ 'email' => 'jane@example.com', 'reactivate_existing' => false, 'send_welcome_email' => true, 'utm_source' => 'newsletter', ]); Beehiiv::subscriptions()->update('sub_00000000-0000-0000-0000-000000000000', ['tier' => 'premium']); Beehiiv::subscriptions()->delete('sub_00000000-0000-0000-0000-000000000000'); // Or target a different publication explicitly Beehiiv::subscriptions()->list(publicationId: 'pub_11111111-1111-1111-1111-111111111111');
Posts
$posts = Beehiiv::posts()->list(filters: ['status' => 'confirmed']); $post = Beehiiv::posts()->get('post_00000000-0000-0000-0000-000000000000'); $post = Beehiiv::posts()->create([ 'title' => 'Hello World', 'subtitle' => 'A short subtitle', 'status' => 'draft', ]); Beehiiv::posts()->delete('post_00000000-0000-0000-0000-000000000000');
Segments, Automations and Referral Program
Beehiiv::segments()->list(); Beehiiv::segments()->get('seg_00000000-0000-0000-0000-000000000000'); Beehiiv::automations()->list(); Beehiiv::automations()->get('aut_00000000-0000-0000-0000-000000000000'); Beehiiv::referralProgram()->get();
Error handling
Any non-2xx API response throws JeffersonGoncalves\Beehiiv\Exceptions\BeehiivException, which exposes the decoded error body:
use JeffersonGoncalves\Beehiiv\Exceptions\BeehiivException; try { Beehiiv::subscriptions()->get('does-not-exist'); } catch (BeehiivException $e) { logger()->error($e->getMessage(), $e->errorBody()); }
Missing required fields/arguments (e.g. email on subscriptions()->create(), title on posts()->create(), or a publication ID when none is configured) throw InvalidArgumentException before any HTTP call is made.
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.
