Skip to content

API Endpoints ​

This document provides detailed information about all available Logstyx API endpoints.

Base URL ​

https://your-domain.com/api

For local development:

http://localhost:5000/api

POST /v1/logs ​

Submit log entries to your Logstyx project. This is the primary endpoint for sending application logs.

Endpoint ​

POST /v1/logs

Rate Limits ​

  • Rate: 20 requests per second per IP address
  • Burst: 50 requests can burst above the rate limit
  • Response on limit exceeded: 503 Service Unavailable or 429 Too Many Requests

Headers ​

Required Headers ​

Content-Type: application/json

Optional Headers (Server Clients Only) ​

timestamp: <unix_timestamp_in_milliseconds>
signature: <hmac_sha256_signature>

These headers are required for server-side authentication. See Authentication for details.

Browser Headers (Automatic) ​

Origin: <browser_origin>

This header is automatically sent by browsers and used for authentication.

Request Body ​

Required Fields ​

FieldTypeDescription
levelstringLog level. Must be one of: info, warning, error, critical
projectIdstringYour Logstyx project ID
dataobjectThe actual log data and message

Optional Fields ​

FieldTypeDescriptionDefault
deviceobjectIdentifier for the device/server sending the log{}
contextobjectAdditional contextual information{}
appidstringApplication ID (required for mobile clients)null

Request Body Schema ​

json
{
  "level": "info|warning|error|critical",
  "projectId": "string",
  "device": {
        "type": "iPhone 15 Pro",
        "origin": null,
        "os": null,
        "platform": null,
        "browser": null,
        "screen": null
    },
  "context": {
    "key": "value"
  },
  "data": {
    "message": "string",
    "additional": "fields"
  },
  "appid": "string (mobile only)"
}

Response ​

All requests return a 200 OK status regardless of success or failure. The log is queued for asynchronous processing.

json
{
  "status": "queued"
}

Log Levels ​

Logstyx supports four log levels, ordered by severity:

LevelDescriptionUse Case
infoInformational messagesGeneral application events, user actions
warningWarning messagesPotential issues that don't stop execution
errorError messagesRuntime errors, failed operations
criticalCritical messagesSystem failures, data corruption, security breaches

Examples ​

Example 1: Basic Info Log (Browser) ​

bash
curl -X POST https://your-domain.com/api/v1/logs \
  -H "Content-Type: application/json" \
  -H "Origin: https://yourapp.com" \
  -d '{
    "level": "info",
    "projectId": "proj_abc123xyz",
    "data": {
      "message": "User completed onboarding",
      "userId": "user_12345",
      "completedSteps": 5
    }
  }'

Example 2: Error Log with Context (Browser) ​

bash
curl -X POST https://your-domain.com/api/v1/logs \
  -H "Content-Type: application/json" \
  -H "Origin: https://yourapp.com" \
  -d '{
    "level": "error",
    "projectId": "proj_abc123xyz",
    "device": {
        "type": "browser",
        "origin": null,
        "os": "Windows",
        "platform": null,
        "browser": "Chrome",
        "screen": "1900x1600"
    },
    "context": {
      "userId": "user_12345",
      "sessionId": "sess_xyz789",
      "route": "/checkout"
    },
    "data": {
      "message": "Payment processing failed",
      "errorCode": "PAYMENT_DECLINED",
      "amount": 99.99,
      "currency": "USD",
      "paymentMethod": "credit_card"
    }
  }'

Example 3: Mobile App Log ​

bash
curl -X POST https://your-domain.com/api/v1/logs \
  -H "Content-Type: application/json" \
  -d '{
    "level": "warning",
    "projectId": "proj_abc123xyz",
    "appid": "com.yourcompany.app.ios",
    "device": {
        "type": "iPhone 15 Pro",
        "origin": null,
        "os": null,
        "platform": null,
        "browser": null,
        "screen": null
    },
    "context": {
      "userId": "user_12345",
      "appVersion": "2.5.1"
    },
    "data": {
      "message": "Network request timeout",
      "endpoint": "/api/v1/products",
      "duration": 30000
    }
  }'

Example 4: Server Log with Signature ​

javascript
const crypto = require('crypto');
const axios = require('axios');

