Developer Documentation

Build with Logsync

Add tamper-proof audit logging to your application in minutes. Complete API documentation, SDKs for 7 languages, and comprehensive guides.

Overview

Logsync provides a simple, powerful API for adding tamper-proof audit logging to any application. Every event you log is cryptographically linked to the previous event using SHA-256 hashes, creating an immutable chain that makes tampering immediately detectable.

Fast Integration

Integrate in under 5 minutes with our SDKs. One API call to log events.

Tamper-Proof

SHA-256 hash chain ensures data integrity. Any modification is detectable.

Compliance Ready

Meet SOC 2, HIPAA, GDPR, and PCI DSS audit logging requirements.

How It Works

  1. 1
    Create a Project - Sign up and create a project in the dashboard to get your API key.
  2. 2
    Install an SDK - Choose from Node.js, Python, Go, Java, .NET, PHP, or Ruby.
  3. 3
    Log Events - Call the log method whenever a significant action occurs in your app. Events are instantly accepted and processed asynchronously.
  4. 4
    Search & Verify - Use the dashboard to search events and verify chain integrity.

High-Performance Async Processing

Events are immediately accepted and queued for processing (~10-20ms response time). Background workers process events within seconds, maintaining hash chain integrity. This architecture supports 10,000+ events/second ingestion.

Quick Start

Get up and running in under 5 minutes. Here's a complete example:

1

Install the SDK

Run this command:

npm install logsync
2

Initialize the Client

Initialize the SDK client:

import { Logsync } from 'logsync';

// Initialize the client with your API key
const audit = new Logsync('ls_your_api_key');

// Or with custom options
const audit = new Logsync('ls_your_api_key', {
  baseUrl: 'https://logsync.dev', // Custom endpoint (optional)
  timeout: 30000,                      // Request timeout in ms
  retries: 3,                          // Auto-retry failed requests
});
3

Log Events

Log your first events:

// Basic event logging
await audit.log({
  actorId: 'user_123',
  action: 'document.created',
  resource: 'doc_456',
});

// Full event with all fields
await audit.log({
  actorId: 'user_123',           // Required: who performed the action
  actorType: 'user',             // Optional: type of actor
  action: 'document.shared',     // Required: what action was performed
  resource: 'doc_456',           // Required: what resource was affected
  resourceType: 'document',      // Optional: type of resource
  timestamp: new Date(),         // Optional: when it happened (defaults to now)
  ip: '192.168.1.1',            // Optional: client IP address
  metadata: {                    // Optional: additional context
    sharedWith: ['team@company.com'],
    permission: 'view',
    expiresAt: '2024-12-31T23:59:59Z'
  }
});

// Response (202 Accepted)
{
  success: true,
  status: 'accepted',
  message: 'Event accepted for processing',
  queuePosition: 42
}
// Events appear in queries within ~5 seconds

Authentication

All API requests require authentication using an API key. You can create API keys in the dashboard after signing up.

Using the API Key

Include your API key in the X-API-Key header:

curl -X POST https://logsync.dev/api/ingest \
  -H "Content-Type: application/json" \
  -H "X-API-Key: ls_your_api_key" \
  -d '{"actorId": "user_123", "action": "login", "resource": "session_456"}'

Keep Your API Key Secret

Never expose your API key in client-side code, public repositories, or logs. Use environment variables and server-side code to make API calls.

Event Schema

Each audit event captures who did what, to what, and when. Here's the complete schema:

FieldTypeRequiredDescription
actorIdstringRequiredIdentifier of who performed the action (user ID, service name, etc.)
actionstringRequiredThe action that was performed (e.g., "document.created", "user.login")
resourcestringRequiredIdentifier of the resource being acted upon
actorTypestringOptionalType of actor (e.g., "user", "admin", "system", "api")
resourceTypestringOptionalType of resource (e.g., "document", "user", "order")
timestampISO 8601OptionalWhen the event occurred. Defaults to current time if not provided.
ipstringOptionalClient IP address. Auto-detected from request headers if not provided.
metadataobjectOptionalAdditional context as a JSON object (max 64KB)

Naming Conventions

Action Names

Use dot notation for hierarchical actions:

  • user.created
  • document.shared
  • order.payment.completed
  • settings.security.2fa.enabled

Actor Types

Common actor type values:

  • user - Regular user
  • admin - Administrator
  • system - Automated process
  • api - External API client

SDKs

Official SDKs are available for all major programming languages. Each SDK includes automatic retries, type definitions, and idiomatic patterns for the language.

REST API

The REST API can be used directly from any language or HTTP client. Base URL: https://logsync.dev

POST/api/ingest— Log an audit event

Request Headers

Content-Type: application/json
X-API-Key: ls_your_api_key

Request Body

