Developer pages

Ingestion API

Public ingestion endpoints from the ingestion-server — auth, paths, and SDK usage notes.

Base URL

ContextTypical base
Productionhttps://ingest.humanbehavior.co
Local stackhttp://localhost:8000 (or your compose port)
Reverse proxyYour first-party prefix (see Reverse proxy)

The SDK sets ingestionUrl to this base and appends the paths below.

Authentication

Most ingestion POSTs from the browser SDK (ordinary fetch) send:

Authorization: Bearer <project_api_key>
Content-Type: application/json

sendBeacon cannot set headers, so some unload / presence paths (notably heartbeat, session-end, and beacon event batches) put apiKey in the JSON body instead. The server accepts either form.

Keys come from Settings → Environments. Invalid keys fail auth at the server; rotate invalidates old keys immediately.

Public endpoints (ingestion-server)

Registered in ingestion-server/src/index.ts:

MethodPathPurposePrimary SDK caller
POST/api/ingestion/initOptional / deprecated bootstrap (session + end user). Normal SDK startup does not call this — ids are local and users are created on first eventtestConnection() / legacy only
POST/api/ingestion/eventsReplay / rrweb chunks (+ event stream)Event flush / chunking
POST/api/ingestion/userIdentify / user upsertidentifyUser
POST/api/ingestion/user/authAuth-field-aware user upsertLow-level api.sendUserAuth (no public tracker.auth() helper in current tracker API)
POST/api/ingestion/customEventSingle analytics eventFallback / non-batch
POST/api/ingestion/customEvent/batchBatched analytics eventscustomEvent batcher
POST/api/ingestion/groupidentifyGroup identify (PostHog-style groups)Present on server; browser tracker usage not verified as a first-class public method in this pass
POST/api/ingestion/ip-infoGeoIP helper inputSDK geo pipeline when used
POST/api/ingestion/logsConsole log ingestConsole tracking
POST/api/ingestion/networkNetwork error ingestNetwork tracking
POST/api/ingestion/spans/batchTrace spansTracing module
POST/api/ingestion/errorsError reports → IssuesError capture
POST/api/ingestion/sourcemapsSource map uploadnpx @humanbehavior/wizard upload-sourcemaps
POST/api/ingestion/heartbeatLive presence ping~30s heartbeat
POST/api/ingestion/session-endUnload presence clearpagehide / unload
GET/healthComprehensive healthOps / load balancers
GET/health/simpleLightweight healthLoad balancers
GET/Simple healthRoot probe

Not public SDK surface

PathNote
POST /api/internal/scan-findingsSecret-guarded static-analysis ingest — not for browser SDKs

Practical constraints (from SDK)

TopicDetail
Chunk sizeReplay payloads split around 1MB encoded JSON
BatchingCustom events: 100ms / 50-event batch; replay flush ~3s (or 150ms when live viewer active)
OfflineFailed batches can persist to localStorage and drain later / on online
UnloadBeacon / keepalive used when fetch is unavailable or sticky-beacon mode engages
Monthly limit429 / monthlyLimitReached causes the SDK to stop sending quietly

Building a custom client

  1. Copy a successful browser request from DevTools as your template (headers + JSON shape).
  2. Always send a stable sessionId and endUserId consistent with your session model.
  3. Prefer the JS SDK in browsers — retry, redaction, and live-flush behavior are non-trivial to reimplement.
  4. Do not treat frontend /api/projects/... routes as a public ingest API; those require dashboard session auth.