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!,
});

// Info — regular operational events
await logger.info('User signed in', { userId: '123' });

// Warning — unusual events worth watching
await logger.warning('API limit at 95%', { used: 950, limit: 1000 });

// Error — failures that need attention
await logger.error('Payment failed', {
  orderId: 'ORD-42',
  reason: 'Card declined',
});

3. 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.

OptionTypeRequiredDescription
apiKeystringYesYour project API key from the dashboard
projectSecretstringYesUsed to sign requests with HMAC-SHA256
baseUrlstringNoOverride for self-hosted instances
timeoutnumberNoRequest 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 payload
x-timestampISO 8601 UTC — must be within 60 seconds of server time
x-nonce32-char random hex — prevents replay attacks

Request Body (JSON)

apiKeyYour project API key (required) — NOT included in the signature
messageEvent message string (required)
severity"info" | "warning" | "error" (required)
contextAny additional JSON object (optional)

Signing Rule

Compute HMAC-SHA256 over the compact JSON string {"message":…,"severity":…,"context":…,"timestamp":…,"nonce":…} using your Project Secret. 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"}'

# Sign ONLY these fields — apiKey is intentionally excluded from the signature.
# Key order must match exactly: message, severity, context, timestamp, nonce
SIGNING_PAYLOAD='{"message":"'"$MESSAGE"'","severity":"'"$SEVERITY"'","context":'"$CONTEXT"',"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"'}'

Something missing?

Our docs are always growing. Join our Discord if you can't find what you need.

Join Discord