async function sendServerLog() {
  const projectId = 'proj_abc123xyz';
  const projectSecret = 'your_secret_key';
  const timestamp = Date.now();
  
  const body = {
    level: 'critical',
    projectId: projectId,
    device: {
        "type": "node",
        "origin": null,
        "os": "linux",
        "platform": null,
        "browser": null,
        "screen": null
    },
    context: {
      service: 'database',
      region: 'us-east-1'
    },
    data: {
      message: 'Database connection pool exhausted',
      activeConnections: 100,
      maxConnections: 100,
      queuedRequests: 47
    }
  };
  
  // Generate signature
  const payload = {
    level: body.level,
    projectId: body.projectId,
    device: body.device,
    context: body.context,
    data: body.data
  };
  
  const params = JSON.stringify(payload);
  const hashString = projectId + params + Math.floor(timestamp);
  const signature = crypto
    .createHmac('SHA256', projectSecret)
    .update(hashString)
    .digest('hex')
    .toUpperCase();
  
  // Send request
  const response = await axios.post(
    'https://your-domain.com/api/v1/logs',
    body,
    {
      headers: {
        'Content-Type': 'application/json',
        'timestamp': timestamp.toString(),
        'signature': signature
      }
    }
  );
  
  return response.data;
}

Example 5: Python Server Client ​

python
import hmac
import hashlib
import json
import time
import requests

def send_log(level, message, additional_data=None):
    project_id = 'proj_abc123xyz'
    project_secret = 'your_secret_key'
    timestamp = int(time.time() * 1000)
    
    body = {
        'level': level,
        'projectId': project_id,
        'device': {
            "type": "python",
            "origin": null,
            "os": "linux",
            "platform": null,
            "browser": null,
            "screen": null
        },
        'context': {
            'environment': 'production',
            'service': 'data-processor'
        },
        'data': {
            'message': message,
            **(additional_data or {})
        }
    }
    
    # Generate signature
    payload = {
        'level': body['level'],
        'projectId': body['projectId'],
        'device': body['device'],
        'context': body['context'],
        'data': body['data']
    }
    
    params = json.dumps(payload, separators=(',', ':'))
    hash_string = f"{project_id}{params}{int(timestamp)}"
    signature = hmac.new(
        project_secret.encode('utf-8'),
        hash_string.encode('utf-8'),
        hashlib.sha256
    ).hexdigest().upper()
    
    # Send request
    response = requests.post(
        'https://your-domain.com/api/v1/logs',
        json=body,
        headers={
            'Content-Type': 'application/json',
            'timestamp': str(timestamp),
            'signature': signature
        }
    )
    
    return response.json()

# Usage
send_log('error', 'Failed to process batch', {
    'batchId': 'batch_789',
    'recordsProcessed': 1543,
    'recordsFailed': 12,
    'errorRate': 0.0078
})

Example 6: Go Server Client ​

go
package main

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"time"
)

type LogData struct {
	Message string                 `json:"message"`
	Extra   map[string]interface{} `json:"extra"` // Standard JSON nesting
}

type Device struct {
	Type     string `json:"type"`
	Origin   string `json:"origin"`
	Os       string `json:"os"`
	Platform string `json:"platform"`
}

type LogRequest struct {
	Level     string                 `json:"level"`
	ProjectID string                 `json:"projectId"`
	Device    Device                 `json:"device"` // Changed from "data" to "device" to avoid conflict
	Context   map[string]interface{} `json:"context"`
	Data      LogData                `json:"data"`
}

func sendLog(projectID, projectSecret, level string, device Device, message string, context, extra map[string]interface{}) error {
	timestamp := time.Now().UnixNano() / int64(time.Millisecond)

	req := LogRequest{
		Level:     level,
		ProjectID: projectID,
		Device:    device,
		Context:   context,
		Data: LogData{
			Message: message,
			Extra:   extra,
		},
	}

	// Generate signature using the request struct directly to ensure consistency
	payloadJSON, _ := json.Marshal(req)
	hashString := fmt.Sprintf("%s%s%d", projectID, string(payloadJSON), timestamp)

	h := hmac.New(sha256.New, []byte(projectSecret))
	h.Write([]byte(hashString))
	signature := strings.ToUpper(hex.EncodeToString(h.Sum(nil)))

	// Send request
	httpReq, err := http.NewRequest("POST", "https://your-domain.com/api/v1/logs", bytes.NewBuffer(payloadJSON))
	if err != nil {
		return err
	}

	httpReq.Header.Set("Content-Type", "application/json")
	httpReq.Header.Set("timestamp", fmt.Sprintf("%d", timestamp))
	httpReq.Header.Set("signature", signature)

	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Do(httpReq)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	fmt.Printf("Log sent! Status: %s\n", resp.Status)
	return nil
}

func main() {
	context := map[string]interface{}{
		"service": "auth",
		"region":  "us-west-2",
	}

	extra := map[string]interface{}{
		"userId":     "user_12345",
		"attemptNum": 3,
	}

	// Use the struct instead of a map for type safety
	device := Device{
		Type: "go",
	}

	err := sendLog(
		"proj_abc123xyz",
		"your_secret_key",
		"warning",
		device,
		"Multiple failed login attempts",
		context,
		extra,
	)
	if err != nil {
		fmt.Println("Error:", err)
	}
}

Example 7: Batch Logging ​

