liberusoftware/notifications-api
REST API endpoints for sending and managing notifications through the Liberu notifications package, with Laravel-native authentication, validation, and JSON responses for quick integration.
Verify what you actually installed before writing a line of code. With zero stars, zero dependents, and a NOASSERTION license, this package has no community validation — treat the first 30 minutes as due diligence, not setup.
composer require liberusoftware/notifications-api
composer show liberusoftware/notifications-api # version, requires, autoload, extra.laravel
Read composer.json first. Three things matter:
require — a "presentation adapter" almost certainly depends on a sibling domain package (something like liberusoftware/module-notifications). If the domain package isn't pulled in transitively, you'll need it, because an adapter shapes data it doesn't own.extra.laravel.providers — tells you whether discovery registers the service provider automatically or you must add it to bootstrap/providers.php.autoload.psr-4 — gives you the namespace root to grep against.Then locate the entry points:
ls vendor/liberusoftware/notifications-api/src
ls vendor/liberusoftware/notifications-api/routes 2>/dev/null
php artisan route:list --path=api # find what it actually registered
php artisan list | grep -i notification # any publish/install commands
First use case: get one authenticated GET returning a list of notifications for the current user, and confirm the JSON envelope. That single request tells you the resource shape, the pagination contract, the auth guard, and the route prefix — the four things everything else in your integration hangs off.
If the package ships publishable config or routes:
php artisan vendor:publish --provider="Liberu\NotificationsApi\NotificationsApiServiceProvider"
Check config/notifications-api.php (or whatever lands) for route prefix, middleware stack, and pagination size before you build anything on top.
The name is explicit: presentation adapter. Its job is turning notification records into HTTP-shaped JSON. So:
If the package hard-registers routes you don't control, the clean move is to disable its route loading (usually a config flag like routes.enabled or register_routes) and re-register the controllers yourself:
// routes/api.php
Route::prefix('v1')
->middleware(['auth:sanctum', 'throttle:api'])
->group(function () {
Route::apiResource('notifications', NotificationController::class)
->only(['index', 'show', 'destroy']);
});
This gives you versioning, rate limiting, and scope middleware that a package default almost never matches your app's conventions.
An adapter registered with api middleware alone will usually be unauthenticated or use whatever the package assumes. For anything user-scoped:
Route::middleware('auth:sanctum')->group(...);
Then verify the adapter scopes queries to the authenticated user. If it resolves notifications by ID without a tenant/user constraint, you have an IDOR — check the controller's show/destroy for a where('user_id', auth()->id()) or a global scope. With a zero-adopter package, assume nothing.
For tests:
Sanctum::actingAs($user);
$this->getJson('/api/v1/notifications')->assertOk()->assertJsonStructure([...]);
Because the envelope (pagination meta keys, data wrapper, date formats) is the product of this package, pin it with a contract test:
it('keeps the notifications index envelope stable', function () {
Notification::factory()->count(3)->for($user)->create();
Sanctum::actingAs($user);
$this->getJson('/api/v1/notifications')
->assertOk()
->assertJsonStructure([
'data' => [['id', 'type', 'read_at', 'created_at']],
'meta' => ['current_page', 'per_page', 'total'],
]);
});
This is your alarm when a patch release silently reshapes output — which, given no dependents and no social proof, is a real risk.
When you need extra fields (unread counts, actor avatars, deep links), wrap the adapter's resource:
class EnrichedNotificationResource extends NotificationResource
{
public function toArray($request): array
{
return parent::toArray($request) + [
'deep_link' => route('dashboard.notifications.show', $this->id),
];
}
}
Rebind it if the package resolves resources from the container; otherwise set it on the controller. Either way, keep the customization in app/, never in vendor/.
The license is the biggest risk, not the code. NOASSERTION means GitHub's detector couldn't classify it — there may be a custom or missing LICENSE file. Check vendor/liberusoftware/notifications-api/LICENSE* before this touches anything commercially distributed. No license file at all means all rights reserved by default, which is a legal blocker regardless of how well it works.
Zero dependents means you are the test suite. No one has hit the edge cases for you. Budget time for reading source rather than docs — the README is likely thin or aspirational.
Watch for the future-dated release. The listed last release (2026-10-26) is anomalous. Confirm the actual tag: composer show -a liberusoftware/notifications-api. Pin an explicit version in composer.json and commit composer.lock. Prefer a specific tag over ^ ranges on a package with this little adoption — a surprise minor bump could change the JSON contract your frontend depends on.
Route collisions are the #1 first-day failure. Packages that auto-load routes into the api middleware group can shadow or be shadowed by your own /api/notifications. Symptom: 404s, or wrong controller firing. Diagnose with php artisan route:list --path=notifications --columns=method,uri,action,middleware. Fix by disabling package routes and registering your own.
vendor:publish may publish nothing. Some modules ship config without a tag. Try bare vendor:publish once and inspect the diff — but don't assume a config file exists; a missing config means values are hardcoded in the service provider. Read the provider if so.
Presentation adapters commonly trigger N+1. If the resource touches a relationship (actor, notifiable subject, notification type metadata), eager loading probably isn't set. Watch DB::listen or Laravel Debugbar on an index of 50 notifications. If you can't configure eager loads through the package, override the controller query:
Notification::with(['actor', 'subject'])->whereBelongsTo($user)->paginate();
Caching will bite you. Notification lists are user-scoped and frequently invalidated. Do not slap a Cache::remember around the index endpoint without a per-user key and an invalidation hook on notification creation — stale unread counts are a support-ticket generator.
Version your endpoint from day one. You're wrapping an unmaintained-looking adapter in your public API surface. /api/v1/... costs nothing now and buys you the option to replace the package wholesale later without breaking clients. Given the scores here (0 stars, 0 dependents, opaque license), assume you will eventually replace it — keep the boundary thin, put your own tests around the envelope, and never let package resource classes leak into your domain layer.
Extension points to look for, in order of preference: container bindings in the service provider (cleanest) → config flags → resource/controller subclassing → publishing and overriding routes → forking (last resort, and only if the license permits it).
How can I help you explore Laravel packages today?