Skip to Content
Timberlogs is in beta. Sign up at app.timberlogs.dev
API ReferenceLog Ingestion

Log Ingestion

Send logs to Timberlogs via the ingestion API.

Endpoint

POST /v1/logs

Base URL: https://timberlogs-ingest.enaboapps.workers.dev

Request

Headers

HeaderRequiredDescription
AuthorizationYesBearer <api-key> or Bearer <jwt>
Content-TypeYesapplication/json

Body

{ "logs": [ { "level": "info", "message": "User signed in", "source": "api-server", "environment": "production", "data": { "userId": "user_123" } } ] }

Log Entry Schema

FieldTypeRequiredDescription
levelstringYesLog level: debug, info, warn, error
messagestringYesLog message (1-10,000 characters)
sourcestringYesApplication/service name (1-100 characters)
environmentstringYesdevelopment, staging, or production
datasetstringNoDataset name for grouping (default: default)
versionstringNoApplication version
userIdstringNoUser identifier
sessionIdstringNoSession identifier
requestIdstringNoRequest identifier for correlation
dataobjectNoArbitrary JSON data
errorNamestringNoError class/name
errorStackstringNoError stack trace
tagsstring[]NoArray of tags (max 20 tags, 50 chars each)
timestampnumberNoUnix timestamp in milliseconds
flowIdstringNoFlow identifier for grouping related logs
stepIndexnumberNoStep index within a flow (0-1000)

Batch Limits

  • Minimum: 1 log per request
  • Maximum: 100 logs per request

Response

Success (200)

{ "success": true, "count": 5, "timestamp": 1704067200000 }
FieldTypeDescription
successbooleanAlways true on success
countnumberNumber of logs ingested
timestampnumberServer timestamp of ingestion

Error Responses

400 Bad Request - Invalid request body

{ "error": "Validation error", "issues": [ { "path": ["logs", 0, "level"], "message": "Invalid enum value" } ] }

401 Unauthorized - Invalid or missing API key

{ "error": "Invalid API key" }

429 Too Many Requests - Rate limit exceeded

{ "error": "Rate limit exceeded", "retryAfter": 60 }

Examples

Basic Log

curl -X POST https://timberlogs-ingest.enaboapps.workers.dev/v1/logs \ -H "Authorization: Bearer tb_live_xxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "logs": [{ "level": "info", "message": "Application started", "source": "my-app", "environment": "production" }] }'

Log with Data

curl -X POST https://timberlogs-ingest.enaboapps.workers.dev/v1/logs \ -H "Authorization: Bearer tb_live_xxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "logs": [{ "level": "info", "message": "User signed in", "source": "auth-service", "environment": "production", "userId": "user_123", "sessionId": "sess_abc", "data": { "method": "oauth", "provider": "google" }, "tags": ["auth", "login"] }] }'

Error Log

curl -X POST https://timberlogs-ingest.enaboapps.workers.dev/v1/logs \ -H "Authorization: Bearer tb_live_xxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "logs": [{ "level": "error", "message": "Database connection failed", "source": "api-server", "environment": "production", "errorName": "ConnectionError", "errorStack": "ConnectionError: ECONNREFUSED\n at connect (/app/db.js:42:11)\n at ...", "tags": ["database", "critical"] }] }'

Batch Logs

curl -X POST https://timberlogs-ingest.enaboapps.workers.dev/v1/logs \ -H "Authorization: Bearer tb_live_xxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "logs": [ { "level": "info", "message": "Request received", "source": "api", "environment": "production", "requestId": "req_xyz" }, { "level": "debug", "message": "Processing request", "source": "api", "environment": "production", "requestId": "req_xyz" }, { "level": "info", "message": "Request completed", "source": "api", "environment": "production", "requestId": "req_xyz", "data": {"duration": 145} } ] }'

Flow Tracking

curl -X POST https://timberlogs-ingest.enaboapps.workers.dev/v1/logs \ -H "Authorization: Bearer tb_live_xxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "logs": [ { "level": "info", "message": "Checkout started", "source": "checkout-service", "environment": "production", "flowId": "checkout-a1b2c3d4", "stepIndex": 0 }, { "level": "info", "message": "Payment processed", "source": "checkout-service", "environment": "production", "flowId": "checkout-a1b2c3d4", "stepIndex": 1 } ] }'

Rate Limits

Rate limits depend on your plan:

PlanRequests/minuteLogs/month
Free6010,000
Pro6001,000,000
EnterpriseUnlimitedCustom

When rate limited, you’ll receive a 429 response with a retryAfter value indicating when to retry.

Best Practices

  1. Batch logs - Send multiple logs per request to reduce overhead
  2. Use the SDK - The TypeScript SDK handles batching and retries automatically
  3. Include context - Add userId, sessionId, and requestId for correlation
  4. Use structured data - Put details in data rather than interpolating into message
  5. Tag appropriately - Use consistent tags for filtering
  6. Handle errors - Implement retry logic with exponential backoff
Last updated on