While the API doesn't support batch endpoints, you can implement client-side batching:

javascript
class LogBatcher {
  constructor(projectId, projectSecret, batchSize = 10, flushInterval = 5000) {
    this.projectId = projectId;
    this.projectSecret = projectSecret;
    this.batchSize = batchSize;
    this.buffer = [];
    
    // Flush periodically
    setInterval(() => this.flush(), flushInterval);
  }
  
  add(level, data, context = {}, device = 'server') {
    this.buffer.push({ level, data, context, device });
    
    if (this.buffer.length >= this.batchSize) {
      this.flush();
    }
  }
  
  async flush() {
    if (this.buffer.length === 0) return;
    
    const logs = [...this.buffer];
    this.buffer = [];
    
    // Send all logs concurrently
    await Promise.all(
      logs.map(log => this.sendLog(log))
    );
  }
  
  async sendLog({ level, data, context, device }) {
    // Implementation from Example 4
    // ... signature generation and request ...
  }
}

// Usage
const batcher = new LogBatcher('proj_abc123xyz', 'your_secret_key');

// Logs are batched and sent automatically
batcher.add('info', { message: 'User login' });
batcher.add('info', { message: 'Page view' });
batcher.add('error', { message: 'API error' });

Field Specifications ​

level Field ​

Can be one of these strings, but you can create your own

  • info
  • warning
  • error
  • critical

projectId Field ​

  • Type: String
  • Obtained from: Logstyx dashboard after project creation

device Field ​

  • Type: Object
  • Optional: Yes

context Field ​

  • Type: Object
  • Optional: Yes
  • Purpose: Store contextual metadata that helps filter and search logs
  • Common fields:
    • userId: User identifier
    • sessionId: Session identifier
    • requestId: Request trace ID
    • environment: production, staging, development
    • service: Service name in microservices architecture
    • version: Application version

data Field ​

  • Type: Object
  • Required: Yes
  • Purpose: Store the actual log content
  • Common fields:
    • title: Human-readable log title (recommended)
    • message: Human-readable log message (recommended)
    • Any additional structured data relevant to the log

appid Field ​

  • Type: String
  • Required for: Mobile clients only
  • Format: Reverse domain notation (e.g., com.company.app.platform)
  • Purpose: Mobile client authentication

Best Practices ​

1. Structured Logging ​

Use consistent field names across your application:

json
{
  "level": "error",
  "projectId": "proj_abc123xyz",
  "context": {
    "userId": "user_12345",
    "requestId": "req_xyz789"
  },
  "data": {
    "message": "Database query failed",
    "operation": "SELECT",
    "table": "users",
    "duration": 5234,
    "error": "Connection timeout"
  }
}

2. Include Relevant Context ​

Always include context that helps debugging:

json
{
  "context": {
    "environment": "production",
    "service": "payment-service",
    "version": "2.5.1",
    "region": "us-east-1",
    "userId": "user_12345",
    "sessionId": "sess_abc123"
  }
}

3. Use Appropriate Log Levels ​

  • info: Normal operations, user actions
  • warning: Deprecated features, non-critical issues
  • error: Failed operations that are handled
  • critical: System failures requiring immediate attention

4. Avoid Logging Sensitive Data ​

Never log:

  • Passwords or API keys
  • Credit card numbers
  • Personal identification numbers
  • Authentication tokens
  • Social security numbers

5. Implement Client-Side Batching ​

Reduce network overhead by batching logs when possible (see Example 7).

6. Handle Rate Limits ​

Implement exponential backoff when rate limits are hit:

javascript
async function sendLogWithRetry(logData, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      await sendLog(logData);
      return;
    } catch (error) {
      if (error.response?.status === 429 || error.response?.status === 503) {
        const delay = Math.pow(2, i) * 1000; // Exponential backoff
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
}

Troubleshooting ​

Issue: Logs not appearing in dashboard ​

Possible causes:

  1. Authentication failure (wrong project ID, invalid origin/appid, incorrect signature)
  2. Rate limiting
  3. Invalid request format

Solutions:

  1. Verify project ID and authentication credentials
  2. Check authentication method matches client type
  3. Ensure request body follows the correct schema
  4. Check for rate limit responses

Issue: 429 or 503 responses ​

Cause: Rate limit exceeded (more than 20 requests/second per IP)

Solutions:

  1. Implement client-side batching
  2. Add exponential backoff retry logic
  3. Reduce logging frequency
  4. Use log sampling for high-volume events

Issue: Signature validation fails (server clients) ​

Common mistakes:

  1. Wrong field order in payload
  2. Signature not in uppercase
  3. Timestamp not converted to integer
  4. Extra spaces in JSON serialization
  5. Using wrong project secret

Solution: Carefully review the signature generation algorithm in Authentication

Released under the MIT License.