Ingest API#

LogTap's client SDKs (Browser/Node, Go, Flutter) all use the HTTP endpoints and JSON data model below for "log" and "event/tracking" reporting. Languages without an SDK can call the HTTP API directly.

Conventions#

  • Base URL: your LogTap gateway address, e.g. http://localhost:8080
  • Project ID: visible on the project page in the console; used as a path parameter /api/:projectId/...
  • Auth (enforced once AUTH_SECRET is set): reporting must carry a project key — any of:
    • X-Project-Key: pk_...
    • Authorization: Bearer pk_...
    • the Sentry SDK's X-Sentry-Auth (sentry_key=...)
  • Batching: the same endpoint accepts a single object or a JSON array
  • Compression: Content-Encoding: gzip is supported
  • Success response: 202 Accepted (the gateway only validates and enqueues; consumers write to the database asynchronously)

1. Structured logs#

Endpoint: POST /api/:projectId/logs/

json
{
  "level": "info",
  "message": "hello",
  "timestamp": "2025-01-01T00:00:00Z",
  "device_id": "d1",
  "trace_id": "t1",
  "span_id": "s1",
  "fields": { "k": "v" },
  "tags": { "env": "prod" },
  "user": { "id": "u1" },
  "contexts": { "app": { "version": "1.2.3" } }
}

Field notes:

  • message: required
  • level: suggested values debug / info / warn / error / fatal; defaults to info server-side when empty
  • timestamp: RFC3339; the server fills in the current UTC time when omitted
  • user.id: used for unique-user metrics (DAU/MAU, funnels); falls back to device_id when absent
  • fields: custom structured fields — put business dimensions here
  • tags / contexts: labels and app context stored with the log and filterable in the console

Batch example (same endpoint, JSON array):

json
[
  { "level": "info", "message": "hello-1", "user": { "id": "u1" }, "fields": { "k": "v1" } },
  { "level": "info", "message": "hello-2", "user": { "id": "u1" }, "fields": { "k": "v2" } }
]

2. Events / tracking#

Endpoint: POST /api/:projectId/track/

json
{
  "name": "signup",
  "timestamp": "2025-01-01T00:00:00Z",
  "user": { "id": "u1" },
  "device_id": "d1",
  "properties": { "plan": "pro", "ab": "b" }
}
  • name: event name, required
  • properties: event properties, used for funnel filtering and property breakdowns

Storage rule: events are written to the logs table (level = "event", message = name, fields = properties), so event analytics only count level="event" rows and stay unpolluted by regular logs.

Batch example:

json
[
  { "name": "signup", "user": { "id": "u1" }, "properties": { "plan": "pro" } },
  { "name": "purchase", "user": { "id": "u1" }, "properties": { "sku": "s1" } }
]

3. Search and queries#

  • Log/event queries, keyword full-text search, time-series aggregation, funnels, and retention are all done through the console
  • Sentry error reporting uses its own protocol — see Sentry compatibility

Recommendations#

  • Keep "logs" and "tracking events" separate: logs go to /logs/, events to /track/
  • For high-volume scenarios prefer batch arrays + gzip to cut request counts and network overhead
  • Put business dimensions into fields / properties — console filtering and funnels are built on structured fields