Integrations

Laravel SDK

The official Laravel package for Beacon. Create incidents, update components, send heartbeats, and automate status communication from your Laravel application. Ships with a Facade, queued requests by default, and zero-config service provider auto-discovery.

Installation

composer require beacon-status/laravel

The package uses Laravel's auto-discovery, so no manual service provider registration is needed.

Configuration

Publish the config file:

php artisan vendor:publish --tag=beacon-config

Add the following environment variables to your .env file:

BEACON_API_TOKEN=your-api-token
BEACON_BASE_URL=https://usebeacon.pro
BEACON_PAGE_SLUG=your-page-slug

Full config reference

// config/beacon.php
return [
    // API token from your Beacon workspace settings
    'token' => env('BEACON_API_TOKEN'),

    // Base URL of your Beacon instance
    'base_url' => env('BEACON_BASE_URL', 'https://usebeacon.pro'),

    // Default status page slug for convenience methods
    'page_slug' => env('BEACON_PAGE_SLUG'),

    // When true, API requests are dispatched via Laravel queue
    'async' => env('BEACON_ASYNC', true),

    // Queue connection and queue name for async requests
    'queue_connection' => env('BEACON_QUEUE_CONNECTION'),
    'queue' => env('BEACON_QUEUE', 'default'),

    // HTTP timeout in seconds
    'timeout' => env('BEACON_TIMEOUT', 10),
];

Facade methods

All methods are available via the Beacon facade.

Beacon::createIncident(array $data)

Create a new incident on your status page.

use Beacon\Laravel\Facades\Beacon;

Beacon::createIncident([
    'title'   => 'Database connection failures',
    'impact'  => 'major',
    'state'   => 'investigating',
    'message' => 'We are seeing connection timeouts to the primary database cluster.',
]);

Beacon::updateIncident(string $id, array $data)

Update an existing incident's properties.

Beacon::updateIncident('inc_01HX9Z...', [
    'state'  => 'identified',
    'impact' => 'critical',
]);

Beacon::addIncidentUpdate(string $id, string $message)

Post an update to an incident timeline.

Beacon::addIncidentUpdate(
    'inc_01HX9Z...',
    'Root cause identified: a misconfigured replica. Failover in progress.'
);

Beacon::resolveIncident(string $id, ?string $message)

Resolve an incident with an optional closing message.

Beacon::resolveIncident(
    'inc_01HX9Z...',
    'Failover complete. All database connections are healthy.'
);

Beacon::updateComponent(string $id, array $data)

Update a component's status or properties.

Beacon::updateComponent('comp_01HX...', [
    'status' => 'degraded_performance',
]);

Beacon::heartbeat(string $token)

Send a heartbeat ping.

Beacon::heartbeat('abc123');

Async mode

By default, all Beacon SDK calls are dispatched via Laravel's queue system using the SendBeaconRequest job. This means your application code does not wait for the HTTP request to Beacon to complete.

To send requests synchronously (useful for testing or CLI commands):

# .env
BEACON_ASYNC=false
Tip: Keep async mode enabled in production. If the Beacon API is temporarily slow or unreachable, your application will not be affected.

Error handling

The SDK is designed to never throw exceptions. If an API request fails, the SDK:

  • Logs a warning via Laravel's logger
  • Returns an error array instead of a response array

This ensures that a Beacon API issue never causes your application to crash. You can inspect the return value if needed:

$result = Beacon::createIncident([...]);

if (isset($result['error'])) {
    // Handle error
    Log::error('Beacon API failed', $result);
} else {
    // $result contains the API response data
    $incidentId = $result['data']['id'];
}

Practical patterns

Exception handler integration

Automatically create incidents when specific exceptions occur:

// app/Exceptions/Handler.php
use Beacon\Laravel\Facades\Beacon;

public function register(): void
{
    $this->reportable(function (DatabaseException $e) {
        Beacon::createIncident([
            'title'   => 'Database connection error',
            'impact'  => 'major',
            'state'   => 'investigating',
            'message' => 'Automated report: ' . $e->getMessage(),
        ]);
    });
}

Scheduler heartbeats

Ping Beacon after critical scheduled tasks:

// app/Console/Kernel.php
$schedule->command('billing:charge')
    ->hourly()
    ->after(fn () => Beacon::heartbeat('billing-job-token'));

$schedule->command('reports:email')
    ->dailyAt('06:00')
    ->after(fn () => Beacon::heartbeat('reports-job-token'));

Deploy script component updates

Set a component to maintenance during deploys:

// deploy.php or Envoy task
Beacon::updateComponent('comp_01HX...', [
    'status' => 'under_maintenance',
]);

// ... deploy steps ...

Beacon::updateComponent('comp_01HX...', [
    'status' => 'operational',
]);

Health check endpoint

Create a health endpoint that also reports to Beacon on failure:

// routes/api.php
Route::get('/health', function () {
    try {
        DB::connection()->getPdo();
        Cache::store()->get('health-check');

        return response()->json(['status' => 'healthy']);
    } catch (\Throwable $e) {
        Beacon::createIncident([
            'title'   => 'Health check failed',
            'impact'  => 'major',
            'state'   => 'investigating',
            'message' => $e->getMessage(),
        ]);

        return response()->json(['status' => 'unhealthy'], 503);
    }
});

Testing

Mock the Beacon facade in your tests to verify calls without hitting the API:

use Beacon\Laravel\Facades\Beacon;

public function test_incident_is_created_on_database_error(): void
{
    Beacon::shouldReceive('createIncident')
        ->once()
        ->with(Mockery::on(fn ($data) =>
            $data['impact'] === 'major'
        ))
        ->andReturn(['data' => ['id' => 'inc_test']]);

    // Trigger the code path that creates the incident
    $this->simulateDatabaseFailure();
}

public function test_heartbeat_is_sent_after_job(): void
{
    Beacon::shouldReceive('heartbeat')
        ->once()
        ->with('billing-job-token');

    // Run the scheduled command
    $this->artisan('billing:charge');
}