{
  "actorId": "user_123",
  "actorType": "user",
  "action": "document.created",
  "resource": "doc_456",
  "resourceType": "document",
  "timestamp": "2024-01-15T10:30:00Z",
  "ip": "192.168.1.1",
  "metadata": {
    "title": "Q4 Report",
    "size": 1024000
  }
}

Response (202 Accepted)

{
  "success": true,
  "status": "accepted",
  "message": "Event accepted for processing",
  "queuePosition": 42
}

Events are processed asynchronously and appear in queries within ~5 seconds.

Response Headers

X-Event-Status: accepted
X-Queue-Position: 42
X-Monthly-Limit: 25000
X-Monthly-Used: 1250
X-Monthly-Queued: 15
X-Monthly-Usage-Percent: 5
GET/api/events— Query events with pagination

Query Parameters

ParameterTypeDescription
limitnumberMax events to return (1-1000, default: 100)
cursorstringPagination cursor from previous response
actorIdstringFilter by actor ID (partial match)
actionstringFilter by action (partial match)
resourcestringFilter by resource (partial match)
startDateISO 8601Filter events after this date
endDateISO 8601Filter events before this date
orderstring"asc" or "desc" (default: "desc")

Example Request

curl -X GET "https://logsync.dev/api/events?limit=50&actorId=user_123" \
  -H "X-API-Key: ls_your_api_key"

Response (200 OK)

{
  "success": true,
  "events": [
    {
      "id": "12345",
      "actorId": "user_123",
      "action": "document.created",
      "resource": "doc_456",
      "timestamp": "2024-01-15T10:30:00Z",
      "hash": "a1b2c3d4...",
      "prevHash": "x9y8z7..."
    }
  ],
  "pagination": {
    "limit": 50,
    "hasMore": true,
    "nextCursor": "12344",
    "total": 1250,
    "order": "desc"
  }
}
GET/api/events/:id— Get a single event by ID

Example Request

curl -X GET "https://logsync.dev/api/events/12345" \
  -H "X-API-Key: ls_your_api_key"

Response (200 OK)

{
  "success": true,
  "event": {
    "id": "12345",
    "actorId": "user_123",
    "action": "document.created",
    "resource": "doc_456",
    "timestamp": "2024-01-15T10:30:00Z",
    "hash": "a1b2c3d4...",
    "prevHash": "x9y8z7..."
  },
  "chain": {
    "previous": { "id": "12344", "hash": "x9y8z7...", "timestamp": "..." },
    "next": { "id": "12346", "hash": "e5f6g7...", "timestamp": "..." },
    "isChainStart": false,
    "isChainEnd": false
  }
}

The chain object provides context for integrity verification.

POST/api/events/verify— Verify integrity of event chain

Request Body

{
  "eventId": "12345",     // Verify single event (optional)
  "startId": "100",       // Verify range start (optional)
  "endId": "200",         // Verify range end (optional)
  "limit": 1000           // Max events to verify (default: 1000)
}

If no parameters provided, verifies the most recent 1000 events.

Example Request

curl -X POST "https://logsync.dev/api/events/verify" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: ls_your_api_key" \
  -d '{"limit": 1000}'

Response (200 OK)

{
  "success": true,
  "valid": true,
  "verified": 1000,
  "chainIntact": true,
  "issues": [],
  "range": {
    "start": { "id": "1", "timestamp": "...", "hash": "..." },
    "end": { "id": "1000", "timestamp": "...", "hash": "..." }
  },
  "summary": "Successfully verified 1000 events. Hash chain is intact."
}

Response with Issues

{
  "success": true,
  "valid": false,
  "verified": 500,
  "chainIntact": false,
  "issues": [
    {
      "eventId": "123",
      "type": "hash_mismatch",
      "message": "Event 123 hash does not match. Data may have been tampered.",
      "expected": "a1b2c3...",
      "actual": "x9y8z7..."
    }
  ],
  "summary": "Found 1 integrity issue(s) in 500 events."
}

Issue types: hash_mismatch, chain_break, missing_link

Cryptographic Hash Chain

Every event in Logsync is cryptographically linked to form a tamper-evident chain. This ensures that any modification to historical events is immediately detectable.

How It Works

1

Event Hashing

Each event's content is hashed using SHA-256, including: actorId, action, resource, timestamp, metadata, and the previous event's hash.

2

Chain Linking

By including the previous hash, each event is cryptographically linked to all events before it, forming an unbreakable chain.

3

Tamper Detection

If any event is modified, its hash changes, breaking the link to the next event. Verification instantly detects the discrepancy.

Chain Structure

Event 1
user.login
prevHash: null
hash: a1b2c3...
Event 2
doc.created
prevHash: a1b2c3...
hash: d4e5f6...
Event 3
doc.shared
prevHash: d4e5f6...
hash: g7h8i9...
...

Each event contains the hash of the previous event, creating an unbreakable chain back to the first event.

