sendseven-laravel maintained by reshapify
SendSeven for Laravel
Unofficial. Not affiliated with or endorsed by SendSeven GmbH or Laravel Holdings.
Laravel integration for reshapify/sendseven, the typed SDK for the SendSeven messaging API (WhatsApp, SMS, email, Telegram, Messenger, Instagram, RCS, browser push).
- Configured client: the
SendSevenfacade, or injectReshapify\SendSeven\Client. - Webhooks in one line:
Route::sendSevenWebhooks()answers SendSeven's verification challenge, verifies signatures, ignores redeliveries and dispatches typed Laravel events. - Customer onboarding:
SendSeven::connect()sends customers to SendSeven's connect page (WhatsApp Embedded Signup, Instagram, Messenger, Telegram…) and tells you when their channel arrives. - One rate limit for every process: web requests, queue workers and the scheduler share the token's 100-requests-a-minute budget through your cache.
php artisan sendseven:doctorchecks the token, the plan, tenancy and the webhook endpoint against the live API.- Fakes for the API and signed webhook deliveries.
Install
composer require reshapify/sendseven-laravel
php artisan vendor:publish --tag=sendseven-config # optional
Composer may ask whether to trust php-http/discovery, a plugin of the core SDK. Laravel already ships an HTTP client, so answering "no" is fine.
SENDSEVEN_API_TOKEN=s7_api_...
Send
use Reshapify\SendSeven\Laravel\Facades\SendSeven;
SendSeven::messages()->send(to: '+4915112345678', channelId: $channelId, text: 'Your order has shipped.');
Every SendSeven endpoint is available; see the SDK docs. For a customer's own token use SendSeven::forToken($token); for a sub-account with a partner token use SendSeven::forTenant($tenantId).
Receive webhooks
// routes/web.php (CSRF is skipped for this route; deliveries are signed instead)
Route::sendSevenWebhooks(); // POST /webhooks/sendseven, named sendseven.webhooks
php artisan sendseven:webhooks:register # creates the endpoint and prints SENDSEVEN_WEBHOOK_SECRET
php artisan sendseven:doctor # confirms SendSeven verified it
Listen for the SDK's own event classes:
use Reshapify\SendSeven\Webhooks\Events\MessageReceived;
final class StoreInboundMessage implements ShouldQueue
{
public function handle(MessageReceived $event): void
{
Inbox::store(from: $event->message->fromId, text: $event->message->text);
}
}
| Event | When |
|---|---|
Reshapify\SendSeven\Webhooks\Events\MessageReceived |
Someone messaged you |
…\MessageStatusUpdated |
Sent, delivered, read or failed (failed(), message->errorCode()) |
…\MessageReactionChanged, ChannelEvent, ContactEvent, ConversationEvent, UnknownEvent |
The rest |
Reshapify\SendSeven\Laravel\Events\ChannelConnected |
A channel was created, e.g. through a connect link |
Reshapify\SendSeven\Laravel\Events\WebhookReceived |
Every delivery, with the route parameters |
Each event ID is handled once (configurable: webhooks.deduplicate_for_seconds).
An endpoint per customer? Put a parameter in the URL and resolve its secret:
Route::sendSevenWebhooks('webhooks/sendseven/{workspace}');
// AppServiceProvider::boot()
SendSeven::resolveWebhookSecretUsing(
fn (Request $request) => Workspace::find($request->route('workspace'))?->sendseven_webhook_secret,
);
Returning null answers 404. To use your own controller instead, add the Reshapify\SendSeven\Laravel\Webhooks\VerifyWebhookSignature middleware and read the event with VerifyWebhookSignature::event($request).
Let customers connect their channels
use Reshapify\SendSeven\Enums\ChannelType;
use Reshapify\SendSeven\Onboarding\ConnectLink;
use Reshapify\SendSeven\Onboarding\WhatsAppMode;
public function store(Workspace $workspace)
{
$connection = SendSeven::connect(
ConnectLink::for(ChannelType::WhatsApp)
->modes(whatsapp: [WhatsAppMode::Classic])
->brandedAs(config('app.name'))
->redirectTo(route('channels.index'))
->singleUse(),
);
$workspace->update(['sendseven_connect_link_id' => $connection->link->id]);
return $connection; // a redirect; Inertia requests get a full-page visit
}
public function handle(ChannelConnected $event): void
{
Workspace::firstWhere('sendseven_connect_link_id', $event->connectLinkId())?->channels()->create([...]);
}
SendSeven runs Meta's Embedded Signup on its connect page; the SDK's onboarding guide covers modes, delegation and what customers see.
Rate limits
SendSeven allows 100 standard requests a minute per token. The add-on counts every request in your cache (set SENDSEVEN_RATE_LIMIT_STORE to a store all processes share, like redis), keeps 10% headroom, and pauses everyone when SendSeven answers 429. When the minute's budget is spent it throws RateLimitExceeded instead of sending:
public function handle(): void
{
try {
SendSeven::messages()->send(...);
} catch (RateLimitExceeded $exception) {
$this->release($exception->retryAfter());
}
}
With a partner token, rate_limit.tenant_share stops one busy tenant from starving the others.
Testing
SendSeven traffic goes through Laravel's HTTP client, so Http::fake(), Http::preventStrayRequests() and Http::assertSent() already cover it. Set SENDSEVEN_MAX_ATTEMPTS=1 in phpunit.xml so faked 5xx responses aren't retried.
Or script SendSeven's responses by endpoint:
$fake = SendSeven::fake([
'POST /messages' => ['id' => 'msg_1', 'direction' => 'outbound', 'message_type' => 'text', 'status' => 'queued', 'created_at' => '2026-10-01T09:00:00Z'],
]);
$this->post('/orders/1/ship');
$fake->assertSent('POST /messages', fn ($request) => $request->body['to'] === '+4915112345678');
Webhooks, signed as SendSeven signs them:
use Reshapify\SendSeven\Laravel\Testing\InteractsWithSendSevenWebhooks;
$this->postSendSevenWebhook('/webhooks/sendseven', $this->sendSevenWebhookPayload('message.received', [
'message' => ['id' => 'msg_1', 'direction' => 'inbound', 'message_type' => 'text', 'text' => 'Hi', 'from_id' => '+4915112345678'],
]))->assertOk();
Commands
| Command | Does |
|---|---|
sendseven:doctor |
Checks the token, plan, tenancy, webhook secret and endpoint, and the rate-limit store |
sendseven:webhooks:register {url?} |
Creates the endpoint, prints its secret, confirms verification |
sendseven:sms-prices {country?} |
SMS prices per segment |
For AI agents
With Laravel Boost, php artisan boost:install picks up this package's guidelines and its sendseven-development skill. Without it, point your agent at vendor/reshapify/sendseven-laravel/resources/boost/skills/sendseven-development/SKILL.md.
Security
Report vulnerabilities privately; see SECURITY.md.
License
MIT. Unofficial: not affiliated with or endorsed by SendSeven GmbH or Laravel Holdings. "SendSeven" and "Laravel" are trademarks of their owners and are used only to say what this package works with.