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

Pushover Laravel Package

sly/pushover

sly/pushover is a Laravel package for sending Pushover push notifications from your PHP applications. It offers a simple integration for delivering real-time alerts to iOS and Android devices via Pushover’s API, with configuration for your application token and user key.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a thin, framework-agnostic PHP client for the Pushover REST API — not a batteries-included Laravel package. There is no service provider, no facade, no config/pushover.php to publish. You get two classes and you wire them up yourself. Plan for ~15 minutes to first send.

1. Install and pin

composer require sly/pushover

Pin the exact version in composer.json (34 stars, zero dependents — treat it as vendored code, not a moving dependency). Run composer audit and confirm the PHP/Laravel constraints before merging.

2. Provision two separate credentials at pushover.net

  • Application token — register an app under "Your Applications". Identifies the sender.
  • User key — on your dashboard (or each recipient's dashboard). Identifies the recipient.

They are not interchangeable. Swapping them returns a 400 with a vague message that costs ten minutes to diagnose. Store them as secrets, not in code.

3. Put them in config and .env

// config/services.php
'pushover' => [
    'token' => env('PUSHOVER_TOKEN'),
    'user'  => env('PUSHOVER_USER'), // default recipient, e.g. ops team
],

4. Where to look first

  • README.md — the entire API surface fits on one screen.
  • src/Sly/PushOver/PushOver.php — the client; holds the token, performs the HTTP call.
  • src/Sly/PushOver/Model/Push.php — the fluent DTO: setUser, setMessage, setTitle, setSound, setDevice, setUrl, setUrlTitle, setTimestamp, setPriority, and emergency-only setRetry / setExpire / setCallback.

5. First use case — prove it in tinker before writing app code

use Sly\PushOver\PushOver;
use Sly\PushOver\Model\Push;

$push = (new Push())
    ->setUser(config('services.pushover.user'))
    ->setTitle('Deploy finished')
    ->setMessage('prod is green')
    ->setSound('pushover');

$client = new PushOver();
$client->setToken(config('services.pushover.token'));
$client->send($push);

If the phone buzzes, everything after this is plumbing. The canonical day-one use case is an internal ops alert (deploy finished, cron failed, incident opened) to on-call — not user-facing notifications.

Implementation Patterns

Bind the client as a singleton in AppServiceProvider::register(). No controller should ever construct PushOver:

$this->app->singleton(PushOver::class, function () {
    $client = new PushOver();
    $client->setToken(config('services.pushover.token'));
    return $client;
});

Wrap it in an application-owned PushoverNotifier. This is the single most important pattern — it gives you an exit hatch when (not if) the package goes stale:

class PushoverNotifier
{
    public function __construct(private PushOver $client) {}

    public function send(string $message, array $opts = []): void
    {
        $push = (new Push())
            ->setUser($opts['user'] ?? config('services.pushover.user'))
            ->setMessage($message)
            ->setTitle($opts['title'] ?? config('app.name'));

        if (isset($opts['priority'])) $push->setPriority($opts['priority']);
        if (isset($opts['sound']))    $push->setSound($opts['sound']);
        if (isset($opts['url']))      $push->setUrl($opts['url']);

        $this->client->send($push);
    }
}

Callers depend on PushoverNotifier; only one file knows about sly/pushover. Swapping to Laravel's Http client later is a one-file change.

Always queue. A synchronous Pushover call inside a request or model observer blocks — and Pushover's own latency is out of your hands. Two idiomatic options:

  • Wrap the notifier in a ShouldQueue job (SendPushoverAlertJob).
  • Or build a Laravel notification channel around it (the assessment-tpm rightly notes the package doesn't ship one — you write ~20 lines):
class PushoverChannel
{
    public function __construct(private PushoverNotifier $notifier) {}

    public function send($notifiable, Notification $notification): void
    {
        $payload = $notification->toPushover($notifiable);
        $this->notifier->send($payload['message'], $payload);
    }
}

// In the Notification:
public function via($notifiable): array { return [PushoverChannel::class]; }
public function toPushover($notifiable): array
{
    return ['title' => 'Order shipped', 'message' => "Order #{$this->order->id} is on its way"];
}

Route by user key, not device. Store pushover_user_key on users (a notification route) and pass it into setUser() per recipient. Reserve setDevice() for the rare case where one user has multiple registered devices and you need to target a specific one. For fan-out to several people, loop in the job — the library sends one Push per call.

Use priority deliberately — it's the feature that earns this library its keep:

Priority Meaning Use for
-2 silent, no notification background confirmations
-1 quiet low-signal info (deploy succeeded)
0 normal default
1 high, bypasses quiet hours paging-adjacent alerts
2 emergency, requires ack true on-call incidents

Capture the request id. Pushover returns JSON with status and request — log both. The request id is what you quote to Pushover support and what lets you reconcile a send with a delivery report afterwards.

Test against a mock, not the real API. The client's HTTP layer is small; bind a fake PushOver (or Http::fake() if you later swap to the Laravel client) in a test service provider so CI never burns your Pushover quota or fires real phones.

Gotchas and Tips

  • No service provider or facade ships with this package. If a tutorial mentions a Pushover facade or a pushover config file, it's describing the separate Symfony bundle (sly/pushover-bundle) or a different package. You register the binding yourself.
  • Emergency priority (2) is rejected without setRetry() and setExpire(). Retry is minimum 30 seconds; expire is maximum 10800 (3 hours). Add setCallback() if you want acknowledgement to come back to your app.
  • Swap-tolerant token handling. setToken() on a singleton is set once at boot — if you ever need multi-app support, don't rely on the singleton; construct per-send.
  • The library throws on failure but the error messages are Pushover's, not Laravel's. Wrap every send() in try/catch, log at error with the exception message, and fail soft — a failed push must never take down the request/job that triggered it.
  • Duplicate sends after retry are real. If a queued send times out ambiguously, a retry can deliver twice. Pushover doesn't dedupe for you. Keep a request id or a local send log and accept that duplicate emergency alerts are worse than a missed quiet one — pick the trade-off deliberately per priority tier.
  • Handle 429/backoff yourself. The library does not implement rate-limit retry. Use Laravel's retry() helper or RateLimited job middleware around the notifier, and monitor failure rate.
  • Quiet hours bite at priority ≥ 1. Priority 1 bypasses quiet hours on the recipient's device; -1 and 0 don't. This is a product decision, not a code one — get ops to agree who gets woken up before you ship.
  • User keys are per-user, tokens are per-app. A single app token can send to any user key; a user key from one Pushover account cannot receive from another account's app. Revoked subscriptions return an error at send time, not at config time — validate at the edge (a "send test" button in admin) rather than assuming a stored key is live.
  • Low adoption = you own the code. 34 stars, 0 dependents, and it may lag PHP/Laravel versions. Budget for a fork. Keep the PushoverNotifier boundary and a documented fallback channel (email/Slack) so a swap is a one-file change when the package rots or Pushover's free tier limits change.
  • Never log the token or user key. Log message, title, priority, and the request id — not the payload's credentials.
  • Delivery is "good enough," not guaranteed. Pushover is an external SaaS on its own SLA. For anything where a missed alert is a real incident: pair this with a fallback (Slack and/or email) triggered on send failure, and add a dead-letter queue for jobs that exhaust retries.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource