OpenAPI 3.1 spec
The full machine-readable spec is at https://api.openanalyticsapi.com/openapi.json. Import it into Postman, Insomnia, Bruno, or your IDE's HTTP client.
Three kinds of endpoints
-
Public collect endpoint —
POST /collectonhttps://api.openanalyticsapi.com. Called by the browser snippet and SDKs. No Bearer token. Auth is implicit via the publicsite_id; abuse protection is rate-limited per IP and per site. -
Server-side events —
POST /v1/projects/{id}/events. Use a privateoa_live_*API key in theAuthorization: Bearer …header. Backend only — never embed in frontend code. -
Management & query API — everything else under
/v1/projects(list projects, query pageviews, sessions, realtime, etc.). Requires the sameoa_live_*key.
About the public collect endpoint. Public browser collection endpoints are intentionally silent and return 204 No Content even when an event is ignored — that includes unknown site_id, missing fields, malformed JSON, and bot User-Agents. This prevents probing site_id existence or schema rules from the browser. For strict validation, use the Verify Installation screen in the console (which reads from Redis + ClickHouse and tells you exactly which events arrived) or the authenticated server-side Events API POST /v1/projects/{id}/events, which returns structured 4xx errors.
Authentication
All /v1/* endpoints require a Bearer token in the Authorization header. Generate keys in the console under Settings → API keys.
Authorization: Bearer oa_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
Keys are prefixed oa_live_. Treat them like a password. A separate test/sandbox mode is planned but not yet available — for development, create a throwaway project on the free tier and use its real key.
Never put an oa_live_* token in browser JavaScript, mobile app bundles, or any public repository. If a key is leaked, revoke it immediately in the console.
Example: list projects
curl https://api.openanalyticsapi.com/v1/projects \
-H "Authorization: Bearer oa_live_xxxxxxxxxxxx"
Example: query pageviews
curl "https://api.openanalyticsapi.com/v1/projects/PROJECT_ID/pageviews?from=2026-05-01&to=2026-05-12&group_by=path" \
-H "Authorization: Bearer oa_live_xxxxxxxxxxxx"
Example: send a server-side event
curl -X POST https://api.openanalyticsapi.com/v1/projects/PROJECT_ID/events \
-H "Authorization: Bearer oa_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"event_type": "conversion",
"event_name": "purchase",
"user_id": "sha256_hash_of_user_id",
"url": "https://example.com/thanks",
"properties": {"plan":"pro"},
"revenue": 49.99,
"currency": "USD",
"timestamp": 1747000000000
}'
Successful writes return 202 Accepted with a JSON body confirming the event was queued. The public POST /collect endpoint (used by the browser snippet) returns 204 No Content instead.
Privacy / DSAR endpoints Beta
Three authenticated endpoints support Data Subject Access Requests. See GDPR & privacy for the full description.
GET /v1/projects/{id}/privacy/user/{user_id}— sanitized per-user data export. Read-only, never writes. Raw IP, raw User-Agent, properties values, and raw replay chunks are excluded. Capped at last 90 days / 10,000 events (truncatedflag when exceeded).DELETE /v1/projects/{id}/privacy/user/{user_id}— queues an asynchronous deletion request, returns202 Accepted. No data is deleted inline.GET /v1/projects/{id}/privacy/requests/{request_id}— poll a queued deletion request's status.
Rate limits
- Free: 60 requests / minute / API key
- Pro: 600 requests / minute / API key
- Business: 6,000 requests / minute / API key
- Enterprise: custom
Rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) are returned on every response. Over-limit requests return 429 Too Many Requests.
Errors
Errors return JSON with error and message fields. HTTP status codes follow REST conventions:
400— validation error401— missing or invalid Bearer token403— token lacks the required scope404— project or resource not found429— rate limit exceeded5xx— server error (safe to retry with backoff)