PHP Integration
ScryWatch accepts logs over HTTP — no PHP SDK required. Use curl, Guzzle, or any HTTP client to send events to the ingest endpoint.
What you’ll need
- A ScryWatch project API key (see API Keys & Settings)
- PHP 7.4+ (or any version that can make HTTP requests)
Endpoint
POST https://ingest.scrywatch.com/v1/ingest
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Step 1: Send a log event
<?php
function scrywatch_log(string $apiKey, string $level, string $message, array $metadata = []): void {
$payload = json_encode([
'events' => [[
'timestamp' => (int) (microtime(true) * 1000),
'level' => $level, // 'info' | 'warn' | 'error' | 'debug'
'type' => 'custom',
'message' => $message,
'service' => $_ENV['APP_SERVICE'] ?? 'php-app',
'environment' => $_ENV['APP_ENV'] ?? 'production',
'metadata' => $metadata ?: null,
]],
]);
$ch = curl_init('https://ingest.scrywatch.com/v1/ingest');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_TIMEOUT => 5,
]);
curl_exec($ch);
curl_close($ch);
}
// Usage
scrywatch_log('YOUR_API_KEY', 'info', 'User signed up', ['user_id' => '123']);
scrywatch_log('YOUR_API_KEY', 'error', 'Payment failed', ['order_id' => '456', 'reason' => 'card_declined']);
Step 2: Batch multiple events
Send up to 250 events in one request to reduce overhead:
<?php
function scrywatch_batch(string $apiKey, array $events): array {
$payload = json_encode(['events' => $events]);
$ch = curl_init('https://ingest.scrywatch.com/v1/ingest');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
],
CURLOPT_TIMEOUT => 10,
]);
$body = curl_exec($ch);
curl_close($ch);
return json_decode($body, true) ?? [];
// Returns: ['accepted_count' => N, 'rejected_count' => N, ...]
}
// Build and send a batch
$events = [];
foreach ($errors as $err) {
$events[] = [
'timestamp' => (int) (microtime(true) * 1000),
'level' => 'error',
'type' => 'custom',
'message' => $err->getMessage(),
'service' => 'php-app',
'environment' => 'production',
'metadata' => [
'file' => $err->getFile(),
'line' => $err->getLine(),
],
];
}
scrywatch_batch('YOUR_API_KEY', $events);
Step 3: Laravel — log channel integration
Add a custom log channel to config/logging.php:
'channels' => [
'scrywatch' => [
'driver' => 'monolog',
'handler' => \App\Logging\ScryWatchHandler::class,
'with' => [
'apiKey' => env('SCRYWATCH_API_KEY'),
],
],
],
Create app/Logging/ScryWatchHandler.php:
<?php
namespace App\Logging;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\LogRecord;
class ScryWatchHandler extends AbstractProcessingHandler
{
public function __construct(private string $apiKey, int $level = 0)
{
parent::__construct($level);
}
protected function write(LogRecord $record): void
{
scrywatch_log(
$this->apiKey,
strtolower($record->level->name),
$record->message,
$record->context
);
}
}
Set in .env:
SCRYWATCH_API_KEY=your_key_here
LOG_CHANNEL=scrywatch
Event fields reference
| Field | Type | Required | Description |
|---|---|---|---|
timestamp | number | ✅ | Unix milliseconds — use (int)(microtime(true) * 1000) |
level | string | ✅ | info | warn | error | debug |
type | string | ✅ | custom | crash | session | navigation | api_call |
message | string | ✅ | Log message |
service | string | — | Service name |
environment | string | — | e.g. production, staging |
user_id | string | — | User identifier |
session_id | string | — | Session identifier |
metadata | object | — | Any additional key/value pairs |
OpenTelemetry note
If you are already running an OpenTelemetry Collector, you can route traces to ScryWatch via the OTLP endpoint. For logs, use the HTTP ingest endpoint above — OTLP log ingestion is not yet supported.
See the OpenTelemetry guide for Collector pipeline configuration.