Search by

auditrails / auditrails-php

lkeio2

Official PHP SDK for auditrails.io — tamper-proof audit logging as a service

Package info

github.com/auditrails/auditrails-php

Homepage

pkg:composer/auditrails/auditrails-php

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 1

v1.0.0 2026-08-18 12:59 UTC

This package is auto-updated.

Last update: 2026-10-14 15:37:44 UTC


README

Official PHP SDK for auditrails.io — tamper-proof audit logging as a service.

Install

composer require auditrails/auditrails-php

Requires PHP 8.1+ and a PSR-18 HTTP client (Guzzle, Symfony HTTP Client, etc.).

Quick Start

use AuditRails\AuditEvent;
use AuditRails\AuditRails;
use AuditRails\Config;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;

$audit = new AuditRails(
    config: new Config(apiKey: $_ENV['AUDITRAILS_API_KEY']),
    httpClient: new Client(['timeout' => 10]),
    requestFactory: new HttpFactory(),
    streamFactory: new HttpFactory(),
);

// Fire-and-forget (buffered, auto-flushed at shutdown)
$audit->log(new AuditEvent(
    action: ComplianceAction::AUTH_LOGIN,  // typed compliance action constant
    actorId: 'user_123',
    resource: 'session/sess_456',
    metadata: ['ip' => '1.2.3.4'],
));

// Events flush automatically via register_shutdown_function

That's it. Your first audit event in under 2 minutes.

Test mode (sandbox)

Every API key has a mode — live or test — set when the key is created in the dashboard. Test keys are designed for integration and CI:

  • Prefix: at_test_… (live keys use at_live_…).
  • Billing: Test traffic is free — never counted toward your monthly quota, never reaches Stripe.
  • Rate limit: Test keys share a separate, smaller pool (default 60 req/s) so a leaked test key can't be used to exhaust your live capacity.
  • Reports: Test events never appear in compliance reports, scheduled exports, or usage aggregates.
  • Retention: 7 days in hot storage. Test data is non-durable by design; do not rely on it for evidence.

Use a test key in dev/staging and during your CI integration tests; switch to a live key in production. No SDK config changes — just pass whichever key the dashboard issued:

// Development / CI
$audit = new AuditRails(config: new Config(apiKey: 'at_test_…'), /* ... */);

// Production
$audit = new AuditRails(config: new Config(apiKey: 'at_live_…'), /* ... */);

Compliance Action Constants

The SDK includes ComplianceAction class with typed constants for all 42 compliance actions:

use AuditRails\ComplianceAction;

$audit->log(new AuditEvent(action: ComplianceAction::AUTH_LOGIN, actorId: 'user_1'));
$audit->log(new AuditEvent(action: ComplianceAction::CONSENT_GIVEN, actorId: 'user_1'));
$audit->log(new AuditEvent(action: ComplianceAction::PHI_ACCESSED, actorId: 'user_1', resource: 'patient/123'));

Raw strings are still accepted for backward compatibility.

PSR-18 HTTP Client

The SDK works with any PSR-18 compliant HTTP client. Pass your own ClientInterface, RequestFactoryInterface, and StreamFactoryInterface to the constructor:

use AuditRails\AuditRails;
use AuditRails\Config;

// With Guzzle
$audit = new AuditRails(
    config: new Config(apiKey: '...'),
    httpClient: new \GuzzleHttp\Client(['timeout' => 10]),
    requestFactory: new \GuzzleHttp\Psr7\HttpFactory(),
    streamFactory: new \GuzzleHttp\Psr7\HttpFactory(),
);

// With Symfony HTTP Client
$audit = new AuditRails(
    config: new Config(apiKey: '...'),
    httpClient: new \Symfony\Component\HttpClient\Psr18Client(),
    requestFactory: new \Nyholm\Psr7\Factory\Psr17Factory(),
    streamFactory: new \Nyholm\Psr7\Factory\Psr17Factory(),
);

API

new AuditRails(config, httpClient, requestFactory, streamFactory, logger?)

Option Type Description
config Config Configuration object (see below)
httpClient ClientInterface PSR-18 HTTP client
requestFactory RequestFactoryInterface PSR-17 request factory
streamFactory StreamFactoryInterface PSR-17 stream factory
logger ?LoggerInterface Optional PSR-3 logger (defaults to NullLogger)

Config

Option Type Default Description
apiKey string required Your API key (at_live_... or at_test_...)
baseUrl string https://api.auditrails.io Ingestion API URL
batchSize int 100 Max events per batch (max 100)
maxRetries int 3 Retry attempts for 5xx errors
timeout int 10 Request timeout in seconds
autoShutdown bool true Auto-flush via register_shutdown_function

$audit->log(AuditEvent)

Buffer an event for batch sending. Never throws — errors are logged silently.

$audit->log(new AuditEvent(
    action: 'document.created',    // required
    actorId: 'user_123',           // who did it
    resource: 'document/doc-456',  // what was affected
    metadata: ['key' => 'value'],  // extra context (max 10 keys)
));

$audit->logDirect(AuditEvent): LogResponse

Send a single event immediately. Throws AuditRailsError on API errors.

$response = $audit->logDirect(new AuditEvent(action: 'user.deleted', actorId: 'admin_1'));
echo $response->logId;      // "01HX..."
echo $response->requestId;  // "req_01HX..."

$audit->logBatchDirect(AuditEvent[]): BatchResponse

Send a batch of events immediately. Throws on error.

$audit->flush(): void

Flush all buffered events immediately.

$audit->close(): void

Flush and shut down. After close(), log() calls are silently ignored.

Error Handling

The SDK never crashes your application:

  • log() never throws — errors are logged via PSR-3 logger
  • logDirect() and logBatchDirect() throw AuditRailsError on API errors
  • 5xx errors are retried with exponential backoff
  • 4xx errors fail immediately (no retry)
use AuditRails\AuditRailsError;

try {
    $audit->logDirect(new AuditEvent(action: 'test'));
} catch (AuditRailsError $e) {
    echo $e->errorCode;   // 'validation/missing_action'
    echo $e->statusCode;  // 422
    echo $e->requestId;   // 'req_...'
    echo $e->docUrl;      // link to docs
}

License

MIT