InvergeDocs
PHP

PHP SDK

inverge/nexus — plain PHP, Laravel (facade, queued delivery, notification channels, Telescope) and Symfony (bundle, Messenger, Doctrine).

composer require inverge/nexus

Plain PHP

use Inverge\Nexus\Config;
use Inverge\Nexus\NexusClient;

$nexus = new NexusClient(new Config(
    apiKey: 'nxs_live_xxx',
    timeout: 10.0,                             // seconds, optional
    defaultHeaders: [],                        // optional
));

$nexus->events()->capture('order_placed', ['total' => 42.0], ['distinctId' => 'user_1']);

Config::fromArray('nxs_…', [...]) works too. Resources: sessions(), events(), logs(), errors(), flags(), remoteConfig(), links(), realtime(), surveys(), push(), inApp(), liveActivities(), telescope(); plus request() for anything else.

Laravel

The service provider registers itself. Configure with .env:

NEXUS_API_KEY=nxs_live_xxx
NEXUS_TIMEOUT=10
NEXUS_QUEUE=false            # true → deliver telemetry on the queue
NEXUS_QUEUE_CONNECTION=
NEXUS_QUEUE_NAME=
NEXUS_LOGGING=false          # true → also forward your default log channel
NEXUS_LOG_LEVEL=debug
NEXUS_CAPTURE_ERRORS=true    # report unhandled exceptions
NEXUS_SERVICE_NAME=orders-api   # Telescope

Publish config/nexus.php with php artisan vendor:publish --tag=nexus-config.

use Inverge\Nexus\Laravel\Nexus;

Nexus::realtime()->emit('orders:42', 'status', ['state' => 'shipped']);
Nexus::events()->capture('order_placed', ['total' => 42], ['distinctId' => (string) auth()->id()]);

app('nexus.queue')->events()->capture('order_placed', [], ['distinctId' => $id]);   // via the queue

Logs — a dedicated nexus log channel is registered: LOG_CHANNEL=nexus sends logs to Nexus instead of the file, or stack it with single. (NEXUS_LOGGING=true piggybacks on your default channel instead — use one or the other.)

Telescope is on as soon as the key is set — see Telescope for Laravel.

Laravel notification channels

Send push, Live Activities and realtime messages from ordinary notifications:

Method on your notificationReturnsOwn channel
toNexusPush($notifiable)NexusPushMessage'nexus-push'
toNexusLiveActivity($notifiable)NexusLiveActivityMessage'nexus-live-activity'
toNexusRealtime($notifiable)NexusRealtimeMessage'nexus-realtime'

Put NexusChannel::class in via() and every method the notification has is sent. Tell Nexus who the notifiable is:

public function routeNotificationForNexus(): string
{
    return "CLIENTS.{$this->id}";   // the distinctId your apps identify with
}
class OrderStatusChanged extends Notification implements ShouldQueue
{
    use Queueable;

    public function __construct(public Order $order) {}

    public function via(object $notifiable): array
    {
        return [NexusChannel::class];
    }

    public function toNexusPush(object $notifiable): NexusPushMessage
    {
        return NexusPushMessage::create('Your fuel is on the way', "Driver: {$this->order->driver_name}")
            ->data(['screen' => "/orders/{$this->order->id}"]);
    }

    public function toNexusLiveActivity(object $notifiable): NexusLiveActivityMessage
    {
        $id = "order_{$this->order->id}";

        return match ($this->order->status) {
            'Pending'   => NexusLiveActivityMessage::create($id)->start('order_tracking')->step('pending')
                               ->etaAt($this->order->eta)->values(['driver' => $this->order->driver_name]),
            'Completed' => NexusLiveActivityMessage::create($id)->end()->step('completed'),
            'Canceled'  => NexusLiveActivityMessage::create($id)->end()->canceled(),
            default     => NexusLiveActivityMessage::create($id)->update()->step($this->order->status),
        };
    }
}
  • A push or Live Activity start goes to the notifiable's route unless the message targets someone itself (toUser(), toSegment(), toAll() / shared()); updates and ends address the activity by id.
  • Per-product routes override the shared one: routeNotificationForNexusPush(), …ForNexusLiveActivity(), …ForNexusRealtime().
  • On demand: Notification::route('nexus', 'CLIENTS.7')->notify(new OrderStatusChanged($order));
  • Safe to queue and retry: each product is sent independently, the job fails so Laravel retries it, and what already went out is remembered (in your cache, keyed by the notification id) — a retry re-sends only what failed.

Symfony

config/packages/nexus.yaml
nexus:
    api_key: '%env(NEXUS_API_KEY)%'
    capture_errors: true
    telescope:
        service: 'orders-api'

Autowire NexusClient. An exception subscriber reports uncaught exceptions, a Messenger handler is available for async delivery, and Telescope records requests, commands, Doctrine and Messenger — see Telescope for Symfony.

Dispatchers & transports

The client sends through a dispatcher — synchronous cURL by default. Swap it so telemetry never blocks a request:

$queued = $nexus->withDispatcher($dispatcher);        // Laravel QueueDispatcher, Symfony MessengerDispatcher, yours
$nexus = new NexusClient($config, $psr18Transport);   // any PSR-18 client

Monolog

use Inverge\Nexus\Monolog\NexusLogHandler;

$logger->pushHandler(new NexusLogHandler($nexus /*, level, bubble, flushAt */));

Low-level requests

$body = $nexus->request('POST', '/partner/events', ['events' => [...]], ['If-None-Match' => $etag]);

Returns the decoded body, or null on failure.

On this page