Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Pushwoosh Laravel Package

laravel-notification-channels/pushwoosh

Send push notifications through Pushwoosh directly from your Laravel app using the native notification system. This channel lets you deliver messages to iOS and Android devices via Laravel notifications, keeping your code clean and consistent with other channels.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the channel and wire up credentials before touching any notification class:

composer require laravel-notification-channels/pushwoosh

As of v4.0.0 the package supports Laravel 13. If you're on an older Laravel, pin to the v3 line (^3.6) — v4 is a major bump, so check the illuminate/* constraints in the package's composer.json before upgrading an existing app, and run a full test pass afterwards even though the release notes advertise only framework support and no API changes.

Add the Pushwoosh app credentials to config/services.php (this package follows the convention of reading from services.php, not a dedicated config file you publish):

'pushwoosh' => [
    'app_id'    => env('PUSHWOOSH_APP_ID'),
    'api_token' => env('PUSHWOOSH_API_TOKEN'),
],

Then set PUSHWOOSH_APP_ID and PUSHWOOSH_API_TOKEN in .env. The API token is the server token from the Pushwoosh control panel (Settings → API access), not the app code — mixing these up is the most common first-day failure.

The first use case is almost always transactional: a notification class that sends one push to one user's registered device(s).

use NotificationChannels\Pushwoosh\PushwooshChannel;
use NotificationChannels\Pushwoosh\PushwooshMessage;

class OrderShipped extends Notification
{
    public function via($notifiable)
    {
        return [PushwooshChannel::class];
    }

    public function toPushwoosh($notifiable)
    {
        return PushwooshMessage::create('Your order is on its way')
            ->setTitle('Order shipped');
    }
}

For targeting, the channel resolves recipients through a routeNotificationForPushwoosh() method on the notifiable (falling back to a device token / Pushwoosh user id field if the package defines one). Start by implementing that method explicitly on your User model:

public function routeNotificationForPushwoosh()
{
    return $this->pushwoosh_user_id ?: $this->deviceTokens()->pluck('token');
}

If you can't get a push delivered in the first ten minutes, verify the recipient resolution before debugging the API — a null route is the usual culprit, and this package will not throw loudly for an empty recipient list.

Implementation Patterns

Single-recipient notifications. The standard pattern: via() returns [PushwooshChannel::class], toPushwoosh() returns a PushwooshMessage. Keep one message class per notification so the payload stays readable.

On-demand pushes. Use Notification::route('pushwoosh', $tokenOrUserId)->notify(new SomeNotification) for one-off sends (broadcast to a support device, an internal alert) where there's no notifiable model. This is the cleanest way to test the channel end-to-end without polluting user models.

Payload/custom data. Pushwoosh messages carry a data payload alongside content. Use the message builder's data/parameter setters to attach deep-link keys, an entity id, or a badge count, and handle them client-side:

return PushwooshMessage::create('New message')
    ->setTitle('Inbox')
    ->setData(['type' => 'message', 'id' => $message->id]);

Keep data values scalar and small — Pushwoosh rejects or truncates oversized payloads, and nested arrays behave inconsistently across platforms.

Queuing. The channel performs a synchronous HTTP call. Always pair it with a queued notification (implements ShouldQueue or ->onQueue()), or you'll block the request on Pushwoosh latency. Because it's queue-friendly, this composes naturally with transactional flows: fire the notification from a listener/job, not from the controller.

Fan-out with fallbacks. A common production pattern is via() returning [PushwooshChannel::class, MailChannel::class], where push is the fast path and mail is the fallback. Since Pushwoosh failures are typically silent (see below), the mail fallback carries a lot of the reliability weight.

Segments and broadcast. For user-segment sends, the cleaner pattern is to do segment targeting with Pushwoosh's own API/console and reserve this package for per-user transactional pushes. Driving segment broadcasts through a Laravel notification ends up fighting the notifiable abstraction and duplicating recipient lists.

Testing. Use Notification::fake() and assert PushwooshChannel::class was included in the channels, then assert message contents with assertSentTo(...). This is the only reliable way to test the channel without hitting the live API, since there's no first-class fake client shipped with the package.

Upgrading to v4. Treat this as a dependency-constraint change plus a framework-support change, not a rewrite: bump the constraint, confirm your app's Laravel/PHP versions satisfy the new requirements, re-run the notification test suite (channel inclusion + message assertions), and do one real send per platform in staging before shipping. No message-builder or channel-API changes are called out in the v4.0.0 notes.

Gotchas and Tips

  • Silent failures. Push notification channels in this family generally swallow HTTP errors or log them at debug level. Wrap sends in logging/monitoring: check storage/logs/laravel.log first, then confirm request/response by temporarily logging the HTTP client or by enabling HTTP client events (Http::globalRequestMiddleware). If a push "doesn't arrive," the channel almost never tells you why.
  • App id vs API token vs app code. Pushwoosh has three identifiers. Only the numeric application id and the API access token are used here. A 401/403 from api.pushwoosh.com is virtually always a token mismatch.
  • Recipient shape matters. Pushwoosh differentiates devices (hwid push tokens) from users (your own user id). Passing the wrong one yields a 200 with zero delivered. Decide up front whether you key on device tokens or Pushwoosh user ids, and be consistent in routeNotificationForPushwoosh().
  • Multi-device users. If you key on user id, Pushwoosh fans out to all registered devices for that user. If you key on device tokens, you must return an array — a single token returns a single push, and stale tokens accumulate silently.
  • Stale tokens. Nothing in this package prunes invalid device tokens. Add your own cleanup by listening for Pushwoosh feedback (unregistered devices) or by refreshing tokens on app launch.
  • Major-version discipline. v4.0.0 is a major bump whose only documented change is Laravel 13 support, which strongly suggests the v4 line dropped older illuminate/* constraints. Pin the version in composer.json, don't blanket-allow *, and read the require block before upgrading. The public surface is still thin, so when in doubt read src/PushwooshMessage.php rather than guessing at setters.
  • Still a small package. Low download counts and few dependents mean issues surface late; there's no security or deprecation safety net beyond upstream PRs. If you outgrow it, the extension point is a custom channel: swap PushwooshChannel::class in via() for your own class that wraps Http::post('https://api.pushwoosh.com/json/1.3/createMessage', ...).
  • Platform-specific fields. iOS and Android accept different keys (sound, badge, priority, TTL). The package passes these through rather than validating them, so a working Android push can silently no-op on iOS. Test on both platforms before shipping — including right after the v4 upgrade, since framework bumps can shift the underlying HTTP client behaviour (timeouts, retries, exception handling).
  • Delivery is asynchronous on Pushwoosh's side too. A successful HTTP 200 and an actual device delivery are different events. Don't build retry logic on the HTTP response alone; treat the send as fire-and-forget and make the user-facing state recoverable (e.g., the in-app inbox shows the same content).
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log