Documentation Index
Fetch the complete documentation index at: https://docs.getimmutable.dev/llms.txt
Use this file to discover all available pages before exploring further.
Installation
composer require getimmutable/laravel
Requirements: PHP 8.2+, Laravel 10+
Configuration
Add your credentials to .env:
GETIMMUTABLE_API_KEY=imk_your_api_key_here
GETIMMUTABLE_BASE_URL=https://getimmutable.dev
GETIMMUTABLE_ASYNC=false
| Variable | Required | Description |
|---|
GETIMMUTABLE_API_KEY | Yes | Your imk_ prefixed API key |
GETIMMUTABLE_BASE_URL | Yes | Base domain URL |
GETIMMUTABLE_ASYNC | No | Set true to dispatch tracking via Laravel queues |
Service Provider
The package auto-discovers GetImmutable\GetImmutableServiceProvider. No manual registration needed.
Facade
use GetImmutable\AuditLog;
Tracking Events
Basic Usage
use GetImmutable\AuditLog;
AuditLog::track('document.created', 'document', [
'actor_id' => 'user_2hG9kLm',
'actor_name' => 'Sarah Chen',
'actor_type' => 'user',
'resource_id' => 'doc_8nXpQr3',
'resource_name' => 'Q4 Financial Report',
'metadata' => ['folder' => 'reports', 'template' => 'quarterly'],
]);
Fluent Builder
use GetImmutable\AuditLog;
AuditLog::actor($user)
->idempotencyKey('unique_key_123')
->version(1)
->session('sess_4kN8pLm')
->actionCategory('documents')
->target('folder', 'folder_3mK9pLq', 'Shared Reports')
->target('team', 'team_5bR7cNx', 'Engineering')
->track('document.created', 'document', [
'folder' => 'reports',
'template' => 'quarterly',
]);
// Or use the currently authenticated user
AuditLog::fromAuth()
->track('document.created', $document, [
'folder' => 'reports',
]);
PendingEvent Methods
| Method | Parameters | Description |
|---|
idempotencyKey($key) | string | Set deduplication key |
version($v) | int | Set event schema version |
session($id) | string | Set session identifier |
actionCategory($cat) | string | Set action category |
target($type, $id?, $name?) | string, string?, string? | Add a single target |
targets($arr) | array | Set all targets at once |
track($action, $resource?, $metadata?) | string, string?, array? | Send the event |
Batch Ingestion
use GetImmutable\AuditLog;
AuditLog::trackBatch([
[
'actor_id' => 'user_2hG9kLm',
'actor_name' => 'Sarah Chen',
'action' => 'document.created',
'resource_id' => 'doc_8nXpQr3',
'resource_name' => 'Q4 Financial Report',
],
[
'actor_id' => 'user_2hG9kLm',
'actor_name' => 'Sarah Chen',
'action' => 'document.shared',
'resource_id' => 'doc_8nXpQr3',
'targets' => [
['type' => 'team', 'id' => 'team_5bR7cNx', 'name' => 'Engineering'],
],
],
]);
Querying Events
$response = AuditLog::getEvents([
'actor_id' => 'user_2hG9kLm',
'action' => 'document.*',
'from' => '2026-03-01T00:00:00Z',
'limit' => 25,
]);
// $response['data'] -- array of events
// $response['pagination']['has_more'] -- boolean
// $response['pagination']['next_cursor'] -- string|null
Retrieving a Single Event
$event = AuditLog::getEvent('9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d');
$event['integrity']['event_hash'];
$event['integrity']['previous_event_hash'];
Verification
$result = AuditLog::verify();
if (!$result['data']['valid']) {
Log::critical('Audit log integrity violation', [
'breaks' => $result['data']['breaks'],
]);
}
// With date range
$result = AuditLog::verify('2026-03-01T00:00:00Z', '2026-03-31T23:59:59Z');
// With custom limit (default: 10000)
$result = AuditLog::verify(null, null, 1000);
Viewer Tokens
$token = AuditLog::createViewerToken([
'tenantId' => 'org_7rT2xBc',
'actorId' => 'user_2hG9kLm',
'ttl' => 7200,
]);
$token['token']; // JWT string
$token['expires_at']; // Unix timestamp (integer)
Alerts
$alerts = AuditLog::getAlerts([
'rule_type' => 'new_country',
'limit' => 25,
]);
Exports
$export = AuditLog::createExport([
'actor_id' => 'user_2hG9kLm',
'from' => '2026-03-01T00:00:00Z',
]);
$status = AuditLog::getExport($export['data']['id']);
// $status['data']['status'] -- 'pending', 'processing', 'completed', or 'failed'
Anchors
// List blockchain anchors
$anchors = AuditLog::client()->getAnchors(10);
foreach ($anchors['data'] as $anchor) {
echo "{$anchor['merkle_root']} — {$anchor['status']} — {$anchor['explorer_url']}";
}
// Get anchor details
$anchor = AuditLog::client()->getAnchor('anchor-uuid');
$anchor['data']['first_event_hash'];
$anchor['data']['last_event_hash'];
// Verify anchor integrity
$result = AuditLog::client()->verifyAnchor('anchor-uuid');
$result['data']['valid']; // Merkle root matches events
$result['data']['chain_valid']; // Anchor chain is intact
Auto-Session Tracking
The Laravel SDK can automatically attach the current Laravel session ID to every tracked event. Enable this in your configuration:
// Auto-session reads from Laravel's session store
// No explicit ->session() calls needed
Eloquent Observer Example
Track model events automatically using an Eloquent observer:
namespace App\Observers;
use App\Models\Document;
use GetImmutable\AuditLog;
class DocumentObserver
{
public function created(Document $document): void
{
AuditLog::fromAuth()
->track('document.created', $document, [
'size' => $document->size,
'mime_type' => $document->mime_type,
]);
}
public function updated(Document $document): void
{
AuditLog::fromAuth()
->track('document.updated', $document, [
'changed_fields' => array_keys($document->getDirty()),
]);
}
public function deleted(Document $document): void
{
AuditLog::fromAuth()
->track('document.deleted', $document);
}
}
Register the observer in your AppServiceProvider:
use App\Models\Document;
use App\Observers\DocumentObserver;
public function boot(): void
{
Document::observe(DocumentObserver::class);
}
Queue Integration
Set GETIMMUTABLE_ASYNC=true in your .env to dispatch tracking calls via Laravel’s queue system instead of making synchronous HTTP requests. This prevents audit logging from blocking your application’s response time.
Ensure your queue worker is running to process the dispatched jobs.