Rate Limits

Rate limits are applied per API key to ensure fair usage and system stability. Higher plans include increased rate limits. With our async processing, you can burst at high rates while events are queued and processed in the background.

PlanRequests/MinuteBurst Limit
Free100/min10/sec
Starter500/min50/sec
Growth2,000/min200/sec
Pro10,000/min1,000/sec

Rate Limit Headers

Every response includes headers to help you track your rate limit status:

X-RateLimit-Limit: 1000        # Your plan's limit
X-RateLimit-Remaining: 950     # Requests remaining
X-RateLimit-Reset: 1705312800  # Unix timestamp when limit resets

Error Handling

The API uses conventional HTTP status codes to indicate success or failure. Error responses include a message explaining what went wrong.

CodeNameDescription
202AcceptedEvent accepted for async processing (success)
400Bad RequestInvalid request body or missing required fields
401UnauthorizedMissing or invalid API key
402Payment RequiredMonthly event limit exceeded, upgrade required
403ForbiddenAPI key does not have access to this resource
404Not FoundResource not found
429Too Many RequestsRate limit exceeded
500Internal Server ErrorSomething went wrong on our end
503Service UnavailableService temporarily unavailable, retry later

Error Response Format

{
  "statusCode": 400,
  "message": "actorId is required and must be a string"
}

Best Practices

Log Meaningful Events

Focus on security-relevant and compliance-important actions: authentication, authorization changes, data access, configuration changes, and administrative actions.

Use Consistent Naming

Establish naming conventions for actions (e.g., resource.verb format) and stick to them. This makes searching and filtering much easier.

Include Relevant Metadata

Add context that will be useful during investigations: IP addresses, user agents, affected field names, before/after values for changes.

Don't Log Sensitive Data

Never include passwords, API keys, credit card numbers, or PII in metadata. Log references (IDs) instead of actual sensitive values.

Handle Failures Gracefully

Our SDKs retry automatically, but always handle logging failures gracefully. Audit logging should never break your application's core functionality.

Understand Async Processing

Events are accepted immediately (202 response) and processed within seconds. If you need to query recently logged events, allow a few seconds for processing to complete.

Verify Integrity Regularly

Use the dashboard or API to periodically verify your audit chain integrity. This proves your logs haven't been tampered with and is often required for compliance.

Frequently Asked Questions

How do I know when my event is processed?

When you log an event, you receive a 202 Accepted response with a queuePosition. The event is then processed asynchronously.

Options to know when processing is complete:

  • Query after delay: Wait ~5 seconds, then query GET /api/events to find your event
  • Check by metadata: Include a unique requestId in metadata, then query for it
  • Dashboard: Events appear in the dashboard automatically once processed

Coming soon: Webhook notifications for event processing completion. if you need this feature urgently.

Can I query events immediately after logging?

Short answer: No, there's a brief delay (~5 seconds) between logging and queryability.

Why? Logsync uses asynchronous processing to achieve high throughput (10,000+ events/second). Events are queued immediately (your 202 Accepted response) and batch-processed every 5 seconds for efficiency.

Timeline:

T+0ms: Logged
T+0-5s: Queued
T+5s: Queryable

Pro tip: If you need to show a "logged" confirmation in your UI, trust the 202 Accepted response. For audit/compliance purposes, the slight delay doesn't matter.

What's the SLA for processing time?
MetricTargetNotes
Ingest response time< 50msTime to receive 202 Accepted
Processing latency~5 secondsTime until queryable
Max processing latency< 30 seconds99th percentile
Queue reliability99.9%Events accepted are guaranteed processed

What if processing fails? Events that fail processing are moved to a Dead Letter Queue (DLQ) and can be manually retried via the admin dashboard. You'll never lose an accepted event.

Enterprise SLA: Pro plans include SLA guarantees with credits. View plans

Is the hash chain maintained with async processing?

Yes, absolutely. Each project has its own dedicated queue, and events are processed in strict FIFO (First-In-First-Out) order.

How it works:

  1. Your event is added to your project's queue
  2. Worker acquires a lock on your project's queue
  3. Events are processed sequentially, computing each hash with the previous event's hash
  4. Entire batch is written atomically to the database

This guarantees the same hash chain integrity as synchronous processing, but with 100x better throughput.

What happens if the server is down when I log an event?

Our SDKs automatically retry failed requests with exponential backoff:

// Retry timeline (default 3 retries)
Attempt 1: Immediate
Attempt 2: +100ms (with jitter)
Attempt 3: +200ms (with jitter)
Attempt 4: +400ms (with jitter)

For extended outages, you should implement local buffering in your application to queue events and replay them when the service recovers.

Best practice: Always handle the SDK's failure response gracefully. Audit logging should never crash your main application.

Ready to Get Started?

Create a free account to get your API key and start logging tamper-proof audit events in minutes.