Documentation
Everything you need to integrate Tiny Owl, understand the API, and keep your applications observable.
Getting Started
Set up Tiny Owl in under 5 minutes. Install the SDK, create your first project, and start receiving events right away.
SDK Reference
Full reference for the @tiny-owl-kit/observability SDK. Covers initialisation options, severity levels, context payloads, and error handling.
Manual HMAC Integration
Integrate without the SDK using raw HTTP requests. Full code examples for cURL, Node.js, Python, PHP, Go, Ruby, Java, and .NET.
Security
HMAC-SHA256 signing, AES-256-GCM encryption, HTTP-only cookie authentication, and role-based access control explained.
Quick-start guide
From zero to your first logged event in under 5 minutes.
1. Install the SDK & set up credentials
# 1 — Install the SDK npm install @tiny-owl-kit/observability # 2 — Add your credentials to .env TINYOWL_API_KEY=tok_live_xxxxxxxxxxxx TINYOWL_PROJECT_SECRET=sec_xxxxxxxxxxxx
Find your API Key and Project Secret in Dashboard → Project → Settings → Security.
2. Initialise the client and log events
import { TinyOwl } from '@tiny-owl-kit/observability';
const logger = new TinyOwl({
apiKey: process.env.TINYOWL_API_KEY!,
projectSecret: process.env.TINYOWL_PROJECT_SECRET!,
autoTraceId: true, // auto-generates a stable trace ID per SDK instance
});
// All three log calls share the same traceId — filterable in the dashboard
await logger.log('User signed in', { severity: 'info', context: { userId: '123' } });
await logger.log('API limit at 95%',{ severity: 'warning', context: { used: 950, limit: 1000 } });
await logger.log('Payment failed', { severity: 'error', context: { orderId: 'ORD-42', reason: 'Card declined' } });
// withContext() creates a child logger bound to a specific traceId
const reqLogger = logger.withContext({ requestId: req.id });
await reqLogger.log('Request started', { severity: 'info', context: { path: '/api/checkout' } });
await reqLogger.log('Request complete',{ severity: 'info', context: { status: 200 } });
// ^ both events share the same traceId — click either one in the dashboard to filter the full trace3. Verify in your dashboard
Open your Tiny Owl dashboard, navigate to your project, and click Events. Your events appear within seconds. Filter by severity, search full-text, or export to CSV/JSON.
SDK Constructor Options
Pass these options when creating a new TinyOwl instance.
| Option | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Yes | Your project API key from the dashboard |
| projectSecret | string | Yes | Used to sign requests with HMAC-SHA256 |
| autoTraceId | boolean | No | Auto-generates a UUID trace ID per SDK instance. All log() calls share it (default: false) |
| defaultContext | object | No | Context fields merged into every log() call from this instance |
| baseUrl | string | No | Override for self-hosted instances |
| timeout | number | No | Request timeout in milliseconds (default: 5000) |
Manual HMAC Integration
Don't want to use the SDK? Call the ingest endpoint directly from any language using raw HTTP. Every request must be signed with HMAC-SHA256 using your Project Secret.
Ingest endpoint: POST https://api.tinyowl.dev/api/ingest
Request Structure
Required Headers
x-signatureHMAC-SHA256 hex digest of the signing payloadx-timestampISO 8601 UTC — must be within 60 seconds of server timex-nonce32-char random hex — prevents replay attacksRequest Body (JSON)
apiKeyYour project API key (required) — NOT included in the signaturemessageEvent message string (required)severity"info" | "warning" | "error" (required)contextAny additional JSON object (optional)traceIdCorrelation ID — optional, max 128 chars. Must be included in the signing payload if sent.Signing Rule
Compute HMAC-SHA256 over the compact JSON string {"message":…,"severity":…,"context":…,"traceId":…,"timestamp":…,"nonce":…} using your Project Secret. Include traceId only when you are sending it — omit it from both the payload and the body if unused. apiKey is intentionally excluded — this prevents a compromised signature from revealing your key.
Code Examples
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
NONCE=$(openssl rand -hex 16)
API_KEY="YOUR_API_KEY"
PROJECT_SECRET="YOUR_PROJECT_SECRET"
MESSAGE="User logged in successfully"
SEVERITY="info"
CONTEXT='{"userId":"12345","ip":"192.168.1.100"}'
TRACE_ID="my-job-run-001" # optional — omit to skip traceId
# Sign ONLY these fields — apiKey intentionally excluded.
# Include traceId only when you are sending it; key order must match exactly.
SIGNING_PAYLOAD='{"message":"'"$MESSAGE"'","severity":"'"$SEVERITY"'","context":'"$CONTEXT"',"traceId":"'"$TRACE_ID"'","timestamp":"'"$TIMESTAMP"'","nonce":"'"$NONCE"'"}'
SIGNATURE=$(echo -n "$SIGNING_PAYLOAD" | openssl dgst -sha256 -hmac "$PROJECT_SECRET" | cut -d' ' -f2)
# apiKey goes in the request body, not as a header
curl -X POST "https://api.tinyowl.dev/api/ingest" \
-H "Content-Type: application/json" \
-H "x-signature: $SIGNATURE" \
-H "x-timestamp: $TIMESTAMP" \
-H "x-nonce: $NONCE" \
-d '{"apiKey":"'"$API_KEY"'","message":"'"$MESSAGE"'","severity":"'"$SEVERITY"'","context":'"$CONTEXT"',"traceId":"'"$TRACE_ID"'"}'
# To skip traceId: remove TRACE_ID from both SIGNING_PAYLOAD and the -d bodySomething missing?
Our docs are always growing. Join our Discord if you can't find what you need.
Join Discord