# Analytics Engine API Reference ## Writing Data ### `writeDataPoint()` Fire-and-forget (returns `void`, not Promise). Writes happen asynchronously. ```typescript interface AnalyticsEngineDataPoint { blobs?: string[]; // Up to 20 strings (dimensions), 16KB each doubles?: number[]; // Up to 20 numbers (metrics) indexes?: string[]; // 1 indexed string for high-cardinality filtering } env.ANALYTICS.writeDataPoint({ blobs: ["/api/users", "GET", "200"], doubles: [145.2, 1], // latency_ms, count indexes: ["customer_abc123"] }); ``` **Behaviors:** No await needed, no error thrown (check tail logs), auto-sampled at high volumes, auto-timestamped. **Blob vs Index:** Blob for GROUP BY (<100k unique), Index for filter-only (millions unique). ### Full Example ```typescript export default { async fetch(request: Request, env: Env): Promise { const start = Date.now(); const url = new URL(request.url); try { const response = await handleRequest(request); env.ANALYTICS.writeDataPoint({ blobs: [url.pathname, request.method, response.status.toString()], doubles: [Date.now() - start, 1], indexes: [request.headers.get("x-api-key") || "anonymous"] }); return response; } catch (error) { env.ANALYTICS.writeDataPoint({ blobs: [url.pathname, request.method, "500"], doubles: [Date.now() - start, 1, 0], }); throw error; } } }; ``` ## SQL API (External Only) ```bash curl -X POST https://api.cloudflare.com/client/v4/accounts/{account_id}/analytics_engine/sql \ -H "Authorization: Bearer $TOKEN" \ -d "SELECT blob1 AS endpoint, COUNT(*) AS requests FROM dataset WHERE timestamp >= NOW() - INTERVAL '1' HOUR GROUP BY blob1" ``` ### Column References ```sql -- blob1..blob20, double1..double20, index1, timestamp SELECT blob1 AS endpoint, SUM(double1) AS latency, COUNT(*) AS requests FROM my_dataset WHERE index1 = 'customer_123' AND timestamp >= NOW() - INTERVAL '7' DAY GROUP BY blob1 HAVING COUNT(*) > 100 ORDER BY requests DESC LIMIT 100 ``` **Aggregations:** `SUM()`, `AVG()`, `COUNT()`, `MIN()`, `MAX()`, `quantile(0.95)()` **Time ranges:** `NOW() - INTERVAL '1' HOUR`, `BETWEEN '2026-01-01' AND '2026-01-31'` ### Query Examples ```sql -- Top endpoints SELECT blob1, COUNT(*) AS requests, AVG(double1) AS avg_latency FROM api_requests WHERE timestamp >= NOW() - INTERVAL '24' HOUR GROUP BY blob1 ORDER BY requests DESC LIMIT 20 -- Error rate SELECT blob1, COUNT(*) AS total, SUM(CASE WHEN blob3 LIKE '5%' THEN 1 ELSE 0 END) AS errors FROM api_requests WHERE timestamp >= NOW() - INTERVAL '1' HOUR GROUP BY blob1 HAVING total > 50 -- P95 latency SELECT blob1, quantile(0.95)(double1) AS p95 FROM api_requests GROUP BY blob1 ``` ## Response Format ```json {"data": [{"endpoint": "/api/users", "requests": 1523}], "rows": 2} ``` ## Limits | Resource | Limit | |----------|-------| | Blobs/Doubles per point | 20 each | | Indexes per point | 1 | | Blob/Index size | 16KB | | Data retention | 90 days | | Query timeout | 30s | **Critical:** High write volumes (>1M/min) trigger automatic sampling.