Quickstart
Install the Slim adapter.
Composer installs the shared PHP Core automatically. Configure a project key, stable service name and deployment environment.
composer require apirelio/slim:^0.1APIRELIO_API_KEY=apr_live_your_key
APIRELIO_ENDPOINT=https://apirelio.com
APIRELIO_SERVICE=billing-api
APIRELIO_ENVIRONMENT=production
APIRELIO_RELEASE=2026.08.12.1Automatic tracking
Respect Slim's LIFO stack.
Add Apirelio before routing middleware. Slim then resolves the route before Apirelio runs, while error middleware remains the outermost exception boundary.
use Apirelio\Slim\ApirelioMiddleware;
use Apirelio\Slim\Config;
$apirelio = new ApirelioMiddleware(new Config(
apiKey: $_ENV['APIRELIO_API_KEY'],
endpoint: $_ENV['APIRELIO_ENDPOINT'],
service: $_ENV['APIRELIO_SERVICE'],
environment: $_ENV['APIRELIO_ENVIRONMENT'],
release: $_ENV['APIRELIO_RELEASE'] ?? null,
paths: ['/api/*'],
bufferPath: __DIR__.'/../var/apirelio/events.ndjson',
));
// Slim middleware is LIFO. Keep this order.
$app->add($apirelio);
$app->addRoutingMiddleware();
$app->addErrorMiddleware(false, true, true);The SDK needs Slim's route pattern such as /api/customers/{id}, not a high-cardinality concrete URL.
Customer context
Connect authentication to account identity.
Resolvers run after upstream authentication middleware and translate your domain objects into stable customer and consuming-application identifiers.
use Apirelio\Core\Data\ApirelioApplication;
use Apirelio\Core\Data\ApirelioCustomer;
$apirelio = new ApirelioMiddleware(
config: $config,
customerResolver: static fn ($request) => new ApirelioCustomer(
id: (string) $request->getAttribute('account')->id,
name: $request->getAttribute('account')->name,
plan: $request->getAttribute('account')->plan,
),
applicationResolver: static fn ($request) => new ApirelioApplication(
id: (string) $request->getAttribute('api_client')->id,
name: $request->getAttribute('api_client')->name,
),
);Diagnostics
Add bounded request context.
The middleware attaches a mutable request context. Only configured scalar metadata survives PHP Core privacy filtering.
use Apirelio\Slim\RequestContext;
$app->post('/api/invoices', function ($request, $response) {
/** @var RequestContext|null $context */
$context = $request->getAttribute(RequestContext::ATTRIBUTE);
$context?->addMetadata(['region' => 'eu-central']);
$context?->setErrorCode('PAYMENT_REQUIRED');
return $response;
});Reliability
Use a locked local buffer.
Configure a writable NDJSON buffer to keep normal requests away from network delivery. Transport failures are contained and never replace the customer response.
new Config(
// ...
bufferPath: __DIR__.'/../var/apirelio/events.ndjson',
batchSize: 500,
flushIntervalSeconds: 10,
)Privacy boundary
Operational metadata only.
Captured
Method, route pattern, status, duration, byte counts and bounded identity.
Excluded
Request and response bodies, query strings, cookies, credentials and exception messages.
Fail-safe
SDK or ingestion failures cannot change Slim's response or exception flow.